1.前言:
本文是最基础的扫雷,排雷通过递归实现,这是原版游戏的链接扫雷基础版。本文尝试对基础版进行简单复刻。
2.代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define se second
#define fi first
#define endl '\n'
#define rep(i, a, b) for (int i=a;i<b;++i)
#define per(i, a, b) for (register int i=a;i>b;--i)
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const ll MOD = 998244353;
const int N = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int a[11][11];
int b[11][11];
int c[8]={-1,-1,-1,0,1,1,1,0};
int d[8]={-1,0,1,1,1,0,-1,-1};
int vis[11][11];
int m,n;
void init_menu()
{
printf("*******************\n");
printf("**** 1.play ****\n");
printf("**** 0.exit ****\n");
printf("*******************\n");
printf("请输入数字确定是否进入游戏\n");
}
void init_mine()
{ rep(i,0,10)
{
int x=rand()%9+1,y=rand()%9+1;
if(!a[x][y])
{
a[x][y]=1;
}
else i--;
}
}
void game_menu()
{
printf(" ");
rep(i,1,10)
printf("%d ",i);
printf("\n");
rep(i,1,10) {
printf("%d ", i);
rep(j, 1, 10) {
switch (b[i][j]) {
case -1:
printf(" ");
break;
case 0:
printf(" *");
break;
}
if (b[i][j] > 0)
printf(" %d", b[i][j]);
}
printf("\n");
}
}
int cnt=0;
void solve(int x,int y)
{
if(x<1||x>9||y<1||y>9) return;//出界
rep(i,0,8)
{
if(a[x+c[i]][y+d[i]])
cnt++;
}
if(cnt==0)
b[x][y]=-1;//这些是设置输出格式,方便game_menu调用
else b[x][y]=cnt;
cnt=0;
if(b[x][y]>0)
return ;
rep(i,0,8)
{
if(!b[x+c[i]][y+d[i]])
solve(x+c[i],y+d[i]);
}
}
void input()
{
while(1)
{
scanf("%d%d",&m,&n);
if(m>0&&n<10&&m>0&&n<10&&b[m][n]!=-1)
break;
else printf("坐标非法,请重新输入\n");
}
}
bool is_win()
{
int count=0;
rep(i,1,10)
{
rep(j,1,10)
{
if(b[m][n])
count++;
}
}
if(count==80)
return true;
return false;
}
void debug_menu()
{
printf("\n");
printf(" ");
rep(i,1,10)
printf("%d ",i);
printf("\n");
rep(i,1,10) {
printf("%d ", i);
rep(j, 1, 10) {
printf("%d ",a[i][j]);
}
printf("\n");
}
}
void game()
{
init_mine();
game_menu();
debug_menu();
while(1)
{
printf("请输入扫雷坐标\n");
input();
if(a[m][n])
{
printf("你被炸死了\n");
return ;
}
solve(m,n);
game_menu();
if(is_win())
{
printf("恭喜你,挑战成功!\n");
return;
}
}
}
int main() {
int choose = 1;
srand((uint) time(NULL));
while (choose) {
init_menu();
scanf("%d", &choose);
if (choose == 1) {
game();
} else if (choose != 0) {
printf("输入数字错误,请重新输入\n");
}
}
printf("游戏结束\n");
return 0;
}
3.代码逻辑讲解:
1.总体游戏思路:
a数组埋雷,b数组通过game_menu函数显示游戏画面,通过solve函数进行递归排雷。
2.内部各函数讲解:
1.init_menu函数:
显示开始界面
void init_menu()
{
printf("*******************\n");
printf("**** 1.play ****\n");
printf("**** 0.exit ****\n");
printf("*******************\n");
printf("请输入数字确定是否进入游戏\n");
}
2.init_menu函数:
通过srand((unsigned int) time(NULL))函数开始随机,通过rand函数随机坐标并埋雷。
void init_mine()
{ rep(i,0,10)
{
int x=rand()%9+1,y=rand()%9+1;
if(!a[x][y])
{
a[x][y]=1;
}
else i--;
}
}
3.game_menu函数:
通过b数组的改变改变游戏显示画面,如果未排则显示为'*',如果排过无雷显示‘ ’,如果有雷显示雷数量。
void game_menu()
{
printf(" ");
rep(i,1,10)
printf("%d ",i);
printf("\n");
rep(i,1,10) {
printf("%d ", i);
rep(j, 1, 10) {
switch (b[i][j]) {
case -1:
printf(" ");
break;
case 0:
printf(" *");
break;
}
if (b[i][j] > 0)
printf(" %d", b[i][j]);
}
printf("\n");
}
}
4.solve函数:
通过slove函数的递归,判断是否有雷得到cnt,cnt改变b数组,b数组判断是否返回。
int cnt=0;
void solve(int x,int y)
{
if(x<1||x>9||y<1||y>9) return;//出界
rep(i,0,8)
{
if(a[x+c[i]][y+d[i]])
cnt++;
}
if(cnt==0)
b[x][y]=-1;//这些是设置输出格式,方便game_menu调用
else b[x][y]=cnt;
cnt=0;
if(b[x][y]>0)
return ;
rep(i,0,8)
{
if(!b[x+c[i]][y+d[i]])
solve(x+c[i],y+d[i]);
}
}
5.input函数:
输入坐标并做判断。
void input()
{
while(1)
{
scanf("%d%d",&m,&n);
if(m>0&&n<10&&m>0&&n<10&&b[m][n]!=-1)
break;
else printf("坐标非法,请重新输入\n");
}
}
6.is_win函数:
判断游戏是否胜利
bool is_win()
{
int count=0;
rep(i,1,10)
{
rep(j,1,10)
{
if(b[m][n])
count++;
}
}
if(count==80)
return true;
return false;
}
7.debug_menu函数:
直接告诉你雷在哪,debug时使用。
void debug_menu()
{
printf("\n");
printf(" ");
rep(i,1,10)
printf("%d ",i);
printf("\n");
rep(i,1,10) {
printf("%d ", i);
rep(j, 1, 10) {
printf("%d ",a[i][j]);
}
printf("\n");
}
}
8.game函数:
游戏主体封装函数
void game()
{
init_mine();
game_menu();
debug_menu();
while(1)
{
printf("请输入扫雷坐标\n");
input();
if(a[m][n])
{
printf("你被炸死了\n");
return ;
}
solve(m,n);
game_menu();
if(is_win())
{
printf("恭喜你,挑战成功!\n");
return;
}
}
}
4.总结:
除了solve函数具有部分算法知识,其他主要还是以模拟为主,比较锻炼人的逻辑能力。