扫雷游戏 我用到了递归函数 循环语句 二维数组 自定义函数为核心
1.首先是游戏的进入菜单界面
代码部分(不做讲解)
void menu()//菜单部分
{
printf("*****************\n");
printf("******1.play*****\n");
printf("******0.exit*****\n");
printf("*****************\n");
}
和游戏进入主函数口
int main()
{
int play ;
do
{
menu();
scanf("%d", &play);
if (play == 1)
{
printf("游戏开始\n");
game();//引用外部函数 用的头文字是自己定义的
}
else if(play != 1&& play !=0)
{
printf("输入错误请重新输入\n");
}
} while (play);
printf("游戏结束\n");
return 0;
}
然后是基础参数的设置
2.然后是最基础的游戏内的代码设置 (我全部批注在代码中)
void game()
{
srand((unsigned int)time(NULL));//设置随机数的基础值
int x; int y; int z;
char arr[X][Y] = { 0 };//这个是开棋盘
char arr_1[X][Y] = { 0 };//这个是要生成雷的位置
Init_game_sc(arr,X,Y);//初始化外棋盘
Init_game_sc_l(arr_1, X, Y);//初始化内棋盘
printf(" 左上角第一个为1 1 第二个为 1 2\n");
game_qp(arr, X, Y);//打印棋盘
game_scqp(arr_1);//生成炸弹 生成炸弹周围的数字
do//基础设置结束后游戏内部的代码
{
printf("请输入你要打开的位置>>");
scanf("%d %d", &x, &y);
while (1)
{
x -= 1; y -= 1;
if (x >= X || x < 0 || y >= Y || y < 0)
{
printf("坐标输入错误请重新输入");
printf("请输入你要打开的位置>>");
scanf("%d %d", &x, &y);
}
else
{
break;
}
}
int cango = game_pd(arr_1,arr, x, y);//判断是否合法,可以合并到这里面
if (cango == 1)
{
game_kq(arr_1, arr, x, y);//打开棋盘内的空位置 并且变成0
}
else if (cango == -1)
{
printf("踩雷了,游戏失败");
game_qp(arr_1, X, Y);
break;
}
z = gameover(arr);//判断游戏是否结束
if (z == L)
{
printf("游戏胜利\n");
game_qp(arr_1, X, Y);
break;
}
game_qp(arr, X, Y);
} while (1);
//game_qp(arr,X,Y);
}
3.逐个功能代码分析
初始化棋盘
void Init_game_sc(char arr[X][Y],int x,int y)//初始化棋盘
{
int i = 0;
int j = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
arr[i][j] = '#';
}
}
}void Init_game_sc_l(char arr[X][Y], int x, int y)//初始化雷的棋盘
{
int i = 0;
int j = 0;
for (i = 0; i < x+1; i++)
{
for (j = 0; j < y; j++)
{
arr[i][j] = ' ';
}
}
}
我认为这里可以合并,可以进一步简化
打印棋盘
void game_qp(char arr[X][Y], int x, int y)//打印棋盘
{
printf("\n");
int i = 0; int j = 0; int z = 0;
printf(" ");
for (z = 0; z < x; z++)
{
printf("%2d ",z + 1);
printf(" ");
}
printf("\n");
printf(" ");
for (z = 0; z < x; z++)
{
printf("---");
printf(" ");
}
printf("\n");
for (i = 0; i < y; i++)
{
printf(" %2d",i + 1);
for (j = 0; j < x; j++)
{
printf(" | ", arr[i][j]);
printf("%c", arr[i][j]);
}
printf(" | ", arr[i][j]);
printf("\n");
printf(" ");
for (z = 0; z < x; z++)
{
printf("---");
printf(" ");
}
printf("\n");}
}
打印部分不做什么解释
判断是否合法
int game_pd(char arr_1[X][Y],char arr[X][Y], int x, int y)//是否合法
{
if (arr_1[x][y] != '*')
{
return 1;
}
else if (arr_1[x][y] == '*')
{
return -1;
}
}
这里的判断是否踩到雷了,踩到雷返回-1 没踩到雷返回1 这个可以合并到游戏主程序里
炸弹生成代码 和 周边数字生成代码
void game_scqp(char arr_1[X][Y])//集成炸弹生成 炸弹周围数字检测生成
{
for (int l = L;l > 0;l--)//炸弹生成 用的rand函数
{
int x = (rand() % X + 1);//0-9
int y = (rand() % Y + 1);//0-9
if(arr_1[x][y] != '*')
{
arr_1[x][y] = '*';
}
else
{
l += 1;
}
}
for (int i = 0; i < X; i++)//炸弹周围数字计数功能
{
for (int j = 0; j < Y; j++)
{if (arr_1[i][j] == '*')
{
continue;
}
else
{
int a;
int b;
int count = 0;
for (a = -1; a < 2; a++)
{
for (b = -1; b < 2; b++)
{
if (i + a < 0 || i + a >= X || j + b < 0 || j + b >= Y)
{
continue;
}
if (arr_1[i + a][j + b] == '*')
{
count++;
}
}
}
if (count != 0)
{
arr_1[i][j] = count + '0';
}
}
}
}
}
炸弹周围数字计数功能,我写的并不是最优解,但是我个人认为比较直观,先找到一个坐标 然后定义数字初始为0 然后以 3 * 3的方式挨个扫描周围 如果有雷 数字加一 几个雷加几个数 数完以后 把数字填写到这个坐标里(我个人认为写的比较麻烦,希望能有更优解)
判定是否胜利
int gameover(char arr[X][Y])
{
int count = 0; int i = 0; int j = 0;
for (i = 0; i < X; i++)
{
for (j = 0; j < Y; j++)
{
if (arr[i][j] == '#')
{
count++;
}
}
}
return count;
}
到最后没有扫的地方 是 # 那么当#的数量等于雷的数量就判断成功
这里返回#的数量给后面的程序判断
然后是打开空格
这里用到递归函数
我的思路就是以十字打开 然后在打开过的非数字的地方变成0 到有数字的地方停止
void game_kq(char arr_1[X][Y], char arr[X][Y], int x, int y)//开启棋盘 打开空棋盘位置
{
arr[x][y] = arr_1[x][y];
if (arr_1[x][y] != '0')
{
if(arr_1[x][y] == ' ')
arr_1[x][y] = '0';
if (x > 0)
{
if (arr_1[x - 1][y] == ' ')
{
game_kq(arr_1, arr, x - 1, y);
}
if (arr_1[x - 1][y] != ' ' && arr_1[x - 1][y] != '*')
{
arr[x - 1][y] = arr_1[x - 1][y];
}
}
if (x < X - 1)
{
if (arr_1[x + 1][y] == ' ')
{
game_kq(arr_1, arr, x + 1, y);
}
if (arr_1[x + 1][y] != ' ' && arr_1[x + 1][y] != '*')
{
arr[x + 1][y] = arr_1[x + 1][y];
}
}
if (y > 0)
{
if (arr_1[x][y - 1] == ' ')
{
game_kq(arr_1, arr, x, y - 1);
}
if (arr_1[x][y - 1] != ' ' && arr_1[x][y - 1] != '*')
{
arr[x][y - 1] = arr_1[x][y - 1];
}
}
if (y < Y - 1)
{
if (arr_1[x][y + 1] == ' ')
{
game_kq(arr_1, arr, x, y + 1);
}
if (arr_1[x][y + 1] != ' ' && arr_1[x][y + 1] != '*')
{
arr[x][y + 1] = arr_1[x][y + 1];
}
}
}
}
因为是十字 所以我写了四个方向的递归(希望有大佬可以给出简化版本,而且能让简化完之后给我的是空格而不是0)
以上是程序的各个部分
//全部函数程序
头文件
#pragma once
#include
#define X 10//长
#define Y 10//宽
#define L 1//雷的个数
void menu();
void game();
主函数
#define _CRT_SECURE_NO_WARNINGS
#include
#include "game.h"
int main()
{
int play ;
do
{
menu();
scanf("%d", &play);
if (play == 1)
{
printf("游戏开始\n");
game();
}
else if(play != 1&& play !=0)
{
printf("输入错误请重新输入\n");
}
} while (play);
printf("游戏结束\n");
return 0;
}
游戏函数
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
#include
#include
void menu()//菜单部分
{
printf("*****************\n");
printf("******1.play*****\n");
printf("******0.exit*****\n");
printf("*****************\n");
}void Init_game_sc(char arr[X][Y],int x,int y)//初始化棋盘
{
int i = 0;
int j = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
arr[i][j] = '#';
}
}
}void Init_game_sc_l(char arr[X][Y], int x, int y)//初始化雷的棋盘
{
int i = 0;
int j = 0;
for (i = 0; i < x+1; i++)
{
for (j = 0; j < y; j++)
{
arr[i][j] = ' ';
}
}
}void game_qp(char arr[X][Y], int x, int y)//打印棋盘
{
printf("\n");
int i = 0; int j = 0; int z = 0;
printf(" ");
for (z = 0; z < x; z++)
{
printf("%2d ",z + 1);
printf(" ");
}
printf("\n");
printf(" ");
for (z = 0; z < x; z++)
{
printf("---");
printf(" ");
}
printf("\n");
for (i = 0; i < y; i++)
{
printf(" %2d",i + 1);
for (j = 0; j < x; j++)
{
printf(" | ", arr[i][j]);
printf("%c", arr[i][j]);
}
printf(" | ", arr[i][j]);
printf("\n");
printf(" ");
for (z = 0; z < x; z++)
{
printf("---");
printf(" ");
}
printf("\n");}
}int game_pd(char arr_1[X][Y],char arr[X][Y], int x, int y)//是否合法
{
if (arr_1[x][y] != '*')
{
return 1;
}
else if (arr_1[x][y] == '*')
{
return -1;
}
}void game_kq(char arr_1[X][Y], char arr[X][Y], int x, int y)//开启棋盘 打开空棋盘位置
{
arr[x][y] = arr_1[x][y];
if (arr_1[x][y] != '0')
{
if(arr_1[x][y] == ' ')
arr_1[x][y] = '0';
if (x > 0)
{
if (arr_1[x - 1][y] == ' ')
{
game_kq(arr_1, arr, x - 1, y);
}
if (arr_1[x - 1][y] != ' ' && arr_1[x - 1][y] != '*')
{
arr[x - 1][y] = arr_1[x - 1][y];
}
}
if (x < X - 1)
{
if (arr_1[x + 1][y] == ' ')
{
game_kq(arr_1, arr, x + 1, y);
}
if (arr_1[x + 1][y] != ' ' && arr_1[x + 1][y] != '*')
{
arr[x + 1][y] = arr_1[x + 1][y];
}
}
if (y > 0)
{
if (arr_1[x][y - 1] == ' ')
{
game_kq(arr_1, arr, x, y - 1);
}
if (arr_1[x][y - 1] != ' ' && arr_1[x][y - 1] != '*')
{
arr[x][y - 1] = arr_1[x][y - 1];
}
}
if (y < Y - 1)
{
if (arr_1[x][y + 1] == ' ')
{
game_kq(arr_1, arr, x, y + 1);
}
if (arr_1[x][y + 1] != ' ' && arr_1[x][y + 1] != '*')
{
arr[x][y + 1] = arr_1[x][y + 1];
}
}
}
}void game_scqp(char arr_1[X][Y])//集成炸弹生成 炸弹周围数字检测生成
{
for (int l = L;l > 0;l--)//炸弹生成
{
int x = (rand() % X + 1);//0-9
int y = (rand() % Y + 1);//0-9
if(arr_1[x][y] != '*')
{
arr_1[x][y] = '*';
}
else
{
l += 1;
}
}
for (int i = 0; i < X; i++)
{
for (int j = 0; j < Y; j++)
{if (arr_1[i][j] == '*')
{
continue;
}
else
{
int a;
int b;
int count = 0;
for (a = -1; a < 2; a++)
{
for (b = -1; b < 2; b++)
{
if (i + a < 0 || i + a >= X || j + b < 0 || j + b >= Y)
{
continue;
}
if (arr_1[i + a][j + b] == '*')
{
count++;
}
}
}
if (count != 0)
{
arr_1[i][j] = count + '0';
}
}
}
}
}int gameover(char arr[X][Y])
{
int count = 0; int i = 0; int j = 0;
for (i = 0; i < X; i++)
{
for (j = 0; j < Y; j++)
{
if (arr[i][j] == '#')
{
count++;
}
}
}
return count;
}void game()
{
srand((unsigned int)time(NULL));//设置随机数的基础值
int x; int y; int z;
char arr[X][Y] = { 0 };//这个是开棋盘
char arr_1[X][Y] = { 0 };//这个是要生成雷的位置
Init_game_sc(arr,X,Y);//初始化外棋盘
Init_game_sc_l(arr_1, X, Y);//初始化内棋盘
printf(" 左上角第一个为1 1 第二个为 1 2\n");
game_qp(arr, X, Y);//打印棋盘
game_scqp(arr_1);//生成炸弹 生成炸弹周围的数字
do//基础设置结束后游戏内部的代码
{
printf("请输入你要打开的位置>>");
scanf("%d %d", &x, &y);
while (1)
{
x -= 1; y -= 1;
if (x >= X || x < 0 || y >= Y || y < 0)
{
printf("坐标输入错误请重新输入");
printf("请输入你要打开的位置>>");
scanf("%d %d", &x, &y);
}
else
{
break;
}
}
int cango = game_pd(arr_1,arr, x, y);//判断是否合法,可以合并到这里面
if (cango == 1)
{
game_kq(arr_1, arr, x, y);//打开棋盘内的空位置 并且变成0
}
else if (cango == -1)
{
printf("踩雷了,游戏失败");
game_qp(arr_1, X, Y);
break;
}
z = gameover(arr);//判断游戏是否结束
if (z == L)
{
printf("游戏胜利\n");
game_qp(arr_1, X, Y);
break;
}
game_qp(arr, X, Y);
} while (1);
//game_qp(arr,X,Y);
}
后言,我的代码并不是最简化,按照直接的思路来写,希望大家能指出不好的地方,分享好的部分给我学习。