标题:做了个扫雷,发现我最后要显示地雷位置的出现了问题,我觉得问题应该是出在 ...
只看楼主
卷毛的企鹅
Rank: 1
等 级:新手上路
帖 子:8
专家分:0
注 册:2013-8-7
结帖率:100%
已结贴  问题点数:20 回复次数:11 
做了个扫雷,发现我最后要显示地雷位置的出现了问题,我觉得问题应该是出在最下面一个方程
我用的是VS,才学了两个多月,感觉有点力不从心。。
整个代码花了半个月来写了。。。

问题是我在最下面的一个void start_game(void)的方程中。我做了一个踩到地雷就显示所以地雷位置,并且自动退出程序。但是放break来退出程序的话,我显示地雷的逻辑就完全没有用了,一定要拿掉才可以显示。。。

另外能不能帮我看看我判断胜利的逻辑有没有问题

感谢啊!!!!!


程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h> 

#define ROW                    18
#define COL                    10
#define MAX_MINES            ROW
#define PADDED_TOP_ROW        1
#define PADDED_LEFT_COL        1
#define PADDED_BOTTOM_ROW    PADDED_TOP_ROW
#define PADDED_RIGHT_COL    PADDED_LEFT_COL
#define MAX_PADDED_ROW    (PADDED_TOP_ROW + ROW + PADDED_BOTTOM_ROW) // top and bottom rows padded     20
#define MAX_PADDED_COL    (PADDED_LEFT_COL + COL + PADDED_RIGHT_COL) // left and right columns padded     12

#define STAR                '*'
#define SPACE                ' '
#define MINE                '1'


void initgrid(char grid[], int row_size, int col_size);
void printgrid(char grid[ROW*COL], int row_size, int col_size);
void start_game(void);
void mineposition(int mine[], int row, int col);
int checknearbymines(int row, int col);
int leftstars(char grid, char mines, int row, int col);

int main(void)
{     
    start_game();
    system("pause");
    return 0;
}

void initgrid(char grid[], char mine[], int row_size, int col_size)
{
    int i,j;
    
    for (i = 0; i < row_size; i++)
    {
        for (j=0;j<col_size;j++)
        {
            if ((i == 0) || (i == row_size -1) || (j == 0) || (j == col_size -1))
                grid[i*col_size+j] = SPACE;
            else
                grid[i*col_size+j] = STAR;
            mine[i*col_size+j] = SPACE;
        }
    }
}

void printgrid(char grid[], int row_size, int col_size)
{
    int i,j;
    
    printf("\t  1 2 3 4 5 6 7 8 9 10\n");
    printf("\t  --------------------\n");
    for(i=0;i<row_size;i++)
    {
        if ((i > 0) && (i < row_size - 1))
            printf("%d|\t", i);
        for(j=0;j<col_size;j++)        
            printf("%c ",grid[i*col_size + j]);        

        printf("\n");    
    }
}
void mineposition(char mine[], int row_size, int col_size)
{
    int         i, j, random, found;
    static int  init=0;
    int         m[MAX_MINES] = {0};
    int            row, col;

    if (init == 0)
    {
        srand(time(NULL));
        init = 1;
    }

    i = 0;
    for(;;)
    {
        random = rand() % (ROW * COL - 1);
        found = 0;
        for (j = 0; j < i; j++)
        {
            if (m[j] == 1)  // 1 = mine, 0 = not a mine
            {
                found = 1;
                break;
            }
        }
        if (found == 0)
        {
            m[i] = random;
            i++;
            if (i >= MAX_MINES)
                break;
        }
    }
    for (i = 0; i < MAX_MINES; i++)
    {
        row = m[i] / COL + 1;
        col = m[i] % COL + 1;
        mine[row * col_size + col] = MINE;
    }
}

int checknearbymines(char board[], int row, int col)
{
    int mines = 0;

 
    if(board[row*MAX_PADDED_COL+col-1] == MINE)  //check left
        mines++;
    if(board[row*MAX_PADDED_COL+col+1] == MINE)  //check right
        mines++;
    if(board[row*MAX_PADDED_COL+col-MAX_PADDED_COL] == MINE)  //check up
        mines++;
    if(board[row*MAX_PADDED_COL+col+MAX_PADDED_COL] == MINE)  //check down
        mines++;
    if(board[row*MAX_PADDED_COL+col-MAX_PADDED_COL-1] == MINE)  //check left top
        mines++;
    if(board[row*MAX_PADDED_COL+col-MAX_PADDED_COL+1] == MINE)   //check right top
        mines++;
    if(board[row*MAX_PADDED_COL+col+MAX_PADDED_COL-1] == MINE)   //check left bottom
        mines++;
    if(board[row*MAX_PADDED_COL+col+MAX_PADDED_COL+1] == MINE)   //check right bottom
        mines++;

 
    return mines;
}

int leftstars(char grid[])
{
    int        i, j, left;
    for(i = 13; i < 227; i++)
    {
        if(grid[i] == STAR)
        left++;
    }
    return left;
}

 

