简易扫雷游戏(代码和一些思考)

本文详细描述了一位C语言初学者如何制作一个简单的扫雷游戏,包括游戏页面设计、雷的生成、玩家操作逻辑以及代码结构。作者通过创建二维数组模拟客户端和服务端,确保游戏流畅进行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

制作一个简易扫雷游戏(c语言萌新编写,或许写的很拙劣,还望大佬们见谅,如果出了什么错误或者问题可以在评论里发)

ps:文章最后有全部代码

1.从结果逆向构思需要的基本的代码结构

程序结果呈现

是否进行游戏页面(图1)

游戏进行页面(图2)

用*代表未知的地方,有的地方有雷有的地方没雷

所以初步想法就是:

这里要建两个二维数组,一个存放这个我们可以看到的页面(类似客户端),另一个存放我们看不到的放置雷,检查雷的页面(类似服务端)

游戏进行页面(图3)

                                           

游戏结束页面(失败)(图4)

                                           

初步思考扫雷游戏逻辑:

扫雷游戏,首先需要有游戏页面,其次需要产生雷,然后玩家输入坐标,程序判断该坐标有无雷,无雷则告诉周围一圈有几个雷,然后重复进行该过程直至踩雷或完成排雷

而检查雷的时候,因为需要检查周围一圈,所以这里就会出现一个问题,如果已经在最边上,周围一圈会溢出数组

这样的话,就只能让它不溢出,所以我们建数组时需要再扩大一圈建立,也就是行和列数+2,但在展示的页面不展示出多出的部分

2.一步一步思考各个部分的代码

(1)是否进行游戏初始页面

第一步也就是开始页面(图1)

很容易得到如下代码(绿色的是代码的注释,加粗的是一些自己的见解,倾斜的是代码内容)

int input = 0;
do
{
    printf("**************************\n");
    printf("**********1.play**********\n");
    printf("**********0.exit**********\n");
    printf("**************************\n");
//菜单页面

    printf("是否开始游戏\n");
    printf("请输入(1/0):");
    scanf("%d", &input)
;//选择进行游戏
    switch (input)
//是否进行游戏,进行分支情况。这里用switch进行分支情况,也可以用if,不管由于是否进行游戏是输入数字进行选择,用switch更方便好看
    {
    case 1:
        game();
//游戏程序
        break;
    case 0:
        printf("退出游戏,游戏结束\n");
        break;
    default:
        printf("输入错误,请重新输入\n");
    }
}
while(input)
//同时因为游戏进行完或者输入错误,还可以再玩,这里用do while进行循环,因为输入0退出游戏,输入其他继续进行,所有这里可以直接用输入值(input)作为判断条件

也可以直接设一个函数来表示这个初始页面,使main函数主体更简单明了

如:

void menu()//初始页面
{
    printf("**************************\n");
    printf("**********1.play*********\n");
    printf("**********0.exit**********\n");
    printf("**************************\n");
    printf("是否开始游戏\n");
    printf("请输入(1/0):");
}

int main()
{
    int input = 0;
    do
    {     

        menu();
        scanf("%d", &input);//选择进行游戏
        switch (input)
        {
        case 1:
          
 game();//游戏程序
            break;
        case 0:
            printf("退出游戏,游戏结束\n");
            break;
        default:
            printf("输入错误,请重新输入\n");
        }
    }
    return 0;
}

扫雷的初始页面和游戏是否进行的逻辑已经完成,接下来就是扫雷游戏程序的编写(即代码中game()函数的具体实现)

(2)扫雷游戏初始页面

从我们想要的扫雷游戏呈现结果入手,我们需要新建两个二维数组先设定行和列,这里先弄9*9的扫雷游戏,所以声明(define)行和列的大小

#define ROW 9

#define COL 9 //这些声明可以放进一个头文件,然后开头包含这个文件,这样更简洁,助于阅读,而且会常用到,声明无法更改大小,所有这里用声明,不用int

#define ROWS ROW+2
#define COLS COL+2
//防止查雷时溢出

