C-扫雷小游戏

版权声明:Zhining https://blog.csdn.net/weixin_43214609/article/details/83349979

要实现的结果:

  • 实现扫雷游戏的基本功能
  • 能够展开一片无雷区域
  • 能够在输入的坐标显示附近八邻域的雷数
  • 不要让玩家走第一步就被"炸死"

实现的思路及代码:


1.想清楚这个游戏应该分为几个板块,什么函数并实现什么功能,函数应放在那个板块等等,然后再一点点填充函数定义。

这个游戏我计划用两个源文件test.c和game.c,头文件game.h。

  • test.c实现的功能是接收玩家选项、实现游戏整体的流程。
  • game.c实现的是扫雷游戏,分为棋盘的初始化、棋盘的输出、布雷、接受玩家输入坐标、返回附近雷数等函数块。
  • game.h实现的是宏常量的定义、头文件定义、函数声明等,可以作为game.c文件的"目录"。.c文件只用调用game.h即可,省去了重复的头文件调用。

2.菜单选项

  • 不管什么游戏,第一个要创建的一定是菜单,用来接收玩家的选项,这里设置输入1代表玩游戏,0代表退出。在test.c中实现并测试整个流程,避免出现复杂的问题。
#include"game.h"

int main()
{
	
	do
	{
        int input = 1;
		printf("##############################\n");
		printf("#########   1. play   ########\n");
		printf("#########   0. exit   ########\n");
		printf("##############################\n");

		printf("请选择:>\n");
		scanf("%d", &input);
		system("cls");
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("<游戏已退出!>\n");
			break;
		default:
			printf("选择错误,请重新输入:>\n");
			break;
		}
	}while(1);


	system("pause");
	return 0;
}

3.现在来填充game.h文件,按照游戏预期效果来设置,

  • 创建棋盘->玩家走第一步->设置随机分布的雷->打印棋盘并在棋盘上输出附近雷数展开安全区->玩家走->判断是否可走->再打印…->①玩家踩雷->游戏结束->输出雷的分布棋盘; ②棋盘满但没有被"炸死"->玩家扫雷成功->输出雷的分布棋盘;

这是我的大致思路,先走第一步是为了不让玩家第一步被"炸死";接下来再game.h中实现声明。

#ifndef __GAME_H__
#define __GAME__H__

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

#define ROW 12
#define COL 12
#define COUNT 10//雷数

extern char show[ROW][COL];//展示数组
extern char mine[ROW][COL];//布雷数组

void player(char mine[ROW][COL], int row, int col, int x, int y);
//玩家走
void init(char show[ROW][COL], char mine[ROW][COL], int row, int col);
//初始化数组函数
void set_min( char mine[ROW][COL], int row, int col);
//随机布雷
int count_mine(char show[ROW][COL], char mine[ROW][COL], int row, int col);
//统计周围雷的个数
void print_player(char show[ROW][COL], char mine[ROW][COL], int row, int col);
//打印玩家棋盘
void print_mine( char mine[ROW][COL], int row, int col);
//打印有雷棋盘 
int game();
//扫雷函数
void open_mine(int x, int y);
//展开函数
int count_show_mine(char show[ROW][COL], char mine[ROW][COL],int row,int col); 
//判断玩家棋盘剩余未知区域的个数

#endif  

3.接下来逐个填充函数

  • 首先从game()开始,将每个函数分配在游戏过程中。
int game()
{
	srand((unsigned int)time(0));
	char show[ROW][COL] = { 0 };
	char mine[ROW][COL] = { 0 }; 
	int x = 0, y = 0;
	int row = ROW, col = COL;
	init_board(show[ROW][COL], mine[ROW][COL], row, col);//初始化雷阵
	print_player(show[ROW][COL], mine[ROW][COL], row, col);
	printf("请输入坐标:>");
	scanf("%d %d", &x, &y);
	show[x][y] = 0;//第一步不会炸死
	print_player(show[ROW][COL], mine[ROW][COL], row, col);//输出棋盘
	set_min(mine[ROW][COL],  row, col);//放雷
	int ret = player(show[ROW][COL], row, col);//玩家走并判断
	if (ret )
	{
		printf("很遗憾,你被'炸死'了\n");
	}
	else
	{
		player(show[ROW][COL], row, col);
	}
	return 1;
}
  • 初始化两个数组

void init(char show[ROW][COL], char mine[ROW][COL], int row, int col)//初始化两个雷阵
{
	int i = 0;
	int j = 0;
	for (int i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			show[i][j] = '*';
			mine[i][j] = '0';
		}
	}
}
  • 输出布雷棋盘和玩家可视棋盘
