亲宝软件园·资讯

展开

C语言扫雷小游戏

Monster_ii 人气:0

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

加载全部内容

相关教程
猜你喜欢
用户评论