用c语言编写一个扫雷游戏

用c语言编写一个扫雷游戏

目录

1.分析和设计扫雷游戏

[][]

2.扫雷游戏的代码实现过程

3.扫雷游戏的最终版本


1.分析和设计扫雷游戏

1.1扫雷游戏的功能

  • 使用控制台实现扫雷游戏
  • 游戏可以通过菜单实现退出
  • 游戏格子为9×9样式(后续如果有需求要方便改动)
  • 随机布置10个地雷
  • 通过输入格子的坐标来排查雷
    • 如果该处不是地雷,则显示周围有几个地雷
    • 如果是地雷,则显示“你被炸死了”,游戏结束
    • 将10个雷全部找出来后,游戏结束

游戏界面
在这里插入图片描述
在这里插入图片描述

1.2扫雷游戏的分析与设计

1.2.1数据结构设计

那应该如何实现扫雷游戏的实现呢?

​ 对于9×9的宫格,我们需要用9×9的二维数组来存放数据。是雷的位置我们存放成1不是雷的位置我们存放成0。当我们排查雷的时候,如果该位置不是雷,我们要排查周围8个位置的雷的个数,因此为了避免使排查出的雷的个数和雷的标记冲突,我们用两个二维数组来记录,其中一个存放布置雷的信息,另一个存放排查出的雷的信息。但是当我们要统计边缘的宫格,统计他们周围8个宫格的雷的数据时,此时边缘宫格周围是不足8个宫格的,同时编写代码时也有数组越界的可能,所以我们将二维数组扩充,让左右多一列,上下多一行,最终我们创建的二维数组是11×11

那我们是设置成字符数组还是整型数组呢?

​ 我们打算采用字符数组,因为我们没排查的时候,宫格中显示的是“*”。

1.2.1文件的结构设计
test.c-----main函数,主要来测试游戏的主逻辑
game.h-----函数的声明
game.c-----函数的实现

2.扫雷游戏的代码实现过程

首先我们到打印一个菜单:

test.c

# include<stdio.h>
void menu()
{
	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;
}

​ 首先,我们利用 do---while 循环来实现多次的输入,根据我们之前的程序构想设计出菜单栏,利用 switch 语句来实现通过输入决定游戏进程。游戏的骨架已经被我们设计出来了。接下来,让程序运行一下,看结果是否按我们所想的那样运行。

在这里插入图片描述


很好,根据我们的测试,我们的逻辑没有错误。接下来我们将 printf("扫雷\n");更改成 game() 函数。来实现游戏逻辑。

# include"game.h"
void menu()
{
	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);
}
int main()
{
    int input = 0;
    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;
}

我们将函数的声明放在头文件中

game.h

# pragma once

# include<stdio.h>

# define ROW 9
# define COL 9   // 定义宏常量也是方便我们后续的修改,之后记得将头文件引用到game.c中
# define ROWS ROW+2
# define COLS COL+2
// 初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, char set);

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

函数声明好之后,我们需要对其实现,函数的定义:

game.c

# incude"game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
    
    int i = 0;
    for(i = 0; i < row; i++)
    {
        int j = 0;
        for(j=0; j < col; j++)
        {
            board[i][j] = set; // 将这里设置成set可以方便我们根据需要设置
        }
    }
}

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

打印棋盘函数写好后,我们运行程序,看是否符合预期。
在这里插入图片描述


很好,答案符合我们的预期。写一点检查一点,可以很好地给我们减少麻烦。现在我们继续完善功能。

我们需要打印九宫格地行号,同时还有我们可以适当的美化一下打印函数

game.c

# include"game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
    
    int i = 0;
    for(i = 0; i < row; i++)
    {
        int j = 0;
        for(j=0; j < col; j++)
        {
            board[i][j] = set; // 将这里设置成set可以方便我们根据需要设置
        }
    }
}

