C语言实现简单扫雷游戏
作者:互联网
基本思路:
- 创建一个布置雷的数组,和一个展示雷附近雷数的数组
随机数方式布置雷
输入数组坐标来进行扫雷,是雷则游戏结束,不是则在这个坐标显示附近雷的个数
循环直至游戏结
关键:
- 扫雷为9*9的方阵,但是要将实际雷的数组定义为11*11的二维数组,以便对一个坐标附近雷数进行计算
- 布雷、扫雷和打印都只是对11*11中间的那9*9数组进行操作
首先是先创建game.c,test.c两个源文件和自定义头文件game.h,游戏函数写在game.c里,在test.c中实现整体游戏逻辑
主体函数如下
数组初始化
传入arr字符数组,行列分别为rows和cols,初始化值为‘set’
void init_game(char arr[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
打印
这里打印的是整体游戏界面,包含数组的参考坐标和扫雷区:
传入的数组为11*11的数组,此函数只打印其中间的9*9元素
void display(char arr[ROWS][COLS], int row, int col)
{
printf("------SEEKMINE------\n");
for (int i = 0; i <= row; i++) //打印参考列
{
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++) //打印扫雷界面
{
printf("%d ", i); //打印参考行
for (int j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]); //打印11*11数组中间的9*9数组
}
printf("\n");
}
printf("------SEEKMINE------\n");
}
随机布雷
注意在使用rand函数前要在主函数中调用srand函数
这里传入的参数是mine[ROWS][COLS]数组,一个定义为11*11的字符数组,布雷函数将雷随机布置在此数组中间的9*9元素中
//设置n个雷
void set_mine(char arr[ROWS][COLS], int row, int col,int n) //传入为11*11的数组,但是雷要赋给其中间的9*9数组
{
for (int i = 0; i < n; i++) //循环次数为n
{
int x = 0, y = 0;
do
{
x = rand() % row; //生成0-8的随机数
y = rand() % col;
} while (arr[x + 1][y + 1] != '0'); //判断此坐标是否有雷,有则再次随机取坐标
arr[x+1][y+1] = '1'; //将雷赋值为‘1’
}
}
判断周围雷数
因为在初始化时mine数组中的值为‘0’,布雷时雷的值为‘1’,所以‘1’-‘0’的ASCII码值为1,所以可以将传入的数组坐标其周围8个数组的元素读出来,再相加,减去8*‘0’,即可得到此坐标周围8个坐标中的雷数,再将此数作为返回值返回
这里就体现出了将雷区数组设置为11*11的好处了,再其中间的9*9数组中,无论哪一个元素的周围都会有8个元素,都可以实现此函数的判断且不会越界
//判断周围雷数
int get_mine(char arr[ROWS][COLS],int x,int y)
{
return arr[x - 1][y - 1] + //读取周围8个格子中的数组元素,减‘0’得到雷的个数
arr[x - 1][y] +
arr[x - 1][y + 1] +
arr[x][y - 1] +
arr[x][y + 1] +
arr[x + 1][y - 1] +
arr[x + 1][y] +
arr[x + 1][y + 1] - 8 * '0';
}
扫雷
此函数传入了两个数组,一个是mine数组,一个时show数组,mine数组里储存了已经布置好的雷的信息,show是用于打印展示的数组,输入坐标,判断mine数组在此坐标没有雷后,调用get_mine函数得到附近雷数,将此值赋值给show数组
int find_mine(char arr1[ROWS][COLS],char arr2[ROWS][COLS],int row,int col)
{
int x = 0, y = 0;
int count = 0;
while (count < row * col - EASYMINE) //判断扫雷是否结束
{
printf("请输入扫雷坐标:");
scanf("%d %d", &x, &y); //x,y为1~9的数
if (arr1[x][y] == '1') //是雷
{
printf("你被炸死了\n");
display(arr1, ROW, COL);
return -1;
}
else if (arr1[x][y] == '0') //不是雷
{
count++; //计数加一
if (get_mine(arr1, x, y) > 0) //如果附近雷数不为0
{
arr2[x][y] = '0' + get_mine(arr1, x, y); //将附近雷数赋给show数组,因为数字的ASCII码值是递增的,所以+n就可以表示对应数字了
}
else arr2[x][y] = ' '; //如果附近雷数为0,则赋值为空格
}
else
{
printf("错误,请重新输入:\n");
}
display(arr2, ROW, COL);
}
if (count == row * col - EASYMINE)
{
printf("扫雷成功\n");
}
return 0;
}
完整代码:
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 9
#define COL 9
#define ROWS 11
#define COLS 11
#define EASYMINE 10 //雷数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
void init_game(char arr[ROWS][COLS], int row, int col, char set);
void display(char arr[ROWS][COLS], int row, int col);
void set_mine(char arr[ROWS][COLS], int row, int col, int n);
void show_mine(char arr[ROWS][COLS], int rows, int cols);
int find_mine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化
void init_game(char arr[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
//打印
void display(char arr[ROWS][COLS], int row, int col)
{
printf("------SEEKMINE------\n");
for (int i = 0; i <= row; i++) //打印参考列
{
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++) //打印扫雷界面
{
printf("%d ", i); //打印参考行
for (int j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]); //打印11*11数组中间的9*9数组
}
printf("\n");
}
printf("------SEEKMINE------\n");
}
//测试函数,用于检查雷是否布置成功
void show_mine(char arr[ROWS][COLS], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
//设置n个雷
void set_mine(char arr[ROWS][COLS], int row, int col,int n) //传入为11*11的数组,但是雷要赋给其中间的9*9数组
{
for (int i = 0; i < n; i++) //循环次数为n
{
int x = 0, y = 0;
do
{
x = rand() % row; //生成0-8的随机数
y = rand() % col;
} while (arr[x + 1][y + 1] != '0'); //判断此坐标是否有雷,有则再次随机取坐标
arr[x+1][y+1] = '1'; //将雷赋值为‘1’
}
}
//判断周围雷数
int get_mine(char arr[ROWS][COLS],int x,int y)
{
return arr[x - 1][y - 1] + //读取周围8个格子中的数组元素,减‘0’得到雷的个数
arr[x - 1][y] +
arr[x - 1][y + 1] +
arr[x][y - 1] +
arr[x][y + 1] +
arr[x + 1][y - 1] +
arr[x + 1][y] +
arr[x + 1][y + 1] - 8 * '0';
}
//扫雷
int find_mine(char arr1[ROWS][COLS],char arr2[ROWS][COLS],int row,int col)
{
int x = 0, y = 0;
int count = 0;
while (count < row * col - EASYMINE)
{
printf("请输入扫雷坐标:");
scanf("%d %d", &x, &y); //x,y为1~9的数
if (arr1[x][y] == '1') //是雷
{
printf("你被炸死了\n");
display(arr1, ROW, COL);
return -1;
}
else if (arr1[x][y] == '0') //不是雷
{
count++; //计数加一
if (get_mine(arr1, x, y) > 0) //如果附近雷数不为0
{
arr2[x][y] = '0' + get_mine(arr1, x, y); //将附近雷数赋给show数组,因为数字的ASCII码值是递增的,所以+n就可以表示对应数字了
}
else arr2[x][y] = ' '; //如果附近雷数为0,则赋值为空格
}
else
{
printf("错误,请重新输入:\n");
}
display(arr2, ROW, COL);
}
if (count == row * col - EASYMINE)
{
printf("扫雷成功\n");
}
return 0;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("**************************\n");
printf("******** 扫雷 *******\n");
printf("**************************\n");
printf("******** 1.play *******\n");
printf("******** 0.quit *******\n");
printf("**************************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 }; //储存雷位置的数组,11*11
init_game(mine, ROWS, COLS, '0'); //初始化数组为0
char show[ROWS][COLS] = { 0 }; //储存显示附近雷个数的数组
init_game(show, ROWS, COLS, '*'); //初始化数组为*
set_mine(mine, ROW, COL, EASYMINE); //设置雷数为EASYMINE的雷
display(show, ROW, COL);
find_mine(mine, show, ROW, COL); //开始扫雷
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
scanf("%d", &input);
switch (input) //根据输入跳选
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("错误,请重新输入:\n");
break;
}
} while (input);
return 0;
}
标签:COLS,arr,ROWS,游戏,int,mine,C语言,扫雷,数组 来源: https://blog.csdn.net/m0_57680308/article/details/122710101