【C语言】—— 实现扫雷小游戏(初阶)

一、思维导图

【C语言】—— 实现扫雷小游戏(初阶)

二、实施步骤

1.创建三个文件

1.test.c    --- 测试游戏;

2.game.c --- 游戏函数实现;

2.对游戏界面以及选项进行编程设计

1. 在test.c文件下创建好游戏的入口,实现基本的界面显示,选项功能;并进行测试,代码及效果如下:

3.game.h --- 游戏函数声明;

#include <stdio.h>
void menu()
{
    printf("**********************************\n");
    printf("********** 扫雷小游戏 ************\n");
    printf("**********   1.Play   ************\n");
    printf("**********   0.Exit   ************\n");
    printf("**********************************\n");
}
int main()
{
    int input = 0;
    do
    {
        menu();
        printf("请输入:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            printf("游戏开始\n");
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("选择错误,请重新输入\n");
            break;
        }
    } while (input);
    return 0;
}

【C语言】—— 实现扫雷小游戏(初阶)

2.开始对游戏部分进行函数封装;

        1. 创建2个数组:

                mine数组 --- 存放雷的数组;

                show数组 --- 排查出雷的数组;

void game()
{
    char mine[9][9] = { 0 };//存放雷的信息
    char show[9][9] = { 0 };//存放排查出的雷的信息
}

此时有几个注意点需要我们去考虑:

       1.现在扫雷棋盘的大小是9*9,在后期想要进行优化,传参的过程会很麻烦,改动会很多,如何解决?;

       解决方案:我们可以用宏定义来定义这个数组的行和列,方便以后棋盘大小可以随意更改;

       2.当玩家在排查雷的时候,如果锁定是左上角,按照规则游戏内部应该去以左上角这个单元为中心去查找周围雷的个数并给予显示信息,但是此时的棋盘是9*9,按照刚才的规则进行,一定会造成越界访问,达不到想要的效果,如何解决?

       解决方案:我们在9*9这个数组的外围上增加两行两列,就变成了11*11的数组,增加的行和列不放雷(0代表无雷),只在内部9*9的数组中放雷(1代表有雷)

图解

【C语言】—— 实现扫雷小游戏(初阶)

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void game()
{
    char mine[ROWS][COLS] = { 0 };//存放雷的信息
    char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
}

4.对棋盘初始化以及打印棋盘

1.对布置雷的棋盘进行初始化,初始化为0;

2.对显示棋盘初始化,初始化为*号;

//初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set)
{
    int i = 0;
    for (i = 0; i < rows; i++)
    {
        int j = 0;for (j = 0; j < cols; j++)
        {
            Board[i][j] = set;
        }
    }
}
//显示棋盘
void DisplayBoard(char Board[ROWS][COLS], int row, int col)
{
    int i = 0;
    for (i = 0; i < row; i++)
    {
        int j = 0;
        for (j = 0; j < col; j++)
        {
            printf("%c ", Board[i][j]);
        }
        printf("\n");
    }
}

【C语言】—— 实现扫雷小游戏(初阶)

初步对两个棋盘进行了初始化以及显示的效果,但是这个效果好像不是很美观:

        1.如果数组行和列过大,我们难以查找想要的坐标,必须的一个一个的数才能找到,能否增加行和列的坐标;

        2.能否将游戏和界面区分一下,整体看上去很大气;

以下为改进效果:

//显示棋盘
void DisplayBoard(char Board[ROWS][COLS], int row, int col)
{
    int i = 0;
    printf("--------------------------------------\n");
    printf("  ");
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        int j = 0;
        printf("%d ", i);
        for (j = 1; j <= col; j++)
        {
            printf("%c ", Board[i][j]);
        }
        printf("\n");
    }
    printf("--------------------------------------\n");
}

【C语言】—— 实现扫雷小游戏(初阶)

 5.布置雷的信息

 需要的函数:

       1.rand   ---随机生成某个数值(在本章中是随机生成行和列的做坐标)

       2.srand ---在使用rang函数前需要使用srand

       3.time   ---它能够获取一个时间戳

备注:这里不做详解,你可以理解为用rand前,先用srand定义一下(srand((unsigned int)time(NULL));)

void SetMine(char Board[ROWS][COLS], int row, int col)
{
    int count = mine_count;
    while (count)
    {
        //生成随机下标
        int x = rand() % row + 1;
        int y = rand() % col + 1;
        if (Board[x][y] != '1')
        {
            Board[x][y] = '1';
            count--;
        }
    }
}

测试前先将初始化棋盘函数和显示棋盘函数进行屏蔽,检测雷布置情况是否正常;

【C语言】—— 实现扫雷小游戏(初阶)

 从上图可以看出通过我们的程序现在能够生成随机的下标并给它布置10个雷(1代表雷);

6.排查雷结果

雷的信息是存放在mine数组中的,而玩家看到的是show数组,我们在设计的时候,需要通过对mine数组的排查反馈到show数组中去,让玩家得到信息,进行后续操作;

