使用C来实现扫雷小游戏

实现扫雷的基本流程

  • 生成棋盘
  • 初始化棋盘
  • 设置地雷数量
  • 显示最终展示的棋盘
  • 开始游戏
  • 输入坐标
  • 判断各种情况:1.输入坐标是否合法。2.是否输入了之前已经排过的雷区 等等
  • 避免第一次直接踩到雷的解决方法
  • 展开一片无雷区域
  • 判断扫雷是否输赢

头文件lei.h

这里面写了实现扫雷各种操作的方法。

#ifndef __LEI_H__
#define __LEI_H__
#include<stdio.h>
#include<stdlib.h>
#define ROW 12//底层面板12行12列,雷区为10*10,最外面的一圈是为了考虑雷区面板的边界情况
#define COL 12
#define MINES 10//设置了10个雷

void InitBoard(char show[ROW][COL], char mine[ROW][COL]);//初始化面板
void Display(char show[ROW][COL], char mine[ROW][COL]);//显示雷区面板或者游戏面板
void SetMine(char show[ROW][COL]);//设置地雷数量,随机设置
int MineNum(char mine[ROW][COL], int a, int b);//统计周围的地雷数目
void Start(char show[ROW][COL], char mine[ROW][COL]);//开始扫雷
void Firstblood(char show[ROW][COL], char mine[ROW][COL], int i, int j);//避免第一次被炸死
void Expand(char show[ROW][COL], char mine[ROW][COL],int x,int y);//展开一片连续无雷区,并在显示雷数
int Iswin(char show[ROW][COL]);//判断游戏输赢
void game(char show[ROW][COL], char mine[ROW][COL]);//游戏函数
#endif

lei.c文件

具体实现扫雷各个操作的步骤:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include"lei.h"
//初始化
void InitBoard(char show[ROW][COL], char mine[ROW][COL])
{
    int i = 0;
    int j = 0;
    for (i = 0; i < ROW; i++)
    {
        for (j = 0; j < COL; j++)
        {
            mine[i][j] = '0';//将雷区面板的所有元素用字符0来表示,表示没有地雷
            show[i][j] = '*'; //将展示面板的所有元素用字符*来表示,表示还没有点击此区域
        }
    }
}
//打印雷区面板或者游戏面板
void Display(char show[ROW][COL])
{
    int i = 0;
    int j = 0;
    for (i = 1; i < ROW - 1; i++)
    {
        printf("----------------------------------------\n");
        for (j = 1; j < COL - 1; j++)
        {
            printf("%3c|", show[i][j]);
        }
        printf("\n");
    }
    printf("----------------------------------------\n");
}
//使用随机方法来设置地雷,地雷应该设置在里面白色区域
void SetMine(char mine[ROW][COL])
{
    srand((unsigned)time(NULL));
    int mines = MINES;
    while (mines > 0)
    {
        int i = rand() % (ROW - 2) + 1;//1-10
        int j = rand() % (COL - 2) + 1;//1-10
        if (mine[i][j] != '+')
        {
            mine[i][j] = '+';
            mines--;
        }
    }
}

这里写图片描述

