调试 15 拼图中的无效移动
Debugging invalid moves in a 15 puzzle
我做了一点15 puzzle,我想在开始时对其进行洗牌。我从完成的状态开始,随机 "fakeClicks" 对根据我的代码有些有效但大部分无效的图块进行随机操作。有效的 "fakeClicks" 导致 emptyTile
和 selectedTile
通过交换它们的 top
和 left
值来交换它们的位置。
一切(除了尚不存在的 checkCompleteness()
方法)似乎都有效 - 直到有人真正尝试解决难题。使用较小的 n,我达到 unsolvable game situation 的概率超过 50%。
在洗牌过程中我只做有效的移动,这怎么可能?显然这一定是关于我的代码检查移动是否有效:
if ((Math.abs(selectedX - emptyX) === tileSize) ^ (Math.abs(selectedY - emptyY) === tileSize)) {
(^(异或)是为了防止对角线移动。)
有人知道问题出在哪里吗?或者有人对好的调试策略有什么建议吗?调试了一个多小时,有点懵
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 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>
你是对的,你的测试是错误的。
想象一个小板,中间是所选的图块
ooooo
ooooo
ooxoo
ooooo
ooooo
现在看看 2 个谓词的两个真值表根据空块的位置给出什么。
ftftf
ftftf
ftxtf
ftftf
ftftf
和
fffff
ttttt
ffxff
ttttt
fffff
将它们与异或运算混合,你会得到
ftftf
tftft
ftxtf
tftft
ftftf
这意味着您在方块周围的 "first circle" 上得到了正确的响应,但是在离方块较远的地方得到了错误的响应。
我做了一点15 puzzle,我想在开始时对其进行洗牌。我从完成的状态开始,随机 "fakeClicks" 对根据我的代码有些有效但大部分无效的图块进行随机操作。有效的 "fakeClicks" 导致 emptyTile
和 selectedTile
通过交换它们的 top
和 left
值来交换它们的位置。
一切(除了尚不存在的 checkCompleteness()
方法)似乎都有效 - 直到有人真正尝试解决难题。使用较小的 n,我达到 unsolvable game situation 的概率超过 50%。
在洗牌过程中我只做有效的移动,这怎么可能?显然这一定是关于我的代码检查移动是否有效:
if ((Math.abs(selectedX - emptyX) === tileSize) ^ (Math.abs(selectedY - emptyY) === tileSize)) {
(^(异或)是为了防止对角线移动。)
有人知道问题出在哪里吗?或者有人对好的调试策略有什么建议吗?调试了一个多小时,有点懵
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 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>
你是对的,你的测试是错误的。
想象一个小板,中间是所选的图块
ooooo
ooooo
ooxoo
ooooo
ooooo
现在看看 2 个谓词的两个真值表根据空块的位置给出什么。
ftftf
ftftf
ftxtf
ftftf
ftftf
和
fffff
ttttt
ffxff
ttttt
fffff
将它们与异或运算混合,你会得到
ftftf
tftft
ftxtf
tftft
ftftf
这意味着您在方块周围的 "first circle" 上得到了正确的响应,但是在离方块较远的地方得到了错误的响应。