扫雷游戏(低配版)

1.扫雷游戏的解法

点击一个区域如果,踩到雷游戏失败,如果没有踩到雷显示周围雷的个数,直到所有雷被全部拍完,游戏胜利。

2.扫雷思路

首先以9*9十个雷的版本为背景讲解,首先我们要初始化棋盘,使棋盘上一颗雷都没有,然后我们在随机的十个位置上生成地雷(每次运行都是不一样的),我们让没有排查的地方以“*”显示,雷用‘1’来表示不是雷用‘0’来表示,由于有‘*’,‘1’,‘0’三种不同的数据,存到一个数组中,不好表示,所以我们创建两个数组mine和show,mine数组用来存放随机生成的地雷,mine为显示在屏幕上用户能够看到的界面,存放排除地方周围有几颗地雷。

3.扫雷代码 

(1)扫雷代码main()函数

int main()
{
	t1();
	return 0;
}

创建一个t1()函数将游戏所有的功能封装在函数中。

 

(2)t1函数的代码及功能实现

void t1()
{
	int n = 0;
	
	do
	{
		
		jm();
		printf("是否开始游戏(1 继续,0 退出):\n");
		scanf("%d", &n);
		switch (n)
		{
		case 1:game(); break;
		case 0:printf("结束游戏\n"); break;
		default:printf("输入错误重新输入\n"); break;
		}
	} while (n);
}

进入t1()函数中首先我们先定义一个jm(),函数用来实现用用户交互的一个界面,然后进入循环寻问“是否开始游戏(1开始0退出)”,然后进入switch语句,若输入为1执行game()函数(包含游戏的功能),若输入为0输出结束游戏然后跳结束switch语句,又因为n为0,所以会跳出循环,从而达到结束游戏的效果。如果我们误触输入了0和1以外的数字会提示“输入错误,重新输入”,然后继续执行循环达到重新输入的效果。

 (3)jm()函数的代码及功能实现

void jm()
{
	printf("--------------------------\n");
	printf("--------  1.play  --------\n");
	printf("--------  0.exit  --------\n");
	printf("--------------------------\n");
}

 制作一个可以与用户沟通的界面,引导用户开始或者结束游戏。

(4)game函数代码及功能实现

在介绍game()函数以前我们先定义几个常量如下:

#define ROW 9  
#define COL 9    //能布雷和可排查的区域
#define ROWS ROW+2
#define COLS COL+2    //方便统计周围雷的个数
#define COUNT 10      //布雷的个数
#define MAX ROW*COL-COUNT    //排查格子的个数

其后我们再来介绍一下再game()函数中所需要的其它函数

<1>初始化函数代码及其功能
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char ch)
{
	int i = 0, j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = ch;
		}
	}
}

        首先,传入要初始化的数组,然后传入数组行高和列宽,以便确定初始化的范围,最后传入一个字符,这个字符决定了该数组初始化成一个什么数组。

        进入函数后,定义i和j两个变量,利用这两个变量遍历数组并将传入的字符依次赋值给数组中的每个元素,完成数组的初始化2操作。

 <2>布雷的代码及其功能
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int i = 0, j = 0, count = COUNT;
	while (count)
	{
		i = rand() % row+1;
		j = rand() % col+1;
		if (mine[i][j] != '1')
		{
			mine[i][j] = '1';
			count--;
		}
	}
}

        首先传入需要布雷的数组,然后传入一个比数组行高和列高分别减2的行和列,因为数组的第一行和最后一行以及第一列和最后一列不需要布置地雷,因为他们只是为了方便统计周围个数来增加的行和列数这个我们在下面会说到。

        然后进入函数,定义i,j,count变量分别存放行、高和布置雷的个数进入while()循环若count不为0则循环一直执行,rand()生成一个伪随机数%行高,因为数组下标是从0开始的为了避免在第一行布雷所以在+1,把该值赋值给i(i = rand() % row+1;)从而获得了一个在数组可布雷范围的随机行,随机列也是同理。

        最后执行if()语句来判断该位置是否为雷('1')若不为雷('0')则在该处埋雷(改为‘1’)然后另count-1表示又布下一个雷。

 <3>输出代码及其功能
