扫雷进阶版

这一章我们将要实现标记和展开一片区域的功能。

标记

游戏途中我们如果推测出某个方格是雷,就可以对其进行标记。

首先我还是要在game.h头文件中定义一个标记函数

game.h

//标记雷
int Mark_Mine(char mine[ROWS][COLS], char showp[ROWS][COLS], int x, int y, int win);

game.c

int Mark_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int win)
{
    int i, j;
    while (1)
    {
        printf("请输入你要标记的坐标:\n");
        scanf("%d %d", &i, &j);
        if (i > 0 && i <= row && j > 0 && j <= col)
        {
            if (show[i][j] == '*')//判断该区域是否排查过
            {
                show[i][j] = '!';//对你认为是雷的区域标记为‘!’
                Display(show, ROW, COL);
                if (mine[i][j] == '1')//如果该区域确实是雷那么win(雷数)就--
                    win--;
                return win;
            }
            else
                printf("坐标已排查,请重新输入:\n");
        }
        else
            printf("坐标错误\n");
    }

最后在主函数判断win=0游戏通过 

展开一片区域

在我们翻开一个格子的时候,如果周围有雷,我们需要显示雷的个数,如果没有,将该位置标记为空白,然后对周围的方格进行递归判定,直到找到周围有雷的方格为止。

game.h

//递归展开
void expand_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);

game.c

void expand_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
    if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
    {
        int i = 0, j = 0;
        int count = CountMine(mine, x, y);
        if (count)//周围区域如果有雷就显示雷的数量
        {
            show[x][y] = count+'0';
        }
        else if (show[x][y] == '*')
        {
            show[x][y] = '  ';//如果周围没有雷就将该方格标记为空白
            for (i = x - 1; i <= x + 1; i++)
                for (j = y - 1; j <= y + 1; j++)
                    expand_blank(mine,show, i, j);//如此一直对周边区域进行排查直到找到周围区                                                                                        域有雷的方格为止
        }
    }

思考 

如果运用了展开一片区域的功能,就不一定知道一次性排查了几个方格,所以就不能用基础版扫雷中的(win=row*col-EASY_count)来判断游戏是否结束,所以要对排雷函数进行一定修改。

game.h

//排雷
int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c

int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0, y = 0;
    while (1)
    {
        printf("请输入要排查的坐标:");
        scanf("%d %d", &x, &y);
        if (x > 0 && x <= row && y > 0 && y <= col)
        {
            if (mine[x][y] == '1')
            {
                printf("很遗憾你被炸死了\n");
                Display(mine, ROW, COL);
                return 1;
            }
            else
            {
                expand_blank(mine, show, x,y);//如果排查方格不是雷就调用expan_blank函数对                                                                        周围进行排查
                Display(show, ROW, COL);
                return 0;//返回1或0来判断排查区域是否为雷
            }
        }
        else
        {
            printf("输入非法坐标,请重新输入");
        }
    }
}

完整代码展示

game.h

#pragma?? ?once

#include
#include
#include

#define EASY_count    10

#define ROW    9
#define    COL    9

#define ROWS    ROW+2
#define COLS    COL+2

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void Display(char arr[ROWS][COLS], int row, int col);

//布置雷
void SetMine(char arr[ROWS][COLS], int row, int col);

//递归展开
void expand_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
//排雷
int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

//标记雷
int Mark_Mine(char mine[ROWS][COLS], char showp[ROWS][COLS], int x, int y, int win);

game.c

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

int CountMine(char mine[ROWS][COLS], int x, int y)
{
    int sum = 0;
    int i = 0, j = 0;
    for (i = x - 1; i <= x + 1; i++)
    {
        for (j = y - 1; j <= y + 1; j++)
            sum += mine[i][j] - '0';
    }
    return sum;
}

void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
    int i = 0, j = 0;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
            board[i][j] = set;
    }
}

void Display(char arr[ROWS][COLS], int row, int col)
{
    int i = 0, j = 0;
    for (i = 0; i <= col; i++)
    {
        printf("%d ", i);
    }
    putchar('\n');
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);
        for (j = 1; j <= col; j++)
            printf("%c ", arr[i][j]);
        printf("\n");
    }
    printf("-------------------\n");
}

void SetMine(char arr[ROWS][COLS], int row, int col)
{
    int count = EASY_count;

    while (count)
    {
        int x = rand() % row + 1;
        int y = rand() % col + 1;
        if (arr[x][y] == '0')
        {
            arr[x][y] = '1';
            count--;
        }
    }

}

void expand_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
    if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
    {
        int i = 0, j = 0;
        int count = CountMine(mine, x, y);
        if (count)
        {
            show[x][y] = count+'0';
        }
        else if (show[x][y] == '*')
        {
            show[x][y] = '  ';
            for (i = x - 1; i <= x + 1; i++)
                for (j = y - 1; j <= y + 1; j++)
                    expand_blank(mine,show, i, j);
        }
    }
}

int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0, y = 0;
    while (1)
    {
        printf("请输入要排查的坐标:");
        scanf("%d %d", &x, &y);
        if (x > 0 && x <= row && y > 0 && y <= col)
        {
            if (mine[x][y] == '1')
            {
                printf("很遗憾你被炸死了\n");
                Display(mine, ROW, COL);
                return 1;
            }
            else
            {
                expand_blank(mine, show, x,y);
                Display(show, ROW, COL);
                return 0;
            }
        }
        else
        {
            printf("输入非法坐标,请重新输入");
        }
    }
}

int Mark_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int win)
{
    int i, j;
    while (1)
    {
        printf("请输入你要标记的坐标:\n");
        scanf("%d %d", &i, &j);
        if (i > 0 && i <= row && j > 0 && j <= col)
        {
            if (show[i][j] == '*')
            {
                show[i][j] = '!';
                Display(show, ROW, COL);
                if (mine[i][j] == '1')
                    win--;
                return win;
            }
            else
                printf("坐标已排查,请重新输入:\n");
        }
        else
            printf("坐标错误\n");
    }
}

 

 test.c

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"

void menu()
{
    printf("**************************\n");
    printf("*******   1.play  ********\n");
    printf("*******   0.exit  ********\n");
    printf("**************************\n");
}

void game()
{
    int win = EASY_count;
    char mine[ROWS][COLS];
    char show[ROWS][COLS];

    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');

    //Display(mine, ROW, COL);
    //Display(show, ROW, COL);

    SetMine(mine, ROW, COL);
    //Display(mine, ROW, COL);

    //FindMine(mine, show, ROW, COL);

    while (win)
    {
        printf("输入1排雷,输入2标记");
        int m = 0;
        scanf("%d", &m);
        if (m == 1)
        {
            if (FindMine(mine, show, ROW, COL))
            {
                break;
            }
        }
        else if (!(Mark_Mine(mine, show, ROW, COL,win)))
        {
            printf("恭喜你赢了!!\n");
            break;
        }
    }
}

int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);

        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏");
            break;
        default:
            printf("选择错误,请重新选择");
            break;
        }
    } while (input);

    return 0;
}

 详细二者间的不同,可以与上一章的代码进行比较

实现某个功能就创建一个函数的思想,但创建新函数的途中可能会对原来某些函数产生影响,所以需要一一排查,避免发生错误。切记耐心是写好代码的条件之一!!! 

你可能感兴趣的:(游戏,c语言)