数组和函数的实践——扫雷游戏的创作

本文介绍了如何用C语言编写一个基本的9*9扫雷游戏,包括游戏规则、数据结构设计(二维数组存储雷和排查信息)、文件管理和函数实现。通过详细步骤展示了从布局雷到排查雷的整个过程。
摘要由CSDN通过智能技术生成

扫雷游戏是一个很经典的电脑小游戏了,相信大家在童年的时候都有玩过,是绞尽脑汁然后通关,还是每次都被炸弹杀死,不管怎样,相信这个游戏都给大家留下了深刻的印象,那么接下来我将介绍如何来写一个9*9的基本扫雷游戏回忆我们的童年。

1.扫雷游戏的分析和设计

1.1扫雷游戏的简单说明

1.9*9的图上随机布置了10个雷

2.排查雷:

a.如果排查的位置不是雷,就显示周围的九宫格内有几个雷

b.如果排查的位置是雷,那么就被炸死了,游戏结束

c.如果找到了所有的雷,则扫雷成功

1.2游戏的分析和设计

1.2.1

我们在进行扫雷游戏的过程中,布置的雷和排查的雷都需要地方储存。

因为我们要写的是一个9*9的扫雷游戏,所以需要在9*9的棋盘上布置雷的信息和排查雷,这样我们最先想到的就是创建一个9*9的二维数组来存放信息。空棋盘如图所示:

如果某个位置上有雷,我们就在此处存放1,若没有雷,就存放0。

这是一个随机布置了雷的棋盘: 

这个时候我们就要开始设想如何来排查雷了,当我们想排查(2,5)时,我们需要访问周围的8个格子,来统计雷的个数。

但是当我们想排查(8,6)这个坐标时,就会发现访问周围的8个格子时下面的3个就会越界,不在我们的数组范围内,为了防止这种情况的发生,我们可以将数组扩大一圈,变为11*11的数组,雷仍然放在中间9*9的格子中。所以我们最后需要的是一个11*11的数组。

让我们继续分析,现在我们已经在棋盘上布置好了雷,也存储了对应的信息即雷(1),非雷(0),现在让我们开始进行排查。我们排查了一个位置,发现这个地方不是雷,但是它的周围有一个雷,那么我们就需要将雷的数量记录并存储下来,并且打印在棋盘上,作为我们接下来排雷的重要参考信息。但是我们会发现,如果将这个信息存入布置雷的数组中就可能会产生混淆,这种方法显然是行不通的。

那么我们为什么不将它们分开储存呢?

我们让一个棋盘(数组lei)来存放布置好的雷的信息,再让另一个棋盘(数组show)存放排查的信息。这样我们就得到了两个互不干扰的数组,将雷布置在lei数组,并且在lei数组中对雷进行排查,再将排查出的数据放入show数组,并将show数组打印出来。

这样我们就可以将show数组初始化为字符‘*’,为了方便打印,我们将两个数组的类型保持一致,lei数组的初始化也使用字符‘1’来表示雷,字符‘0’来表示非雷。

两个数组的初始化情况如下图所示:

char lei[11][11] = {0};//⽤来存放布置好的雷的信息
char show[11][11] = {0};//⽤来存放排查出的雷的个数信息

 1.2.2

为了方便文件的管理,以及实践多文件形式下的函数声明和定义,我们设计三个文件来满足需要:

test.c // ⽂件中写游戏的测试逻辑
game.c // ⽂件中写游戏中函数的实现等
game.h // ⽂件中写游戏需 要的数据类型和函数声明等

2.扫雷游戏的代码实现

game.h

#pragma once//写游戏需要的数据类型和函数声明等

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

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

#define EASY 10

void initboard(char arr[ROWS][COLS],int rows ,int cols ,char set);//初始化

void printboard(char arr[ROWS][COLS],int rows ,int cols );//打印棋盘

void setlei(char arr[ROWS][COLS], int row, int col);//布置雷

//排查雷
void findlei(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int rows, int cols);

game.c

#define _CRT_SECURE_NO_WARNINGS 1//游戏中函数的实现等

#include "game.h"

void initboard(char arr[ROWS][COLS], int rows, int cols,char set)
{
	int a = 0;

	for (a = 0; a < rows; a++)
	{
		
		int b = 0;

		for (b = 0; b < cols; b++)
		{
			int x = 1;
		
			arr[a][b] = set;
		}
	}
}

void printboard(char arr[ROWS][COLS], int rows, int cols)
{
	int a = 0;
	for (a = 0; a < rows - 1; a++)
	{
		printf("%d ", a);
	}
	printf("\n");

	for (a = 1; a < rows-1; a++)
	{
		printf("%d ", a);

		int b = 0;	
		for (b = 1; b < cols - 1; b++)
		{   
			printf("%c ", arr[a][b]);
		}

		printf("\n");
	}
}

void setlei(char arr[ROWS][COLS], int row, int col)
{
	int sum = EASY;//布置十个雷

	while (sum)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;//控制随机数的范围在1-9

		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';
			sum--;
		}
	}
}

int getleinum(char arr[ROWS][COLS], int x, int y)
{
	return arr[x - 1][y - 1] + arr[x - 1][y] + arr[x - 1][y + 1] + arr[x][y - 1] + arr[x][y + 1] + arr[x + 1][y - 1] + arr[x + 1][y] + arr[x + 1][y + 1] - 8 * '0';//从字符转换为数字‘n’-'0'=n
}

void findlei(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int rows, int cols)
{
	int x = 0;
	int y = 0;

	int win = 0;
	while (win < ROW * COL - EASY)
	{
		printf("请输入要排查的坐标:");
		scanf("%d %d", &x, &y);

		if (x >= 1 && x <= rows && y >= 1 && y <= cols)
		{
			if (arr1[x][y] == '1')
			{
				printf("很遗憾,你被炸死了");
				printboard(arr1, ROWS, COLS);
				break;
			}
			else
			{
				int n = getleinum(arr1, x, y);//找周围有几个雷
				arr2[x][y] = n + '0';//数字转换为对应的字符n+'0'='n'
				printboard(arr2, ROWS, COLS);
				win++;
			}
		}
		else
		{
			printf("坐标错误,请重新输入坐标");
		}
	}
	
	if (win == ROW * COL - EASY)
	{
		printf("恭喜你,游戏成功");
		printboard(arr1, ROWS, COLS);
	}
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1//游戏的测试逻辑

#include "game.h"

void menu()
{
	printf("**************************\n");
	printf("*****     1.play     *****\n");
	printf("*****     0.exit     *****\n");
	printf("**************************\n");
}

void game()
{
	char lei[ROWS][COLS];
	char show[ROWS][COLS];

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

	//布置雷
	setlei(lei, ROW, COL);

	//打印棋盘,我们不需要将11*11全部打印,只需要中间的9*9
	printboard(show, ROWS, COLS);

	//排查雷
	findlei(lei, show, ROW ,COL);

	
}
int main()
{
	srand((unsigned int)time(NULL));//产生随机数

	int i = 0;
	do
	{
		menu();

		printf("请输入你的选择:");
		scanf("%d", &i);

		switch (i)
		{
		case 1:
			printf("扫雷开始\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新选择!!!\n");
			break;
		}
		printf("\n");
	} while (i);

	return 0;
}

 注:代码中使用了rand()函数等,对此不了解的可以看我的这篇文章,里面有对这几种函数的基本介绍http://t.csdnimg.cn/a9h8v

如果对代码有什么疑问欢迎在评论区留言,我看到后会尽可能解答。

代码的写法不止一种,如果有什么好的想法也欢迎在评论区提出。

  • 25
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值