C语言实现简易的扫雷小游戏

 更新时间:2022年05月07日 13:21:34   作者:Monster_ii  
这篇文章主要为大家详细介绍了C语言实现简易的扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

这是一个用C语言实现的控制台扫雷小游戏,实现了随机布置炸弹、扫描炸弹、标记炸弹、百分百第一次不被炸死等功能。

编译器:vs2015

功能模块图

源代码

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

void show(int cbd[10][10],int u[10][10])  //界面输出函数
{
    int i, j;
    //for (i = 0; i < 10; i++)  //输出全部炸弹信息(上帝视角,调试用)
    //{
    //  for (j = 0; j < 10; j++)
    //  {
    //      printf("%2d ", cbd[i][j]);
    //  }
    //  printf("\n");
    //}
    printf("     1 2 3 4 5 6 7 8 9 10\n"); //行标
    printf("    --------------------\n");
    for (i = 0; i<10; i++)  //根据u数组和cbd数组的值选择输出
    {            //■:未扫描,□:周围无炸弹,◇:炸弹标记
        for (j = 0; j<10; j++)
        {
            if (j == 0)printf("%2d║ ", i+1);
            if (u[i][j] == 0)printf("■");
            else if (u[i][j] == 1)
            {
                if (cbd[i][j] == 0)printf("□");
                else printf("%2d", cbd[i][j]);
            }
            else if (u[i][j] == -1) 
            {
                printf("◇");
            }
        }
        printf("\n");
    }
}

int find(int cbd[10][10], int i, int j)  //扫描周围炸弹数目
{
    int l, c,lmin,cmin, lmax, cmax, num = 0;
    l = lmin = (i - 1) >= 0 ? (i - 1) : 0;  //计算行、列起点
    c = cmin = (j - 1) >= 0 ? (j - 1) : 0;
    lmax = ((i + 1) < 10 ? (i + 1) : 9);  //计算行、列终点
    cmax = ((j + 1) < 10 ? (j + 1) : 9);

    for (l = lmin; l <= lmax; l++)
    {
        for (c = cmin; c <= cmax; c++)
        {
            if (l == i&&c == j)continue;  //跳过自身
            if (cbd[l][c] == -1)num++;  //炸弹计数
        }
    }
    return num;
}

void init(int cbd[10][10])   //cbd数组初始化(随机布置炸弹并填充各个格子的数目)
{
    int n = 10, l, c, i, j;
    srand(time(NULL));    //随机数种子设置
    for (i = 0; i< 10; i++)
    {
        for (j = 0; j< 10; j++)
        {
            cbd[i][j] = 0;  //全0填充
        }
    }
    while (n--)   //随机行列放置炸弹
    {
        l = rand() % 10;
        c = rand() % 10;
        if (cbd[l][c] != -1)cbd[l][c] = -1;   //炸弹重复处理
        else n++;
    }
    for (i = 0; i< 10; i++)
    {
        for (j = 0; j< 10; j++)
        {
            if (cbd[i][j] != -1)
            {
                cbd[i][j] = find(cbd, i, j); //炸弹数目填充
            }
        }
    }
}

void open(int cbd[10][10],int u[10][10], int i, int j)  //周围无炸弹时的展开函数(递归展开)
{
    u[i][j] = 1;
    if (cbd[i][j] == 0)
    {
        if(i - 1 >= 0 && u[i - 1][j] != 1)open(cbd, u, i - 1, j);   //上
        if(j - 1 >= 0 && u[i][j - 1] != 1)open(cbd, u, i, j - 1);   //左
        if (i + 1 <= 9 && u[i + 1][j] != 1)open(cbd, u, i + 1, j);  //下
        if (j + 1 <= 9 && u[i][j + 1] != 1)open(cbd, u, i, j + 1);  //右
    }
}

int judge(int u[10][10]) //判断游戏是否通关
{
    int i, j, num = 0;
    for (i = 0; i < 10; i++)
    {
        for (j = 0; j < 10; j++)
        {
            if (u[i][j] == 0 || u[i][j] == -1)num++;
        }
    }
    if (num == 10)return 1;
    else return 0;
}

void fail(int cbd[10][10], int u[10][10])  //游戏失败函数
{
    int i, j;
    for (i = 0; i < 10; i++)   //输出全部炸弹信息
    {
        for (j = 0; j < 10; j++)
        {
            if (cbd[i][j] == 0)printf("  ");
            else if (cbd[i][j] != -1)printf("%2d", cbd[i][j]); 
            else printf("●");
        }
        printf("\n");
    }
    printf("请大侠重新来过~\n");
}

