扫雷游戏的实现步骤和代码

目录

一. 游戏所需的功能设计
二.步骤和代码
三.效果展示
 

一. 游戏所需的功能设计


1.    设计棋盘的大小范围,可以设计为10@10,也可以设计为16@16,需要用二维数组来打印棋盘;
2.    设计玩家棋盘,和设计者棋盘;
3.    设计避免刚开局就扫到雷的机会;
4.    设计输入坐标之后,展开周围的功能;
5.    设计统计坐标周围8个方位雷的个数;
6.    计算剩余总雷数,判断胜利与否;
7.    计算游戏从开始到结束的时间。

二. 步骤和代码


该程序需要三个文件,分别为创建主题文件的test.c, 存放头文件的game.h, 和游戏的实现文件game.c。

2.1 test.c文件(创建主题文件)

#include"game.h"
double start, finish;

void menu()
{
	printf("****************************************\n");
	printf("**************    1.Play    ************\n");
	printf("**************    0.Exit    ************\n");
	printf("****************************************\n");
}
void game()
{
	int ret = 0;
	init_mine();//初始化棋盘
	set_mine();//布雷
	print_mine();//打印设计者棋盘
	printf("\n");
	print_player();//打印玩家棋盘
	start = clock();//游戏开始时间
	safe_mine();//避免首开炸雷

	if (count_show_mine() == COUNT)//如果开局就赢
	{
		print_mine();
		printf("玩家赢了!\n");
		return;
	}
	print_player();//打印玩家棋盘

	while (1)//循环扫雷
	{
		int ret = sweep_mine();//扫到雷返回1,没扫到返回0
		if(count_show_mine()==COUNT)//如果玩家获胜
		{
			print_mine();
			printf("玩家赢了!\n");
			finish = clock();//游戏结束时间
			printf("用时%d秒\n", (int)(finish - start) / CLOCKS_PER_SEC);
			break;
		}
		if (ret)//判断是否扫到雷了
		{
			printf("扫到雷了!\t");
			finish = clock();//游戏结束时间
			printf("用时%d秒\n", (int)(finish - start) / CLOCKS_PER_SEC);
			print_mine();//打印设计者棋盘查看雷的分布
			break;
		}
		print_player();//打印玩家棋盘
	}
}

int main()
{
	srand((unsigned int)time(NULL));//产生随机种子值
	int input = 0;
	menu();
	do {
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入:>\n");
			break;
		}
	} while (input);
	return 0;
}


在该文件中设计了游戏从开始到结束的时间,以及一开局就胜利的机会。用safe_mine函数设置了避免开局就扫到雷的机会。

2.2 game.h (配置环境存放头文件)

在头文件中声明用到的函数。

#pragma once

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

#define row 11
#define col 11
#define COUNT 10//雷的总数
char show_mine[row][col];//棋盘展示
char real_mine[row][col];//棋盘部署
void menu();//菜单
void init_mine();//初始化棋盘
void set_mine();//部署雷
int count_mine();//计算周围雷的个数
void print_player();//玩家棋盘
void print_mine();//设计者棋盘
int sweep_mine();//扫雷
void safe_mine();//避免开盘炸雷
void open_mine(int x, int y);//棋盘展开
int count_show_mine();//判断玩家棋盘剩余未知区域的个数


2.3 game.c (存放游戏的实现逻辑)

该游戏需要初始化两个棋盘:设计者棋盘,和玩家棋盘。在设计者棋盘中,字符0代表“非雷”,字符1代表“雷”。

#include"game.h"

void init_mine()//初始化设计者和玩家的棋盘
{
	int i = 0;
	int j = 0;
	for (int i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			show_mine[i][j] = '*';
			real_mine[i][j] = '0';
		}
	}
}


打印两个棋盘的时候,需要打印横坐标和纵坐标的序号(0-9),如下图:

void print_player()//打印玩家棋盘
{
	int i = 0;
	int j = 0;
	printf("0 ");
	for (i = 1; i < row - 1; i++)//打印横坐标0-9
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i < row - 2; i++)//打印纵坐标0-9
	{
		printf("%d ", i);
		for(j = 1; j < col - 1;j++)
		{
			printf("%c ", show_mine[i][j]);
		}
		printf("\n");
	}
	printf("9 ");//打印最后一行
	for (i = 1; i < row - 1; i++)
	{
		printf("%c ", show_mine[9][i]);
	}
	printf("\n");
}
void print_mine()//打印设计者棋盘
{
	int i = 0;
	int j = 0;
	printf("0 ");
	for (i = 1; i < row - 1; i++)//打印横坐标0-9
	{
		printf("%d ", i);
	}
printf("\n");
for (i = 1; i < row - 2; i++)//打印纵坐标0-9
{
	printf("%d ", i);
	for (j = 1; j < col - 1; j++)
	{
		printf("%c ", real_mine[i][j]);
	}
	printf("\n");
}
printf("9 ");//打印最后一行
for (i = 1; i < row - 1; i++)
{
	printf("%c ", real_mine[9][i]);
}
printf("\n");
}


