Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 22.05.2013, 16:48
Интересующийся
Отправить личное сообщение для ed-210 Посмотреть профиль Найти все сообщения от ed-210
 
Регистрация: 22.05.2013
Сообщений: 14

Глюки с рекурсией
Народ, подскажите пожалуйста кто чем может! Есть такая вот проблема, что в скрипте, который я тут выкладываю, присутствует рекурсивная функция, исследующая значения в массиве и определяющая совпадения со случайным получаемым значением в этой функции. В целом, сценарий направлен на создание игры "Пятнашки".

Глюк такой, что когда я вставляю строчные выражения внутрь функции, никак на прямую не связанные с логикой функции и не влияющие на её работу, то мой сценарий начинает нормально работать и не допускает повторения значений в результирующем массиве. Они только лишь для вывода отчетов по этапам работы функции и в окончательном варианте не нужны. НО как только функция лишается этих выражений с отчетом, то сразу же наблюдается повторное попадание совпадающих значений в массив.

script.js ( обратить внимание на рекурсивную функцию getCubeCoords(), если в ней убрать или закомментировать все строки, где встречается переменная otchet1, то все будет плохо , а именно, может быть не с первого раза, но со второго или третьего раза обновления страницы, появятся совпадающие значения в массиве cubeMap, что пагубно отражается на расстановке квадратов в выделенном для них поле field):
var fieldSize = 16;

var cubeMap = [];
var otchet1 = '<table border="1">\n'
			+ '<tr><td>№<\/td><td>Выбранные координаты<\/td><td>Результат<\/td><td>Окончательные координаты<\/td><\/tr>';
genCubeMap();
otchet1 += '<\/table>';

function genCubeMap(){
	var reqX, reqY;
	
	for (var i=0; i < fieldSize; i++){
		getCubeCoords();
	}

	function getCubeCoords(){
		reqX = parseInt(Math.random()*4);
		reqY = parseInt(Math.random()*4);

		otchet1 += '<tr><td>'+ (i+1) +'<\/td><td>'+ reqX +':'+ reqY +'<\/td>';

		var zanyato = false;
		for (var n=0; n < i+1; n++){
			if (cubeMap[n] && cubeMap[n][1] == reqX && cubeMap[n][2] == reqY){
        		zanyato = true;
        		break;
        	}	
        }

		if (zanyato !== false){
			otchet1 += '<td>заняты квадратом №'+ (n+1) +'<\/td><td>&nbsp;<\/td><\/tr>\n';
			getCubeCoords();
			return;
		} else {
			otchet1 += '<td>Свободны<\/td><td>'+ reqX +':'+ reqY +'<\/td><\/tr>\n';
		}

		cubeMap[i] = [i<fieldSize-1 ? i+1 : null, reqX, reqY, '|'];
	}
}

function placeCubs(){
	for (var i=0; i < fieldSize-1; i++){
		this['cube'+(i+1)].style.left = cubeMap[i][1]*53 +'px';
		this['cube'+(i+1)].style.top  = cubeMap[i][2]*53 +'px';
	}
}

var d = document;
var field, cube1, cube2, cube3, cube4, cube5, cube6, cube7, cube8, cube9, cube10, cube11, cube12, cube13, cube14, cube15;
var info, info2;
window.onload = function(){
	info   = d.getElementById('info');
	info2  = d.getElementById('info2');

	field  = d.getElementById('field');

	cube1  = d.getElementById('cube1');
	cube2  = d.getElementById('cube2');
	cube3  = d.getElementById('cube3');
	cube4  = d.getElementById('cube4');
	cube5  = d.getElementById('cube5');
	cube6  = d.getElementById('cube6');
	cube7  = d.getElementById('cube7');
	cube8  = d.getElementById('cube8');
	cube9  = d.getElementById('cube9');
	cube10 = d.getElementById('cube10');
	cube11 = d.getElementById('cube11');
	cube12 = d.getElementById('cube12');
	cube13 = d.getElementById('cube13');
	cube14 = d.getElementById('cube14');
	cube15 = d.getElementById('cube15');

	placeCubs();

	info.innerHTML = otchet1;
}

default.css :
body {
	background: #fff;
	color: #000;
	margin: 5px;
	padding-top: 1px;
}
#info {
	position: absolute;
	font: normal 12px Arial;
}
#info2 {
	position: absolute;
	right: 0;
}
#field {
	border: 1px solid #000;
	width: 211px; height: 211px;
	padding: 1px;
	margin: 100px auto 0;
	background: #FFF;
	
}
#field div {
	width: 50px; height: 50px;
	border: 1px solid #000;
	margin: 0 -52px -52px 0;
	background: #566DFF;
	text-align: center;
	font: bold 38px Arial;
	position: relative;
	cursor: pointer;
}

index.html :
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <title>JavaScript - "Пятнашки"</title>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   <link rel="stylesheet" type="text/css" href="./default.css" />
   <script type="text/javascript" src="./script.js"></script>
