数组实现扫雷游戏

一:数组设计扫雷游戏原理

目录

一:数组设计扫雷游戏原理

1.1  扫雷游戏说明

1.2  数组实现的扫雷游戏原理

1.2.1 设计“排雷”的操作页面

1.2.2 设置雷的位置

1.2.3统计坐标周围雷的数量

二:建立头文件和源文件

三:建立函数

3.1 菜单的创建

3.2 初始化函数

3.3  展示数组

3.4布置雷的位置

3.5获取周围雷的数量

3.6 进行排雷游戏

四:完整代码

1.头文件

4.1.1  gobal.h

4.1.2  service_mine.h

4.1.3  function_mine.h

2. 源文件

4.2.1  game.c

4.2.2  service_mine.c

4.2.3  function_mine.c


1.1  扫雷游戏说明

1.2  数组实现的扫雷游戏原理

目前要实现功能

1.2.1 设计“排雷”的操作页面
通过控制台无法点击方块,所以可以输入该位置的坐标进行判断,基于此原理,可以设计一个二维数组实现排雷游戏的基本界面。其中包含的信息:盲区、已知区、雷区、非雷区。
由于数据过多,为了编写方便,我设计了两个数组:一个储存:盲区、已知区;另一个储存雷区、非雷区。
为了后期方便计算“雷”的数量,使用“1”表示“雷”,“0”表示“非雷”。使用“*”表示未探索区域,当探索某位置后,将显示该位置周围的“雷”的数量。
1.2.2 设置雷的位置

“雷”的位置是随机分布的,可以通过 srand((unsigned int)time(NULL))和rand() 随机生成“雷”的位置

1.2.3统计坐标周围雷的数量

计算该坐标周围数组的储存的数据信息来确定周围雷的数量。

但如果是边界周围位置,容易发生越界访问,程序运行出错。如下图(一),黑色矩形区域未发生越界访问,而红色矩形区域明显超出分配空间,越界访问。

那如何解决此问题呢?

仔细观察之后,我们发现越界访问区域只有界限旁边一圈,如果这一圈也包含在数组之中,就不会造成越界访问的问题。我们可以将数组在游戏范围基础上在行和列上额外设置两组,如下图(二),将char mine[row][col]改为char mine[row+2][col+2]

二:建立头文件和源文件

通过建立不同源文件可以使代码更加简洁,增加可读性。如果只在一个源文件中编写程序,对于小程序完全可行,但对于成千上万行的代码来说,就十分糟糕。你难以找到想要那段代码,也容易减少阅读欲望。

为此,建立了三个不同的源文件。game.c包含main()函数,用于调用其他子函数。service_mine.c主要储存面向用户的函数,例如游戏使用说明等。function_mine.c主要储存一些功能函数,例如数组的初始化,设置雷的位置等。如果main()函数想要调用其他函数,就需要设置相应的头文件,如service_mine.h和function_mine.h。同时我额外设置一个gobal.h的头文件,将所需的全局变量储存在这里,便于寻找和修改。

三:建立函数

该扫雷游戏建立的是9*9游戏布局

3.1 菜单的创建

提供玩家程序运行后的用法,类似于介绍界面。同时也可以添加游戏的详细信息和玩法·

void MenuGame() 
{
	printf("************************\n");
	printf("****欢迎进入扫雷游戏****\n");
	printf("*****请输入下列选项*****\n");
	printf("******* 1.  play *******\n");
	printf("******* 0.  exit *******\n");
	printf("************************\n");

}


3.2 初始化函数

通过两个for循环进行遍历,初始化数组。前往已经提过一共设置了两个不同的数组,初始化时所初始的字符不同,为避免冗杂,直接设置了char set,代表舒适化的字符。

此处 ROWS、COLS、rows、cols 都取值为11.

//初始化数组
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{

		int j = 0;
		for (j = 0; j < cols; j++)
			board[i][j] = set;
	}

}

3.3  展示数组

该游戏时通过输入坐标进行选择,需要在扫雷界面周围设置一系列数字表示位置,方便进行游戏操作。使用两个for循环遍历输出。

此处 ROWS、COLS 取值为11.,row、col 取值为9.

//展示数组
void DisplayBoard(char board[ROWS][COLS], int row, int col)
 {
	int i = 0;

	printf("--------扫雷-------\n");

	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}

	printf("\n");

	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		int j = 1;
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}

}

3.4布置雷的位置

通过时间种子,生成一系列随机数。如果生成相同的坐标,跳过if 语句,不会再生成雷,雷的数量不会改变。当雷为0时,恰好为假,跳出循环,函数运行完成。

此处num代表雷的数量, ROWS、COLS 取值为11.,row、col 取值为9。只需要给1-9下标的数组赋值,所以取值为9,方便运行。

//布置雷的位置
void SetMine(char board[ROWS][COLS], int row, int col,int num)
{
	
	int count = num;
	while (count)
	{
		//随机生成雷的位置
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')    //重复坐标跳过该语句
		{
			board[x][y] = '1';
			count--;
		}
	}
}

3.5获取周围雷的数量

已知输入的 X、Y 值,可以直接输出周围八个数的数组下标。之前设置“1”代表“雷”,“0”代表“非雷”。若有雷,则直接输出 mine[x][y] 的值,代表有一个雷。累积计算就是该位置周围雷的数量。


