【C语言初阶】扫雷的代码与设计思路

扫雷RAP

如果你想玩扫雷,(七句句末押韵)
雷将会与你跟随。
无雷格将被包围,
营造紧张的氛围,
只有C 语言相陪,
将你的失败挽回。
while循环将重回,
直至你下次突围。

扫雷规则

以及条件在一个9*9或自定义大小的方块矩阵中随机布置一定量的地雷初级为10个。由玩家逐个翻开方块,以找出所有地雷为最终游戏目标。如果玩家翻开的方块有地雷,则游戏结束。

扫雷背景

扫雷最原始的版本可以追溯到1973年一款名为“方块”的游戏。  1981年,微软公司的罗伯特·杜尔和卡特·约翰逊两位工程师在Windows3.1系统上加载了该游戏,扫雷游戏才正式在全世界推广开来。

扫雷经典图片

扫雷游戏经典图片
因为初次接触到C语言写的较长程序如果讲解和代码有问题,请在评论区指正和批判

步骤初识

当我想玩扫雷首先我要对规则和判定进行了解和构建我们要建立的是一个9*9的棋盘给里边去存放数据所以我们要先建立棋盘,随后要给里边进行数据的填写也就是雷的布置和输入,其次要做的事对雷的扫描与识别对于任意一个方格中我们要是别他的周围有多少个雷也就是我们要实现的功能扫雷。

菜单打印

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

游戏的初期我们要打印菜单让玩家首先能进入到游戏当中去

游戏选择

int main()
{
    
    
	int input = 0;
	//time_t -- 整形
	srand((unsigned int)time(NULL));//设置随机数的生成起点的

	do
	{
    
    
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			game();//扫雷游戏
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
		//
	} while (input);
	return 0;
}

当打印完菜单我们就需要玩家对扫雷游戏进入进行选择如果你选择1那么恭喜你进入扫雷游戏如果0那么退出程序 选择其他就会继续进行循环 srand函数是之后我们布置雷的时候随需要的随机数详解在上一篇三子棋当中。

游戏程序(game)

void game()
{
    
    
	//真正扫雷的过程
	//创建2个数组
	//存放布置好的雷
	char mine[ROWS][COLS] = {
    
     0 };//'0'
	//存放排查出来的雷的信息
	char show[ROWS][COLS] = {
    
     0 };//'*'
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');
	DisplayBoard(show, ROW, COL);
	//布置好的雷的信息不应该轻易打印
	//DisplayBoard(mine, ROW, COL);
	//1. 布置雷
	SetMine(mine, ROW, COL);
	DisplayBoard(mine, ROW, COL);
	//2. 扫雷
	FindMine(mine, show, ROW, COL);
}

这是我们扫雷游戏所需要的函数和游戏程序设计接下来一一对各部分经行解释和分析。

建立数组

//真正扫雷的过程
	//创建2个数组
	//存放布置好的雷
	char mine[ROWS][COLS] = {
    
     0 };//'0'
	//存放排查出来的雷的信息
	char show[ROWS][COLS] = {
    
     0 };//'*'

因为在边缘一排的棋盘格无法成一个圈型结构所以我们需要构建另一个数组也就是show多加一行多加一列这样就形成了9*9的棋盘格补充了有空白的缺陷。

创建棋盘

void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
    
    
	int i = 0;
	int j = 0;

	for (i = 0; i < rows; i++)
	{
    
    
		for (j = 0; j < cols; j++)
		{
    
    
			board[i][j] = set;
		}
	}
}
InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

利用了for循环将99打印出来并将各数组数据进行参数里边的赋值。‘0’ '’。

将棋盘格加上行列

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	printf("----------------------------------\n");
	//列号的打印
	for (i = 0; i <= col; 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");

}
DisplayBoard(show, ROW, COL);

也是用了for循环语句在每一行的前边进行赋值每一列的上边进行赋值因为每一列每一行的数字与其相对应所以直接打印board[i][j]。

扫描二维码关注公众号,回复: 12081716 查看本文章

雷的布置

//1. 布置雷
	SetMine(mine, ROW, COL);
	DisplayBoard(mine, ROW, COL);
void SetMine(char board[ROWS][COLS], int row, int col)
{
    
    
	//1. 随机找坐标布置雷
	//布置多少个雷 - 10
	int count = 10;
	while (count)
	{
    
    
		//布置成功一个雷,count--
		//1. 生产随机的坐标
		int x = rand() % row + 1;//1-9
		int y = rand() % col + 1;//1-9
		//2. 布置
		if (board[x][y] == '0')
		{
    
    
			board[x][y] = '1';
			count--;
		}
	}
}

布置雷我们初期设定了10个用了while循环并运用随机数来实现生成时进行判断如果其中为空则放入相反则继续执行循环。

扫雷的巧妙实现

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';
}

一个点周围的雷数显示在这个点里我们可以换个思路想每一个不是雷的是0 有雷则是1 将其转化为ASC码值周围一共八个将周围的减去八个0剩余则就是那个点的值然后将值赋予进去就实现了扫描的功能

输赢的判断


	FindMine(mine, show, ROW, COL);
void FindMine(char mine[ROWS][COLS],
	char show[ROWS][COLS],
	int row,
	int col)
{
    
    
	int x = 0;
	int y = 0;
	int win = 0;

	while (win<ROW*COL - 10)
	{
    
    
		printf("请输入要排查的坐标:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
    
    
			//判断x,y坐标处是否是雷
			if (mine[x][y] == '1')
			{
    
    
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
    
    
				//如果x,y坐标不是雷,就统计周围有几个雷
				int count = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
    
    
			printf("坐标非法\n");
		}
	}
	if (win == ROW*COL - 10)
	{
    
    
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, row, col);
	}
}

先定义一个win先去判断是否在区间内 如果不在 就不用考虑后事了 在用if来判断如果第一步就踩到雷也就是格子内为1 那就break跳出循环 很遗憾你失败了。如果不是就扫描雷数统计周围的雷 直到最后你走的步数等于总格子减去雷的个数那么恭喜你取得阶段性的胜利

声明

#define _CRT_SECURE_NO_WARNINGS 1

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

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2
//初始化
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 mine[ROWS][COLS], int row, int col);

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

在game头函数中对我们在程序中所运用的程序进行声明并且在其中对我们的行和列进行输入。

学习总结

这是初识别C语言遇到的第二个较长的代码,扫雷之前一直觉得扫雷游戏肯定都是些我不懂的函数和算法那些,当老师在编辑器中敲出的代码发现都是自己可以实现的函数,都是一些简单的数组实现和函数的调用创建 举个例子 findmine函数很巧妙 扫描周围的雷 使用0,1的ASCII 码字符的值进行相减 例如周围0为一个数 如果有1周围一圈的值进行相加再减去一圈的0的值最终得出周围有几个值,这样一想真是巧妙和简单我们对于程序的理解和游戏的编程

猜你喜欢

转载自blog.csdn.net/weixin_43762735/article/details/108490073
今日推荐