TvT——C语言初阶の扫雷游戏

本文详细介绍了扫雷游戏的逻辑和C语言实现,包括初始化棋盘、随机布置雷、排查雷函数、标记与取消标记功能,以及游戏胜利和失败的判断。通过递归展开相邻安全区,实现游戏的智能推进。同时,提供了游戏菜单和交互操作,增强了用户体验。
摘要由CSDN通过智能技术生成

一、游戏基本逻辑

扫雷游戏:一个棋盘上存在数个不知位置的地雷,需要玩家根据安全区域周围雷的个数判断地雷的具体位置,直到棋盘上仅剩地雷为止,扫雷成功,游戏胜利。

二、代码实现

1.最先显示的菜单menu

打印菜单。

void menu()
{
	printf("************************************\n");
	printf("********  1.扫雷游戏   *************\n");
	printf("********  0.退出       *************\n");
	printf("************************************\n");
}

2.game函数

void game()
{
	char mineboard[ROWS][COLS];
	char showboard[ROWS][COLS];
	//初始化棋盘
	Initboard(mineboard, ROWS, COLS,'0');
	Initboard(showboard, ROWS, COLS,'*');
	//打印棋盘
	//Displayboard(mineboard, ROW, COL);
	Displayboard(showboard, ROW, COL);
	//布置雷
	Setmine(mineboard, ROW, COL);
	//Displayboard(mineboard, ROW, COL);
	//排查雷
	Putmine(mineboard,showboard, ROWS, COLS);

}
①.初始化棋盘函数
void Initboard(char board[ROWS][COLS], int rows, int cols,char ret)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ret;
		}
	}
}
②.布置雷函数

利用库的时间函数实现随机布置雷。

void Setmine(char board[ROWS][COLS], int row, int col)//设置雷
{
	int i = 0;

	while( i < count )
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] != '1')//判断合理性
		{
			board[x][y] = '1';
			i++;
		}
	}
}
③.排查雷函数

包括判断坐标合理性、判断游戏是否失败或胜利功能。

void Putmine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{

	int x = 0;
	int y = 0;
	int m = 0;
	int n = 0;
	int ret = 0;
	int input = 0;
	while (1)
	{
		while (1)
		{
			menu1();
			scanf("%d", &input);
			switch (input)
			{
			case 1:
			{
				while (1)
				{
					printf("请输入需要排查的坐标:> ");
					scanf("%d %d", &x, &y);//需要判断合理性
					if (x <= ROW && y <= COL)
					{
						break;
					}
					else
					{
						printf("输入的坐标错误,请重新输入。\n");

					}
				}
				break;
			}
			case 2:
			{
				while (1)
				{
					printf("请输入需要标记的坐标:> ");
					scanf_s("%d %d", &m, &n);//需要判断合理性
					if (m <= ROW && n <= COL)
					{
						break;
					}
					else
					{
						printf("输入的坐标错误,请重新输入。\n");
					}
				}
				sign_board(show, m, n);
				break;
			}
			case 3:
			{
				{
					while (1)
					{
						printf("请输入需要取消标记的坐标:> ");
						scanf_s("%d %d", &m, &n);//需要判断合理性
						if (m <= ROW && n <= COL)
						{
							break;
						}
						else
						{
							printf("输入的坐标错误,请重新输入。\n");
						}
					}
					void_board(show, m, n);
					break;
				}
			}
			}

			if (mine[x][y] == '1')
			{
				printf("很遗憾,您被炸死了\n");
				Displayboard(mine, ROW, COL);
				break;
			}
			if (mine[x][y] != '1')
			{
				/*int num = EASE_count(mine, x, y);
				show[x][y] = num +'0';*/
				Sqre_count(mine, show, x, y);
				Displayboard(show, ROW, COL);
				ret++;
				if (ret == ROW * COL - count)
				{
					printf("恭喜你,游戏胜利。\n");
					break;
				}
			}
		}
		break;

	}
}
a.雷个数统计函数
static int EASE_count(char board[ROWS][COLS],int a,int b)//个数统计
{
	return board[a - 1][b - 1]
		+ board[a - 1][b]
		+ board[a - 1][b + 1]
		+ board[a][b + 1]
		+ board[a][b - 1]
		+ board[a + 1][b - 1]
		+ board[a + 1][b]
		+ board[a + 1][b + 1]
		- 8 * '0';
}
b.展开一片函数

