目录
写在前面:棋盘大小是11*11的二维数组。雷为1,非雷为0。
初始化
11*11而非9*9的原因:
正常情况下,要数出来这个格子周围的八个格子里面有没有雷;但是边边角角的区域,可能只有5个格子、3个格子。
所以在设计的时候,设计成11*11的棋盘。
但只展示中间的9*9数组,即在打印棋盘的时候循环遍历只能从1-9。在随机生成雷的时候,循环遍历只能从1-9。
实际上要用两个棋盘,一个数组(mine)存放实际布置好的雷的信息,一个数组(show)存放排查出来的雷的信息,周围有几个雷就显示几。
mine数组
初始化为'0'
,布置雷为'1'
show数组
初始化为'*'
,排查雷后具体位置改为数字字符
布置雷
随机生成雷的x,y坐标,范围是1-9。如果这个位置上没有雷就布置雷
排查雷
这个函数有4个参数,要将排查mine的信息反馈到show数组。
1)按到不是雷的坐标,就递归展开一片
条件:1、该坐标不是雷;2、该坐标未被排查过;3、该坐标周围没有雷。
1.若该坐标没有雷,则赋值为空格。之后,判断周围八个坐标的周围是否有雷,周围没有雷的坐标同样赋值为空格,周围没有雷的坐标则继续向外展开,直到遇到周围有雷的坐标或达到了扫雷盘面的边缘,则停止递归。
2.若该坐标有雷,则直接赋值为周围雷的个数。
2)结束
1、找出全部71个非雷位置;
2、踩雷
小Tips
如何将int类型的数字num(0-9)
变成字符ch的('0'-'9')
?
char ch = num + '0';
同理,字符转int
int num = ch - '0';
完整代码如下
//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 EASY_COUNT 10
//初始化棋盘
void init_board(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void display_board(char board[ROWS][COLS], int row, int col);
//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col);
//排查雷
void fine_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//计算周围8个格子是否有雷
int get_mine(char mine[ROWS][COLS], int x, int y);
//扩展空白区域
void ExpandBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* win);
//game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void init_board(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 display_board(char board[ROWS][COLS], int row, int col)
{
//列号,显示在1行
for (int j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
//打印行号,显示在1列
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n");
}
void set_mine(char mine[ROWS][COLS], int row, int col)
{
//布置10个雷
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;//坐标范围从1到9
int y = rand() % row + 1;
//检查是否已经有雷
if (mine[x][y] == '0')
{
mine[x][y] = '1';
//布置成功就--
count--;
}
}
}
int get_mine(char mine[ROWS][COLS], int x, int y)
{
//统计周围8个格子的雷的个数,char转int
return (mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1]
+ mine[x - 1][y] + mine[x + 1][y]
+ mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1]
- 8 * '0');
}
void ExpandBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* win)
{
int count = get_mine(mine, x, y);
if (count == 0)
{
show[x][y] = ' ';//没有雷的坐标赋值为空格
(*win)++;
//递归周围的八个格子
if (show[x - 1][y - 1] == '*' && x - 1 > 0 && x - 1 < ROWS && y - 1 > 0 && y - 1 < COLS)
ExpandBoard(mine, show, x - 1, y - 1, win);
if (show[x - 1][y] == '*' && x - 1 > 0 && x - 1 < ROWS && y > 0 && y < COLS)
ExpandBoard(mine, show, x - 1, y, win);
if (show[x - 1][y + 1] == '*' && x - 1 > 0 && x - 1 < ROWS && y + 1 > 0 && y + 1 < COLS)
ExpandBoard(mine, show, x - 1, y + 1, win);
if (show[x][y - 1] == '*' && x > 0 && x < ROWS && y - 1 > 0 && y - 1 < COLS)
ExpandBoard(mine, show, x, y - 1, win);
if (show[x][y + 1] == '*' && x > 0 && x < ROWS && y + 1 > 0 && y + 1 < COLS)
ExpandBoard(mine, show, x, y + 1, win);
if (show[x + 1][y - 1] == '*' && x + 1 > 0 && x + 1 < ROWS && y - 1 > 0 && y - 1 < COLS)
ExpandBoard(mine, show, x + 1, y - 1, win);
if (show[x + 1][y] == '*' && x + 1 > 0 && x + 1 < ROWS && y > 0 && y < COLS)
ExpandBoard(mine, show, x + 1, y, win);
if (show[x + 1][y + 1] == '*' && x + 1 > 0 && x + 1 < ROWS && y + 1 > 0 && y + 1 < COLS)
ExpandBoard(mine, show, x + 1, y + 1, win);
}
else
{
show[x][y] = count + '0';
}
}
void fine_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < (row * col - EASY_COUNT))
{
printf("请输入排查的坐标:>(范围1-9)\n");
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(mine, ROW, COL);
break;
}
else
{
//排查到无雷区域不会展开
//排查雷
//int count = get_mine(mine, x, y);
//show[x][y] = count + '0';//这样存放的就是字符数字
//display_board(show, ROW, COL);
没踩到雷,就是成功
//win++;
//排查到无雷区域可展开
//该坐标周围没有雷
int count = get_mine(mine, x, y);
if (0 == count)
{
ExpandBoard(mine, show, x, y, &win);
display_board(show, ROW, COL);
}
else
{
show[x][y] = count + '0';//这样存放的就是字符数字
display_board(show, ROW, COL);
//没踩到雷,就是成功
win++;
}
}
}
else
{
printf("该坐标已经排查过了\n");
}
}
else
{
printf("坐标非法,请重新输入!\n");
}
}
//最终判断 是否成功排雷
if (win == row * col - EASY_COUNT)
{
printf("恭喜你!排雷成功!\n");
}
}
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("--------------------\n");
printf(" 1.play \n");
printf(" 0.exit \n");
printf("--------------------\n");
}
void game()
{
//printf("扫雷\n");
//定义两个字符数组mine show
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
//mine全'0' show全'*'
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
//打印棋盘
//display_board(mine, ROW, COL);//不打印雷的信息
display_board(show, ROW, COL);
//布置雷
set_mine(mine, ROW, COL);
//display_board(mine, ROW, COL);
//排查雷
fine_mine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("选择错误,请重新输入!\n");
break;
}
} while (input);
return 0;
}