game.h(头文件):
//.h文件通常存放:函数声明,定义的常量
#include <time.h>//要用到随机数
#include <stdlib.h>//要用到随机数
#include <windows.h>//要清理屏幕
//定义常量避免到处修改
#define ROW 9
#define COL 9
#define ROWS ROW+2//避免越界
#define COLS COL+2//避免越界
//菜单函数
void menu();
//初始化棋盘函数
void set(char a[ROWS][COLS], int rows, int cols, char b);
//布置地雷函数
void setMine(char a[ROWS][COLS], int rows, int cols);
//打印棋盘函数
void showBoard(char a[ROWS][COLS], int row, int col);
//计算地雷个数函数
int count(char a[ROWS][COLS],int m,int n);
game.c(函数实现文件):
#include "game.h"//包含函数声明,定义的常量
#include <stdio.h>
//菜单函数
void menu()
{
printf("**********************************\n");
printf("******* 1 play *******\n");
printf("******* 0 exit *******\n");
printf("**********************************\n");
}
//实现扫雷游戏的主要逻辑在这个函数
void game()
{
char Board[ROWS][COLS];//玩家看到的雷区
char Mine[ROWS][COLS];//布好的地雷放在这个数组
//初始化棋盘
set(Board, ROWS, COLS, '*');
//初始化地雷
set(Mine, ROWS, COLS, '0');
//布置地雷
setMine(Mine, ROW, COL);
printf("------扫雷游戏-------\n");
//展示棋盘
showBoard(Board, ROW, COL);
//可以边写边测,不要把所有代码写完再调试,“coding一时爽,调试火葬场”
//可以对照生成的地雷来测试
//showBoard(Mine, ROW, COL);
//让玩家先输入一维(纵),再输入二维(横)
printf("请输入要排查的坐标:(先纵后横)");
int m = 0;
int n = 0;
while (1)//死循环的排查,直到踩雷
{
scanf("%d %d", &m, &n);//m 横 n 纵
//玩家万一输错坐标
if (m < 1 || m>ROW || n < 1 || n>ROW)
{
printf("坐标有误,请重新输入:");
continue;
}
//玩家输入已排查的坐标
if (Board[m][n] != '*')
{
printf("这个位置已经排查过了,请重新输入坐标:");
continue;
}
//玩家踩雷了
if (Mine[m][n] == '1')
{
system("cls");
printf("你被炸死了,地雷排布如下(1是地雷):\n");
//把地雷展示给玩家
showBoard(Mine, ROW, COL);
break;
}
//玩家没踩雷,要显示玩家输入的坐标附近的地雷数量
else
{
system("cls");
int r;
//count函数:计算排查的坐标附近的地雷数量,并赋值给r
r = count(Mine, m, n);
//棋盘数组是字符型数组,比如要显示字符‘3’,'0'+r可以表示3的ASCII值
Board[m][n] = '0'+r;
//把排查后的棋盘展示给玩家,供玩家决策
printf("------扫雷游戏-------\n");
showBoard(Board, ROW, COL);
printf("请输入要排查的坐标:(先纵后横)");
}
}
}
//初始化棋盘函数
void set(char a[ROWS][COLS], int rows, int cols, char b)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
a[i][j] = b;
}
}
}
//布置地雷函数
void setMine(char a[ROWS][COLS], int row, int col)
{
//一共布置10个地雷
int count = 10;
do {
int m = rand() % row + 1;//棋盘是9*9大小,所以要生成1-9的随机数
int n = rand() % row + 1;
//生成的随机数可能会重复
if (a[m][n] == '1')
{
continue;
}
//用‘1’表示地雷
a[m][n] = '1';
//成功布雷后使count减一
count--;
} while (count);//直到count==0,就不再布雷
}
//打印棋盘函数
void showBoard(char a[ROWS][COLS], int row, int col)
{
//提醒玩家
printf(" 横");
//打印横坐标
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
}
printf("\n"); //横坐标与棋盘有一定距离(为了美观)
printf("\n");
printf("纵");
printf("\n");
for (int i = 1; i <= row; i++)
{
//每次打印一行棋盘前,打印纵坐标
printf("%d", i);
//纵坐标与棋盘有一定距离(为了美观)
printf(" ");
for (int j = 1; j <= col; j++)
{
printf("%c ", a[i][j]);
}
//打印一行棋盘后,注意换行
printf("\n");
}
}
//计算地雷个数函数
int count(char a[ROWS][COLS],int m,int n)
{
//返回值是地雷个数的ASCII码值,用%c打印
return a[m - 1][n - 1] +
a[m - 1][n] +
a[m - 1][n + 1] +
a[m][n - 1] +
a[m][n + 1] +
a[m + 1][n - 1] +
a[m + 1][n] +
a[m + 1][n + 1] - 8 * '0';
}
test.c(主函数):
#include <stdio.h>
#include "game.h"
int main()
{
int input;
srand((unsigned int)time(NULL));//随机生成随机数的种子,
//放在主函数的原因是:不能
//短时间多次生成,否则随机性
//会降低
do
{
menu();//调用菜单函数,打印菜单
printf("请选择---->");
scanf("%d", &input);
system("cls");
switch (input)
{
case 0:printf("已退出游戏\n"); break;
case 1:game(); break;
default:printf("输入错误,请重新输入\n"); break;
}
} while (input);
return 0;
}
运行示例:
待改进的地方:
1、用函数递归实现连片排查
2、难度选择
3、地雷标记
4、胜利条件