// 打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    printf("----------扫雷----------\n");
    for(i = 0; i <= col; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for(i = 1; i <= row; i++)
    {
        printf("%d ", i); // 打印行号
        for(j = 1; j <= col; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
    printf("----------扫雷----------\n");
}

调整后,运行一下,看看效果:


效果很好,说明以上代码没有任何问题,接下来我们来布置雷

test.c

# include"game.h"
void menu()
{
	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,'*');
    
    // 布置雷
    SetMine(mine, ROW, COL);
    DisplayBoard(mine, 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;
}

game.c

# include"game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
    
    int i = 0;
    for(i = 0; i < row; i++)
    {
        int j = 0;
        for(j=0; j < col; j++)
        {
            board[i][j] = set; // 将这里设置成set可以方便我们根据需要设置
        }
    }
}

// 打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    printf("----------扫雷----------\n");
    for(i = 0; i <= col; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for(i = 1; i <= row; i++)
    {
        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 = 10;
    while(count)
    {
        // 生成随机坐标
        // 行的坐标1~9
        // 列的坐标1~9
        int x = rand() % row + 1;  // 记得加时间戳
        int y = rand() % col + 1;
        // 还要判断随机坐标是否已经布置成雷
        if(board[x][y] != '1')
        {
            board[x][y] = '1';
            count--;
        }
        
    }
}

game.h

# pragma once

# include<stdio.h>
# include<stdlib.h> // srand函数的头文件
# include<time.h>  // time函数的头文件

# define ROW 9
# define COL 9   // 定义宏常量也是方便我们后续的修改,之后记得将头文件引用到game.c中
# define ROWS ROW+2
# define COLS COL+2
// 初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, char set);

// 打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
   
// 布置雷
void SetMine(char board[ROWS][COLS], int row, int col);

完成布置雷后, 我们可以检验一下是否布置成功,只要再test.c中 game() 函数里 SetMine(mine, ROW, COL);后添加打印棋盘函数 DisplayBoard(mine, ROW, COL);即可。

在这里插入图片描述

可见,我们对于雷的布置是成功的。


紧接着我们着手设计排查雷了!!!!

在mine数组中排查,之后要放到show数组中显示。排查的范围是9行9列

test.c

# include"game.h"
void menu()
{
	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,'*');
    
    // 布置雷
    SetMine(mine, ROW, COL);
    DisplayBoard(mine, 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;
}

game.c

# include"game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
    
    int i = 0;
    for(i = 0; i < row; i++)
    {
        int j = 0;
        for(j=0; j < col; j++)
        {
            board[i][j] = set; // 将这里设置成set可以方便我们根据需要设置
        }
    }
}

// 打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    printf("----------扫雷----------\n");
    for(i = 0; i <= col; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for(i = 1; i <= row; i++)
    {
        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 = 10;
    while(count)
    {
        // 生成随机坐标
        // 行的坐标1~9
        // 列的坐标1~9
        int x = rand() % row + 1;  // 记得加时间戳
        int y = rand() % col + 1;
        // 还要判断随机坐标是否已经布置成雷
        if(board[x][y] != '1')
        {
            board[x][y] = '1';
            count--;
        }
        
    }
}
int Get_Mine_Count(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;
    while(1)
    {
        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);  // 统计周围8个坐标的雷的个数
				show[x][y] = count + '0';              // 在show数组中显示出来
				DisplayBoard(show, ROW, COL);
            }
        }
        else
        {
            printf("坐标非法,重新输入\n");
        }
        
    }
}

game.h

# pragma once

# include<stdio.h>
# include<stdlib.h> // srand函数的头文件
# include<time.h>  // time函数的头文件

# define ROW 9
# define COL 9   // 定义宏常量也是方便我们后续的修改,之后记得将头文件引用到game.c中
# define ROWS ROW+2
# define COLS COL+2
// 初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, 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);

// 统计雷的个数
int Get_Mine_Count(char mine[ROWS][COLS], int x, int y);

完成排查雷后, 我们可以检验一下是否能排查成功,只要再test.c中 game() 函数里 SetMine(mine, ROW, COL);后添加打印棋盘函数 DisplayBoard(mine, ROW, COL);即可。, 我们就可以对照雷表来判断我们的统计雷的个数的函数,是否写正确了

在这里插入图片描述

可以看到,执行正确。


设计结束条件

game.c

# include"game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
    
    int i = 0;
    for(i = 0; i < row; i++)
    {
        int j = 0;
        for(j=0; j < col; j++)
        {
            board[i][j] = set; // 将这里设置成set可以方便我们根据需要设置
        }
    }
}

