I made a little 15 puzzle which I want to be shuffled in the beginning. I start from the completed state and do 1000 random "fakeClicks" on tiles of which some are valid according to my code and most are not. The valid "fakeClicks" cause the emptyTile and the selectedTile to swap their positions by swaping their top and left values.
Everything (except the checkCompleteness() method which does not exist yet) seems to work - until one actually tries to solve the puzzle. With a small n, I reached the unsolvable game situation more than 50 percent of the time.
How is this possible when during shuffling I do valid moves only? Obviously it must be something about my code checking if a move is valid or not:
if ((Math.abs(selectedX - emptyX) === tileSize) ^ (Math.abs(selectedY - emptyY) === tileSize)) {
(The ^ (xor) is to prevent diagonal moves.)
Does anyone see where the problem is to be found? Or does anyone have a suggestion for a good debugging strategy? After more than an hour of debugging, I am kind of clueless.
var idList = ["t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10", "t11", "t12", "t13", "t14", "t15", "t0"];
var tileSize = 100;
var init = function() {
// place tiles on the board and add listener
for (var column = 0; column < 4; column++) {
for (var row = 0; row < 4; row++) {
var div = document.querySelector("." + idList[row * 4 + column]);
div.style.top = row * tileSize + "px";
div.style.left = column * tileSize + "px";
if (idList[row * 4 + column] !== "t0") {
div.addEventListener("click", clickListener);
}
}
}
// shuffle tiles
for (i = 0; i < 1000; i++) {
var fakeClick = parseInt(Math.random() * 15);
swapTiles(idList[fakeClick]);
}
};
var clickListener = function(e) {
var selectedTileClass = e.target.classList[1];
swapTiles(selectedTileClass);
//checkCompleteness(); // to be done later
};
var swapTiles = function(selectedTileClass) {
// get indices of empty tile and selected tile
var emptyTileIndex = 0;
var selectedTileIndex = 0;
for (var i = 0; i < idList.length; i++) {
if (idList[i] === "t0") {
emptyTileIndex = i;
}
if (idList[i] === selectedTileClass) {
selectedTileIndex = i;
}
}
// get empty tile and selected tile
var selectedTile = document.querySelector("." + selectedTileClass);
var selectedX = parseInt(selectedTile.style.left);
var selectedY = parseInt(selectedTile.style.top);
var emptyTile = document.querySelector(".t0");
var emptyX = parseInt(emptyTile.style.left);
var emptyY = parseInt(emptyTile.style.top);
// only swap tiles if selected tile "next to" empty tile
if ((Math.abs(selectedX - emptyX) === tileSize) ^ (Math.abs(selectedY - emptyY) === tileSize)) {
selectedTile.style.left = emptyX + "px";
selectedTile.style.top = emptyY + "px";
emptyTile.style.left = selectedX + "px";
emptyTile.style.top = selectedY + "px";
}
};
.board {
position: relative;
width: 400px;
height: 400px;
margin: auto;
background-color: firebrick;
border: 2px firebrick solid;
}
.tile {
position: absolute;
width: 100px;
height: 100px;
border: 2px firebrick solid;
box-sizing: border-box;
background-color: orange;
line-height: 100px;
font-size: 2rem;
font-weight: bold;
font-family: Arial, sans-serif;
color: firebrick;
text-align: center;
transition: all .25s linear;
cursor: pointer;
}
.t0 {
position: absolute;
width: 96px;
height: 96px;
margin: 2px;
border: 2px orange solid;
box-sizing: border-box;
pointer-events: none;
transition: all .25s linear;
}
<html>
<meta charset="utf-8">
<head>
<script type="text/javascript" src="js.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body onload="init();">
<div class="wrapper">
<div class="center">
<div class="board">
<div class="tile t1">1</div>
<div class="tile t2">2</div>
<div class="tile t3">3</div>
<div class="tile t4">4</div>
<div class="tile t5">5</div>
<div class="tile t6">6</div>
<div class="tile t7">7</div>
<div class="tile t8">8</div>
<div class="tile t9">9</div>
<div class="tile t10">10</div>
<div class="tile t11">11</div>
<div class="tile t12">12</div>
<div class="tile t13">13</div>
<div class="tile t14">14</div>
<div class="tile t15">15</div>
<div class="t0"></div>
</div>
</div>
</div>
</body>
</html>
Aucun commentaire:
Enregistrer un commentaire