我为一个项目创建了minesweeper的javascript版本,但我正在尝试引入一个额外的功能,以更好地模仿我记得玩的桌面版本。
我的完整代码可在以下位置找到: jsfiddle
我遇到的特殊功能是" clickTile()"功能。基本要求是添加“已选择的”课程。以及点击的图块的html的相邻地雷数量。我试图解决的附加要求是递归自动点击没有相邻地雷的瓷砖。
现有的功能是:
function clickTile($tile) {
if ($tile.hasClass('mine')) {
alert('game over');
$('.mine').css("background", "red");
} else if (!$tile.hasClass("selected")){
mines = getNumberOfAdjacentMines($tile);
$tile.addClass("selected");
$tile.html(mines);
//recursively call clickTile function as long as there are no adjacent mines
if (mines <= 0) {
height = $('#field .row').length;
width = $('#field .row .tile').length / height;
rowNum = $tile.parent().prevAll('div').length
colNum = $tile.prevAll('div').length
$above = $tile // td
.parent() // tr
.parent() // table or tbody
.children('.row')
.eq(rowNum - 1) // the row above this one
.children('.tile')
.eq(colNum) // in the same column as this
;
$below = $tile // td
.parent() // tr
.parent() // table or tbody
.children('.row')
.eq(rowNum + 1) // the row below this one
.children('.tile')
.eq(colNum) // in the same column as this
;
if (rowNum > 0) {
if (!$above.hasClass('mine') && !$above.hasClass('selected')){
clickTile($above);
}
}
if (colNum < (width-1)){
if(!$tile.next().hasClass('selected')) {
clickTile($tile.next());
}
}
if (rowNum < (height-1)){
if(!$below.hasClass('mine') && !$below.hasClass('selected')) {
clickTile($below);
}
}
if (colNum > 0){
if (!$tile.prev().hasClass('selected')) {
clickTile($tile.prev());
}
}
}
}
}
对我来说,这应该以递归方式点击所有具有0个相邻地雷的地块,但事实并非如此。任何人都可以帮我理解我可能在哪里出错吗?这种行为非常挑剔。
答案 0 :(得分:1)
嗯,你在选择器上遇到了一些麻烦,导致了太多的递归错误,有时这是一个无限循环。我试图找到错误,在某些情况下,您发送到递归单击函数空选择器,因此它无法正常工作。我不喜欢那些选择器,所以我自己的方式获得上面,下面,下一个和前面的元素,它工作得很好!这是代码:
function clickTile($tile) {
var tiles=$(".tile");
var rows=8;
var columns=8;
var index=tiles.index($tile);
if($tile.length ==0) return false;
if ($tile.hasClass('mine')) {
alert('game over');
$('.mine').css("background", "red");
} else if (!$tile.hasClass("selected")){
mines = getNumberOfAdjacentMines($tile);
$tile.html(mines);
$tile.addClass("selected");
//recursively call clickTile function as long as there are no adjacent mines
if (mines <= 0) {
if (index >= rows) {
$above=$(tiles.get(index-rows));
if (!$above.hasClass('mine') && !$above.hasClass('selected')){
clickTile($above);
}
}
if ((index+1)%columns !=0 ){
$next=$(tiles.get(index+1))
if(!$next.hasClass('selected')) {
clickTile($next);
}
}
if (index+rows < (rows*columns) ){
$below=$(tiles.get(index+rows));
if(!$below.hasClass('mine') && !$below.hasClass('selected')) {
clickTile($below);
}
}
if ((index+1)%columns != 1){
$prev=$(tiles.get(index-1))
if (!$prev.hasClass('selected')) {
clickTile($prev);
}
}
}
}
}
以下是旅行邻居的简短版本:
if (mines <= 0) {
var posInRow=(index+1)%columns;
var neighbours=[];
if(index >= rows) neighbours.push(index-rows);//up
if(index+rows < (rows*columns) ) neighbours.push(index+rows);//down
if(posInRow != 0) neighbours.push(index+1);//right
if(posInRow != 1) neighbours.push(index-1);//left
for(var i=0;i<neighbours.length;i++){
var neighbour=$(tiles.get(neighbours[i]));
if (!neighbour.hasClass('mine') && !neighbour.hasClass('selected')){
clickTile(neighbour);
}
}
}
答案 1 :(得分:1)
您的代码存在的问题是变量是在没有var
关键字的情况下定义的,因此它们是在全局范围内定义的。
在clickTile函数中,您应该替换
// rowNum is defined in the global scope,
// Its value is overwritten with each recursive call
rowNum = $tile.parent().prevAll('div').length
带
// rowNum has the function as a scope,
// its keeps different rowNum values for each recursive function call
var rowNum = $tile.parent().prevAll('div').length
rowNum
(和其他变量)值被递归调用覆盖,因此其他条件的行为将不正确
if (rowNum > 0) { // rowNum can be anything at this point
// The condition is randomly met
}
将var
关键字添加到您的变量中,您的代码应按预期工作。
有关javascript范围的更多信息here。