扫雷的分析与实现——C语言

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扫雷的分析与实现——C语言相关的知识,希望对你有一定的参考价值。

扫雷作为一款经典游戏,为大家所熟知。今天我使用C语言来编写一个简单的扫雷程序。

主要功能有

1.第一次下子不被炸死;
2.下子后显示周围布雷数;

分析游戏及功能

首先可以将扫雷的游戏界面看做一个二维数组;然后有限的雷随机排布在这个二维数组中,玩家通过输入坐标来确定该坐标对应的二维数组坐标是否是雷,若不是则显示周围布雷数,这时考虑坐标如果在数组的中间则少显示周围8个坐标布雷情况,而在数组边缘则小于8。因此我在创建数组时创建一个比所需数大2行2列。将所需数组视为中间数组即可;如图:

技术图片

代码创建

创建test.c,game.c和game.h三个文件

1.创建主函数,打印菜单用do,whlie语句实现基选择功能;

代码如下:

int main()

    srand((unsigned int)time(NULL));//产生随机数生成器
    int input = 0;
    do
    
        muen();
        scanf("%d", &input);
        switch (input)
        
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("输入错误,重新输入\n");
            break;
        
     while (input);
    system("pause");
    return 0;

2.在game.c中先完成菜单,数组的创建,以及玩家的界面,和布雷的界面

代码如下;

void muen()

    printf("*******************************\n");
    printf("*****1.play       0.exit*******\n");
    printf("*******************************\n");


void init_mine()//初始化两个棋盘

    int i = 0;
    int j = 0;
    for (int i = 0; i < row; i++)
    
        for (j = 0; j < col; j++)
        
            show_mine[i][j] = ‘*‘;
            real_mine[i][j] = ‘0‘;
        
    


void print_player()//打印玩家棋盘

    int i = 0;
    int j = 0;
    printf("0  ");
    for (i = 1; i <row - 1; i++)
    
        printf("%d ", i);
    
    printf("\n");
    for (i = 1; i <row - 2; i++)
    
        printf("%d  ", i);
        for (j = 1; j < col - 1; j++)
        
            printf("%c ", show_mine[i][j]);//玩家棋盘数组
        
        printf("\n");
    
    printf("10 ");//开始打印最后一行
    for (i = 1; i < row - 1; i++)
    
        printf("%c ", show_mine[10][i]);
    
    printf("\n");


void print_mine()//打印设计者棋盘

    int i = 0;
    int j = 0;
    printf("0  ");
    for (i = 1; i <row - 1; i++)
    
        printf("%d ", i);
    
    printf("\n");
    for (i = 1; i <row - 2; i++)
    
        printf("%d  ", i);
        for (j = 1; j < col - 1; j++)
        
            printf("%c ", real_mine[i][j]);
        
        printf("\n");
    
    printf("10 ");//开始打印最后一行
    for (i = 1; i < row - 1; i++)
    
        printf("%c ", real_mine[10][i]);
    
    printf("\n");

效果如图:
技术图片

3.完成布雷函数以及扫雷函数

代码如下:

void set_mine()        //给设计者棋盘布雷

    int x = 0;
    int y = 0;
    int count = COUNT; //雷总数
    while (count)      //雷布完后跳出循环
    
        int x = rand() % 10 + 1;     //产生1到10的随机数,在数组下标为1到10的范围内布雷
        int y = rand() % 10 + 1;     //产生1到10的随机数,在数组下标为1到10的范围内布雷
        if (real_mine[x][y] == ‘0‘)  //找不是雷的地方布雷
        
            real_mine[x][y] = ‘1‘;
            count--;
        
    

int sweep_mine()//扫雷函数,踩到雷返回1,没有踩到雷返回0

    int x = 0;
    int y = 0;
    int count = 0;
    printf("输入坐标扫雷\n");
    scanf("%d%d", &x, &y);
    if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输入坐标是否有误,输入错误重新输入
    
        if (real_mine[x][y] == ‘0‘)//没踩到雷
        
            char ch = count_mine(x, y);
            show_mine[x][y] = ch + ‘0‘;//数字对应的ASCII值和数字字符对应的ASCII值相差48,即‘0‘的ASCII值
            open_mine(x, y);
            if (count_show_mine() == COUNT)//判断剩余未知区域的个数,个数为雷数时玩家赢
            
                return 0;
            
        
        else if (real_mine[x][y] == ‘1‘)//踩到雷
        
            return 1;
        
    
    else
    
        printf("输入错误重新输入\n");
    
    return 0;//没踩到雷

4.完成防止第一步被炸死的函数

代码如下:

void safe_mine()//避免第一次炸死

    int x = 0;
    int y = 0;
    char ch = 0;
    int count = 0;
    int ret = 1;
    printf("游戏开始\n");
    printf("输入坐标扫雷\n");
    while (1)
    
        scanf("%d%d", &x, &y);//只能输入1到10,输入错误重新输入
        if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输入坐标是否有误
        
            if (real_mine[x][y] == ‘1‘)//第一次踩到雷后补救
            
                real_mine[x][y] = ‘0‘;
                char ch = count_mine(x, y);
                show_mine[x][y] = ch + ‘0‘;//数字对应的ASCII值和数字字符对应的ASCII值相差48,即‘0‘的ASCII值
                open_mine(x, y);
                while (ret)//在其余有空的地方设置一个雷
                
                    int x = rand() % 10 + 1;//产生1到10的随机数,在数组下标为1到10的范围内布雷
                    int y = rand() % 10 + 1;//产生1到10的随机数,在数组下标为1到10的范围内布雷
                    if (real_mine[x][y] == ‘0‘)//找不是雷的地方布雷
                    
                        real_mine[x][y] = ‘1‘;
                        ret--;
                        break;
                    
                break;//跳出此函数  
            
            if (real_mine[x][y] == ‘0‘)
            
                char ch = count_mine(x, y);
                show_mine[x][y] = ch + ‘0‘;//数字对应的ASCII值和数字字符对应的ASCII值相差48,即‘0‘的ASCII值
                open_mine(x, y);
                break;
            
        
        else//坐标错误
        
            printf("输入错误重新输入\n");
        
    

5.完成检测周围雷数并显示函数

int count_mine(int x, int y)//检测周围8个区域雷的个数

    int count = 0;
    if (real_mine[x - 1][y - 1] == ‘1‘)
        count++;
    if (real_mine[x - 1][y] == ‘1‘)
        count++;
    if (real_mine[x - 1][y + 1] == ‘1‘)
        count++;
    if (real_mine[x][y - 1] == ‘1‘)
        count++;
    if (real_mine[x][y + 1] == ‘1‘)
        count++;
    if (real_mine[x + 1][y - 1] == ‘1‘)
        count++;
    if (real_mine[x + 1][y] == ‘1‘)
        count++;
    if (real_mine[x + 1][y + 1] == ‘1‘)
        count++;
    return count;


void open_mine(int x, int y)//坐标周围展开函数

    if (real_mine[x - 1][y - 1] == ‘0‘)
    
        show_mine[x - 1][y - 1] = count_mine(x - 1, y - 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x - 1][y] == ‘0‘)
    
        show_mine[x - 1][y] = count_mine(x - 1, y) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x - 1][y + 1] == ‘0‘)
    
        show_mine[x - 1][y + 1] = count_mine(x - 1, y + 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x][y - 1] == ‘0‘)
    
        show_mine[x][y - 1] = count_mine(x, y - 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x][y + 1] == ‘0‘)
    
        show_mine[x][y + 1] = count_mine(x, y + 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x + 1][y - 1] == ‘0‘)
    
        show_mine[x + 1][y - 1] = count_mine(x + 1, y - 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x + 1][y] == ‘0‘)
    
        show_mine[x + 1][y] = count_mine(x + 1, y) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x + 1][y + 1] == ‘0‘)
    
        show_mine[x + 1][y + 1] = count_mine(x + 1, y + 1) + ‘0‘;//显示该坐标周围雷数
    

6.最后完成判断玩家赢的函数

代码如下;

int count_show_mine()//判断剩余未知区域的个数,个数为雷数时玩家赢

    int count = 0;
    int i = 0;
    int j = 0;
    for (i = 1; i <= row - 2; i++)
    
        for (j = 1; j <= col - 2; j++)
        
            if (show_mine[i][j] == ‘*‘)
            
                count++;
            
        
    
    return count;

最后运行测试

查看第一是否可以炸死(根据布雷图,输入有雷坐标未被炸死):
技术图片

第二步输入有雷坐标:
技术图片
判断玩家赢;
技术图片

