目录
1.模块化与思路
可以采用模块化的方式来制作,这里我们创建两个源文件,一个头文件。
game.h的头文件里存放头文件,函数定义和自定义信息。
test.c 实现大体逻辑和游戏的主体功能。
game.c里面实现所有具体功能的函数。
test.c main函数思路:
主要封装两个函数
-menu()打印菜单
-minesweeper()扫雷游戏
minesweeper()扫雷游戏思路:
棋盘实现思路:
假如用于实现初级的扫雷: 需要9 * 9的格子来展示,所以需要使用二维数组来构建棋盘。
因为打印出来给玩家看的数组不能暴露雷的位置,还要时时打印排雷的位置上周围雷的位置。我们可以创建两个棋盘mine,show。一个是用于放雷的(玩家不可见),拿来记录雷的位置便于统计周围的雷的数字。另一个是用于排查显示的,需要初始化为全*,随时更新和打印给玩家看。
为了可以较方便改变雷的数目和棋盘的大小,在game.h里定义棋盘的行数列数和雷的个数。
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE_COUNT 10
//因为计算坐标周围雷的个数时,要计算周围八个坐标中雷的个数之和。为了防止当坐标在边角时,计算周围雷的个数时发生数组越界,mine数组和show数组大小都应在扫雷盘面的大小基础上各增加两行或两列。
minesweeper()扫雷游戏封装函数和功能
主要封装五个函数
-init_show(show,ROWS,COLS); //初始化show数组全为*
-init_mine(mine, ROWS, COLS, MINE_COUNT); //初始化mine数组全为0,随机数布置雷(记1)
-print(arr, ROW, COL);//打印show或者mine棋盘,根据arr传进来啥就打印啥
-dispose(show, mine, ROWS, COLS, i, j);
//对玩家要排雷的坐标进行处理。 如果是雷返回1,如果不是,尽可能把所有的非雷数字放进show数组,返回0
//像下面两种都是非雷的情况。对于坐标来说,如果周围一圈都是非雷,需要类似再处理周围八个坐标。
-numof(show, ROW, COL)//计算当前棋盘的空位并返回,用于判断是否成功排完所有雷了
2.各文件和函数具体实现
注释都在daim!
test.c文件
-主要是main函数实现循环逻辑
-menu 和minesweepr 在game.c具体实现
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
int main()
{
srand((unsigned int)time(NULL));
int flag = 0;
do {
menu();
scanf("%d", &flag);
if (1 == flag)
{
system("cls");
minesweeper();
}
else if (0 == flag)
printf("退出游戏!");
else
printf("输入的数字无效,请重新输入!");
} while (flag);
return 0;
}
game.c文件
menu和minesweepr函数:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h" //包含头文件
void menu()
{
printf("--------welcom!--------\n");
printf("--------1.play --------\n");
printf("--------0.exit --------\n");
printf("-----请输入选择:>------\n");
}
void minesweeper()
{
char show[ROWS][COLS] = { 0 };
char mine[ROWS][COLS] = { 0 };
init_show(show,ROWS,COLS);
init_mine(mine, ROWS, COLS, MINE_COUNT);
print(show, ROW, COL);
int i = 0;
int j = 0;
do {
if (numof(show, ROW, COL) > MINE_COUNT)
{
//有空位
printf("请输入您要排雷的坐标:>");
scanf("%d %d", &i, &j);
if (i >= 1 && i <= 9 && j >= 1 && j <= 9)
{
//坐标没超出范围
int flag = dispose(show, mine, ROWS, COLS, i, j);
//如果是雷返回1,否则把所有的非雷数字放进show数组,返回0
if (flag)
{
print(mine, ROW, COL);
printf("很遗憾,您扫雷失败。\n");
break;
}
else
{
print(show, ROW, COL);
}
}
else
{
//坐标超范围
printf("您输入的坐标有误!请重新输入!\n");
}
}
else
{
//没空位
printf("恭喜你,扫雷成功!\n");
break;
}
} while (1);
}
init_show和init_mine函数
void init_show(char show[ROWS][COLS], int rows, int cols)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
show[i][j] = '*';
}
}
}
void init_mine(char mine[ROWS][COLS], int rows, int cols,int mine_count)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
mine[i][j] = '0';
}
}
//布雷
while (mine_count > 0)
{
i = rand() % 9 + 1;
j = rand() % 9 + 1;
if (mine[i][j] == '0')
{
mine[i][j] = '1';
mine_count--;
}
}
}
print函数
void print(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//美化打印出来的棋盘,加上列数坐标
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n - - - - - - - - -\n");
for (i = 1; i <= row; i++)
{
printf("%d|", i);//美化打印出来的棋盘,加行数坐标
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
numof函数
int numof(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int num = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*')
num++;
}
}
return num;
}
dispose函数
int dispose(char show[ROWS][COLS], char mine[ROWS][COLS], int rows, int cols, int i, int j)
{
//判断是不是雷
if (mine[i][j] == '1')
{
return 1;
}
else
{
int flag = mine[i - 1][j - 1] + mine[i][j - 1] + mine[i + 1][j - 1]
+ mine[i - 1][j] + mine[i + 1][j]
+ mine[i - 1][j + 1] + mine[i][j + 1] + mine[i + 1][j + 1];
if (flag == '0' * 8)
{
//周围都是0,没有雷,递归
show[i][j] = ' ';
if(show[i - 1][j - 1]=='*') //说明没有处理过,递归处理
dispose( show,mine, ROWS, COLS, i-1, j-1);
if (show[i][j - 1] == '*')
dispose(show, mine, ROWS, COLS, i , j - 1);
if (show[i + 1][j - 1] == '*')
dispose(show, mine, ROWS, COLS, i + 1, j - 1);
if (show[i - 1][j ] == '*')
dispose(show, mine, ROWS, COLS, i - 1, j );
if (show[i + 1][j ] == '*')
dispose(show, mine, ROWS, COLS, i + 1, j );
if (show[i - 1][j + 1] == '*')
dispose(show, mine, ROWS, COLS, i - 1, j + 1);
if (show[i ][j + 1] == '*')
dispose(show, mine, ROWS, COLS, i , j + 1);
if (show[i + 1][j + 1] == '*')
dispose(show, mine, ROWS, COLS, i + 1, j + 1);
return 0;
}
else
{
//周围有雷,记录周围雷的个数并打印
show[i][j] = flag - '0' * 8+'0';
return 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 MINE_COUNT 10
void menu();
void minesweeper();
void init_show(char show[ROWS][COLS],int rows, int cols);
void init_mine(char mine[ROWS][COLS], int rows, int cols,int mine_count);
void print(char arr[ROWS][COLS], int row, int col);
int dispose(char show[ROWS][COLS], char mine[ROWS][COLS], int rows,int cols, int i,int j);
int numof(char show[ROWS][COLS], int row, int col);