意外结果 C++
Unexpected result C++
我正在制作扫雷游戏。然而,在测试生成函数时,它几乎总是(如果不是总是)发生故障,我不明白为什么。
这是我的代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
struct board {
int width=9, mines=10;
char board[9][9];
/* char board[][]
* -1 = Mine
* 0 = No mines near
* 0+ = x amount of mines are near
*/
};
struct point {
int x,y;
};
board newBoard(){
board board1;
point randPoint;
for(int i=0;i<board1.width;i++){
for(int j=0;j<board1.width;j++) board1.board[i][j]=0; // Initialize array
}
for(int i=0;i<board1.mines;i++){
randPoint.x=rand()%board1.width, randPoint.y=rand()%board1.width; // Where will the mine go?
if(board1.board[randPoint.x][randPoint.y]!=-1){ // If not already a mine
board1.board[randPoint.x][randPoint.y]=-1; //make a mine
} else i--; //else don't count this
}
for(int i=0;i<board1.width;i++){
for(int j=0;j<board1.width;j++){
if(board1.board[i][j]==-1) { // If mine exists
// The if checks preceding the ++'s are to prevent out of bounds erors
if (j-1>=0) board1.board[i][j-1]++;
if (j+1<board1.width) board1.board[i][j+1]++;
if (i-1>=0) board1.board[i-1][j]++;
if (i+1<board1.width) board1.board[i+1][j]++;
if ((i-1>=0) && (j-1>=0)) board1.board[i-1][j-1]++;
if ((i-1>=0) && (j+1<board1.width))board1.board[i-1][j+1]++;
if ((i+1<board1.width) && (j-1>=0))board1.board[i+1][j-1]++;
if ((i+1<board1.width) && (j+1<board1.width))board1.board[i+1][j+1]++;
}
}
}
return board1;
}
int main() {
board boardGame=newBoard();
printf("- ");
for(int i=0;i<boardGame.width;i++) printf("%i ",i+1);
printf("\n\n");
for(int i=0;i<boardGame.width;i++){
printf("%i. ",i+1);
for(int j=0;j<boardGame.width;j++) if (boardGame.board[i][j]==-1) {
printf(" X");
} else {
printf(" %i", boardGame.board[i][j]);
}
printf("\n");
}
return 0;
}
这会产生:
- 1 2 3 4 5 6 7 8 9
1. 0 0 0 0 1 X 1 0 0
2. 1 1 0 0 2 2 2 1 1
3. X 2 1 1 1 X 1 1 X
4. 1 2 X 0 1 1 0 1 1
5. 0 1 1 1 0 0 0 0 0
6. 0 0 0 0 1 1 1 0 0
7. 0 0 1 1 2 X 1 0 0
8. 1 1 2 X 2 1 1 0 0
9. 1 X 2 1 1 0 0 0 0
你可能已经知道,在扫雷游戏中,有地雷(在这种情况下会被标记为X
),所有附近的网格点都是它附近的地雷数量(如果您还不熟悉它 this 页面可能会有用)。如您所见,4,7 和 4,4 处的数字不正确。
不知道为什么会这样。有人可以帮助我理解这一点,并告诉我如何解决这个问题吗?
此外,我刚刚注意到每次 运行 时都会产生相同的输出。为什么?
当 2 个地雷靠近时会出现问题:当您添加地雷数量时,您没有检查该方格是否有地雷。
假设你在 (0, 0) 上有一个地雷,在 (0, 1) 上有另一个。当你添加到 (0, 0) 附近的地雷计数时,你不小心也添加了 (0, 1) 中的地雷,将它从 -1 更改为 0。这也会使正在处理的第二个地雷消失。
我建议使用另一个数字来表示地雷,例如-999,并在查找时检查数字是否为负数。这比为您已有的所有 if 子句添加另一个条件更容易。
Ioums 是正确的,您没有在递增之前检查单元格是否是地雷。但是,根据您的代码当前设置的方式,这将意味着在每个 if 语句中添加一个单元格不等于 -1 的检查。您应该考虑创建一个函数来安全地增加单元格,如果它在边界内而不是地雷内,就像这样:
void safeIncrement(int x, int y, board& b)
{
if(x >= 0 && y >= 0 && x < b.width && y < b.width && b.board[x][y] != -1)
{
b.board[x][y]++;
}
}
这意味着您可以将 if 语句替换为:
safeIncrement(i-1,j,board1);
safeIncrement(i-1,j-1,board1);
safeIncrement(i-1,j+1,board1);
safeIncrement(i,j-1,board1);
safeIncrement(i,j+1,board1);
safeIncrement(i+1,j,board1);
safeIncrement(i+1,j-1,board1);
safeIncrement(i+1,j+1,board1);
我认为这更具可读性。此外,由于如果单元格是地雷,该函数不会递增单元格,因此您还可以用以下代码替换 if 语句!
for(int a=-1; a<=1; a++)
{
for(int b=-1; b<=1; b++)
{
safeIncrement(i+a,j+b, board1);
}
}
我正在制作扫雷游戏。然而,在测试生成函数时,它几乎总是(如果不是总是)发生故障,我不明白为什么。
这是我的代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
struct board {
int width=9, mines=10;
char board[9][9];
/* char board[][]
* -1 = Mine
* 0 = No mines near
* 0+ = x amount of mines are near
*/
};
struct point {
int x,y;
};
board newBoard(){
board board1;
point randPoint;
for(int i=0;i<board1.width;i++){
for(int j=0;j<board1.width;j++) board1.board[i][j]=0; // Initialize array
}
for(int i=0;i<board1.mines;i++){
randPoint.x=rand()%board1.width, randPoint.y=rand()%board1.width; // Where will the mine go?
if(board1.board[randPoint.x][randPoint.y]!=-1){ // If not already a mine
board1.board[randPoint.x][randPoint.y]=-1; //make a mine
} else i--; //else don't count this
}
for(int i=0;i<board1.width;i++){
for(int j=0;j<board1.width;j++){
if(board1.board[i][j]==-1) { // If mine exists
// The if checks preceding the ++'s are to prevent out of bounds erors
if (j-1>=0) board1.board[i][j-1]++;
if (j+1<board1.width) board1.board[i][j+1]++;
if (i-1>=0) board1.board[i-1][j]++;
if (i+1<board1.width) board1.board[i+1][j]++;
if ((i-1>=0) && (j-1>=0)) board1.board[i-1][j-1]++;
if ((i-1>=0) && (j+1<board1.width))board1.board[i-1][j+1]++;
if ((i+1<board1.width) && (j-1>=0))board1.board[i+1][j-1]++;
if ((i+1<board1.width) && (j+1<board1.width))board1.board[i+1][j+1]++;
}
}
}
return board1;
}
int main() {
board boardGame=newBoard();
printf("- ");
for(int i=0;i<boardGame.width;i++) printf("%i ",i+1);
printf("\n\n");
for(int i=0;i<boardGame.width;i++){
printf("%i. ",i+1);
for(int j=0;j<boardGame.width;j++) if (boardGame.board[i][j]==-1) {
printf(" X");
} else {
printf(" %i", boardGame.board[i][j]);
}
printf("\n");
}
return 0;
}
这会产生:
- 1 2 3 4 5 6 7 8 9
1. 0 0 0 0 1 X 1 0 0
2. 1 1 0 0 2 2 2 1 1
3. X 2 1 1 1 X 1 1 X
4. 1 2 X 0 1 1 0 1 1
5. 0 1 1 1 0 0 0 0 0
6. 0 0 0 0 1 1 1 0 0
7. 0 0 1 1 2 X 1 0 0
8. 1 1 2 X 2 1 1 0 0
9. 1 X 2 1 1 0 0 0 0
你可能已经知道,在扫雷游戏中,有地雷(在这种情况下会被标记为X
),所有附近的网格点都是它附近的地雷数量(如果您还不熟悉它 this 页面可能会有用)。如您所见,4,7 和 4,4 处的数字不正确。
不知道为什么会这样。有人可以帮助我理解这一点,并告诉我如何解决这个问题吗?
此外,我刚刚注意到每次 运行 时都会产生相同的输出。为什么?
当 2 个地雷靠近时会出现问题:当您添加地雷数量时,您没有检查该方格是否有地雷。
假设你在 (0, 0) 上有一个地雷,在 (0, 1) 上有另一个。当你添加到 (0, 0) 附近的地雷计数时,你不小心也添加了 (0, 1) 中的地雷,将它从 -1 更改为 0。这也会使正在处理的第二个地雷消失。
我建议使用另一个数字来表示地雷,例如-999,并在查找时检查数字是否为负数。这比为您已有的所有 if 子句添加另一个条件更容易。
Ioums 是正确的,您没有在递增之前检查单元格是否是地雷。但是,根据您的代码当前设置的方式,这将意味着在每个 if 语句中添加一个单元格不等于 -1 的检查。您应该考虑创建一个函数来安全地增加单元格,如果它在边界内而不是地雷内,就像这样:
void safeIncrement(int x, int y, board& b)
{
if(x >= 0 && y >= 0 && x < b.width && y < b.width && b.board[x][y] != -1)
{
b.board[x][y]++;
}
}
这意味着您可以将 if 语句替换为:
safeIncrement(i-1,j,board1);
safeIncrement(i-1,j-1,board1);
safeIncrement(i-1,j+1,board1);
safeIncrement(i,j-1,board1);
safeIncrement(i,j+1,board1);
safeIncrement(i+1,j,board1);
safeIncrement(i+1,j-1,board1);
safeIncrement(i+1,j+1,board1);
我认为这更具可读性。此外,由于如果单元格是地雷,该函数不会递增单元格,因此您还可以用以下代码替换 if 语句!
for(int a=-1; a<=1; a++)
{
for(int b=-1; b<=1; b++)
{
safeIncrement(i+a,j+b, board1);
}
}