void menu(int cbd[10][10],int u[10][10])  //菜单函数
{
    int chs,i,j;
    int boom = 10;  //剩余炸弹数
    int num = 0;   //步数
    while (1)                                   
    {
        system("cls");
        show(cbd,u);
        printf("还有%d个炸弹\n",boom);
        printf("1.扫描    2.标记    3.取消标记\n");
        printf("请输入选项:>");
        scanf("%d", &chs);
        if (chs > 3 || chs < 1) {
            printf("请输入正确选项!\n");
            system("pause");
            continue;
        }
        printf("请输入坐标:>");
        scanf("%d %d", &i, &j);
        if (i < 1 || i>10)
        {
            printf("请输入正确坐标!\n");
            system("pause");
            continue;
        }
        i--;  //输入行列数处理(适用数组下标)
        j--;
        if (chs == 1)
        {
            if (cbd[i][j] == -1) {
                if (num == 0) { //若第一步扫描到炸弹,就重新初始化棋盘
                    init(cbd);
                    show(cbd, u);
                    open(cbd, u, i, j);
                    num++;
                    continue;
                }
                else
                {
                    fail(cbd, u);  //否则游戏失败,循环跳出
                    break;
                }
            }
            if (u[i][j] == 1)  //重复扫描时的处理
            {
                printf("该位置已经扫描过了!\n");
                system("pause");
                continue;
            }
            open(cbd, u, i, j);
            num++;
        }
        else if(chs == 2)
        {
            if (u[i][j] == 1) {
                printf("该位置已经扫描过了!\n"); //只能标记未扫描到的
                system("pause");
                continue;
            }
            u[i][j] = -1;
            boom --;            
        }
        else if (chs == 3)
        {
            if (u[i][j] != -1) {
                printf("该位置没有标记!\n"); //只能取消标记过的
                system("pause");
                continue;
            }
            u[i][j] = 0;
            boom++;
        }
        if (judge(u))  //判断游戏是否通关
        {
            printf("Old Fe 666!\n"); //老铁666!,循环跳出
            break;
        }
    }
}

int main()
{
    int cbd[10][10] = { 0 }; //保存炸弹信息的二维数组
    int u[10][10] = { 0 };  //保存是否翻开信息的二维数组
    init(cbd);   //数组初始化
    menu(cbd, u);  //进入菜单
    return 0;
}

Tips:在扫描到周围无炸弹的格子时,要将此格子周围的部分依次打开,直到上下左右都出现炸弹数字为止,这里要用到递归的方法,我的顺序为依次递归处理上、左、下、右的格子,这里顺序可以任意。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 基于一个简单定长内存池的实现方法详解

    基于一个简单定长内存池的实现方法详解

    本篇文章对一个简单定长内存池的实现方法进行了详细的分析介绍。需要的朋友参考下
    2013-05-05
  • C++ LeetCode1832题解判断句子是否为全字母句

    C++ LeetCode1832题解判断句子是否为全字母句

    这篇文章主要为大家介绍了C++ LeetCode1832题解判断句子是否为全字母句示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 浅析结束程序函数exit, _exit,atexit的区别

    浅析结束程序函数exit, _exit,atexit的区别

    在一个程序中最多可以用atexit()注册32个处理函数,这些处理函数的调用顺序与其注册的顺序相反,也即最先注册的最后调用,最后注册的最先调用
    2013-09-09
  • C++中图片类型的识别与转换详解方法

    C++中图片类型的识别与转换详解方法

    本文简单的介绍一下C++语言中如何识别图片文件的类型,以及各图片类型之间的转换方法,并提供相关的源码供大家参考,感兴趣的朋友快来看看吧
    2021-11-11
  • C语言数据结构与算法之单链表

    C语言数据结构与算法之单链表

    单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。本文将为大家介绍C语言中单链表的基本概念与读取数据元素,需要的可以参考一下
    2021-12-12
  • 深入C++浮点数无效值定义与判定的解决办法

    深入C++浮点数无效值定义与判定的解决办法

    本篇文章是对C++中浮点数无效值定义与判定进行了介绍,需要的朋友参考下
    2013-05-05
  • C语言将数组中元素的数排序输出的相关问题解决

    C语言将数组中元素的数排序输出的相关问题解决

    这篇文章主要介绍了C语言将数组中元素的数排序输出的相关问题解决,文中的题目是将元素连接起来排成一个数并要求出这类结果中数最小的一个,需要的朋友可以参考下
    2016-03-03
  • 详谈C语言指针

    详谈C语言指针

    这篇文章主要介绍了C语言的指针,介绍了其相关概念,然后分享了几种用法,具有一定参考价值。需要的朋友可以了解下
    2021-10-10
  • C语言实现简单的<三子棋>案例

    C语言实现简单的<三子棋>案例

    这篇文章主要介绍了C语言实现简单的《三子棋》,本文通过功能区分一步步实现该案例,通过逐步的解析和代码列举,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言调用摄像头生成avi视频程序

    C语言调用摄像头生成avi视频程序

    这篇文章主要为大家详细介绍了C语言如何调用摄像头生成avi视频程序,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2023-11-11

最新评论