void print_player(char show[ROW][COL], char mine[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i <row - 1; i++)
	{
		printf("%d ", i);//打印横标(0--10)
	}
	printf("\n");
	for (i = 1; i <row - 2; i++)//打印竖标(1--10)
	{
		printf("%d  ", i);
		for (j = 1; j < col - 1; j++)
		{
			printf("%c ", show[i][j]);//玩家棋盘数组
		}
		printf("\n");
	}
	printf("10 ");//开始打印最后一行
	for (i = 1; i < row - 1; i++)
	{
		printf("%c ", show[10][i]);
	}
	printf("\n");
}

void print_mine(char mine[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i <row - 1; i++)
	{
		printf("%d ", i);//打印横标(0--10)
	}
	printf("\n");
	for (i = 1; i <row - 2; i++)//打印竖标(1--10)
	{
		printf("%d  ", i);
		for (j = 1; j < col - 1; j++)
		{
			printf("%c ", mine[i][j]);
		}
		printf("\n");
	}
	printf("10 ");//开始打印最后一行
	for (i = 1; i < row - 1; i++)
	{
		printf("%c ", mine[10][i]);
	}
	printf("\n");
}
  • 玩家输入坐标
int player(char show[ROW][COL],int row, int col)
{
	int x = 0, y = 0;
	printf("请输入坐标:>");
	scanf("%d %d", &x, &y);
	while (1)
	{
		if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输入坐标是否有误

		{
			if (mine[x][y] == '0')//没踩到雷
			{
				char ch = count_mine(x, y);
				show[x][y] = ch + '0';//数字对应的ASCII值和数字字符对应的ASCII值相差48,即'0'的ASCII值
				open_mine(show[ROW][COL], mine[ROW][COL], row, col, x, y);//展开
				print_player(show[ROW][COL], row, col);

				if (count_show_mine(show[ROW][COL], mine[ROW][COL], row, col) == COUNT)//判断剩余未知区域的个数,个数为雷数时玩家赢
				{
					print_mine( mine[ROW][COL], row, col);
					printf("玩家赢!>\n");
					break;
				}
			}
			else if (mine[x][y] == '1')//踩到雷
			{
				return 1;
			}

		}

		else
		{
			printf("输入错误重新输入\n");
		}
		return 0;//没踩到雷
	}
}
  • 布雷并展开
void set_min(char mine[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = COUNT;//雷总数
	while (count)//雷布完后跳出循环
	{
		int x = rand() % 10 + 1;//产生1到10的随机数
		int y = rand() % 10 + 1;
		if (mine[x][y] == '0')//找不是雷的地方布雷
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

void open_mine(char mine[ROW][COL], int row, int col,int x, int y)//坐标周围展开函数
{
	if (mine[x - 1][y - 1] == '0')
	{
		show[x - 1][y - 1] = count_mine(x - 1, y - 1) + '0';//显示该坐标周围雷数
	}
	if (mine[x - 1][y] == '0')
	{
		show[x - 1][y] = count_mine(x - 1, y) + '0';//显示该坐标周围雷数
	}
	if (mine[x - 1][y + 1] == '0')
	{
		show[x - 1][y + 1] = count_mine(x - 1, y + 1) + '0';//显示该坐标周围雷数
	}
	if (mine[x][y - 1] == '0')
	{
		show[x][y - 1] = count_mine(x, y - 1) + '0';//显示该坐标周围雷数
	}
	if (mine[x][y + 1] == '0')
	{
		show[x][y + 1] = count_mine(x, y + 1) + '0';//显示该坐标周围雷数
	}
	if (mine[x + 1][y - 1] == '0')
	{
		show[x + 1][y - 1] = count_mine(x + 1, y - 1) + '0';//显示该坐标周围雷数
	}
	if (mine[x + 1][y] == '0')
	{
		show[x + 1][y] = count_mine(x + 1, y) + '0';//显示该坐标周围雷数
	}
	if (mine[x + 1][y + 1] == '0')
	{
		show[x + 1][y + 1] = count_mine(x + 1, y + 1) + '0';//显示该坐标周围雷数
	}
}
  • 判断周围8邻域的雷个数
int count_show_mine(char mine[ROW][COL], int row, int col)
//判断剩余未知区域的个数,个数为雷数时玩家赢
{
	int count = 0;
	int i = 0;
	int j = 0;
	for (i = 1; i <= row - 2; i++)
	{
		for (j = 1; j <= col - 2; j++)
		{
			if (show[i][j] == '*')
			{
				count++;
			}
		}

	}
	return count;
}

结论:

  • 扫雷游戏就是创建两个棋盘。
  • 在玩家输入第一个坐标后,在玩家可见棋盘上返回那个位置的附近雷数为0。
  • 在玩家不可见的棋盘里随机生成雷。
  • 重复性的输入坐标、判断坐标有效性、判断是否踩雷、判断是否赢得游戏。
  • 展开附近坐标的周围雷数。
  • 重复上步。

猜你喜欢

转载自blog.csdn.net/weixin_43214609/article/details/83349979