1.菜单的打印
玩游戏菜单不可缺少,首先进行菜单的互动。
void menu()
{
printf("****************\n");
printf("*****1.play*****\n");
printf("*****2.exit*****\n");
printf("****************\n");
}
玩游戏不可能只玩一把,我们利用do(while),循环来实现多把游戏,同时利用switch语句实现功能的选择
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf_s("%d", &input);
switch (input)
{
case 1:
printf("扫雷\n");
break;
case 2:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input!=2);
return 0;
}
这个时候运行代码(游戏代码部分并没有写入)
2.扫雷游戏的底层逻辑
我们先玩一把扫雷,了解扫雷游戏的运行关系
基础版是个9*9的棋盘,左上角显示雷的数量,点击一下
展开了一部分,1代表周围8个格子中有一个雷,2代表周围8个格子中有两个雷,依次类推
点到雷就game over。
那我们就对扫雷有个基础的了解:
1.如果排查的位置是雷,就game over。
2.如果排查的位置不是雷,就显示周围雷的数量
那么我们首先完成对棋盘的数据的记录
这是一个对数据的记录,我们利用9*9的数组来实现,利用0代表空,1代表雷,来区分这个位置是否有雷,但是如果这样布置会出现一个问题
按照我们的逻辑这个时候黄色区域中间的0应该会显示为1,虽然可行,但是我们所需要打印的棋盘会很杂乱。所以我们会在创建一个数组,专门来存放我们排查雷的信息,实例如下
如果我们点击的黄色区域的中间区域,我们就将下面这个“*”的矩阵相同位置替换成“1”,这样就达到了我们的目标。 但是9*9的格子就够用了吗?
我们排查雷时,需要排查周围8个方格,但是当我们排查到边界时,这个时候就越界了,所以我们创建一个11*11的数组,边界全部放“0”,这个时候越界的问题就解决了
01数组我们命名为“ben”,“*”数组我们命名为“xian”,那么01数组应该初始化为0,先数组应该初始化为“*”,同时为了方便,我们都将数组命名字符数组。
void game()
{
//数组的创建
char ben[11][11];
char xian[11][11];
shuzuchushihua(ben, 11, 11);
shuzuchushihua(xian, 11, 11);
}
这个时候只需要编写shuzuchushihua就可以了,但是这样不方便我们以后代码的更改,如果我们想让棋盘更大我能就需要更改掉所有的11,过于麻烦,这个时候我们可以创建新的头文件来帮助我们
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
在把头文件放到我们所需的.c文件中就行
这个时候我们下面的代码改为这样
void game()
{
//数组的创建
char ben[ROWS][COLS];
char xian[ROWS][COLS];
shuzuchushihua(ben, ROWS, COLS,'0');
shuzuchushihua(xian, ROWS, COLS,'*');
}
这样就方便我们以后的更改了
棋盘的初始化
我们创建了一个中间量set这样可以分别打印我们的字符了
void shuzuchushihua(char board[ROWS][COLS], int rows, int cols,char set)
{
int j = 0;
for (j = 0; j < rows; j++)
{
int i = 0;
for (i = 0; i < cols; i++)
{
board[j][i] = set;
}
}
}
棋盘的打印
void DY(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf(" ");//空格不能省略,因为会不好看
for ( i = 1; i <=row; i++)
{
printf(" %d", i);//打印横向坐标
}
printf("\n");
for ( i = 1; i <= row ; i++)
{
printf("%d", i);//打印竖向坐标
int j = 0;
for ( j = 1; j <= col ; j++)
{
printf(" %c", board[i][j]);
}
printf("\n");
}
}
布置雷
根据规则我们需要随机的布置的10个雷,我们利用srand这个函数来实现,同时利用time用作种子生成随机数,并且我们只需要1-9的数,所以我们将其取模10,就可以得到随机的1-9了
void setben(char ben[ROWS][COLS], int row, int col)
{
int count = 10;//雷的数量
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
//生成随机的横坐标和纵坐标。
if ( ben[x][y]=='0')
{
ben[x][y] = '1';
count--;
}
}
}
我这里用的是row+1,之前定义row为9,9+1=10,效果一样
这里用到的rand函数需要新的头文件
运行出来的结果
当然我们运行时只会展示“*”这个棋盘,这个01棋盘我们不会展示出来
排查雷
我们排查的范围是个9*9的数组,同时将周围的字符“1”的数量显示出来,并且换成一个值替换到字符“*”棋盘中,根据ASCII表可知,字符“1”与字符“0”仅仅相差一位,所以我们可以把排查点周围所有的字符加起来-8*“0”就可以得到雷的数量。
//显示雷的数量
int XS(char ben[ROWS][COLS], int x, int y)
{
return (ben[x - 1][y - 1]
+ ben[x - 1][y]
+ ben[x - 1][y + 1]
+ ben[x][y - 1]
+ ben[x][y + 1]
+ ben[x + 1][y - 1]
+ ben[x + 1][y]
+ ben[x + 1][y + 1]
- 8 * '0');
}
//排查雷
void chazhao(char ben[ROWS][COLS],char xian[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < row * col - 10)//胜利条件
{
printf("请输入排查的坐标:");
scanf_s("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (ben[x][y] == '1')
{
printf("game over\n");
DY(ben, ROW, COL);
break;
}
else
{
//得到这个坐标周围雷的数量
int count = XS(ben, x, y);
xian[x][y] = count + '0';
DY(xian, ROW, COL);
win++;
}
}
else
{
printf("坐标非法,请重新输入:\n");
break;
}
}
if (win == row * col - 10)
{
printf("game win\n");
}
}
完整代码
//游戏代码
#include "game.h"
//初始化数组
void shuzuchushihua(char board[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印棋盘
void DY(char board[ROWS][COLS], int row, int col)
{
int i = 0;
for ( i = 0; i <=row; i++)
{
printf("%d ", i);
}
printf("\n");
for ( i = 1; i <= row ; i++)
{
printf("%d ", i);
int j = 0;
for ( j = 1; j <= col ; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//生成雷
void setben(char ben[ROWS][COLS], int row, int col)
{
int count = 10;//雷的数量
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
//生成随机的横坐标和纵坐标。
if ( ben[x][y]=='0')
{
ben[x][y] = '1';
count--;
}
}
}
//显示雷的数量
int XS(char ben[ROWS][COLS], int x, int y)
{
return (ben[x - 1][y - 1]
+ ben[x - 1][y]
+ ben[x - 1][y + 1]
+ ben[x][y - 1]
+ ben[x][y + 1]
+ ben[x + 1][y - 1]
+ ben[x + 1][y]
+ ben[x + 1][y + 1]
- 8 * '0');
}
//排查雷
void chazhao(char ben[ROWS][COLS],char xian[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < row * col - 10)//胜利条件
{
printf("请输入排查的坐标:");
scanf_s("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (ben[x][y] == '1')
{
printf("game over\n");
DY(ben, ROW, COL);
break;
}
else
{
//得到这个坐标周围雷的数量
int count = XS(ben, x, y);
xian[x][y] = count + '0';
DY(xian, ROW, COL);
win++;
}
}
else
{
printf("坐标非法,请重新输入:\n");
break;
}
}
if (win == row * col - 10)
{
printf("game win\n");
}
}
//菜单代码
#include "game.h"
void menu()
{
printf("****************\n");
printf("*****1.play*****\n");
printf("*****2.exit*****\n");
printf("****************\n");
}
void game()
{
//数组的创建
char ben[ROWS][COLS];
char xian[ROWS][COLS];
shuzuchushihua(ben, ROWS, COLS,'0');
shuzuchushihua(xian, ROWS, COLS,'*');
//打印棋盘
DY(xian, ROW, COL);
//DY(ben, ROW, COL);
//布置雷
setben(ben,ROW,COL);
//
//排查雷
chazhao(ben,xian, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请选择:");
scanf_s("%d", &input);
switch (input)
{
case 1:
game();
break;
case 2:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input!=2);
return 0;
}
//函数调用和头文件
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define _CAR_SECURE_NO_WARNINGS 1
//初始化棋盘
void shuzuchushihua(char board[ROWS][COLS], int rows, int cols,char set);
//打印棋盘
void DY(char board[ROWS][COLS], int rows, int cols);
//布置雷
void setben(char ben[ROWS][COLS], int row, int col);
//排查雷
void chazhao(char ben[ROW][COL],char xian[ROW][COL], int row, int col);
//显示雷
int XS(char ben[ROWS][COLS], int x, int y);