数组的应用——扫雷

扫雷

1.在game.h中进行宏定义,头文件引入以及函数声明
2.在main.c中实现主函数
3.在game.c中实现功能函数

除了基本的功能外,还实现以下几个功能:
1.第一步不会炸
2.点到周围没有雷的区域会自动展开
3.可以做标记
4.显示当前雷数
5.显示已用时间

待拓展的功能:选关

需要定义两个二维数组,一个作为记录雷的位置,一个作为展示界面,除此之外,实际定义的数组应比展示出来的界面大一圈,这样便于统计雷数

埋雷

void SetMine(char board[ROWS][COLS], int row, int col)
{
    int i = 0;
    int x = 0, y = 0;
    int n = EASY_COUNT;
    while (n--) {
        x = rand() % row + 1;
        y = rand() % col + 1;
        if (board[x][y] == '0')
            board[x][y] = '1';
        else n++;
    }
}

在棋盘内随机选取10个位置埋雷。
用到了rand()函数生成伪随机数,使用rand函数前应先调用srand()唤醒,并用时间做参数。

查看坐标周围雷数

int GetMineCount(char board[ROWS][COLS],Location loc)
{
    int count = 0;
    int i, j;
    for (i = loc.x - 1; i <= loc.x + 1; i++) {
        for (j = loc.y - 1; j <= loc.y + 1; j++) {
            if (i == loc.x && loc.y == j) continue;
            if (board[i][j] == '1')
                count++;
        }
    }
    return count;
}

排雷并且保证第一步不炸

int SweepMine(char Show[ROWS][COLS],char Mine[ROWS][COLS], int rows, int cols, Location loc,int *pfirst)
{
    int ret = 0;
    if (Show[loc.x][loc.y] != '*' || loc.x>ROW || loc.x<1 || loc.y>COL || loc.y<1) {
        printf("\n             该坐标不可选\n");
        return 0;
    }

    //如果是第一步
    if ((*pfirst) == 1) {
        (*pfirst) = 0;
        //如果踩到雷
        if (Mine[loc.x][loc.y] == '1') {
            //那就进入循环,重新埋雷,直到这个坐标不是雷
            do {
                InitBoard(Mine, ROWS, COLS, '0');
                SetMine(Mine, ROW, COL);
            } while (Mine[loc.x][loc.y] == '1');
        }

    if (Mine[loc.x][loc.y] == '1') {
        printf("\n            1为雷区,0为安全区\n");
        PrintBoard(Mine, ROWS, COLS);
        printf("\n            砰~!很遗憾,你输了\n");
        return 2;
    }
    else {
        ret = GetMineCount(Mine, loc);
        if (ret == 0)
            Expand(Show, Mine, rows - 2, cols - 2, loc);
        else Show[loc.x][loc.y] = ret + '0';
        PrintBoard(Show, ROWS, COLS);
    }
    return 1;
}

自动展开

void Expand(char show[ROWS][COLS], char mine[ROWS][COLS],int row, int col, Location loc)
{
    int i, j;
    int ret = 0;
    Location coord = { -1,-1 };
    if (show[loc.x][loc.y] != '*')
        return;
    if (GetMineCount(mine, loc) == 0) {
        show[loc.x][loc.y] = '0';
        //判断它周围8个位置是否为0
        for (i = loc.x - 1; i <= loc.x + 1; i++) {
            for (j = loc.y - 1; j <= loc.y + 1; j++) {
                if (i == loc.x&&j == loc.y)continue;
                if (i > row || i<1 || j>col || j < 1)
                    continue;
                coord.x = i;
                coord.y = j;
                ret = GetMineCount(mine, coord);
                if (ret == 0) {
                    Expand(show, mine, row, col, coord);
                }
                else show[i][j] = ret + '0';
            }
        }
    }
}

如果点到雷数是0的位置,就递归,展开到坐标雷数不是0(第一个不是0的位置也显示出来)
这里写图片描述

第一步下的是(5,5),显示雷数1,然后第二步是(9,9),雷数是0自动展开,直到雷数不是0

做标记

int Label(char show[ROWS][COLS], int rows, int cols, Location loc,int *pflag)
{
    if (loc.x>ROW || loc.x<1 || loc.y>COL || loc.y<1) {
        printf("\n             该坐标不可选\n");
        return 0;
    }
    if (show[loc.x][loc.y] == '*') {
        show[loc.x][loc.y] = 'X';
        (*pflag)++;
    }
    else if (show[loc.x][loc.y] == 'X') {
        show[loc.x][loc.y] = '*';
        (*pflag)--;
    }
    else {
        printf("\n            该坐标不可选\n");
        return 0;
    }
    PrintBoard(show, rows, cols);
    return 1;
}

如果有标记就取消,如果没有标记就做标记

显示雷数

不知道大家是怎么做的,我设置的是做一个标记雷数就减一

显示时间

这个用clock()函数就能实现,具体是,定义三个变量

clock_t start, finish;
double time;

在刚刚进入游戏时,
start = clock();
clock函数返回开启这个进程到调用clock()函数的CPU时钟单元
结束时间也是这样,

finish = clock();
time = (double)(finish - start) / CLOCKS_PER_SEC;//宏表示一秒钟有多少时钟单元

每次展开一个坐标就显示一次雷数和时间
printf("\n 当前雷数:%d 已用时:%.0f s\n",EASY_COUNT-flag,time);

判断输赢

当玩家选中有雷坐标时就输了
判断获胜会麻烦一点

//查看当前显示格子数目
int CheckMine(char show[ROWS][COLS], char mine[ROWS][COLS], int rows, int cols)
{
    int i, j;
    int count = 0;
    for (i = 1; i < rows - 1; i++) {
        for (j = 1; j < cols - 1; j++) {
            if (show[i][j] != '*' && mine[i][j] == '0')
                count++;
        }
    }
    return count;
}

函数名字起的比较糟糕,功能是返回当前显示出来格子的数目
当所有不是雷的格子都显示出来时,玩家就获胜了

运行效果

刚刚让舍友玩了一局,她说界面太花了。。。这个是最需要改进的,目前我也没办法。。。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值