test.c代码

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
double  start, finish;
void game()

    int ret = 0;
    init_mine();             //初始化玩家棋盘和设计者棋盘
    set_mine();              //给设计者棋盘布雷
    print_mine();            //打印设计者棋盘(可不打印)
    printf("\n");            
    print_player();          //打印玩家棋盘
    start = clock();
    safe_mine();             //避免第一次被炸死

    if (count_show_mine() == COUNT)//一步就赢的情况
    
        print_mine();
        printf("玩家赢!\n\n");
        return;
     
    print_player();
    while (1)//循环扫雷
    
        int ret = sweep_mine();//扫雷,踩到雷返回1,没有踩到雷返回0
        if (count_show_mine() == COUNT)//若玩家棋盘的‘*‘个数为雷数时,扫雷完成,游戏胜利
        
            print_mine();    //打印设计者棋盘
            printf("玩家赢!\n\n");
            finish = clock();//取结束时间
            printf("用时%d 秒\n", (int)(finish - start) / CLOCKS_PER_SEC);
            break;
        
        if (ret)//判断是否踩到雷
        
            printf("被雷炸死\t");
            finish = clock();//取结束时间
            printf("用时%d 秒\n", (int)(finish - start) / CLOCKS_PER_SEC);
            print_mine();//打印设计者雷阵查看雷的分布
            break;
        
        print_player();//打印玩家棋盘
    


int main()

    srand((unsigned int)time(NULL));//产生随机数生成器
    int input = 0;
    do
    
        muen();
        scanf("%d", &input);
        switch (input)
        
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("输入错误,重新输入\n");
            break;
        
     while (input);//循环玩游戏
    system("pause");
    return 0;

game.c代码

#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
char show_mine[row][col] =  0 ;
char real_mine[row][col] =  0 ;

void muen()

    printf("*******************************\n");
    printf("*****1.play       0.exit*******\n");
    printf("*******************************\n");


void init_mine()//初始化两个棋盘

    int i = 0;
    int j = 0;
    for (int i = 0; i < row; i++)
    
        for (j = 0; j < col; j++)
        
            show_mine[i][j] = ‘*‘;
            real_mine[i][j] = ‘0‘;
        
    


void print_player()//打印玩家棋盘

    int i = 0;
    int j = 0;
    printf("0  ");
    for (i = 1; i <row - 1; i++)
    
        printf("%d ", i);//打印横标(0--10)
    
    printf("\n");
    for (i = 1; i <row - 2; i++)//打印竖标(1--10)
    
        printf("%d  ", i);
        for (j = 1; j < col - 1; j++)
        
            printf("%c ", show_mine[i][j]);//玩家棋盘数组
        
        printf("\n");
    
    printf("10 ");//开始打印最后一行
    for (i = 1; i < row - 1; i++)
    
        printf("%c ", show_mine[10][i]);
    
    printf("\n");


void print_mine()//打印设计者棋盘

    int i = 0;
    int j = 0;
    printf("0  ");
    for (i = 1; i <row - 1; i++)
    
        printf("%d ", i);
    
    printf("\n");
    for (i = 1; i <row - 2; i++)
    
        printf("%d  ", i);
        for (j = 1; j < col - 1; j++)
        
            printf("%c ", real_mine[i][j]);
        
        printf("\n");
    
    printf("10 ");//开始打印最后一行
    for (i = 1; i < row - 1; i++)
    
        printf("%c ", real_mine[10][i]);
    
    printf("\n");


void set_mine()        //给设计者棋盘布雷

    int x = 0;
    int y = 0;
    int count = COUNT; //雷总数
    while (count)      //雷布完后跳出循环
    
        int x = rand() % 10 + 1;     //产生1到10的随机数,在数组下标为1到10的范围内布雷
        int y = rand() % 10 + 1;     //产生1到10的随机数,在数组下标为1到10的范围内布雷
        if (real_mine[x][y] == ‘0‘)  //找不是雷的地方布雷
        
            real_mine[x][y] = ‘1‘;
            count--;
        
    

int sweep_mine()//扫雷函数,踩到雷返回1,没有踩到雷返回0

    int x = 0;
    int y = 0;
    int count = 0;
    printf("输入坐标扫雷\n");
    scanf("%d%d", &x, &y);
    if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输入坐标是否有误,输入错误重新输入
    
        if (real_mine[x][y] == ‘0‘)//没踩到雷
        
            char ch = count_mine(x, y);
            show_mine[x][y] = ch + ‘0‘;//数字对应的ASCII值和数字字符对应的ASCII值相差48,即‘0‘的ASCII值
            open_mine(x, y);
            if (count_show_mine() == COUNT)//判断剩余未知区域的个数,个数为雷数时玩家赢
            
                return 0;
            
        
        else if (real_mine[x][y] == ‘1‘)//踩到雷
        
            return 1;
        
    
    else
    
        printf("输入错误重新输入\n");
    
    return 0;//没踩到雷