//创建初始棋盘
char put[ROWS][COLS] = { 0 };// 放置雷的信息,看不见
char show[ROWS][COLS] = { 0 };//排查雷的信息,看得见

board_show(put,  '0');
board_show(show,  '*');//创建好两个数组

print_board(show);//传show,put的数组不需要打印展示出来

void board_show(char board[ROWS][COLS], char set)//注意,函数主体要放在main前面,这里                                                                                             方便阅读理解就放后面了
{
    int i = 0;
    int j = 0;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] = set;
//将创建的数组每个元素都存进set,put的棋盘存的字符‘ 0 ’,show的棋盘存的字符‘ * ’
      
 }
    }
}

void print_board(char board[ROWS][COLS])//打印扫雷棋盘

{
    int i = 0;
    int j = 0;

    printf("******扫雷游戏******\n\n");

    for (i = 1; i <= ROW; i++)
    {
        for (j = 1; j <= COL; j++)
        {
            printf("%c ", board[i][j]);
//打印出每个位置是‘ * ’的扫雷棋盘
        }
        printf("\n");
//每一行一个换行符
    }
    printf("\n*******************\n\n");
}

这时运行程序会得到该图

(3)扫雷内部处理情况

1) 产生雷

所以接下来需要产生雷,也就是要在put棋盘中产生字符‘ 1 ’(其他字符也可以,1最方便)

先声明雷的个数 

#define TNT 9//可以改,不超过棋盘个数就行

然后产生雷,因为要生成随机位置的雷,我们可以用rand和time(时间戳)产生随机数,注意头文件要包含<stdlib.h><time.h>

srand((unsigned)time(FULL));//产生随机数,要放在main函数主体的开头

put_TNT(put);

void put_TNT(char board[ROWS][COLS])
{
    int count = TNT;
    while (count)
//用for循环不好,有可能会出现雷在一个位置,因为该while循环中利用count判断结束,只有在雷位置不重复的条件下count才变化,如果用for会很麻烦
    {
        int i = rand() % (TNT - 1) + 1;
        int j = rand() % (TNT - 1) + 1;
//创建雷位置,雷位置要在1到行数,列数之间,因为数组的序列从零开始
        if (board[i][j] == '0')
        {
            board[i][j] = '1';
            count--;
        }
    }
}

2)玩家排雷,检查周围雷的数量

void Player_check(char put[ROWS][COLS], char show[ROWS][COLS])//玩家行动,检查周围雷需要put的数组,给出玩家该信息需要show数组,所以传两个数组。

{
  
 //玩家输入坐标
    int x = 0;
    int y = 0;
    int a = ROW * COL - TNT;//即a为没有雷的格子数
    while (a > 0)
    {
        printf("玩家请输入坐标:");
        scanf("%d%d", &x, &y);
        if (x > 0 && x <= ROW && y>0 && y <= COL)
        {
            if (put[x][y] == '1')
//踩雷
            {
                printf("\n\n\n你被炸死,游戏结束\n\n\n");
                DisplayBoard(put);
//打印放置雷的页面,让玩家在踩雷后知道雷都在哪些位置。
                break;
            }
            else if (put[x][y] == '0')
//得出周围雷的信息,put数组中没雷是字符‘ 0 ’,有雷是字符‘ 1 ’,所有将周围八个元素相加就可以得到雷的数量,如果不用字符0,1表示会麻烦一点,可以创建一个新变量,然后用循环加条件判断,得出雷数量。

            {
                char c = put[x - 1][y - 1] + put[x - 1][y] +
                    put[x - 1][y + 1] + put[x][y + 1] +
                    put[x][y - 1] + put[x + 1][y] +
                    put[x + 1][y - 1] + put[x + 1][y + 1] - 8 * '0';
//必须是减8*‘ 0 ’,减去一个不行,因为是八个元素都要变成字符来储存,所有要减去八个字符‘ 0 ’,少的话雷的数量会无法显示,系统会打印出‘ ?’
                show[x][y] = c + '0';
                DisplayBoard(show);
//在玩家看到的show页面打印出雷信息
                a--;//用while循环进行判断雷是否排完
                if (a == 1)
                    printf("游戏胜利\n");
            }
        }
        else
        {
            printf("输入坐标错误,请重新输入\n");
        }
    }

}