展开函数运用了递归的方法。
首先我们要知道递归需要有一个限制范围。
这个展开函数需要满足三个条件才可以继续执行
1.自身不是雷
2.自身周围八个坐标没有雷
3.不可以递归已经排查过的坐标
第一个问题很好理解,根据排查雷函数,只有当自身不是雷的时候才会调用展开一片函数,而如果自身周围有雷的话根本不会进行递归,所以不存在自身是雷这个问题。

		if (mine[x][y] == '1')
			{
				printf("很遗憾,您被炸死了\n");
				Displayboard(mine, ROW, COL);
				break;
			}
			if (mine[x][y] != '1')
			{
				/*int num = EASE_count(mine, x, y);
				show[x][y] = num +'0';*/
				Sqre_count(mine, show, x, y);
				Displayboard(show, ROW, COL);
				ret++;
				if (ret == ROW * COL - count)
				{
					printf("恭喜你,游戏胜利。\n");
					break;
				}
			}

第二个问题是自身周围没有雷,调用雷个数统计函数可知坐标周围雷的个数,如坐标周围有雷则会结束函数,不会进行递归。
第三个问题是不递归之前已经递归过的坐标,只要检查show[i][j]就可以知道此坐标有没有被递归过,如果show[i][j]被递归过则此坐标在棋盘中将不会为‘*’。

static void Sqre_count(char board[ROWS][COLS],char show[ROWS][COLS],int a,int b)//展开
{
	int x = 0;
	x = EASE_count(board, a, b);
	
	if (x == 0)
	{
		show[a][b] = ' ';
		int i = 0;
		for (i = a - 1; i <= a + 1; i++)
		{
			int j = 0;
			for (j = b - 1; j <= b + 1; j++)
			{
				if (show[i][j] == '*')
					Sqre_count(board, show, i, j);
			}
		}
	}
	else 
	{
		show[a][b] = x + '0';
	}
	
	
}
c.标记函数
static void sign_board( char show[ROWS][COLS], int a, int b)//标记
{
	if (show[a][b] == '*')
	{
		show[a][b] = '_';
	}
	else
	{
		printf("此位置不可标记。\n");
	}
}
d.取消标记函数
static void void_board(char show[ROWS][COLS], int a, int b)//取消标记
{
	if (show[a][b] == '_')
	{
		show[a][b] = '*';
	}
	else
	{
		printf("此位置不可取消标记。\n");
	}
}
e.判断是扫雷还是标记还是取消标记的菜单
static void menu1()
{
	printf("************************************\n");
	printf("********  1.排查坐标   *************\n");
	printf("********  2.标记坐标   *************\n");
	printf("********  3.取消坐标   *************\n");
	printf("************************************\n");
}
④.打印棋盘函数
void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	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");
	}
	printf("----------扫雷游戏------------------\n");
}

3.main函数

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

三、总代码

1.test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

//扫雷
//1.创建雷盘
//2.扫雷
//3.判断是否爆炸
void menu()
{
	printf("************************************\n");
	printf("********  1.扫雷游戏   *************\n");
	printf("********  0.退出       *************\n");
	printf("************************************\n");
}

void game()
{
	char mineboard[ROWS][COLS];
	char showboard[ROWS][COLS];
	//初始化棋盘
	Initboard(mineboard, ROWS, COLS,'0');
	Initboard(showboard, ROWS, COLS,'*');
	//打印棋盘
	//Displayboard(mineboard, ROW, COL);
	Displayboard(showboard, ROW, COL);
	//布置雷
	Setmine(mineboard, ROW, COL);
	//Displayboard(mineboard, ROW, COL);
	//排查雷
	Putmine(mineboard,showboard, ROWS, COLS);

}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

2.game.c

#pragma once
#include"game.h"


void Initboard(char board[ROWS][COLS], int rows, int cols,char ret)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ret;
		}
	}
}

void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	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");
	}
	printf("----------扫雷游戏------------------\n");
}