</head>
<body>
<div id="info">&nbsp;</div>
<div id="info2">&nbsp;</div>
<div id="field">
	<div id="cube1">1</div>
	<div id="cube2">2</div>
	<div id="cube3">3</div>
	<div id="cube4">4</div>
	<div id="cube5">5</div>
	<div id="cube6">6</div>
	<div id="cube7">7</div>
	<div id="cube8">8</div>
	<div id="cube9">9</div>
	<div id="cube10">10</div>
	<div id="cube11">11</div>
	<div id="cube12">12</div>
	<div id="cube13">13</div>
	<div id="cube14">14</div>
	<div id="cube15">15</div>
</div>
</body>
</html>

Никак не могу взять в толк в чем здесь проблема. ХЕЛП!

Последний раз редактировалось ed-210, 23.05.2013 в 13:58.
Ответить с цитированием
  #2 (permalink)  
Старый 23.05.2013, 09:55
Профессор
Отправить личное сообщение для skrudjmakdak Посмотреть профиль Найти все сообщения от skrudjmakdak
 
Регистрация: 27.04.2012
Сообщений: 1,410

очень странно тут у вас.. функция placeCubs, разберем для начала ее..
this['cube'+(i+1)].style.left = cubeMap[i][1]*53 +'px';
что это??
this - это window. а window, это не массив. это объект
this['cube'+(i+1)] - этого быть не может!!

вот массив cubeMap[i][1] - что это?? на момент пока вы его вызвайте - он пустой!! разумеется будет ошибка!!

используйте фаербаг!!! чтобы его вызвать в хроме нажмите f12, там будет вкладка console. туда и будут сыпаться ваши ошибки
Ответить с цитированием
  #3 (permalink)  
Старый 23.05.2013, 09:58
Профессор
Отправить личное сообщение для skrudjmakdak Посмотреть профиль Найти все сообщения от skrudjmakdak
 
Регистрация: 27.04.2012
Сообщений: 1,410

field  = d.getElementById('field');

	cube1  = d.getElementById('cube1');
	cube2  = d.getElementById('cube2');
	cube3  = d.getElementById('cube3');
	cube4  = d.getElementById('cube4');
	cube5  = d.getElementById('cube5');
	cube6  = d.getElementById('cube6');
	cube7  = d.getElementById('cube7');
	cube8  = d.getElementById('cube8');
	cube9  = d.getElementById('cube9');
	cube10 = d.getElementById('cube10');
	cube11 = d.getElementById('cube11');
	cube12 = d.getElementById('cube12');
	cube13 = d.getElementById('cube13');
	cube14 = d.getElementById('cube14');
	cube15 = d.getElementById('cube15');


это все нафига?
один раз нашли фиелд и хватит
field = d.getElementById('field');
дальше можно делать так:
cube1  = field.children[0];
cube2  = field.children[1];
cube3  = field.children[2];
... ну и дальше в таком духе. а можно так массивом и хранить
Ответить с цитированием
  #4 (permalink)  
Старый 23.05.2013, 12:55
Интересующийся
Отправить личное сообщение для ed-210 Посмотреть профиль Найти все сообщения от ed-210
 
Регистрация: 22.05.2013
Сообщений: 14

Ну, во первых, с ошибками у меня тут все в порядке Все проверено и сбоев нет благодаря отличному инструменту Web Developer для Firefox!

Во вторых, этот this в функции placeCubs() действительно содержит объект окна, но вот интересная штука - кроме этого он содержит еще и все переменные, которые были созданы раньше обращения к этому объекту в такой форме, в виде массива с ассоциативными ключами, которые соответствуют именам этих переменных! Вот статья по этой теме!

В третьих, спасибо за совет насчет field.children[0]..., действительно это слегка уменьшает код и при этом работает! Я действительно не знал, что можно так делать

В четвертых, элемент массива cubeMap[i][1] в 43 строке скрипта не пустой, так как при загрузке сценария в браузер запускается функция genCubeMap() с локальной рекурсивной функцией внутри, которая создает значения в массиве cubeMap в виде массива 2ого уровня с рядом значений в 37 строке скрипта. Затем, после срабатывания события window.onload запускается функция placeCubs(), которая начинает обращаться к массиву cubeMap, в котором уже присутствуют 16 элементов с индексами с 0 по 15, из которых задействуются 15 элементов с индексами с 0 по 14.

Эта функция расставляет имеющиеся в HTML документе блоки с id="cube1" и до "cube15", с помощью свойств стиля left и top, в соответствии со значениями, помещенными рекурсивной функцией getCubeCoords() в массив cubeMap[i] с индексами [1] и [2], т.е. эти значения оказываются в cubeMap[i][1] и cubeMap[i][2] позициях и, по сути, являются координатами месторасположения каждого конкретного блока внутри поля field.

Надеюсь, я понятно объяснил?

Последний раз редактировалось ed-210, 23.05.2013 в 13:25.
Ответить с цитированием
  #5 (permalink)  
Старый 23.05.2013, 13:33
Профессор
Отправить личное сообщение для skrudjmakdak Посмотреть профиль Найти все сообщения от skrudjmakdak
 