//获取坐标周围雷的数量
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * ' 0');
}

3.6 进行排雷游戏

此处num代表雷的数量, ROWS、COLS 取值为11.,row、col 取值为9。win 代表玩家清除的非雷区域的数量。当玩家猜对一个位置,win 就增加1,当win 的数量与 row * col - num (所有非雷区域的数量)相同时,跳出循环,进行获胜判断,若相等,就运行 if 语句,游戏获胜。如果踩到雷,break 跳出循环,if 语句条件不成立,游戏失败。

//进行排雷游戏
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int num)
{
	int x = 0,y=0;
	int win = 0;
	while (win < row * col - num)
	{
		//printf("\n");
		//printf("---- 雷的分布图 ----\n");
		//DisplayBoard(mine, ROW, COL);     //打印雷的位置,插入此代码,可以直接获取雷的位置
		printf("请输入要排查的坐标(行,列):>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				printf("\n");
				printf("---- 雷的分布图 ----\n");
				DisplayBoard(mine, ROW, COL);    //打印雷的位置
				break;
			}
			else
			{
				system("cls");    //清除之前游戏记录

				//该位置不是雷,统计该坐标周围雷的数量,对该位置重新赋值
				show[x][y] = GetMineCount(mine, x, y) + '0';
				
				DisplayBoard(show, ROW, COL);    //打印雷的位置
				win++;
			}
		}
		else
		{
			printf("输入坐标错误,请重新输入\n");
		}
	}

    //判断是否获胜
	if (win == row * col - num)  
	{
		printf("\n");
		printf("!!!恭喜你,排雷成功!!!\n");

		printf("\n");
		printf("---- 雷的分布图 ----\n");
		DisplayBoard(mine, ROW, COL);    //打印雷的位置
	}
}

四:完整代码

1.头文件

4.1.1  gobal.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
4.1.2  service_mine.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void MenuGame();

void game();
4.1.3  function_mine.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

//布置雷
void SetMine(char board[ROWS][COLS], int row, int col,int num);

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int num);

2. 源文件

4.2.1  game.c
#include "gobal.h"
#include "service_mine.h"
#include "function_mine.h"


int main() {

	int choice;
	srand((unsigned int)time(NULL));

	do {
		 MenuGame();
		scanf("%d", &choice);

		switch (choice) {
		case 1:
			
			game();

			break;

		case 0:
			printf("退出游戏成功,欢迎下次使用\n");
			break;

		defalut:
			printf("该选项无效,请重新输入!\n");
			break;
		}
	} while (choice != 0);
	return 0;

}
4.2.2  service_mine.c
#include "gobal.h"
#include "service_mine.h"
#include "function_mine.h"

void MenuGame() 
{
	printf("************************\n");
	printf("****欢迎进入扫雷游戏****\n");
	printf("*****请输入下列选项*****\n");
	printf("******* 1.  play *******\n");
	printf("******* 0.  exit *******\n");
	printf("************************\n");
}



void game() {
	int NUM;

	do {
		printf("请设置雷的数量(1-80):");
		scanf("%d", &NUM);
	} while ( NUM<1||NUM>80);

	printf("现在正式开始游戏\n");

	char mine[ROWS][COLS] = { 0 };    //布置雷
	char show[ROWS][COLS] = { 0 };   //展示信息

	//初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	DisplayBoard(show, ROW, COL);

	SetMine(mine, ROW, COL,NUM);

	//DisplayBoard(mine, ROW, COL);    //打印雷的位置
	FindMine(mine, show, ROW, COL,NUM);
}
4.2.3  function_mine.c
#include "gobal.h"
#include "service_mine.h"
#include "function_mine.h"

//初始化数组
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{

		int j = 0;
		for (j = 0; j < cols; j++)
			board[i][j] = set;
	}

}


//展示数组
void DisplayBoard(char board[ROWS][COLS], int row, int col) {

	int i = 0;

	printf("--------扫雷-------\n");

	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}

	printf("\n");

	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		int j = 1;
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}

}


//布置雷的位置
void SetMine(char board[ROWS][COLS], int row, int col,int num)
{
	
	int count = num;
	while (count)
	{

		//随机生成雷的位置
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}


//获取坐标周围雷的数量
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * ' 0');
}


//进行排雷游戏
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int num)
{
	int x = 0,y=0;
	int win = 0;
	while (win < row * col - num)
	{
		//printf("\n");
		//printf("---- 雷的分布图 ----\n");
		//DisplayBoard(mine, ROW, COL);    //打印雷的位置

		printf("请输入要排查的坐标(行,列):>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				printf("\n");
				printf("---- 雷的分布图 ----\n");
				DisplayBoard(mine, ROW, COL);    //打印雷的位置
				break;
			}
			else
			{
				system("cls");
				//该位置不是雷,就统计这个坐标周围有⼏个雷
				show[x][y] = GetMineCount(mine, x, y) + '0';
				
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("输入坐标错误,请重新输入\n");
		}
	}
	if (win == row * col - num)
	{
		printf("\n");
		printf("!!!恭喜你,排雷成功!!!\n");

		printf("\n");
		printf("---- 雷的分布图 ----\n");
		DisplayBoard(mine, ROW, COL);    //打印雷的位置
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值