void start_game(void)
{
    char field[MAX_PADDED_ROW * MAX_PADDED_COL];
    char mine[MAX_PADDED_ROW * MAX_PADDED_COL] = {0};
    int  row, col, a, i, j;

    initgrid(field, mine, MAX_PADDED_ROW, MAX_PADDED_COL);
    mineposition(mine, MAX_PADDED_ROW, MAX_PADDED_COL);

    for(;;)
    {
        
        printgrid(field,MAX_PADDED_ROW,MAX_PADDED_COL);
        
        // begin: to be deleted: for testing purpose
        for (i=0;i<MAX_PADDED_ROW;i++)
        {
            for (j = 0; j < MAX_PADDED_COL; j++)
            {
                if (mine[i * MAX_PADDED_COL + j] == MINE)
                {
                    printf("[%d][%d]\t", (i * MAX_PADDED_COL + j) / MAX_PADDED_COL, (i * MAX_PADDED_COL + j) % MAX_PADDED_COL);
                }
            }
        }
        // end: to be deleted: for testing purpose
//mine[row * col_size + col]    
        printf("\nEnter <-1 -1> to exit game...\n\n");
        printf("row and column <[row] [col]>':\n");
        scanf("%d %d",&row,&col);
        if (row == -1 && col == -1)
        {
            printf("\n\nExiting from game...\n");
            break;
        }
        else if (((row < 1 )||( row > ROW)) && ((col<1)||(col >COL)))
        {
            printf("\nInvalid tile position! Please enter row and column again...\n\n");
        }
        else
        {
            if(mine[row*MAX_PADDED_COL+col] != MINE)
            {
            // need to translate the row & col in the field array to the corresponding index in mine array
                
                a = checknearbymines(mine, row,col);
                if(a==0)
                {
                    field[row*MAX_PADDED_COL+col]=' '; //centre position
                    field[row*MAX_PADDED_COL+col-1]=' '; //left 
                    field[row*MAX_PADDED_COL+col+1]=' '; //right
                    field[row*MAX_PADDED_COL+col-MAX_PADDED_COL]=' ';//top
                    field[row*MAX_PADDED_COL+col+MAX_PADDED_COL]=' '; //bottom
                    field[row*MAX_PADDED_COL+col-MAX_PADDED_COL-1]=' ';  //left top
                    field[row*MAX_PADDED_COL+col+MAX_PADDED_COL+1]=' ';  //right bottom
                    field[row*MAX_PADDED_COL+col-MAX_PADDED_COL+1]=' ';  //right top
                    field[row*MAX_PADDED_COL+col+MAX_PADDED_COL-1]=' ';   //left bottom
                }
                else if(a==1)
                {
                    field[row*MAX_PADDED_COL+col]='1';
                }
                else if(a==2)
                {
                    field[row*MAX_PADDED_COL+col]='2';
                }
                else if(a==3)
                {
                    field[row*MAX_PADDED_COL+col]='3';
                }
                else if(a==4)
                {
                    field[row*MAX_PADDED_COL+col]='4';
                }
                else if(a==5)
                {
                    field[row*MAX_PADDED_COL+col]='5';
                }
                else if(a==6)
                {
                    field[row*MAX_PADDED_COL+col]='6';
                }
                else if(a==7)
                {
                    field[row*MAX_PADDED_COL+col]='7';
                }
                else
                {
                    field[row*MAX_PADDED_COL+col]='8';
                }
            
                //if (leftstars(field) == MAX_MINES)
                //{
                //    printf("Congratulations!! You won!!");
                //}
            }
            else
            {                
                for (i=0;i<MAX_PADDED_ROW;i++)
                {
                    for (j = 0; j < MAX_PADDED_COL; j++)
                    {
                        if (mine[i * MAX_PADDED_COL + j] == MINE)
                        {                            
                            field[i * MAX_PADDED_COL + j]= 'X';
                            field[row*MAX_PADDED_COL+col] = 'Y';
                        }
                    }
                }
                
                printf("You hit a mine!! Game over...");                
                system("cls");
                system("pause");
                
                
            }
            
        }
        system("cls");
    }
}







[ 本帖最后由 卷毛的企鹅 于 2013-8-7 23:55 编辑 ]
搜索更多相关主题的帖子: 胜利 color 
2013-08-07 22:56
幽灵X
Rank: 5Rank: 5
等 级:职业侠客
帖 子:128
专家分:328
注 册:2013-1-28
得分:0 
楼主厉害啊
2013-08-07 23:17
卷毛的企鹅
Rank: 1
等 级:新手上路
帖 子:8
专家分:0
注 册:2013-8-7
得分:0 
做了半个月了。。。现在已经是想的一头的浆糊 不知道怎么改了。。。
2013-08-07 23:19
卷毛的企鹅
Rank: 1
等 级:新手上路
帖 子:8
专家分:0
注 册:2013-8-7
得分:0 
好多bug啊。。。真是头疼。。。测试完之后发现不能判断胜利。。。
原问题还没有解决。。。

求大神 求正能量
2013-08-08 00:26
manesol
Rank: 1
等 级:新手上路
帖 子:53
专家分:0
注 册:2013-7-6
得分:0 
能说说你的思路么?
2013-08-08 08:47
卷毛的企鹅
Rank: 1
等 级:新手上路
帖 子:8
专家分:0
注 册:2013-8-7
得分:0 
回复 5楼 manesol
是要哪一部分的思路?
2013-08-08 10:43
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
得分:20 
顺着你代码执行顺序读的代码,