Регистрация: 27.04.2012
Сообщений: 1,410

сори.. эт я протупил.. объяснили понятно. вот только ошибка все равно есть в js.посмотрите свой код еще раз, где то не хватает скобок закрывающих (1 шт). может когда копировали не докопировали..))
Ответить с цитированием
  #6 (permalink)  
Старый 23.05.2013, 13:45
Профессор
Отправить личное сообщение для skrudjmakdak Посмотреть профиль Найти все сообщения от skrudjmakdak
 
Регистрация: 27.04.2012
Сообщений: 1,410

а отчет вам зачем?
вот эта байда:
var otchet1 = '<table border="1">\n'
			+ '<tr><td>№<\/td><td>Выбранные координаты<\/td><td>Результат<\/td><td>Окончательные координаты<\/td><\/tr>';
otchet1 += '<\/table>';


я так понял для отладки? честно говоря я наверное материться буду. вот почти каждому отвечающему говорю одно и тоже!! есть фаербаг для этого!!

у вас фаерфокс я так понял? это тогда устанавливать его надо. для установки надо скачать, попробуйте здесь:
https://addons.mozilla.org/ru/firefox/addon/firebug/

в хроме он идет стандартно, устанавливать не надо.
если хтите погуглите..

и после установки для вызова фаербага нажимайте f12, там есть вкладка консоль, чтобы туда сыпать сообщения вместо вашего: otchet1 += '<td>заняты квадратом №'+ (n+1) +'<\/td><td>&nbsp;<\/td><\/tr>\n';

нужно прописать: console.log('заняты квадратом №'+ (n+1));
Ответить с цитированием
  #7 (permalink)  
Старый 23.05.2013, 13:59
Интересующийся
Отправить личное сообщение для ed-210 Посмотреть профиль Найти все сообщения от ed-210
 
Регистрация: 22.05.2013
Сообщений: 14

Сообщение от skrudjmakdak Посмотреть сообщение
... может когда копировали не докопировали..))
Да, действительно при копировании пропустил скобку в цикле for (var n=0; n < i+1; n++) исправил уже.
Ответить с цитированием
  #8 (permalink)  
Старый 23.05.2013, 14:16
Профессор
Отправить личное сообщение для skrudjmakdak Посмотреть профиль Найти все сообщения от skrudjmakdak
 
Регистрация: 27.04.2012
Сообщений: 1,410

так, давайте еще раз. если нет текстовых переменных то у вас не правильно формируется cubeMap.

cubeMap[i] = [i<fieldSize-1 ? i+1 : null, reqX, reqY, '|'];

в дальнейшем используется только индексы 1 (reqX) и 2 (reqY)
индекс 0 и 4 не используются.. на них можно не смотреть?
Ответить с цитированием
  #9 (permalink)  
Старый 23.05.2013, 14:29
Интересующийся
Отправить личное сообщение для ed-210 Посмотреть профиль Найти все сообщения от ed-210
 
Регистрация: 22.05.2013
Сообщений: 14

да, можно не смотреть...
Ответить с цитированием
  #10 (permalink)  
Старый 23.05.2013, 14:30
Профессор
Отправить личное сообщение для skrudjmakdak Посмотреть профиль Найти все сообщения от skrudjmakdak
 
Регистрация: 27.04.2012
Сообщений: 1,410

вот немного переписал функцию:
function genCubeMap()
	{
	var reqX, reqY;
	
	var zanyato = false;
	for (var i=0; i < fieldSize; i++)
		{
		do
			{
			zanyato = false;
			reqX = parseInt(Math.random()*4);
			if (reqX == 4) reqX = 3;
			reqY = parseInt(Math.random()*4);
			if (reqY == 4) reqY = 3;
			
			for (var n=0; n < i+1; n++)
				{
				if (cubeMap[n] && cubeMap[n][1] == reqX && cubeMap[n][2] == reqY)
					{
					zanyato = true;
					break;
					}	
				}
			}
		while (zanyato);
		cubeMap[i] = [i<fieldSize-1 ? i+1 : null, reqX, reqY, '|'];
		}
	}


я большой противник рекурсий. лучше рекурсию заменить на цикл.
и метод random принимает значения от 0 до 1. т.е. вам нужен диапазон от 0 до 3. если при вашем подходе рандом выдаст 1.. и умножить на 4, то получится 4.. это конечно редко будет по теории вероятности, но будет...
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Глюки с умножением! misteralexander Общие вопросы Javascript 6 21.05.2013 21:46
Глюки таймера при переключении вкладки браузера denfer12 Общие вопросы Javascript 1 11.05.2012 22:18
SVG - размер холста 10.000.000 = глюки Shasoft Библиотеки/Тулкиты/Фреймворки 2 30.11.2009 11:21
Глюки форума? ZoNT Оффтопик 11 19.10.2009 14:40
Глюки IE Elfinit Prototype & script.aculo.us 5 05.08.2008 09:15