打印完两个棋盘和序号之后,开始布雷,用count 函数布置了10个雷,用rand函数让每一次的棋盘中的雷的分布都不同。

void set_mine()//设计者棋盘布雷
{
	int x = 0;
	int y = 0;
	int count = COUNT;//雷的总数
	while (count)
	{
		int x = rand() % 10 + 1;//随机横坐标0-9
		int y = rand() % 10 + 1;//随机纵坐标0-9
		if (real_mine[x][y] == '0')
		{
			real_mine[x][y] = '1';
			count--;
		}//所有雷布置完后跳出循环
	}
}
int count_mine(int x, int y)//统计周围8个区域的雷的个数
{
	int count = 0;
	if (real_mine[x - 1][y - 1] == '1')
		count++;
	if (real_mine[x - 1][y] == '1')
		count++;
	if (real_mine[x - 1][y + 1] == '1')
		count++;
	if (real_mine[x][y - 1] == '1')
		count++;
	if (real_mine[x + 1][y - 1] == '1')
		count++;
	if (real_mine[x + 1][y] == '1')
		count++;
	if (real_mine[x + 1][y + 1] == '1')
		count++;
	return count;
}

为了避免一开局就点到雷,用safe_mine避免该情况的发生。

void safe_mine()//避免首开被炸
{
	int x = 0;
	int y = 0;
	char ch = 0;
	int count = 0;
	int ret = 1;
	printf("请输入坐标:>");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))
		{
			if (real_mine[x][y] == '1')//如果首开扫到雷
			{
				real_mine[x][y] = '0';
				char ch = count_mine(x, y);
				show_mine[x][y] = ch + '0';
				open_mine(x, y);
				while (ret)//在周围设置雷
				{
					int x = rand() % 10 + 1;
					int y = rand() % 10 + 1;
					if (real_mine[x][y] == '0')//在没有雷的地方布雷
					{
						real_mine[x][y] = '1';
						ret--;
						break;
					}
				}break;
			}
			if (real_mine[x][y] == '0')
			{
				char ch = count_mine(x, y);
				show_mine[x][y] = ch + '0';
				open_mine(x, y);
				break;
			}
		}
		else
		{
			printf("输入错误,请重新输入:>");
		}
	}
}

如文章开头的图片那样,想要实现展开功能,使得展开的坐标显示其周围的雷的数量.

void open_mine(int x, int y)//展开坐标周围区域
{
	if(real_mine[x - 1][y - 1] == '0')
	{
		show_mine[x - 1][y - 1] = count_mine(x - 1, y - 1) + '0';
	}
	if(real_mine[x - 1][y] == '0')
	{
		show_mine[x - 1][y] = count_mine(x - 1, y) + '0';
	}
	if(real_mine[x - 1][y + 1] == '0')
	{
		show_mine[x - 1][y + 1] = count_mine(x - 1, y + 1) + '0';
	}
	if(real_mine[x][y - 1] == '0')
	{
		show_mine[x][y - 1] = count_mine(x, y - 1) + '0';
	}
	if(real_mine[x][y + 1] == '0')
	{
		show_mine[x][y + 1] = count_mine(x, y + 1) + '0';
	}
	if(real_mine[x+1][y - 1] == '0')
	{
		show_mine[x + 1][y - 1] = count_mine(x + 1, y - 1) + '0';
	}
	if(real_mine[x + 1][y] == '0')
	{
		show_mine[x + 1][y] = count_mine(x + 1, y) + '0';
	}
	if(real_mine[x + 1][y + 1] == '0')
	{
		show_mine[x + 1][y + 1] = count_mine(x + 1, y + 1) + '0';
	}
}

接下来,是扫雷函数的实现。

int sweep_mine()//扫雷函数
{
	int x = 0;
	int y = 0;
	int count = 0;
	printf("请输入坐标:>\n");
	scanf("%d %d", &x, &y);//1-9
	if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))
	{
		if (real_mine[x][y] == '0')//如果没有扫到雷
		{
			char ch = count_mine(x, y);
			show_mine[x][y] = ch + '0';
			open_mine(x, y);
			if (count_show_mine() == COUNT)//判断未知区域坐标的个数
			{
				print_mine();
				printf("玩家赢了!\n");
				return 0;
			}
		}
		else if (real_mine[x][y] == '1')//如果扫到雷了
		{
			return 1;
		}
	}
	else
	{
		printf("输入错误,请重新输入:>");
	}
	return 0;
}


最后,是实现游戏胜利的函数,通过统计玩家棋盘中剩余坐标的个数和雷的总数来判断,如果剩余坐标的个数和雷的总数一致,则游戏胜利。

int count_show_mine()//判断未知区域坐标雷的个数
{
	int count = 0;
	int i = 0;
	int j = 0;
	for (i = 1; i <= row - 2; i++)
	{
		for (j = 1; j <= row - 2; j++)
		{
			if (show_mine[i][j] == '*')
			{
				count++;
			}
		}
	}
	return count;
}

三.效果展示

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值