整理出的思路脑图
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#ifndef __GAME_H__
#define __GAME_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS (ROW+2)
#define COLS (COL+2)
#define EASY_MODE 10
int book[ROWS][COLS];
void DisplayBoard(char board[ROWS][COLS], int row, int col);
void Init(char board[ROWS][COLS], int row, int col, char ch);
void setMine(char mine[ROWS][COLS], int row, int col);
int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
int GetCount(char mine[ROWS][COLS], int x, int y);
void SafeMove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
int CountShow(char show[ROWS][COLS], int row, int col);
#endif //__GAME_H_
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()
{
int is = 0;
//mine 数组存储雷的位置 0 为空,1 为雷
char mine[ROWS][COLS] = { 0 };
//show 数组存储游戏盘,并且在每次点击后显示周围雷的个数
char show[ROWS][COLS] = { 0 };
//初始化mine 数组所有元素为'0',show 数组所有元素为'*'
//Init(mine, show, ROWS, COLS);
Init(mine, ROWS, COLS, '0');
Init(show, ROWS, COLS, '*');
//设置地雷
setMine(mine, ROWS, COLS);
//打印mine 数组
DisplayBoard(mine, ROWS, COLS);
printf("\n");
printf("-------------------------\n");
printf("\n");
//打印游戏面板
DisplayBoard(show, ROWS, COLS);
//第一步不被炸死
SafeMove(mine, show, ROWS, COLS);
//如果面板上剩下的'*' 与地雷的总数相同时,玩家赢
if (CountShow(show, ROWS, COLS) == EASY_MODE)
{
printf("-------------------------\n");
DisplayBoard(mine, ROWS, COLS);
printf("恭喜你!你赢了!\n");
return;
}
/*DisplayBoard(mine, ROWS, COLS);
printf("\n");
printf("-------------------------\n");
printf("\n");*/
DisplayBoard(show, ROWS, COLS);
while (1)
{
//判断玩家选择的坐标是不是地雷,若是则返回1,若不是则展开附近地雷信息
is = FindMine(mine, show, ROWS, COLS);
//如果面板上剩下的'*' 与地雷的总数相同时,玩家赢
if (CountShow(show, ROWS, COLS) == EASY_MODE)
{
printf("-------------------------\n");
DisplayBoard(mine, ROWS, COLS);
printf("恭喜你!你赢了!\n");
break;
}
if (is == 1)
{
printf("BOOM!!!!!!!!!!\n");
printf("很遗憾,你被炸死了!\n");
DisplayBoard(mine, ROWS, COLS);
break;
}
/* DisplayBoard(mine, ROWS, COLS);
printf("\n");
printf("-------------------------\n");
printf("\n");*/
DisplayBoard(show, ROWS, COLS);
}
}
int main(void)
{
int i = 0;
int j = 0;
int input = 0;
srand((unsigned int)time(NULL));
//调用菜单函数,打印游戏菜单
menu();
do
{
printf("请输入您要选的选项:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("输入错误!请重新输入!\n");
break;
}
} while (input);
system("pause");
return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void Init(char board[ROWS][COLS], int row, int col, char ch)
{
memset(&board[0][0], ch, row*col*sizeof(board[0][0]));
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//打印横坐标
printf("0 ");
for (i = 1; i < row - 1; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i < row - 1; i++)
{
printf("%d ", i);
for (j = 1; j < col - 1; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void setMine(char mine[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = EASY_MODE;
while (count)
{
//我们需要9个数字,如果%10产生的是0~8, 9个数字
//但是我们需要1~9,所以先%9产生8个数字,再加1就好
x = rand() % 9 + 1;
y = rand() % 9 + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
//踩到雷返回1,没有踩到雷返回0
int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
printf("请输入您选择的坐标:");
scanf("%d%d", &x, &y);
if (x < 1 && x > COL && y < 1 && y > ROW)
{
printf("您输入的坐标超过当前地图,请重新输入!\n");
}
else
{
if (mine[x][y] == '0')
{
char ch = GetCount(mine, x, y);
show[x][y] = ch + '0';
book[x][y] = 1;
open(mine, show, x, y);
if (CountShow(show, row, col) == EASY_MODE)
{
return 0;
}
}
else if (mine[x][y] == '1')
{
return 1;
}
}
return 0;
}
int GetCount(char mine[ROWS][COLS], int x, int y)
{
int count = 0;
//分别对(x,y)坐标周围8个格子进行判断,如果是雷则count + 1
//最后返回count就是(x,y)周围的地雷个数
if (mine[x - 1][y] == '1')
count++;
if (mine[x - 1][y - 1] == '1')
count++;
if (mine[x][y - 1] == '1')
count++;
if (mine[x + 1][y - 1] == '1')
count++;
if (mine[x + 1][y] == '1')
count++;
if (mine[x + 1][y + 1] == '1')
count++;
if (mine[x][y + 1] == '1')
count++;
if (mine[x - 1][y + 1] == '1')
count++;
return count;
}
//SafeMove函数是保证玩家输入第一个坐标时不被炸死
void SafeMove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int flag = 1;
int count = 0;
char ch = 0;
while (1)
{
printf("请输入您要选择的坐标:");
scanf("%d%d", &x, &y);
if (x < 1 && x > COL && y < 1 && y > ROW)
{
printf("您输入的坐标超过当前地图,请重新输入!\n");
continue;
}
if (mine[x][y] == '1')
{
//如果玩家输入的坐标是1,则强行把这个坐标改为0
mine[x][y] = '0';
char ch = GetCount(mine, x, y);
show[x][y] = ch + '0';
book[x][y] = 1;
open(mine, show, x, y);
//将一个地雷改为了空地,则需要再随机填一个雷
while (flag)
{
x = rand() % 9 + 1;
y = rand() % 9 + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
flag--;
break;
}
}break;
}
else if (mine[x][y] == '0')
{
char ch = GetCount(mine, x, y);
show[x][y] = ch + '0';
book[x][y] = 1;
open(mine, show, x, y);
break;
}
}
}
//用深度优先搜索来对面板展开
void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int tx = 0;
int ty = 0;
int k = 0;
//定义next数组,用来对四个方向进行搜索
int next[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
//在展开的时候如果GetCount函数返回的不是0,则给show数组赋返回的值
if (GetCount(mine, x, y) != 0)
{
show[x][y] = GetCount(mine, x, y) + '0';
}
//如果是0,给show数组那个位置赋空格
else if (GetCount(mine, x, y) == 0)
{
show[x][y] = ' ';
}
for (k = 0; k <= 3; k++)
{
tx = x + next[k][0];
ty = y + next[k][1];
if (tx < 1 || tx > ROW || ty < 1 || ty > COL)
{
continue;
}
if (mine[tx][ty] == '0' && book[tx][ty] == 0 && GetCount(mine, tx, ty) < 1)
{
book[tx][ty] = 1;
open(mine, show, tx, ty);
}
//这一步很关键,是展开时遇到数字停下来的一步
if (mine[tx][ty] == '0' && book[tx][ty] == 0 && GetCount(mine, tx, ty) > 0)
{
show[tx][ty] = GetCount(mine, tx, ty) + '0';
continue;
}
}
return;
}
//统计面板上剩下的'*'
int CountShow(char show[ROWS][COLS], int row, int col)//判断剩余未知区域的个数,个数为雷数时玩家赢
{
int count = 0;
int i = 0;
int j = 0;
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if (show[i][j] == '*')
{
count++;
}
}
}
return count;
}