void safe_mine()//避免第一次炸死

    int x = 0;
    int y = 0;
    char ch = 0;
    int count = 0;
    int ret = 1;
    printf("游戏开始\n");
    printf("输入坐标扫雷\n");
    while (1)
    
        scanf("%d%d", &x, &y);//只能输入1到10,输入错误重新输入
        if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输入坐标是否有误
        
            if (real_mine[x][y] == ‘1‘)//第一次踩到雷后补救
            
                real_mine[x][y] = ‘0‘;
                char ch = count_mine(x, y);
                show_mine[x][y] = ch + ‘0‘;//数字对应的ASCII值和数字字符对应的ASCII值相差48,即‘0‘的ASCII值
                open_mine(x, y);
                while (ret)//在其余有空的地方设置一个雷
                
                    int x = rand() % 10 + 1;//产生1到10的随机数,在数组下标为1到10的范围内布雷
                    int y = rand() % 10 + 1;//产生1到10的随机数,在数组下标为1到10的范围内布雷
                    if (real_mine[x][y] == ‘0‘)//找不是雷的地方布雷
                    
                        real_mine[x][y] = ‘1‘;
                        ret--;
                        break;
                    
                break;//跳出此函数  
            
            if (real_mine[x][y] == ‘0‘)
            
                char ch = count_mine(x, y);
                show_mine[x][y] = ch + ‘0‘;//数字对应的ASCII值和数字字符对应的ASCII值相差48,即‘0‘的ASCII值
                open_mine(x, y);
                break;
            
        
        else//坐标错误
        
            printf("输入错误重新输入\n");
        
    


int count_mine(int x, int y)//检测周围8个区域雷的个数

    int count = 0;
    if (real_mine[x - 1][y - 1] == ‘1‘)
        count++;
    if (real_mine[x - 1][y] == ‘1‘)
        count++;
    if (real_mine[x - 1][y + 1] == ‘1‘)
        count++;
    if (real_mine[x][y - 1] == ‘1‘)
        count++;
    if (real_mine[x][y + 1] == ‘1‘)
        count++;
    if (real_mine[x + 1][y - 1] == ‘1‘)
        count++;
    if (real_mine[x + 1][y] == ‘1‘)
        count++;
    if (real_mine[x + 1][y + 1] == ‘1‘)
        count++;
    return count;


void open_mine(int x, int y)//坐标周围展开函数

    if (real_mine[x - 1][y - 1] == ‘0‘)
    
        show_mine[x - 1][y - 1] = count_mine(x - 1, y - 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x - 1][y] == ‘0‘)
    
        show_mine[x - 1][y] = count_mine(x - 1, y) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x - 1][y + 1] == ‘0‘)
    
        show_mine[x - 1][y + 1] = count_mine(x - 1, y + 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x][y - 1] == ‘0‘)
    
        show_mine[x][y - 1] = count_mine(x, y - 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x][y + 1] == ‘0‘)
    
        show_mine[x][y + 1] = count_mine(x, y + 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x + 1][y - 1] == ‘0‘)
    
        show_mine[x + 1][y - 1] = count_mine(x + 1, y - 1) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x + 1][y] == ‘0‘)
    
        show_mine[x + 1][y] = count_mine(x + 1, y) + ‘0‘;//显示该坐标周围雷数
    
    if (real_mine[x + 1][y + 1] == ‘0‘)
    
        show_mine[x + 1][y + 1] = count_mine(x + 1, y + 1) + ‘0‘;//显示该坐标周围雷数
    


int count_show_mine()//判断剩余未知区域的个数,个数为雷数时玩家赢

    int count = 0;
    int i = 0;
    int j = 0;
    for (i = 1; i <= row - 2; i++)
    
        for (j = 1; j <= col - 2; j++)
        
            if (show_mine[i][j] == ‘*‘)
            
                count++;
            
        
    
    return count;

game.h代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

#define row 12
#define col 12
#define COUNT 10//棋盘中雷的总数
extern char real_mine[row][col];//布雷数组

void muen();           //菜单函数
void init_mine();      //初始化数组函数
void print_player();   //打印玩家棋盘
void print_mine();     //打印设计者棋盘 
void set_mine();       //布雷函数
int count_mine();      //统计周围雷的个数
void safe_mine();      //避免第一次被雷炸死的函数
int  sweep_mine();     //扫雷函数
void open_mine(int x, int y);//展开函数
int count_show_mine(); //判断玩家棋盘剩余未知区域的个数

以上是关于扫雷的分析与实现——C语言的主要内容,如果未能解决你的问题,请参考以下文章

c语言数组简单实现童年回忆——扫雷

分析并实现 —— 扫雷小游戏(利用C语言实现)

扫雷(C语言版)

图形化界面扫雷(C语言+easyx实现,多图教学)

C语言实现全面的扫雷小游戏(包括空白展开标记等)具体步骤加代码分析

C语言实现简易版扫雷