void DisolayBoard(char arr[ROWS][COLS], int rows, int cols)
{
	int i = 0, j = 0;
	for (i = 1; i <= rows; i++)
	{
		for (j = 1; j <= cols; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

        首先传入一个比数组行高和列高分别减2的行和列。

        然后定义两个i和j变量,分别用来接收行和高的数据让i和j都从1开始跳过第一行和第一列不输处,因为第一行,第一列,最后一行,最后一行是方便统计周围雷的个数的所以不需要显示。

        最后就是执行两个for()循环依次遍历并输出数组。

 <4>排雷代码及其功能

在讲解排雷前我们还需要补充一个统计函数

<1. 统计函数的代码及其功能
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
	return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] +
		mine[x][y - 1] + mine[x][y + 1] +
		mine[x + 1][y - 1] + mine[x + 1][y + 1] + mine[x + 1][y] - 8 * '0' + '0';
}

        首先进入函数传入要统计的行和列的坐标。

        因为要返回九宫格内除自身外有几个雷的个数,传入的是字符数组,且‘0’为所以要把周围8个元素的相加然后减去8 * ‘0’从而得到周围0的个数然后再加上‘0’将其转化为字符的形式并返回。

 下面介绍排雷函数

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0, y = 0;
	int cou = 0, max = 0;
	while (1)
	{
		printf("请输入需排查的坐标:");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= 9 || y >= 1 && x <= 9)
		{
			if (mine[x][y] == '1')
			{
				printf("踩到雷了游戏,游戏失败\n");
				DisolayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				cou = GetMineCount(mine, x, y);
				show[x][y] = cou;
				//DisolayBoard(mine, ROW, COL);
				DisolayBoard(show, ROW, COL);
				max++;
				if (max == MAX)
				{
					printf("游戏成功\n");
					break;

				}
			}
		}
		else
		{
			printf("输入错误请重新输入\n");
		}
	}

        首先传入存雷的数组,显示周围雷个数的数组,传入一个比数组行高和列高分别减2的行和列。

        定义x,y分别存储要排查的行和列,再定义cou和max变量分别存储周围雷的个数,和统计非雷坐标个数。

        进入while()循环,首先输入要排查的行和列,若输入的坐标在排查的范围内则执行if()语句,否则提示输入错误重新输入,继续输入。

        这里我们假设输入坐标正确,若为雷则输出布雷的数组,显示所有为的位置,然后跳出循环。

        若输入不为雷用上面的统计函数统计周围雷的个数给cou变量,再将cou变量赋值给统计布雷个数的数组,然后打印该数组显示排查点周围雷的个数。

        随后max++表示排查非雷坐标的个数。当max == MAX时表示所有地雷全部排完,输出游戏成功并跳出循环。

 game()代码及其讲解

void game()
{
	srand((unsigned int)time(NULL));
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	InitBoard(show, ROWS, COLS, '*');
	InitBoard(mine, ROWS, COLS, '0');
	SetMine(mine, ROW, COL);
	FindMine(mine, show, ROW, COL);
}
        首先执行,srand((unsigned int)time(NULL));通过时间的变化生成不同的值,生成为随机数,为布雷做了铺垫。
        然后定义两个数组 一个用来布雷,另一个用来存储非雷时雷的个数,并呈现给用户。
        将布雷数组全初始化为‘0’,统计数组全部初始化为‘*’号,使用布雷函数在规定区域内随机布置规定个数的雷,最后进入排雷函数,判断各种情况,到此扫雷游戏讲解完毕。

 4.小结

        由于小编刚入门且博客写的不多,如果有程序错误,或者博客书写缺陷希望大家指正,小编定会积极改正,追后祝大家在编程的道路上能不断进步,加油!!!

5.扫雷的完整代码

#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 COUNT 10
#define MAX ROW*COL-COUNT


void InitBoard(char arr[ROWS][COLS], int rows, int cols, char ch)
{
	int i = 0, j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = ch;
		}
	}
}
void DisolayBoard(char arr[ROWS][COLS], int rows, int cols)
{
	int i = 0, j = 0;
	for (i = 1; i <= rows; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= cols; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int i = 0, j = 0, count = COUNT;
	while (count)
	{
		i = rand() % row+1;
		j = rand() % col+1;
		if (mine[i][j] != '1')
		{
			mine[i][j] = '1';
			count--;
		}
	}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
	return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] +
		mine[x][y - 1] + mine[x][y + 1] +
		mine[x + 1][y - 1] + mine[x + 1][y + 1] + mine[x + 1][y] - 8 * '0' + '0';
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0, y = 0;
	int cou = 0, max = 0;
	while (1)
	{
		printf("请输入需排查的坐标:");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= 9 || y >= 1 && x <= 9)
		{
			if (mine[x][y] == '1')
			{
				printf("踩到雷了游戏,游戏失败\n");
				DisolayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				cou = GetMineCount(mine, x, y);
				show[x][y] = cou;
				//DisolayBoard(mine, ROW, COL);
				DisolayBoard(show, ROW, COL);
				max++;
				if (max == MAX)
				{
					printf("游戏成功\n");
					break;

				}
			}
		}
		else
		{
			printf("输入错误请重新输入\n");
		}
	}
}

void jm()
{
	printf("--------------------------\n");
	printf("--------  1.play  --------\n");
	printf("--------  0.exit  --------\n");
	printf("--------------------------\n");
}

void game()
{
	srand((unsigned int)time(NULL));
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	InitBoard(show, ROWS, COLS, '*');
	InitBoard(mine, ROWS, COLS, '0');
	SetMine(mine, ROW, COL);
	DisolayBoard(mine, ROW, COL);
	DisolayBoard(show, ROW, COL);
	FindMine(mine, show, ROW, COL);
}

void t1()
{
	int n;
	
	do
	{
		system("cls");
		jm();
		printf("是否开始游戏(1 继续,0 退出):\n");
		scanf("%d", &n);
		switch (n)
		{
		case 1:game(); break;
		case 0:printf("结束游戏\n"); break;
		default:printf("输入错误重新输入\n"); break;
		}
	} while (n);
}
int main()
{
	t1();
	return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值