void Setmine(char board[ROWS][COLS], int row, int col)//设置雷
{
	int i = 0;

	while( i < count )
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] != '1')//判断合理性
		{
			board[x][y] = '1';
			i++;
		}
	}
}

static int EASE_count(char board[ROWS][COLS],int a,int b)//个数统计
{
	return board[a - 1][b - 1]
		+ board[a - 1][b]
		+ board[a - 1][b + 1]
		+ board[a][b + 1]
		+ board[a][b - 1]
		+ board[a + 1][b - 1]
		+ board[a + 1][b]
		+ board[a + 1][b + 1]
		- 8 * '0';
}

static void Sqre_count(char board[ROWS][COLS],char show[ROWS][COLS],int a,int b)//展开
{
	int x = 0;
	x = EASE_count(board, a, b);
	
	if (x == 0)
	{
		show[a][b] = ' ';
		int i = 0;
		for (i = a - 1; i <= a + 1; i++)
		{
			int j = 0;
			for (j = b - 1; j <= b + 1; j++)
			{
				if (show[i][j] == '*')
					Sqre_count(board, show, i, j);
			}
		}
	}
	else 
	{
		show[a][b] = x + '0';
	}
	
	
}

static void sign_board( char show[ROWS][COLS], int a, int b)//标记
{
	if (show[a][b] == '*')
	{
		show[a][b] = '_';
	}
	else
	{
		printf("此位置不可标记。\n");
	}
}

static void void_board(char show[ROWS][COLS], int a, int b)//取消标记
{
	if (show[a][b] == '_')
	{
		show[a][b] = '*';
	}
	else
	{
		printf("此位置不可取消标记。\n");
	}
}

static void menu1()
{
	printf("************************************\n");
	printf("********  1.排查坐标   *************\n");
	printf("********  2.标记坐标   *************\n");
	printf("********  3.取消坐标   *************\n");
	printf("************************************\n");
}
void Putmine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{

	int x = 0;
	int y = 0;
	int m = 0;
	int n = 0;
	int ret = 0;
	int input = 0;
	while (1)
	{
		while (1)
		{
			menu1();
			scanf("%d", &input);
			switch (input)
			{
			case 1:
			{
				while (1)
				{
					printf("请输入需要排查的坐标:> ");
					scanf("%d %d", &x, &y);//需要判断合理性
					if (x <= ROW && y <= COL)
					{
						break;
					}
					else
					{
						printf("输入的坐标错误,请重新输入。\n");

					}
				}
				break;
			}
			case 2:
			{
				while (1)
				{
					printf("请输入需要标记的坐标:> ");
					scanf_s("%d %d", &m, &n);//需要判断合理性
					if (m <= ROW && n <= COL)
					{
						break;
					}
					else
					{
						printf("输入的坐标错误,请重新输入。\n");
					}
				}
				sign_board(show, m, n);
				break;
			}
			case 3:
			{
				{
					while (1)
					{
						printf("请输入需要取消标记的坐标:> ");
						scanf_s("%d %d", &m, &n);//需要判断合理性
						if (m <= ROW && n <= COL)
						{
							break;
						}
						else
						{
							printf("输入的坐标错误,请重新输入。\n");
						}
					}
					void_board(show, m, n);
					break;
				}
			}
			}

			if (mine[x][y] == '1')
			{
				printf("很遗憾,您被炸死了\n");
				Displayboard(mine, ROW, COL);
				break;
			}
			if (mine[x][y] != '1')
			{
				/*int num = EASE_count(mine, x, y);
				show[x][y] = num +'0';*/
				Sqre_count(mine, show, x, y);
				Displayboard(show, ROW, COL);
				ret++;
				if (ret == ROW * COL - count)
				{
					printf("恭喜你,游戏胜利。\n");
					break;
				}
			}
		}
		break;

	}
}

3.game.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROWS 11
#define COLS 11
#define ROW ROWS-2
#define COL COLS-2
#define count 10

void Initboard(char board[ROWS][COLS], int rows, int cols,char ret);

void Displayboard(char board[ROWS][COLS], int row, int col);

void Setmine(char board[ROWS][COLS], int row,int col);

void Putmine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值