扫雷游戏需要用到两个源文件(.c)和一个头文件(.h)
因此,创建了test.c、game.c文件与game.h文件
test.c(游戏逻辑)
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void mnue()
{
printf("*******************\n");
printf("***** 1. play ****\n");
printf("***** 0. exit ****\n");
printf("*******************\n");
}
void game()
{
//定义两个二维字符数组,并且行列相同,这样做的目的是为了排查雷的时候更方便
char arr1[ROWS][COLS] = { 0 };//arr1用于布置雷的雷数
char arr2[ROWS][COLS] = { 0 };//arr2用于提供排查雷的信息
//初始化雷盘
My_play(arr1, ROWS, COLS, '0');//假设'0'为非雷,'1'为雷
My_play(arr2, ROWS, COLS, '*');//假设'*'为未排查的地方
//打印雷盘(这里打印ROW、COL的雷盘即可,因为我们只在此雷盘内排雷
//My_cup(arr1, ROW, COL);
My_cup(arr2, ROW, COL);
//布置雷
My_Live(arr1, ROW, COL);//在arr1雷盘内布置雷,同样也只需在ROW、COL内布置
My_cup(arr1, ROW, COL);
//排查雷
My_Look(arr1, arr2, ROW, COL);//此处需将arr1,arr2数组都传过去,因为当排查一次,arr2数组
//就得提供排查雷的信息
}
int main()
{
int input = 0;
//用do-while循环,实现游戏的开始和退出
//随机数
srand((unsigned int)time(NULL));
do
{
//调用函数,打印游戏菜单
mnue();
printf("请选择:>");
scanf("%d", &input);
//利用switch语句,实现游戏
switch (input)
{
case 1:
game();//调用函数,实现游戏逻辑
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
game.c(游戏实现)
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化雷盘
void My_play(char board[ROWS][COLS], int rows, int cols, char set)
{
//因为要布置更大的雷盘,因此我们行和列就得用ROWS、COLS
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印雷盘
void My_cup(char arr2[ROWS][COLS], int row, int col)
{
printf("***** 扫雷 *****\n");
int i = 0;
int j = 0;
//此处是为了给很列标上序号,让玩家明了的知道坐标
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");//打印完列序号之和换行,之后打印行序号
//打印我们实际排雷的雷盘,范围应该在1~9
for (i = 1; i <= row; i++)
{
printf("%d ", i);//作用相同,给行标上序号
for (j = 1; j <= col; j++)
{
printf("%c ", arr2[i][j]);
}
printf("\n");
}
}
//布置雷
void My_Live(char arr1[ROWS][COLS], int row, int col)
{
int cont = Sum;//雷的总个数
//利用循环,依次布置雷
while (cont)
{
//利用随机值,生成雷的坐标
int x = rand() % row + 1;//随机值%row = 0~8之间,再加1 = 1~9 之间
int y = rand() % col + 1;//随机值%col = 0~8之间,再加1 = 1~9 之间
if (arr1[x][y] == '0')//当雷盘位置为'0'时,代表没布置过
{
arr1[x][y] = '1';
cont--;//直到布置完,退出循环
}
}
}
int My_Get(char arr1[ROWS][COLS],int x,int y)
{
return (arr1[x - 1][y] +
arr1[x - 1][y - 1] +
arr1[x][y - 1] +
arr1[x + 1][y - 1] +
arr1[x + 1][y] +
arr1[x + 1][y + 1] +
arr1[x][y + 1] +
arr1[x - 1][y + 1]) - 8 * '0';
}
//排查雷
void My_Look(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col)
{
//定义两个变量,用于排查雷的坐标
int x = 0;
int y = 0;
int win = 0;//用于计算排查的次数
while (win<row*col-Sum)//表达式的意思为,当win持续++后,直到大于(雷盘总数-雷的个数)时,代表排雷成功,跳出循环
{
printf("请选择要排查的坐标:>");
scanf("%d %d", &x, &y);
//判断输入坐标是否符合范围
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断输入的坐标是否被占用
if (arr2[x][y] == '*')//当坐标为'*'时,则代表该位置没被排查过
{
//判断输赢
if (arr1[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
//炸死后让玩家看雷的位置
My_cup(arr1, ROW, COL);
break;
}
else
{
//调用函数,用于计算该坐标周围的雷数
int sum = My_Get(arr1, x, y);
//将周围雷的个数,更新到arr2雷盘上
arr2[x][y] = sum + '0';//这里sum + '0' 的作用是为了让数字变为字符数字
//打印arr2雷盘
My_cup(arr2, ROW, COL);
win++;//排查一个+1,直到跳出循环
}
}
else
{
printf("坐标吧被占用\n");
}
}
else
{
printf("超出范围\n");
}
}
if (win >= row * col - Sum)
{
printf("恭喜你,排雷成功!\n");
}
}
game.h(游戏所包含的头文件与函数声明)
#pragma once
#include<stdio.h>
//布置随机值的头文件
#include<stdlib.h>
#include<time.h>
//定义两个标识符,作为排雷的雷盘
#define ROW 9
#define COL 9
//再定义两个标识符,作为完整的雷盘,目的是为了防止计算周围雷个数时,越界了,
//因此需将原本的雷盘布置的更大一些,让排查靠边的雷时,不越界
#define ROWS ROW+2
#define COLS COL+2
//定义标识符,用于制定雷的个数
#define Sum 80
//初始化雷盘
void My_play(char board[ROWS][COLS],int rows,int cols,char set);
//这里形参部分多定义char set用于接受传过来的'0'或者'*',目的是为了同时初始化
//arr1雷盘和arr2雷盘
//因为arr1与arr2数组的行列都相同,所以我们调用一个函数就可以同时完成两个数组的初始化
//打印雷盘
void My_cup(char arr2[ROWS][COLS],int row,int col);
//布置雷
void My_Live(char arr1[ROWS][COLS],int row,int col);
//排查雷
void My_Look(char arr1[ROWS][COLS],char arr2[ROWS][COLS],int row,int col);
计算周围雷个数的方法以及数字转换为字符数字,字符数字转换为数字的方法
知道一处坐标后,周围的坐标如下:
数字转换为字符数字:
我们知道字符是以ASCll码存储的,并且在ASCll中,字符数字是连续存放的,
所以当我们要将数字转化为字符数字时,我们只需:
数字 + ‘0’= ‘数字’,数字为整型,字符的ASCll码也是整数,
‘0’的ASCll为48,当数字加上48后,其对应的字符数字也就是本身了
字符数字转换为数字:
也是相同的道理,当字符数字的ASCll码值 - ‘0’时,
所得到的就是数字了
因此,计算坐标周围雷的个数就显而易见了:
首先将周围坐标加起来,然后减去8个‘0’,得到数字,
这种表达式就是字符数字转换为数字,因为在最开始,我们定义arr1数组时说明
‘0’为非雷,‘1’为雷,这样就便利我们求出周围雷的个数了,
最后只需要将数字转换为字符数字,更新到arr2数组里即可