// 打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    printf("----------扫雷----------\n");
    for(i = 0; i <= col; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for(i = 1; i <= row; i++)
    {
        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 = 10;
    while(count)
    {
        // 生成随机坐标
        // 行的坐标1~9
        // 列的坐标1~9
        int x = rand() % row + 1;  // 记得加时间戳
        int y = rand() % col + 1;
        // 还要判断随机坐标是否已经布置成雷
        if(board[x][y] != '1')
        {
            board[x][y] = '1';
            count--;
        }
        
    }
}
int Get_Mine_Count(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 < col*row - define EASY_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
            {
                win++;
                int count = GetMineCount(mine, x, y);  // 统计周围8个坐标的雷的个数
				show[x][y] = count + '0';              // 在show数组中显示出来
				DisplayBoard(show, ROW, COL);
            }
        }
        else
        {
            printf("坐标非法,重新输入\n");
        }
        
    }
    if(win == col*row - define EASY_COUNT)
    {
        printf("恭喜排雷成功\n");
        DisplayBoard(mine, ROW, COL);
    }
    
}

game.h

# pragma once

# include<stdio.h>
# include<stdlib.h> // srand函数的头文件
# include<time.h>  // time函数的头文件

# define EASY_COUNT = 10; // 简单版本雷的个数

# define ROW 9
# define COL 9   // 定义宏常量也是方便我们后续的修改,之后记得将头文件引用到game.c中
# define ROWS ROW+2
# define COLS COL+2
// 初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, 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);

// 统计雷的个数
int Get_Mine_Count(char mine[ROWS][COLS], int x, int y);

3.扫雷游戏的最终版本

test.c

# include"game.h"
void menu()
{
	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,'*');
    
    // 布置雷
    SetMine(mine, ROW, COL);
    DisplayBoard(mine, 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;
}

game.c

# include"game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
    
    int i = 0;
    for(i = 0; i < row; i++)
    {
        int j = 0;
        for(j=0; j < col; j++)
        {
            board[i][j] = set; // 将这里设置成set可以方便我们根据需要设置
        }
    }
}

// 打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    printf("----------扫雷----------\n");
    for(i = 0; i <= col; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for(i = 1; i <= row; i++)
    {
        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 = 10;
    while(count)
    {
        // 生成随机坐标
        // 行的坐标1~9
        // 列的坐标1~9
        int x = rand() % row + 1;  // 记得加时间戳
        int y = rand() % col + 1;
        // 还要判断随机坐标是否已经布置成雷
        if(board[x][y] != '1')
        {
            board[x][y] = '1';
            count--;
        }
        
    }
}
int Get_Mine_Count(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 < col*row - define EASY_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
            {
                win++;
                int count = GetMineCount(mine, x, y);  // 统计周围8个坐标的雷的个数
				show[x][y] = count + '0';              // 在show数组中显示出来
				DisplayBoard(show, ROW, COL);
            }
        }
        else
        {
            printf("坐标非法,重新输入\n");
        }
        
    }
    if(win == col*row - define EASY_COUNT)
    {
        printf("恭喜排雷成功\n");
        DisplayBoard(mine, ROW, COL);
    }
    
}

game.h

# pragma once

# include<stdio.h>
# include<stdlib.h> // srand函数的头文件
# include<time.h>  // time函数的头文件

# define ROW 9
# define COL 9   // 定义宏常量也是方便我们后续的修改,之后记得将头文件引用到game.c中
# define ROWS ROW+2
# define COLS COL+2
// 初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, 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);

// 统计雷的个数
int Get_Mine_Count(char mine[ROWS][COLS], int x, int y);
        // 在show数组中显示出来
			DisplayBoard(show, ROW, COL);
        }
    }
    else
    {
        printf("坐标非法,重新输入\n");
    }
    
}
if(win == col*row - define EASY_COUNT)
{
    printf("恭喜排雷成功\n");
    DisplayBoard(mine, ROW, COL);
}

}


game.h

```c
# pragma once

# include<stdio.h>
# include<stdlib.h> // srand函数的头文件
# include<time.h>  // time函数的头文件

# define ROW 9
# define COL 9   // 定义宏常量也是方便我们后续的修改,之后记得将头文件引用到game.c中
# define ROWS ROW+2
# define COLS COL+2
// 初始化棋盘
void InitBoard(char board[ROWS][COLS], int row, int col, 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);

// 统计雷的个数
int Get_Mine_Count(char mine[ROWS][COLS], int x, int y);
  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值