基本框架
三个文件
game.h ===头文件,函数声明
game.c===函数实现
test.c===游戏主体逻辑
#pragma once
#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
#define easy_count 10 //雷的个数
#include
#include
#include
void init(char board[ROWS][COLS], int rows, int cols, char set);
void print_board(char board[ROWS][COLS], int row, int col);
void set_bomb(char mine[ROWS][COLS], int row, int col);
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row,int col);
判断输赢姑且先用 计算show数组里面的*的个数来算,如果等于雷数就赢了。
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void init(char board[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] =set ;
}
}
}
void print_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("----------扫雷---------\n");
for (i = 0; i <= 9; i++)
{
printf("%d ",i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ",board[i][j]);
}
printf("\n");
}
printf("----------扫雷---------\n");
}
void set_bomb(char mine[ROWS][COLS], int row, int col)
{
int count = 0;
while (1)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count++;
}
if (count == easy_count)
{
break;
}
}
}
int search_around(char mine[ROWS][COLS], int x,int y) //返回的是周围雷的个数 //也可以用循环,转一圈看有多少个1
{
return ( mine[x - 1][y] + mine[x + 1][y] + mine[x][y - 1] + mine[x][y + 1] +
mine[x - 1][y - 1] + mine[x + 1][y + 1] + mine[x + 1][y - 1] +
mine[x - 1][y + 1] - 8 * '0'); //数组保存的是字符,-‘0’是等于‘2’-‘0’(50-48=2),变回了整数2
}
void open_board(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y,int* p)
{
int n = search_around(mine, x, y);
if (show[x][y] == '*') //如果显示数组里还是*,则没被排查过,如果不设置这个条件,递归会递归排查过的坐标,有可能死递归
{ //也就是递归条件要求: 1.x,y这个位置没被排查过
if (mine[x][y] != '1' && n == 0) //2.x,y位置不能是雷 并且 它周围8个位置也不是雷
{
show[x][y] = ' ';
(*p)++;
//因为下边涉及x,y的变化,所以设立条件是必要的
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)//满足条件进入周围坐标的递归,如果不设置这个条件,限制行列坐标在1~9,
{ //那么递归会进入11x11-9x9之间的坐标,就会导致不能将展开限制在周围都有雷的情况
int i = 0; //也就是点左边展开,右边也展开,还有可能全都展开了。
int j = 0;
for (i = x - 1; i <= x + 1; i++) //循环下列8个递归函数,加上本身x,y一共9个,本身x,y被排查过不进入递归。
{
for (j = y - 1; j <= y + 1; j++)
{
open_board(mine, show, i, j, p);
}
}
//open_board(mine, show, x - 1, y,p);
//open_board(mine, show, x + 1, y,p); 和上边一样,就是少了个原本的x,y(也就是输入的中心坐标)
//open_board(mine, show, x, y - 1,p);
//open_board(mine, show, x, y + 1,p);
//open_board(mine, show, x - 1, y - 1,p);
//open_board(mine, show, x + 1, y + 1,p);
//open_board(mine, show, x + 1, y - 1,p);
//open_board(mine, show, x - 1, y + 1,p);
}
}
if (n != 0) //如果x,y这个坐标周围有雷,那么就不进入递归,把周围雷数放到show里就行了。
{
show[x][y] = n + '0'; //2+'0'=2+48=50='2'(理解) 我认为它整形提升了,结果仍然加的是0的asci码值
(*p)++;
}
}
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int win = 0;
int x = 0;
int y = 0;
while (1) //win< (row * col - easy_count)
{
printf("请输入坐标\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("该坐标已经被排查过了\n");
continue;
}
if (mine[x][y] == '1')
{
printf("这是雷,游戏结束\n");
print_board(mine, ROW, COL);
break;
}
else
{
open_board(mine, show, x, y,&win);
print_board(mine, ROW, COL);
print_board(show, ROW, COL);
}
}
else
{
printf("输入错误,重新输入\n");
}
int count = 0;
for (int j = 1; j <= 9; j++)
{
for (int i = 1; i <= 9; i++)
{
if (show[j][i] == '*')//用了数show里面的*来判断
count++;
}
}
if (count == easy_count)
{
printf("扫雷成功!\n");
print_board(mine, ROW, COL);
break;
}
}
//if (win == (row * col - easy_count)) //在雷数少的时候比如说5,就得
//{ //让win>=(row * col - easy_count)
// printf("扫雷成功!\n"); //不然点开延展的时候,win的指针++(调试是115次)
// print_board(mine, ROW, COL); //次数会大于81 -5,这里就不输出成功
// //此时并不能win次数 来判断游戏结束
//} //这个判断还需要优化,我用了数show里面的*来判断
//那么win这个判断输赢基本就没用了
}
要同时设置两个雷盘,一个初始化全为0方便后续找周围8个雷,另一个初始化全为*,打印出来就是要扫雷的雷盘。
并且排查雷还需要行列都加2,才不会越界
进行递归雷盘展开时,需要注意把坐标x,y限制在1-9,不然会导致递归进入雷盘外,导致不想展开的地方也多展开了。
递归的条件是,第一不是雷并且它周围的8个也不是雷,而且还要没被排查过,不然会死递归。
如果它周围有雷,那么就不进入递归,直接把周围的雷数显示到show就行。
要的结果就是展开后,周围一圈除了边界,就是周围都是数字,就是周边有雷的个数,就结束
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("*********** 扫雷 **********\n");
printf("***********1.玩游戏**********\n");
printf("**********0.退出游戏**********\n");
}
void game()
{
//1.需要存放布置好的雷的信息,存放排查出雷的信息,我们需要2个二维数组
//2.排查坐标的时候,为了防止坐标越界,我们给数组的行列,同时增加2
char mine[ROWS][COLS] = { 0 };//布置好雷的信息
char show[ROWS][COLS] = { 0 };//排查出雷的信息
init(mine, ROWS, COLS,'0');
init(show, ROWS, COLS,'*');
set_bomb(mine, ROW, COL);
print_board(mine, ROW, COL);
print_board(show, ROW, COL);
find_mine(mine, show, ROW, COL);//扫雷判断输赢及周围雷的个数
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择->\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("选择错误,重新输入\n");
break;
}
} while (input);
return 0;
}