用C写一个简单的扫雷游戏(与原版几乎无异)(简单易懂)

前言:

                当我们初学了c语言,已经学会了一些基础的语法。面对一些简单的算法已经可以轻松拿下。

                但是我们可能会生成一个疑惑:

                                                                除了算法题,我还能拿它做些什么呢?

                而今天,就给大家推荐一用c做个简单的小游戏:扫雷,;来用上我们所学的知识,融汇贯通,充分吸收知识,也能提高我们对编程的兴趣。

目录

前言

游戏逻辑实现

 代码实现 

最后


游戏逻辑实现:

                在我们动手写代码之前,我们需要提前对代码实现的逻辑进行梳理;不然盲目去写代码,只会一地鸡毛,bug重重。

                

                让我们先观察一下扫雷的基本结构:

图一              

           

                                                                图二

 

                                                                图三

                我们由图一可以发现基本框架是由一个9*9的结构组成和10个雷,因此我们需要:

1.一个9*9的数组

2.10个雷

                (难点)在有图二中,我们发现当我们点击一个没有雷的位置后,能够引起一片的扫雷,而此机制由我查询,是以你点击的位置,对此位置3*3的位置进行“查雷”后扩散。

                    那么“查雷“是个什么操作呢 ?————对你所点击的位置(没雷的前提下)对3*3范围的8 个位置进行再次的以8个位置进行 3*3的范围查询雷数量,如果该位置的3*3范围里没有雷;此位置就属于扩散区域   ,因此,我们需要一个可以对此机制的算法

总结:

1.一个9*9的数组

2.10个雷

3.扩散算法

  

 代码实现 :

头文件展示:

#pragma once
#include<stdio.h>
#include<stdlib.h>

#define ROWS 11
#define COLS 11
#define Boomnumber 10

void InitBorad(char borad[ROWS][COLS], int row, int col, char x);

void DisplayBorad(char borad[ROWS][COLS], int row, int col);

void MineBorad(char borad[ROWS][COLS], int row, int col);

Minesweeper(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

我们先进行简单的菜单显示:

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

int main()
{
    srand((unsigned int)time(NULL));
    //用input 来记录游戏启动还是退出
    int input = 1;
    do
    {
        meun();
        printf("请输入你的选择 :\n");
        scanf("%d", &input);
        switch (input)
        {
        case 0:
        {
            input = 0;
            break;
        }
        case 1:
        {
            //游戏函数
            play();
            break;
        }
        default:
        {
            printf("非法输入,请重新输入\n");
        }
        }
    } while (input);
}           

   简单的菜单写完,我们就需要进行游戏代码的实现了:

重点一:

由于我们需要在棋盘上显示地雷的状态,一个棋盘完全不能够显示那么多的信息,于是我们需要两个棋盘来分别记录信息:  mine棋盘用于记录什么地方有雷,什么地方没雷,show棋盘用于展示玩家玩时的状态。

如图:

                        mine                                                                                        show

重点二:

在检测靠四边位置的位置 3*3内雷的数量时,由于在最边上,旁边没有格子,会给我们写代码时造成麻烦,因此我们将两个棋盘都 扩大到11*11,其中四边是不向玩家展示,只做辅助用。

void play()
{
    //设置扫雷大小,我们写一个简单模式下的扫雷:9*9大小,但是为了方便进行“排雷”操作计算地雷数量,将扩大一圈,也就是 11*11
    //这个是用来埋雷的;
    char mine[ROWS][COLS];
    //记录雷的状态,当此位置没有雷,与mine雷盘对应的位置下,show盘就显示附件(以此位置3*3大小)雷的数量
    char show[ROWS][COLS];
    //初始化mine棋盘  0表示没有地雷
    InitBorad(mine, ROWS, COLS, '0');
    //初始化show棋盘
    InitBorad(show,ROWS, COLS, '*');
    //进行埋雷,对mine棋盘
    MineBorad(mine, ROWS, COLS, '1');
    //打印棋盘
    DisplayBorad(show, ROWS, COLS);
    //进行扫雷
    Minesweeper(mine, show, ROWS, COLS);
}

各部分函数实现

InitBorad(mine, ROWS, COLS, '0')

//char 用于选择初始化什么字符

void InitBorad(char borad[ROWS][COLS], int row, int col, char x)
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            borad[i][j] = x;
        }
    }
}

MineBorad(mine, ROWS, COLS, '1');

//用1来表示表示地雷

void MineBorad(char borad[ROWS][COLS], int row, int col)
{
    
    int count = Boomnumber;
    while (count)
    {
        int x = 0, y = 0;
        x = rand() % 9 + 1;
        y = rand() % 9 + 1;
        if (borad[x][y] == '0')
        {
            borad[x][y] = '1';
            count--;
        }
    }
}

DisplayBorad(show, ROWS, COLS);

void DisplayBorad(char borad[ROWS][COLS], int row, int col)
{    
    printf("    %d  %d  %d  %d  %d  %d  %d  %d  %d\n\n",1,2,3,4,5,6,7,8,9);//显示多少列
    for (int i = 1; i < row-1; i++)
    {    
        //显示多少行
        printf("%d  ", i);
        for (int j = 1; j < col-1; j++)
        {
            
            printf(" %c ", borad[i][j]);
        }
        printf("\n");
    }
}

下图是打印出的棋盘

Minesweeper函数是代码中最复杂的部分,含有三个函数:

Minesweeper     sweeper         Minesnumber

其中Minesweeper是主体函数,使用了其他两个函数

sweeper函数主要实现了当我们点击一个位置时,却能够联动周围3*3雷数量为0的一起被显示,从而不需要一个一个的扫雷。

Minenumber函数实现了,查询某位子3*3范围里雷的数量

Minesweeper(mine, show, ROWS, COLS);

//

char Minesnumber(char mine[ROWS][COLS], int x, int y)
{

        // ’0‘=48(ASCII值)  ’1‘-’0‘=1   1+’0’=‘1’
    char ret = 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] + mine[x+1][y +1] - 7 * '0';
    return ret;
}

void sweeper(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y)
{
    if (x > 0&& x < 10 && y>0 && y < 10)
    {
        //对3*3范围里,是零的就继续扫,非零就停止
        //x-1 y-1
        if (Minesnumber(mine, x - 1, y - 1)=='0' && show[x-1][y-1] == '*')
        {
            show[x - 1][y - 1] = '0';
            sweeper(mine,show, x - 1, y - 1);
        }
        else if (Minesnumber(mine,  x - 1, y - 1) != '0')
        {
            show[x - 1][y - 1] = Minesnumber(mine, x - 1, y - 1);
        }
        //x y-1
        if (Minesnumber(mine, x , y - 1) == '0' && show[x][y-1] == '*')
        {
            show[x - 1][y - 1] = '0';
            sweeper(mine, show, x , y -1);
        }
        else if (Minesnumber(mine, x, y - 1) != '0')
        {
            show[x][y - 1] = Minesnumber(mine, x, y - 1);
        }
        //x+1 y-1
        if (Minesnumber(mine,  x+1, y - 1) == '0' && show[x+1][y-1] == '*')
        {
            show[x +1][y - 1] = '0';
            sweeper(mine, show, x+1, y - 1);
        }
        else if (Minesnumber(mine,x+1, y - 1) != '0')
        {
            show[x +1][y - 1] = Minesnumber(mine,  x+1, y - 1);
        }
        //x-1 y
        if (Minesnumber(mine,  x-1, y ) == '0' && show[x-1][y] == '*')
        {
            show[x - 1][y ] = '0';
            sweeper(mine, show, x-1, y );
        }
        else if (Minesnumber(mine,  x-1, y ) != '0')
        {
            show[x - 1][y ] = Minesnumber(mine,  x-1, y );
        }
        //x-1 y+1
        if (Minesnumber(mine, x-1, y +1) == '0' && show[x-1][y+1] == '*')
        {
            show[x - 1][y +1] = '0';
            sweeper(mine, show, x-1, y + 1);
        }
        else if (Minesnumber(mine,  x-1, y - 1) != '0')
        {
            show[x - 1][y +1 ] = Minesnumber(mine,  x-1, y + 1);
        }
        //x y+1
        if (Minesnumber(mine, x, y + 1) == '0' && show[x][y+1] == '*')
        {
            show[x ][y + 1] = '0';
            sweeper(mine, show, x, y + 1);
        }
        else if (Minesnumber(mine,  x, y + 1) != '0')
        {
            show[x][y + 1] = Minesnumber(mine,  x, y + 1);
        }
        //x+1 y
        if (Minesnumber(mine,  x+1, y ) == '0' && show[x+1][y] == '*')
        {
            show[x +1][y ] = '0';
            sweeper(mine, show, x+1, y );
        }
        else if (Minesnumber(mine, x, y - 1) != '0')
        {
            show[x +1][y ] = Minesnumber(mine,  x+1, y );
        }
        //x+1 y+1
        if (Minesnumber(mine,  x+1, y + 1) == '0' && show[x+1][y+1] == '*')
        {
            show[x + 1][y + 1] = '0';
            sweeper(mine, show, x+1, y +1 );
        }
        else if (Minesnumber(mine,  x+1, y + 1) != '0')
        {
            show[x + 1][y + 1] = Minesnumber(mine,x+1, y + 1);
        }
    }
    //将最外维的格子除去,默认为零
    else if ((x==0&&(y<=10&&y>=0))||(x==10 && (y <= 10 && y >= 0))||(y==0&&(x<10&&x>0))|| (y == 10 && (x < 10 && x>0)))
    {
        show[x][y] = '0';
    }
}


Minesweeper(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x, y;
    int win=0;
    while (win<71)
    {
        printf("\n");
        printf("请输入你要排查的下标:\n");
        scanf("%d %d", &x, &y);
        if (x > 0 && x < 10 && y>0 && y < 10)
        {
            if (mine[x][y] == '1')
            {

                printf("你踩到雷了!\n");
                DisplayBorad(mine, ROWS, COLS);
                break;
            }
            //将x,y位置3*3格子,雷数量为0 的扫出,知道格子附近有雷
            else {
                show[x][y] = Minesnumber(mine, x, y);
                sweeper(mine, show, x, y);
                DisplayBorad(show, ROWS, COLS);
                win++;
            }
            
        }
        else
        {
            printf("非法输入\n");
        }
    }
    
    if (win == 71)
    {
        printf("你赢了\n");
        DisplayBorad(mine, ROWS, COLS);
    }


}

 

最后:

至此,我们的扫雷就完成了,如果大家觉得有用的话,希望大家多多给我点赞,关注。

                        

                

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值