坐标非法的情况:

       当输入坐标(10,10)时,我们设计的是9*9的扫雷棋盘,很明显坐标不合法,应该给予提示“坐标非法,请重新输入”;

坐标合法的情况:

       1.当输入坐标(1,1)时,(假设无雷)此时屏幕上应该显示的是以坐标(1,1)为中心,它的周围有多少个雷;

       2.当输入坐标(1,1)时,(假设有雷)此时应该提示“你被炸死了”并显示棋盘信息;

排完雷的情况:

       当排查完所有雷时,应该给予提示“恭喜你,排雷成功”;

//排查雷
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
    return (mine[x - 1][y] +
        mine[x - 1][y - 1] +
        mine[x][y - 1] +
        mine[x + 1][y - 1] +
        mine[x + 1][y] +
        mine[x + 1][y + 1] +
        mine[x][y + 1] +
        mine[x - 1][y + 1] - 8 * '0');
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    while (win<(row*col-mine_count))
    {
        printf("请输入要排查的坐标:>");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (mine[x][y] == '1')
            {
                printf("你被炸死了\n");
                DisplayBoard(mine, ROW, COL);
                break;
            }
            else
            {
                int count = GetMineCount(mine, x, y);
                show[x][y] = count + '0';
                DisplayBoard(show, ROW, COL);
                win++;
            }
        }
        else
        {
            printf("坐标非法,请重新输入\n");
        }
    }
    if (win == (row * col - mine_count))
    {
        printf("恭喜你,排雷成功\n");
        DisplayBoard(mine, ROW, COL);
    }
}

【C语言】—— 实现扫雷小游戏(初阶)

代码运行情况:

【C语言】—— 实现扫雷小游戏(初阶)

三、源代码

1.game.h

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define mine_count 10
//初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set);
//显示棋盘
void DisplayBoard(char Board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char Board[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

 2.test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
    printf("**********************************\n");
    printf("********** 扫雷小游戏 ************\n");
    printf("**********   1.Play   ************\n");
    printf("**********   0.Exit   ************\n");
    printf("**********************************\n");
}
void game()
{
    char mine[ROWS][COLS] = { 0 };//存放雷的信息
    char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
    //初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');
    //显示棋盘
    //DisplayBoard(mine, ROW, COL);
    //DisplayBoard(show, ROW, COL);
//  布置雷
    SetMine(mine, ROW, COL);
//  DisplayBoard(mine, ROW, COL);//测试雷的布置情况
    DisplayBoard(show, ROW, COL);
    //排查雷
    FindMine(mine, show, ROW, COL);
}
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("退出游戏\n");
            break;
        default:
            printf("选择错误,请重新输入\n");
            break;
        }
    } while (input);
    return 0;
}

 3.game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set)
{
    int i = 0;
    for (i = 0; i < rows; i++)
    {
        int j = 0;
        for (j = 0; j < cols; j++)
        {
            Board[i][j] = set;
        }
    }
}
//显示棋盘
void DisplayBoard(char Board[ROWS][COLS], int row, int col)
{
    int i = 0;
    printf("--------------------------------------\n");
    printf("  ");
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        int j = 0;
        printf("%d ", i);
        for (j = 1; j <= col; j++)
        {
            printf("%c ", Board[i][j]);
        }
        printf("\n");
    }
    printf("--------------------------------------\n");
}
//布置雷
void SetMine(char Board[ROWS][COLS], int row, int col)
{
    int count = mine_count;
    while (count)
    {
        //生成随机下标
        int x = rand() % row + 1;
        int y = rand() % col + 1;
        if (Board[x][y] != '1')
        {
            Board[x][y] = '1';
            count--;
        }
    }
}
//排查雷
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
    return (mine[x - 1][y] +
        mine[x - 1][y - 1] +
        mine[x][y - 1] +
        mine[x + 1][y - 1] +
        mine[x + 1][y] +
        mine[x + 1][y + 1] +
        mine[x][y + 1] +
        mine[x - 1][y + 1] - 8 * '0');
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    while (win<(row*col-mine_count))
    {
        printf("请输入要排查的坐标:>");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (mine[x][y] == '1')
            {
                printf("你被炸死了\n");
                DisplayBoard(mine, ROW, COL);
                break;
            }
            else
            {
                int count = GetMineCount(mine, x, y);
                show[x][y] = count + '0';
                DisplayBoard(show, ROW, COL);
                win++;
            }
        }
        else
        {
            printf("坐标非法,请重新输入\n");
        }
    }
    if (win == (row * col - mine_count))
    {
        printf("恭喜你,排雷成功\n");
        DisplayBoard(mine, ROW, COL);
    }
}

四、总结

       以上是扫雷整个游戏的代码实现和整个思路,但是功能不是很完美。后期会对扫雷的界面、布雷的个数、排雷的显示以及增加闯关类型的设计进行优化及时分享给博友们,希望我的代码能够给大家提供帮助并从中感受到快乐。