//计算一个坐标周围的地雷总数
int MineNum(char mine[ROW][COL], int a, int b)
{
    int sum = 0;
    if (mine[a - 1][b] == '+') { sum++; }
    if (mine[a - 1][b - 1] == '+') { sum++; }
    if (mine[a - 1][b + 1] == '+') { sum++; }
    if (mine[a][b - 1] == '+') { sum++; }
    if (mine[a][b + 1] == '+') { sum++; }
    if (mine[a + 1][b] == '+') { sum++; }
    if (mine[a + 1][b - 1] == '+') { sum++; }
    if (mine[a + 1][b + 1] == '+') { sum++; }
    return sum;
}
//避免第一次就踩到地雷
void Firstblood(char show[ROW][COL], char mine[ROW][COL],int i,int j)
{
    int a = 0;
    int b = 0;
    if (mine[i][j] == '+')//如果第一次踩到雷
    {
        do
        {
            //再随机生成一个坐标
            int a = rand() % (ROW - 2) + 1;
            int b = rand() % (COL - 2) + 1;
            if (mine[a][b] != '+')//如果新生成的坐标位置,原来没有地雷
            {
                mine[a][b] = '+';//那么就可以在此位置设一个地雷
                mine[i][j] = '0';//把之前的那个雷去掉,变成无雷
                break;//跳出循环即可
            }
        } while (1);
    }
}
//展开一片无雷区的方法
void Expand(char show[ROW][COL], char mine[ROW][COL],int x,int y)
{
    int leisum = 0;
    leisum = MineNum(mine, x, y);//先计算一个坐标周围的雷数
    show[x][y] = '0' + leisum;//游戏面板显示那个坐标的雷数
    if (show[x][y] == '0')//如果一个坐标周围没有地雷,进入判断
    {
    //在上面条件满足情况下,如果输入坐标的周围八个区域没有雷,并且坐标还没有被排过雷,就进行展开,并计算显示雷数
        if (x - 1 >= 1 && x - 1 <= 10 && y - 1 >= 1 && y - 1 <= 10 && show[x - 1][y - 1] == '*')
            Expand(show, mine, x - 1, y - 1);
        if (x - 1 >= 1 && x - 1 <= 10 && y >= 1 && y <= 10 && show[x - 1][y] == '*')
            Expand(show, mine, x - 1, y);
        if (x - 1 >= 1 && x - 1 <= 10 && y + 1 >= 1 && y + 1 <= 10 && show[x - 1][y + 1] == '*')
            Expand(show, mine, x - 1, y + 1);
        if (x >= 1 && x <= 10 && y - 1 >= 1 && y - 1 <= 10 && show[x][y - 1] == '*')
            Expand(show, mine, x, y - 1);
        if (x >= 1 && x <= 10 && y + 1 >= 1 && y + 1 <= 10 && show[x][y + 1] == '*')
            Expand(show, mine, x, y + 1);
        if (x + 1 >= 1 && x + 1 <= 10 && y - 1 >= 1 && y - 1 <= 10 && show[x + 1][y - 1] == '*')
            Expand(show, mine, x + 1, y - 1);
        if (x + 1 >= 1 && x + 1 <= 10 && y >= 1 && y <= 10 && show[x + 1][y] == '*')
            Expand(show, mine, x + 1, y);
        if (x + 1 >= 1 && x + 1 <= 10 && y + 1 >= 1 && y + 1 <= 10 && show[x + 1][y + 1] == '*')
            Expand(show, mine, x + 1, y + 1);
    }
}
//判断输赢
int Iswin(char show[ROW][COL])
{
    int i = 0;
    int j = 0;
    int sum = 0;
    //统计游戏棋盘中*的个数
    for (i = 1; i < ROW - 1; i++)
    {
        for (j = 1; j < COL - 1; j++)
        {
            if (show[i][j] == '*')
            {
                sum++;
            }
        }
    }
    if (sum == 10)//如果*剩下10个,说明剩下的都是地雷
    {
        return 1;
    }
    return 0;
}
//扫雷流程
void Start(char show[ROW][COL], char mine[ROW][COL])
{
    int a = 0;
    int b = 0;
    int i = 1;
    while (1)
    {
    //这个死循环是为了判断是否输入了排过雷的坐标
        for (;;)
        {
            printf("请输入坐标:");
            scanf("%d%d", &a, &b);
            if (show[a][b] != '*')
            {
                printf("您已经排查过这里的地雷!\n");
            }
            else
                break;
        }

        if (i == 1)//防止第一输入踩到雷
        {
            Firstblood(show, mine, a, b);
        }
        i++;

        int mines = MineNum(mine, a, b);//计算周围雷数

        if (mine[a][b] == '+')//如果猜到了地雷,游戏结束
        {
            printf("loose\n");
            break;
        }
        else if (mine[a][b] == '0')//如果不是雷,则显示周围雷的数量
        {
            show[a][b] = '0' + mines;
        }

        Expand(show, mine, a, b);//然后展开周围无雷区域
        Display(show);//到此,可以展示给玩家现在的游戏棋盘
        Iswin(show);//判断输赢
        if (Iswin(show) == 1)
        {
            printf("win\n");
            break;
        }
    }

}
//总游戏函数
void game(char show[ROW][COL], char mine[ROW][COL])
{
    InitBoard(show, mine);
    SetMine(mine);
    Display(mine);
    Display(show);
    Start(show, mine);
}

主函数文件 main.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include"lei.h"
#define ROW 12
#define COL 12

int menu()
{
    int sele = 0;
    printf("---------------------\n");
    printf("------1.开始游戏-----\n");
    printf("------0.退出游戏-----\n");
    printf("---------------------\n");
    printf("请输入菜单号码:>");
    scanf("%d", &sele);
    return sele;
}

int main()
{
    char mine[ROW][COL] = { '0' };
    char show[ROW][COL] = { '0' };
    int choose = 0;
    do
    {
        choose = menu();
        switch (choose)
        {
        case 1:
            game(show, mine);
            break;
        case0:
            break;
        default:
            break;
        }
    } while (choose);
}

地雷面板
可以展开无雷区域

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值