c语言实现扫雷(含循环递归展开)
🍉博客主页: 🍁如风暖阳🍁
🍉欢迎点赞 👍 收藏 ?留言评论 📝私信必回哟😁
🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉
🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言
🍉博客中涉及源码及博主日常练习代码均已上传码云(gitee)
??前言??
本笔记通过c语言实现扫雷小游戏(包含递归展开)
游戏实现逻辑位于test.c文件,整个游戏头文件位于game.h,游戏进程的具体操作于game.c中实现。?
🍅1.游戏概述
该游戏有9*9个格子(在头文件game.h中玩家可通过改变ROW COL的值来改变棋盘行列数),格子中已随机布置生成10颗雷(玩家也可通过改变EASY_COUNT的值来自行改变雷的数目),test.c中的文件实时记录已经排查过的格子个数,当玩家把雷全部找出且没有选中雷时,游戏胜利,否则,游戏失败!
🍅2.游戏设计
本游戏代码设计通过两个棋盘来完成,在mine棋盘中存储雷的信息,0表示非雷,1表示为类;在show棋盘中初始状态全为’*‘,当玩家开始游戏后,排查出的不是雷的位置有两种情况,1是该位置为数字,即表示该位置周围的雷的数量,2是空格,即表示该位置周围没有雷
🍅3.代码实现
请读者先按照test.c文件来理清游戏逻辑,再去game.c文件中进一步探究步骤的具体实现(game.h只是头文件及函数的声明)
🍎?test.c
该文件的阅读请从main函数开始梳理游戏逻辑
#include"game.h"
void menu()
{
printf("****************\n");
printf("*****1.play*****\n");
printf("*****0.exit*****\n");
printf("****************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');
displayBoard(show, ROW, COL);
setMine(mine, ROW, COL);
fineBoard(mine, show, ROW, COL);
}
int main()
{
system("color f4");
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择>\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("游戏开始\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
}
🍎?game.h(该文件只是头文件引用及函数的声明,无需过多阅读)
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
void initBoard(char board[ROWS][COLS], int rows, int cols, char set);
void displayBoard(char board[ROWS][COLS], int row, int col);
void setMine(char mine[ROWS][COLS], int row, int col);
void fineBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
🍎?game.c
🍓initBoard(初始化棋盘)
两个棋盘传过来棋盘数组及行列数进行初始化,还有一个字符参数用set变量接受,mine棋盘全部初始化为‘0’,show棋盘全部初始化为‘*’
void initBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
🍓displayBoard(棋盘打印)
该部分就是通过循环将棋盘打印,以下为样图
void displayBoard(char board[ROWS][COLS], int row, int col)
{
printf("---------------------------\n");
printf("---------------------------\n");
int i, j;
for (j = 0; j <= COL; j++)
{
printf("|---");
}
printf("|\n");
for (i = 0; i <= COL; i++)
{
printf("| %d ", i);
}
printf("|\n");
for (i = 0; i < ROW; i++) {
for (j = 0; j <= COL; j++) {
printf("|---");
}
printf("|\n");
printf("| %d ", i + 1);
for (j = 0; j < COL; j++) {
printf("| %c ", board[i+1][j+1]);
}
printf("|\n");
}
for (j = 0; j <= COL; j++)
{
printf("|---");
}
printf("|\n");
}
🍓setMine(随机安放雷在mine棋盘上)
count为雷的数量,玩家可通过更改game.h文件中EASY_COUNT的值来自行改变雷的数目
void setMine(char mine[ROWS][COLS], int row, int col)
{
int x = 0, y = 0, count = EASY_COUNT;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
🍓fineBoard(玩家扫雷)
实现这一步需要三个函数fineBoard,expandBoard,getCount来共同完成
🍑fineBoard
void fineBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
printf("请输入你要排查的位置>\n");
int x, y;
int win = 0;
while (win<row*col-EASY_COUNT)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
displayBoard(mine, ROW, COL);
break;
}
else
{
expandBoard(mine, show, x, y,&win);
displayBoard(show, ROW, COL);
}
}
else
{
printf("你输入的坐标非法,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你获得胜利!\n");
displayBoard(mine, ROW, COL);
}
}
🍑expandBoard(设置循环递归展开)
进入该函数是因为该位置不是雷才会进入,如果该位置周围有雷则该位置对应show棋盘变为数字,不会进入递归,若周围无雷则才会经过判断后进行递归展开
static void expandBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y,int*win)
{
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (show[x][y] == ' ' || show[x][y] != '*')
return;
else if (getCount(mine, x, y) != 0)
{
show[x][y] = getCount(mine, x, y) + '0';
(*win)++;
return;
}
else
{
show[x][y] = ' ';
(*win)++;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
expandBoard(mine, show, x + i, y + j, win);
}
}
}
}
}
🍑getCount(计算当前位置周围雷的数量)
通过设置循环将该位置的周围八个位置计算,因为棋盘数组为字符,则需要通过-‘0’将其转变为int型
static int getCount(char mine[ROWS][COLS], int x, int y)
{
int i, j;
int count = 0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
count = count+mine[x + i][y + j]-'0';
}
}
return count;
}
以下为game.c文件全部源码
#include"game.h"
void initBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void displayBoard(char board[ROWS][COLS], int row, int col)
{
printf("---------------------------\n");
printf("---------------------------\n");
int i, j;
for (j = 0; j <= COL; j++)
{
printf("|---");
}
printf("|\n");
for (i = 0; i <= COL; i++)
{
printf("| %d ", i);
}
printf("|\n");
for (i = 0; i < ROW; i++) {
for (j = 0; j <= COL; j++) {
printf("|---");
}
printf("|\n");
printf("| %d ", i + 1);
for (j = 0; j < COL; j++) {
printf("| %c ", board[i+1][j+1]);
}
printf("|\n");
}
for (j = 0; j <= COL; j++)
{
printf("|---");
}
printf("|\n");
}
void setMine(char mine[ROWS][COLS], int row, int col)
{
int x = 0, y = 0, count = EASY_COUNT;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
static int getCount(char mine[ROWS][COLS], int x, int y)
{
int i, j;
int count = 0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
count = count+mine[x + i][y + j]-'0';
}
}
return count;
}
static void expandBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y,int*win)
{
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (show[x][y] == ' ' || show[x][y] != '*')
return;
else if (getCount(mine, x, y) != 0)
{
show[x][y] = getCount(mine, x, y) + '0';
(*win)++;
return;
}
else
{
show[x][y] = ' ';
(*win)++;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
expandBoard(mine, show, x + i, y + j, win);
}
}
}
}
}
void fineBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
printf("请输入你要排查的位置>\n");
int x, y;
int win = 0;
while (win<row*col-EASY_COUNT)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
displayBoard(mine, ROW, COL);
break;
}
else
{
expandBoard(mine, show, x, y,&win);
displayBoard(show, ROW, COL);
}
}
else
{
printf("你输入的坐标非法,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你获得胜利!\n");
displayBoard(mine, ROW, COL);
}
}
??最后的话??
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁
|