你好
我正试图创建“我的游戏”的模拟
假设我们有矩阵
0 0 0 0
0 0 -1 0
0 0 0 -1
0 -1 0 -1
现在每个不等于-1的单元应该代表地雷的数量
这里的代码
for(int i = 0; i
for(int j=0;j<N;j++)
if(box[i][j]!=-1)
{
switch (i)
{
case 0:
iLEFT=0;
iRIGHT=1;break;
case 3:
iRIGHT=0;
iLEFT=1;
break;
case 1:
iLEFT=1;
iRIGHT=1;
break;
case 2:
iLEFT=1;
iRIGHT=1;
break;
default:
iLEFT=1;
iRIGHT=1;
break;
}
switch (j)
{
case 0:
jLEFT=0;`
jRIGHT=1;
break;
case 3:
jRIGHT=0;
jLEFT=1;
break;
case 1:
jLEFT=1;
jRIGHT=1;
break;
case 2:
jLEFT=1;
jRIGHT=1;
break;
default:
jLEFT=1;
jRIGHT=1;
break;
}
// checking neighbor
if(box[i][j+jRIGHT]==-1)
count+=1;
if(box[i][j-jLEFT]==-1)
count+=1;
if(box[i+iRIGHT][j]==-1)
count+=1;
if (box[i-iLEFT][j]==-1)
count+=1;
if(box[i-iLEFT][j-jLEFT]==-1)
{
if(i-iLEFT!=i) // trying to avoid double checking
count+=1;
}
if(box[i+iRIGHT][j-jLEFT]==-1)
{
if(i+iRIGHT!=i) //trying to avoid double checking
count+=1;
}
if (box[i-iLEFT][j+jRIGHT]==-1)
{
if(i!=iLEFT) //trying to avoid double checking
count+=1;
}
if (box[i+iRIGHT][j+jRIGHT]==-1)
{
if(i!=iRIGHT) //trying to avoid double checking
count+=1;
}
box[i][j]=count;
count=0;
}
我的算法
iLEFT现在向左行。
iRIGHT目前行步右。
对于列,jLEFT和JRIGHT相同
假设i = 0,所以我们只能向右一步(向下)
如果i = 1,我们可以提升并完成...相同的j
“案例陈述”更新iLEFT / iRIGTH和jLEFT / jRIGHT用于启用侧步骤
现在“if”语句检查左/右上/下2个对角线为方框[i] [j](总共只有一步)
计数盒[i] [j]
你可以看到我仍然对同一个单元格进行双重检查
0 1 1 1
0 1 -1 2
1 2 4 -1
2 -1 4 -1
答案 0 :(得分:2)
您还应该概述您的算法以及代码,以更好地了解您如何处理问题。没有附带的算法,很难理解这段代码。
您可以用简单的英语概述您的算法,不必是伪代码。它将帮助您更好地理解问题和解决方案。例如,像这样:
我认为你检查边界条件的方式过于复杂。让我们假设雷区在每个方向上都是无限大的。如果我们随后挑选了任何随机cell(i,j)
,那么 8 邻居将会在:
cell(i-1, j-1) // top-left
cell(i-1, j) // top
cell(i-1, j+1) // top-right
cell(i, j-1) // left
cell(i, j+1) // right
cell(i+1, j-1) // bottom-left
cell(i+1, j) // bottom
cell(i+1, j+1) // bottom-right
现在回到实际的有限长度案例。我建议不要预先计算一个单元格是否在边界内,而应该检查所有8个邻居,并丢弃无效的邻居。
检查单元格是否有效的函数很容易编写:
bool is_cell_valid(int x, int y, int rows, int cols) {
if(x < 0 || x >= cols) {
return false;
}
if(y < 0 || y >= rows) {
return false;
}
return true;
}
我现在终于明白了你的算法:)
正在进行双重检查,因为您没有检查所有正在变化的变量。例如,在这种情况下,您使用iLEFT和jLEFT转到左上角的单元格。由于正在使用这两个变量,因此必须确保它们都是非零的。
if(box[i-iLEFT][j-jLEFT]==-1)
{
if(i-iLEFT!=i) // trying to avoid double checking
count+=1;
}
上面应该是
if(iLEFT != 0 && jLEFT != 0)
{
if(box[i-iLEFT][j-jLEFT]==-1)
count+=1;
}
此检查应该应用于8个单元格中的每一个,而不仅仅是对角线单元格。
这是一个很小的替代方案,可以在(x,y)处查看与某个单元格相邻的所有8个单元格,而不使用每个邻居的if。
for(int i = -1; i < = 1; i++) {
for(int j = -1; j <= 1; j++) {
if(i == 0 && j == 0) {
continue;
}
if(is_cell_valid(x + i, y + j, N, N);
// cell is adjacent and within boundaries
// do whatever calculations are needed
}
}
}
答案 1 :(得分:0)
我的第二个包括你的算法的插图,这将更容易阅读 我以前做过minesweeper游戏的方式,这可能是生成函数的轮廓
附加功能 在第一次点击后延迟炸弹的产生,这样你就可以确保不在用户点击的第一个牢房上放置炸弹
这是一段代码片段
var i = 0
while (i < bombsNum){
//generate a random location for the bomb
var col=Math.floor(Math.random()*cols);
var row=Math.floor(Math.random()*rows);
//if new location is already a bomb
if (cellsData[row][col] == -1) continue;
//if new location is near the start region
if (col == startCol-1 || col == startCol || col == startCol +1){
if (row == startRow -1 || row == startRow || row == startRow+1)
continue;
}
i++;
cellsData[row][col] = -1;
//increment all the neighbors cells and make sure to handle the special cases cells (cells at the corner)
}