mineposition就存在逻辑错误。m数组是用来存地雷的坐标的吧,而下现在代码中

        for (j = 0; j < i; j++)
        {
            if (m[j] == 1)  // 1 = mine, 0 = not a mine
            {
                found = 1;
                break;
            }
        }
 
你又是把它当标记用的。后果是最终你布置的地雷数量可能达不到MAX_MINES,也就是说它没有达到你想去重的效果。

start_game里

printf("[%d][%d]\t", (i * MAX_PADDED_COL + j) / MAX_PADDED_COL, (i * MAX_PADDED_COL + j) % MAX_PADDED_COL);

这句实在是觉得...你直接printf("[%d][%d]\t", i, j);不就完了。虽然只是段测试代码,但为什么要绕腾自己呢?

                if(a==0)
                {
                    field[row*MAX_PADDED_COL+col]=' '; //centre position
                    field[row*MAX_PADDED_COL+col-1]=' '; //left
                    field[row*MAX_PADDED_COL+col+1]=' '; //right
                    field[row*MAX_PADDED_COL+col-MAX_PADDED_COL]=' ';//top
                    field[row*MAX_PADDED_COL+col+MAX_PADDED_COL]=' '; //bottom
                    field[row*MAX_PADDED_COL+col-MAX_PADDED_COL-1]=' ';  //left top
                    field[row*MAX_PADDED_COL+col+MAX_PADDED_COL+1]=' ';  //right bottom
                    field[row*MAX_PADDED_COL+col-MAX_PADDED_COL+1]=' ';  //right top
                    field[row*MAX_PADDED_COL+col+MAX_PADDED_COL-1]=' ';   //left bottom
                }

这一段也不对。a==0只能说明这个位置为空,为什么要把相邻的八个位置也置空呢?它们很可能标记为数字对不对?

                for (i=0;i<MAX_PADDED_ROW;i++)
                {
                    for (j = 0; j < MAX_PADDED_COL; j++)
                    {
                        if (mine[i * MAX_PADDED_COL + j] == MINE)
                        {                           
                            field[i * MAX_PADDED_COL + j]= 'X';
                            field[row*MAX_PADDED_COL+col] = 'Y';
                        }
                    }
                }
               
触雷后的这段逻辑,你将有雷的地方标记为'X',将点错的地方标记为'Y'。关于'Y'的设置放在循环里是一种浪费,应该放在循环外。而且标记完了你并没有显示它们,之后也没有退出外层的for(;;)循环。


以上只是阅读代码时发现的问题,没有实际调试,细节上是否还存在其它错误犹未可知。

整体来说,代码中的冗余逻辑太多,写这么长我还以为你是打算实现智能扫雷,结果只是简单地模拟扫雷游戏。

而其中一个相对有技术含量的逻辑你并没有实现,那就是当点到一个空位置时展开与此位置相邻的所有空位置直至数字边界。

关于这个游戏给你一点建议:

1、使用二维数组将使你的代码更清晰直观,效率绝不比你用一维数组再自己换算坐标索引低。

2、在初始化地图时即计算每个无雷格子相邻雷的数量,保存在你的mine数组里就行,这样可以简化逻辑,使你的代码更短更清晰,效率更高。

重剑无锋,大巧不工
2013-08-08 19:43
卷毛的企鹅
Rank: 1
等 级:新手上路
帖 子:8
专家分:0
注 册:2013-8-7
得分:0 
回复 7楼 beyondyf
谢谢斑竹
对于那个mineposition来说,是不是指有的时候会少过MAX_MINES的数量。。
因为我debug了上百次了。。确实有一次出现了7个mine的情况。。。后来又都是8个了,所以就没有当回事了。。
这样的话有没有什么好的解决方法呢?

那个测试代码是借来的。。没有过脑就放上去了。。感谢斑竹指正。。

第三个部分,我也已经发现了,但是感觉如果要保留已经显示数字会很麻烦。。所以就懒的改了。。请斑竹支个招。。。


“而且标记完了你并没有显示它们,之后也没有退出外层的for(;;)循环。”   ------这个没有太理解,不好意思。。。

感谢建议
我还不太敢用二维数组,因为还没有学到,怕用了以后出来问题我会解决不了,毕竟一维的比较熟悉。。
关于效率,我完全是零理解。。。感谢指正,我会努力修改的。。
2013-08-08 21:14
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
得分:0 
连二维数组都没学到就能写成这样,我该鼓励一下你

重剑无锋,大巧不工
2013-08-08 23:06
卷毛的企鹅
Rank: 1
等 级:新手上路
帖 子:8
专家分:0
注 册:2013-8-7
得分:0 
回复 9楼 beyondyf
是我太能折腾了。。。
半个月找了好多东西来参考。。。

只是那个最有技术含量的地方我还在尝试。。。
希望我举例胜利不远了。。
2013-08-09 00:11



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-418770-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.048194 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved