C语言版扫雷(纯代码)

Posted 庸人冲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言版扫雷(纯代码)相关的知识,希望对你有一定的参考价值。

简介

游戏通过game.hgame.ctest.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语言版扫雷(纯代码)的主要内容,如果未能解决你的问题,请参考以下文章

C语言实现简易版 扫雷 步骤及代码

C语言实现简易版 扫雷 步骤及代码

如何用C语言快速实现初级版扫雷(步骤详细)

扫雷(C语言版)

C语言实现扫雷简易版

急求C语言编译的小游戏(如扫雷),附带源代码和注释。