综上扫雷游戏各个部分都已经写好,只需要进行整合即可。

3.将各个部分按顺序整理

最后上述所有代码归纳集合:

注意:该代码将所有代码放进一个源文件中,也可以将game()函数放进其他源文件,建一个game.h头文件来传数据,不过该方法在传数据时需要多传行和列,并在两个源文件中包含该头文件,也可以将所有include,define放进头文件,这样更方便看懂各个部分的代码,条理更清晰。

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2
//防止查雷时溢出

#define TNT 10


void menu()
{
    printf("**************************\n");
    printf("**********1.play**********\n");
    printf("**********0.exit**********\n");
    printf("**************************\n");
    printf("是否开始游戏\n");
    printf("请输入(1/0):");
}
void board_show(char board[ROWS][COLS], char set)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < ROWS; i++)
    {
        for (j = 0; j < COLS; j++)
        {
            board[i][j] = set;
        }
    }
}
void DisplayBoard(char board[ROWS][COLS])
//打印扫雷棋盘
{
    int i = 0;
    int j = 0;

    printf("******扫雷游戏******\n\n");

    for (i = 1; i <= ROW; i++)
    {
        for (j = 1; j <= COL; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
    printf("\n*******************\n\n");
}

void c_TNT(char board[ROWS][COLS])//产生雷
{
    int count = TNT;
    while (count)
//用for循环不好,有可能会出现雷在一个位置
    {
        int i = rand() % (TNT - 1) + 1;
        int j = rand() % (TNT - 1) + 1;
//创建雷位置
        if (board[i][j] == '0')
        {
            board[i][j] = '1';
            count--;
        }
    }
}

void Player_check(char put[ROWS][COLS], char show[ROWS][COLS])//玩家行动和检查周围雷数量
{
    //玩家输入坐标
    int x = 0;
    int y = 0;
    int a = ROW * COL - TNT;
    while (a > 0)
    {
        printf("玩家请输入坐标:");
        scanf("%d%d", &x, &y);
        if (x > 0 && x <= ROW && y>0 && y <= COL)
        {
            if (put[x][y] == '1')
            {
                printf("\n\n\n你被炸死,游戏结束\n\n\n");
                DisplayBoard(put);
                break;
            }
            else if (put[x][y] == '0')
            {
              
 //得出周围雷的信息
                char c = put[x - 1][y - 1] + put[x - 1][y] +
                    put[x - 1][y + 1] + put[x][y + 1] +
                    put[x][y - 1] + put[x + 1][y] +
                    put[x + 1][y - 1] + put[x + 1][y + 1] - 8 * '0';
//必须是减8*,减去一个数不行
                show[x][y] = c + '0';
                DisplayBoard(show);
                a--;
                if (a == 1)
                    printf("游戏胜利\n");
            }
        }
        else
        {
            printf("输入坐标错误,请重新输入\n");
        }
    }

}
void
game()//game()函数主体,以该函数的顺序进行代码
{

    //创建初始棋盘
    char put[ROWS][COLS] = { 0 };// 放置雷的信息
    char show[ROWS][COLS] = { 0 };//排查雷的信息,玩家看到的棋盘信息

    board_show(put,  '0');
    board_show(show,  '*');
  
 //放置雷
    c_TNT(put);
  
 //DisplayBoard(put, ROW, COL);不打印,可以在编写时打印看是否程序出问题
    DisplayBoard(show);
    //玩家行动
    Player_check(put, show);

}

int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));
//创建随机数,用于创建随机位置的雷
    do
    {
        menu();
//初始页面
        scanf("%d", &input);//选择进行游戏
        switch (input)
        {
        case 1:
            
game();
            break;
        case 0:
            printf("退出游戏,游戏结束\n");
            break;
        default:
            printf("输入错误,请重新输入\n");
        }
    } while (input);


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值