C语言版扫雷(纯代码)
Posted 庸人冲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言版扫雷(纯代码)相关的知识,希望对你有一定的参考价值。
简介
游戏通过game.h
、game.c
和test.c
三个文件协同实现,因为最近时间比较紧张,暂时先把代码贴出来,希望能帮到有需要的小伙伴,同时代码中也存在不足的地方,还请各位大佬批评指正。
game.h 文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9 // 棋盘显示的行数
#define COL 9 // 棋盘显示的列数
#define ROWS COL+2 // 实际的行数
#define COLS ROW+2 // 实际的列数
#define EASY 10 // 简单模式(表示雷的数量)
#define MEDIUM 30 // 普通模式
#define HARD 50 // 困难模式
#define EXTREME 80 // 极端模式
/*
初始化棋盘
操作条件:未初始化的棋盘
操作结果:将棋盘中每个空格都初始化为指定默认值set
*/
extern void InitBoard(char board[ROWS][COLS],int rows,int cols, char set);
/*
显示棋盘
操作条件:以初始化的棋盘
操作结果:显示棋盘 1~ROW行 1~COL列的元素
*/
extern void ShowBoard(char board[ROWS][COLS], int row, int col);
/*
布置雷
操作条件: 以初始化的棋盘,雷的位置 行:1~ROW 列:1~COL
操作结果:在棋盘中随机布置指定个数的雷
*/
extern void SetMine(char mine[ROWS][COLS], int row, int col, int game_mode);
/*
扫雷
操作条件:以布置完毕的棋盘
操作结果:提示玩家输入合理坐标,并根据玩家输入的坐标,显示找到相应的区域并判断
1. 如果坐标不合适,则提示玩家重新输入。
2. 如果坐标合适,则判断该位置是否有雷。
1.1 如果有雷则提示玩家失败,并退出函数
1.2 如果没有雷,则判断周围该坐标周围8个位置雷的个数,并将该数赋值给show棋盘相应位置
*/
extern void SweepMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row, int col);
/*
统计周围雷的数量
操作条件:以布置完毕的棋盘
操作结果:返回指定坐标周围8个位置雷的数量;
*/
extern int CountMineNum(char mine[ROWS][COLS], int x, int y);
/*
* 打开周围非雷区域
* 操作条件:玩家选择扫雷位置后
* 操作结果:根据条件选择是否递归将周围的空白区域打开,并赋值给show棋盘相应位置
*/
extern void OpenNull(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);
/*
判断是否玩家胜利
操作条件:玩家选择扫雷位置后
操作结果:如果count == 当前模式中雷的数量,则胜利返回0, 否则返回1
*/
extern int isWin(char show[ROWS][COLS], int row, int col);
game.c 文件
#include "game.h"
/*
初始化棋盘
操作条件:为初始化的棋盘
操作结果:将棋盘中每个空格都初始化为指定默认值set
*/
void InitBoard(char board[ROWS][COLS],int rows,int cols, char set)
{
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
/*
显示棋盘
操作条件:以初始的棋盘
操作结果:显示棋盘中 1~ROW行 1~COL列 的元素
*/
void ShowBoard(char board[ROWS][COLS], int row, int col)
{
int i, j;
printf("====================\\n");
for (i = 0; i <= row; 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"); // 换行
}
}
/*
布置雷
操作条件: 以初始化的棋盘,雷的位置 行:1~ROW 列:1~COL
操作结果:在棋盘中随机布置指定个数的雷,雷使用'1'来表示
*/
void SetMine(char mine[ROWS][COLS], int row, int col, int count)
{
// 每当设置成功一个雷,count--;
while (count)
{
int x = rand() % row + 1; // 设置随机生成x坐标的范围
int y = rand() % col + 1; // 设置随机生成y坐标的范围
if (mine[x][y] != '1')
{
mine[x][y] = '1';
count--;
}
}
}
/*
扫雷
操作条件:以布置完毕的棋盘
操作结果:提示玩家输入合理坐标,并根据玩家输入的坐标,显示找到相应的区域并判断
1. 如果坐标不合适,则提示玩家重新输入。
2. 如果坐标合适,则判断该位置是否有雷。
1.1 如果有雷则提示玩家失败,并退出函数
1.2 如果没有雷,则判断周围该坐标周围8个位置雷的个数,并将该数赋值给show棋盘相应位置
*/
void SweepMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0, y = 0,num = 0,count = 0,win = 1;
// 输入坐标
while (win)
{
// 显示棋盘
ShowBoard(show, ROW, COL);
printf("请输入坐标:>");
scanf("%d%d", &x, &y);
if (x < 1 || x > row || y < 1 || y > col) // 当位置不合适时
{
printf("输入有误,请重新输入!\\n");
}
else if (mine[x][y] == '1') // 当踩雷时
{
printf("扫雷失败,再接再厉!\\n");
ShowBoard(mine, ROW, COL); // 显示mine棋盘
return;
}
else { // 当位置合适时
OpenNull(mine,show,x,y,row,col);
win = isWin(show, row, col); // 判断输赢
}
}
printf("扫雷成功,恭喜!!\\n");
}
/*
统计周围雷的数量
操作条件:玩家选择扫雷位置后
操作结果:返回指定坐标周围8个位置雷的数量;
*/
int CountMineNum(char mine[ROWS][COLS],int x, int y)
{
int i = 0, j = 0, count = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (mine[i][j] == '1')
count++;
}
}
return count;
}
/*
* 打开周围非雷区域
* 操作条件:玩家选择扫雷位置后
* 操作结果:根据条件选择是否递归将周围的空白区域打开,并赋值给show棋盘相应位置
*/
void OpenNull(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col)
{
int i = 0, j = 0,count = 0;
int num = CountMineNum(mine, x, y); // 如果 num == 0 则说明 (x,y)周围一圈没有雷
if (!num && 1 <= x && x <= row && 1 <= y && y <= col ) // 当num == 0 并且 x,y 的坐标合适时进入
{
show[x][y] = ' '; // 将 num == 0 的这个位置 赋值为空
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (show[i][j] != ' ')
{
OpenNull(mine, show, i, j, row, col);
}
}
}
}
else {
show[x][y] = num + '0';
}
}
/*
判断是否玩家胜利
操作条件:玩家选择扫雷位置后
操作结果:如果count == 当前模式中雷的数量,则胜利返回0, 否则返回1
*/
int isWin(char show[ROWS][COLS], int row, int col)
{
int i = 0, j = 0,count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*') // 遍历整个show棋盘,统计当前棋盘中 '*' 的数量
{
count++;
}
}
}
if (count == EASY) // 如果count统计的数 == 当前模式下雷的数量,说明剩余未翻开的位置全部是雷,则胜利
return 0; // 返回0,使得外部主调函数退出循环
return 1; // 否则return 1,表示继续
}
test.c 文件
#include "game.h"
// 菜单函数
void menu()
{
printf("**********************************************************\\n");
printf("******************* 1. Play *********************\\n");
printf("******************* 0. Exit *********************\\n");
printf("**********************************************************\\n");
printf("请输入选择:>");
}
void game()
{
printf("欢迎进入扫雷游戏!\\n");
srand((unsigned int)time(NULL));
// 创建两个棋盘
char mine[ROWS][COLS]; // 用来存放雷的信息
char show[ROWS][COLS]; // 用来显示排查雷的信息
// 初始化两个棋盘
InitBoard(mine,ROWS,COLS, '0'); // 设置'0' 为mine棋盘中默认值
InitBoard(show, ROWS, COLS, '*'); // 设置'*' 为show棋盘中默认值
// 布置雷
SetMine(mine, ROW, COL, EASY);
// 扫雷
SweepMine(mine, show, ROW, COL);
}
int main()
{
int input = 1;
while (input)
{
menu();
scanf("%d", &input);
while (getchar() != '\\n') {
; // 防止玩家输入非数字导致死循环
}
switch (input)
{
case 1:
// 进入游戏
game();
break;
case 0:
// 退出游戏
printf("退出成功!\\n");
break;
default:
printf("输入有误请重新输入!\\n");
break;
}
}
return 0;
}
游戏效果
以上是关于C语言版扫雷(纯代码)的主要内容,如果未能解决你的问题,请参考以下文章