递归函数提前返回,只检查一条路径



我正在创建一个连接四游戏,我正在使用递归来检查所做的移动是否是成功的移动。 x 和 y 是 7x6 网格上移动的坐标。

我还没有实现检查点的方向是否正确匹配(所以现在如果 4 个部分以任何方式接触,它仍然应该检测到获胜)。但在我这样做之前,我遇到了一个问题。即使所做的移动应该导致获胜,如果有另一条路径连续没有四个,则该函数返回 false。

函数错误地未检测到胜利的示例(绿线是应该检测到的,红线是我相信函数提前返回 false 的路径): https://prnt.sc/fjhia1

这是我的代码:

function isVisited(x,y,visited){
var pointStr = x + "," + y;
var result = visited.some(function(e){
return e.join() == pointStr;
});
return result;
}
function checkWin(x, y, color, visited, count) {
if(count==3) return true;
for(i=-1; i<2; i++) {
for (j=-1; j<2; j++) {
if(!(i==0 && j==0) && (x+i)<7 && (y+j)<6 && (x+i)>-1 && (y+j)>-1 && grid[x+i][y+j] != null) {
if (grid[x+i][y+j] == color && !isVisited(x+i,y+j,visited)) {
visited.push([x, y]);
if(checkWin(x+i, y+j, color, visited, count+1)) return true;
}
}
}
}
return false;
}

为了澄清,i 和 j 是用于检查起点周围所有点的偏移量。

颜色参数为"黑色"或"红色"。网格是一个 7x6 2D 数组,用于存储哪些玩家棋子在哪里,并在玩家移动时更新。整个 checkWin() 函数在每次移动后被调用,x 和 y 参数是刚刚播放的移动的坐标。数组中颜色的示例显示在链接的图片中。

来自图像的网格示例,当在 x=5、y=3、color="black" 处传递到 checkWin() 时,这应该返回 true,但它没有:

[[null,null,null,null,null,null],[null,null,null,null,null,null],[null,null,null,null,null,null],[null,null,null,null,null,"black"],[null,null,null,null,"black","red"],[null,null,null,"black","black","black"],[null,null,null,"red","red","red"]]

这是一些工作代码。我试图将您的grid放入代码中。

你的代码有一些问题,但我认为主要的问题是你没有正确总结计数。在代码中,会遇到以下情况:

starting here
|
v
R R R R

您将首先探索此节点的左侧,您会发现连续没有四个红色。然后您将向右探索,发现连续没有四个红色。但你需要做的是总结这些。您需要计算起始节点,然后是左侧的两个节点,然后是右侧的两个节点,以获得连续四个的正确总数。

下面的代码采用该策略。这有点重写,但我试图让它与您的原始代码有些相似。如果不清楚,请告诉我。(这个代码和你的代码一样,并不真正关心"连续",而只是"触摸"。

const N = null, B = "black", R = "red";
const grid = [
//   0  1  2  3  4  5  6
[N, N, N, N, N, N, N],  // 0
[N, N, N, N, N, N, N],  // 1
[N, N, N, N, N, N, N],  // 2
[N, N, N, N, N, B, R],  // 3
[N, N, N, N, B, B, R],  // 4
[N, N, N, B, R, B, R],  // 5
];
function isVisited(x, y, visited) {
var pointStr = [x, y].join();
return visited.some(function (e) {
return e.join() == pointStr;
});
}
function checkWin(x, y) {
function countNeighbors(x, y, color, visited) {
if (y > 5 || x > 6) {  // out of bounds
return 0;
}
if (isVisited(x, y, visited)) {  // already visited
return 0;
}
visited.push([x, y]);
if (grid[y][x] !== color) {  // wrong color
return 0;
}
var count = 1;  // Count ourselves first.
// For each neighbor,
for (var i = -1; i < 2; i++) {
for (var j = -1; j < 2; j++) {
// add the count starting at that neighbor.
count += countNeighbors(x+i, y+j, color, visited);
}
}
// Return the total found.
return count;
}
// There's a win if the count is at least four.
return countNeighbors(x, y, grid[y][x], []) >= 4;
}
console.log(checkWin(3, 5));  // true
console.log(checkWin(5, 3));  // true
console.log(checkWin(6, 3));  // false

您将错误的网格单元格索引推送到visited列表。应该是[x + i, y + j].

或者,您可以将语句移动到函数的顶部并保持原样,在我看来这更好。该函数本身检查一个单元格,在开始时将该单元格标记为选中或访问更有意义。

最新更新