目录
前言
一、扫雷游戏规则
二、展示效果
三、 游戏设计思路
四、代码展示
一、游戏交互界面
二、游戏主体
二、扫雷代码实现
1.游戏框架搭建
2.初始化雷盘
3.打印雷盘
4.放置雷
5.遍历获取坐标周围八个雷的个数
6.遍历打开不是雷的地方
7.寻找雷
完整代码
game.h
game.c
test.c
说起扫雷,相信大家应该都不陌生吧。windows系统里的小游戏,扫雷有着不可撼动的地位。
今天我们就用c语言来复刻扫雷小游戏!
玩家需要排查出格子中的雷,点开一个方块后,显示数字,数字是几就表示它周围的八个方块有几个雷。
比如说这个红色的方框里面就存在一个雷。
雷盘相当于一个二维的数组
一、游戏交互界面
- 创建游戏菜单
- 创建游戏逻辑主体
二、扫雷游戏实现
- 创建扫雷棋盘
- 初始化扫雷棋盘
- 布置雷
- 打印扫雷棋盘
- 用户排查雷
- 判断输赢
1.设计扫雷游戏的时候,二维数组的行数和列数需要比真正想要得到的棋盘多两行和多两列
为什么呢?
因为我们排查雷的时候,需要遍历坐标走位八个格子是否有雷,当输入坐标为雷盘边界坐标时,遍历周围的雷就会出现越界的问题!
2.创建两个雷盘,一个用于显示,一个用于存放地雷
只创建一个棋盘,那么这一个棋盘上就要放置3种信息。分别为雷、非雷、排查出周围雷的信息。虽然这种方法也没太大的问题,但是一个棋盘上放置3种信息会给之后打印棋盘时造成麻烦,不易打印。
3.使用宏常量
方便雷盘大小的修改,不会写死程序,提高代码的灵活性。
void menu()
{
printf("**************************\n");
printf("********1.开始游戏********\n");
printf("********0.退出游戏********\n");
printf("**************************\n");
}
int main()
{
srand((unsigned int)time(NULL));
int intput = 0;
again:
menu();
scanf("%d", &intput);
do
{
switch (intput)
{
case 1:
printf("游戏开始\n");
game();
goto again;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误请重新输入\n");
break;
}
} while(intput);
return 0;
}
void game()
{
//设置两个数组,mine数组用来存放设置雷的信息,show数组用来存放排查雷的信息
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
init_board(show,ROWS,COLS,'*');
init_board(mine, ROWS, COLS, '0');
//display_board(mine, ROW, COL);
display_board(show, ROW, COL);
set_mine(mine,ROW,COL);
//display_board(mine, ROW, COL);
find_mine(mine,show,ROW,COL);
}
void init_board(char board[][COLS],int rows,int cols,char set)//初始化雷盘,set是需要初始化成什么字符
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void display_board(char board[][COLS], int row, int col)
{
printf("---------扫雷游戏-------------\n");
printf(" ");
for (int n = 1; n <= col; n++)
{
printf("%d ",n);
}
printf("\n");
printf("------------------------------\n");
for (int i = 1; i <= row; i++)
{
printf("%d |",i);
for (int j = 1; j <= col; j++)
{
printf("%c ",board[i][j]);
}
printf("|");
printf("\n");
}
printf("-----------------------------\n");
}
void set_mine(char board[][COLS], int row, int col)
{
int count = MINENUMS;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;//设置1~9随机数布置雷
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
//获取坐标周围的雷数目(八个格子)
int get_minecount(char mine[][COLS], int x, int y)
{
int n = mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0';//减去八个字符零是因为八个字符相加,要转换成数字得到和
return n;
}
void ergodic(char mine[][COLS],char show[][COLS],int x,int y,int *w)//遍历打开不是雷的区域
{
int mine_num = get_minecount(mine, x, y);
if (mine_num == 0)
{
show[x][y] = ' ';//如果这个坐标周围都没有雷的话,显示为空格
(*w)++;
system("cls");
display_board(show, ROW, COL);
/*display_board(mine, ROW, COL);*/
if ((x - 1 >= 1 && x - 1 <= ROW) && (y - 1 >= 1 && y - 1 <= COL) && show[x - 1][y - 1] == '*')
{
ergodic(mine,show,x-1,y-1,w);
}
if ((x - 1 >= 1 && x - 1 <= ROW) && (y >= 1 && y <= COL) && show[x - 1][y] == '*')
{
ergodic(mine, show, x - 1, y,w );
}
if ((x - 1 >= 1 && x - 1 <= ROW) && (y +1>= 1 && y+1 <= COL) && show[x - 1][y+1] == '*')
{
ergodic(mine, show, x - 1, y+1,w);
}
if((x>=1&&x<=ROW)&&(y - 1 >= 1 && y - 1 <= COL) && show[x ][y - 1] == '*')
{
ergodic(mine, show, x , y - 1,w);
}
if ((x >= 1 && x <= ROW) && (y + 1 >= 1 && y + 1 <= COL) && show[x][y + 1] == '*')
{
ergodic(mine, show, x, y + 1,w);
}
if ((x + 1 >= 1 && x + 1 <= ROW) && (y - 1 >= 1 && y - 1 <= COL) && show[x + 1][y - 1] == '*')
{
ergodic(mine, show, x + 1, y - 1,w);
}
if ((x + 1 >= 1 && x + 1 <= ROW) && (y >= 1 && y <= COL) && show[x + 1][y] == '*')
{
ergodic(mine, show, x + 1, y,w);
}
if ((x + 1 >= 1 && x + 1 <= ROW) && (y + 1 >= 1 && y + 1 <= COL) && show[x + 1][y + 1] == '*')
{
ergodic(mine, show, x + 1, y + 1,w);
}
}
else
{
show[x][y] = mine_num + '0';
///* display_board(mine, ROW, COL);*/
(*w)++;
}
}
void find_mine(char mine[][COLS],char show[][COLS],int row,int col)//寻找雷
{
int x = 0;
int y = 0;
int win = 0;
int* w = &win;
while (win < (row * col - MINENUMS))//判断是否已经排查完毕,win相当于一个计数器
{
printf("请输入需要排雷的坐标: ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("你被炸死了!\n");
display_board(show,row,col);
break;
}
else
{
/* int count = get_minecount(mine,x,y);
show[x][y] = count + '0';*/
ergodic(mine,show,x,y,w);
system("cls");
display_board(show, ROW, COL);
/*display_board(mine, ROW, COL);*/
/*win++;*/
}
}
else
{
printf("坐标已经被排查过啦!\n");
}
}
else
{
printf("输入的坐标有误!\n");
}
}
if (win == row * col - MINENUMS)
{
printf("恭喜你,排雷成功!\n\n\n\n");
display_board(show, ROW, COL);
}
}
这里的win相当于计数器,排一个格子,win就加一,作为判断输赢的条件
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
#include
#define ROW 9
#define COL 9//雷盘大小
#define ROWS ROW+2
#define COLS COL+2
#define MINENUMS 10//布置雷数
void game();
void init_board(char board[][COLS], int rows, int cols, char set);
void display_board(char board[][COLS], int row, int col);
void set_mine(char board[][COLS], int row, int col);
void find_mine(char mine[][COLS], char show[][COLS], int row, int col);
#include"game.h"
void game()
{
//设置两个数组,mine数组用来存放设置雷的信息,show数组用来存放排查雷的信息
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
init_board(show,ROWS,COLS,'*');
init_board(mine, ROWS, COLS, '0');
//display_board(mine, ROW, COL);
display_board(show, ROW, COL);
set_mine(mine,ROW,COL);
//display_board(mine, ROW, COL);
find_mine(mine,show,ROW,COL);
}
void init_board(char board[][COLS],int rows,int cols,char set)//初始化雷盘,set是需要初始化成什么字符
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印雷盘,制作的是9x9的雷盘
//把雷盘看成一个二维数组打印,为了防止数组越界,我们数组的行和列分别要比想要棋盘的行和列多2
void display_board(char board[][COLS], int row, int col)
{
printf("---------扫雷游戏-------------\n");
printf(" ");
for (int n = 1; n <= col; n++)
{
printf("%d ",n);
}
printf("\n");
printf("------------------------------\n");
for (int i = 1; i <= row; i++)
{
printf("%d |",i);
for (int j = 1; j <= col; j++)
{
printf("%c ",board[i][j]);
}
printf("|");
printf("\n");
}
printf("-----------------------------\n");
}
void set_mine(char board[][COLS], int row, int col)
{
int count = MINENUMS;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;//设置1~9随机数布置雷
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
//获取坐标周围的雷数目(八个格子)
int get_minecount(char mine[][COLS], int x, int y)
{
int n = mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0';//减去八个字符零是因为八个字符相加,要转换成数字得到和
return n;
}
void ergodic(char mine[][COLS],char show[][COLS],int x,int y,int *w)//遍历打开不是雷的区域
{
int mine_num = get_minecount(mine, x, y);
if (mine_num == 0)
{
show[x][y] = ' ';//如果这个坐标周围都没有雷的话,显示为空格
(*w)++;
system("cls");
display_board(show, ROW, COL);
/*display_board(mine, ROW, COL);*/
if ((x - 1 >= 1 && x - 1 <= ROW) && (y - 1 >= 1 && y - 1 <= COL) && show[x - 1][y - 1] == '*')
{
ergodic(mine,show,x-1,y-1,w);
}
if ((x - 1 >= 1 && x - 1 <= ROW) && (y >= 1 && y <= COL) && show[x - 1][y] == '*')
{
ergodic(mine, show, x - 1, y,w );
}
if ((x - 1 >= 1 && x - 1 <= ROW) && (y +1>= 1 && y+1 <= COL) && show[x - 1][y+1] == '*')
{
ergodic(mine, show, x - 1, y+1,w);
}
if((x>=1&&x<=ROW)&&(y - 1 >= 1 && y - 1 <= COL) && show[x ][y - 1] == '*')
{
ergodic(mine, show, x , y - 1,w);
}
if ((x >= 1 && x <= ROW) && (y + 1 >= 1 && y + 1 <= COL) && show[x][y + 1] == '*')
{
ergodic(mine, show, x, y + 1,w);
}
if ((x + 1 >= 1 && x + 1 <= ROW) && (y - 1 >= 1 && y - 1 <= COL) && show[x + 1][y - 1] == '*')
{
ergodic(mine, show, x + 1, y - 1,w);
}
if ((x + 1 >= 1 && x + 1 <= ROW) && (y >= 1 && y <= COL) && show[x + 1][y] == '*')
{
ergodic(mine, show, x + 1, y,w);
}
if ((x + 1 >= 1 && x + 1 <= ROW) && (y + 1 >= 1 && y + 1 <= COL) && show[x + 1][y + 1] == '*')
{
ergodic(mine, show, x + 1, y + 1,w);
}
}
else
{
show[x][y] = mine_num + '0';
///* display_board(mine, ROW, COL);*/
(*w)++;
}
}
void find_mine(char mine[][COLS],char show[][COLS],int row,int col)//寻找雷
{
int x = 0;
int y = 0;
int win = 0;
int* w = &win;
while (win < (row * col - MINENUMS))//判断是否已经排查完毕,win相当于一个计数器
{
printf("请输入需要排雷的坐标: ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("你被炸死了!\n");
display_board(show,row,col);
break;
}
else
{
/* int count = get_minecount(mine,x,y);
show[x][y] = count + '0';*/
ergodic(mine,show,x,y,w);
system("cls");
display_board(show, ROW, COL);
/*display_board(mine, ROW, COL);*/
/*win++;*/
}
}
else
{
printf("坐标已经被排查过啦!\n");
}
}
else
{
printf("输入的坐标有误!\n");
}
}
if (win == row * col - MINENUMS)
{
printf("恭喜你,排雷成功!\n\n\n\n");
display_board(show, ROW, COL);
}
}
#include"game.h" void menu() { printf("**************************\n"); printf("********1.开始游戏********\n"); printf("********0.退出游戏********\n"); printf("**************************\n"); } int main() { srand((unsigned int)time(NULL)); int intput = 0; again: menu(); scanf("%d", &intput); do { switch (intput) { case 1: printf("游戏开始\n"); game(); goto again; case 0: printf("退出游戏\n"); break; default: printf("输入错误请重新输入\n"); break; } } while(intput); return 0; }
制作不易,给博主一键3连吧!蟹蟹!!!
制作不易,给博主一键3连吧!蟹蟹!!!
制作不易,给博主一键3连吧!蟹蟹!!!