2015-10-26 105 views
-2

我正在创建一个扫雷游戏。然而,在测试生成函数时,几乎总是(如果不是总是)出现故障,我不明白为什么。意外的结果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的数字是不正确的。

我不知道这是为什么这样。有人能帮助我理解这一点,并告诉我如何解决这个问题吗?


此外,我只是注意到,它每次运行时都会产生相同的输出。为什么?

+5

五块钱说你可以通过调试器走过去,并尽快找出错误的位置。 – user4581301

+0

当增加矿山计数器时,你需要检查矿山是否有矿。你正在挖矿(== -1)并添加一个。 – ioums

+1

“它出现故障”是什么意思?崩溃?不会崩溃但会给出错误的结果? – PaulMcKenzie

回答

2

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); 
    } 
} 
+0

非常感谢您的安全增量功能。我无法弄清楚如何使它更具可读性。 –

0

2个地雷靠得很近时会发生问题:当您添加到地雷数量时,您不检查该地方是否有地雷。

假设你在(0,0)和另一个在(0,1)上得到了一个地雷。当你在(0,0)附近增加矿点数时,你无意中也会在(0,1)中加入矿,并将其从-1改为0.这也使得正在处理的第二个矿正在消失。

我建议使用另一个数字来表示矿井,例如-999,并在查找时检查数字是否定的。如果你已经有了子句,那么比添加另一个条件更容易。