使用C来实现扫雷小游戏
程序员文章站
2024-03-18 12:17:28
...
实现扫雷的基本流程
- 生成棋盘
- 初始化棋盘
- 设置地雷数量
- 显示最终展示的棋盘
- 开始游戏
- 输入坐标
- 判断各种情况: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);
}
上一篇: 扫雷游戏的简单实现
下一篇: Python基础——异常处理