扫雷游戏(9*9)

1.实现结果

仅简单模式,9*9排雷节目大小,共有10个雷。

当排查到雷所在坐标时,游戏失败。

当排雷界面上仅有雷,也即未排查数归零时,游戏胜利。

①开始界面

②开始游戏

输入1并回车

③排查

排查4 4

重开再排查4 5、6 3

2.实现思路

①头文件引用和参数设置

整个项目包含三个文件:main.c , function.h , function.c

main.c 中是main函数、打印游戏初始界面的menu函数、和执行游戏主体的game函数

在main.c和function.c中引用function.h

function.h中:

②main函数设计

 扫雷游戏需要布置雷,所以先设置随机数种子为之后雷的生成做准备

用do while循环来实现重复游玩的功能

通过intput变量的值来选择开始或结束游戏

③menu函数设计

④game函数设计

  su是success的缩写,存放雷盘上未排查并且无雷的坐标数,当su值为零时,跳出while循环,游戏胜利

mine数组中存放布雷信息,无雷的坐标数组值为字符0,有雷的坐标数组值为字符1

show数组是游戏时展示的界面,初始全部显示为字符*,代表未排查

init函数初始化mine数组和show数组:

a->自定义init函数

在function.c中定义init,用两层for循环对传入的数组进行赋值,赋为传入的指定数值 

b->自定义prinarr函数

打印传入的数组 ,并在第一行第一列加上坐标数方便寻找雷盘中的指定数

c->自定义putmine函数

 利用随机数生成雷的位置,如果这个位置在棋盘内并且还没有布上雷,那么给这个位置的数组值赋为‘1’来代表有雷

 while循环用来判断su,实现对雷盘的重复排查

对输入的坐标进行判断,首先这个数必须在雷盘之中,否则提示坐标错误

在while循环中有两个分支,一个是排查坐标刚好有雷,那么要判断游戏失败跳出循环;一个是排查坐标无雷,统计周围8个坐标的雷数并显示在展示的雷盘(show数组)中,如果周围雷数是0,那么再向四周统计并显示,知道雷数不为0

第一种情况:

if (mine[px][py] == '1')
			{
				system("Cls");
				printf("很遗憾,你被炸死了。\n");
				prinarr(show, ROWS, COLS);
				prinarr(mine, ROWS, COLS);
				break;
			}

第二种情况:

			else
			{
				system("Cls");
				release(mine, show, px, py);
				prinarr(show, ROWS, COLS);
			}

接下来是整个程序设计的难点,如何实现上述向四周排查,也就是点一下可以展开一片的效果。这里我们写成一个release函数,在function.c中进行定义

d->自定义release函数
void release(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y)
{//					arr1->mine		arr2->show
	arr2[x][y] = countsum(arr1, x, y) + '0';
	//int stx = x, sty = y;
	if (arr2[x][y] == '0')
	{
		int i = 0, j = 0;
		for (j = 1; (y - j >= 1) && (countsum(arr1, x, y - j + 1) == 0); j++)
		{
			if (arr1[x][y - j] == '0' && arr2[x][y - j] == '*')
			{
				arr2[x][y - j] = countsum(arr1, x, y - j) + '0';
			}
			else break;
		}
		for (j = 1; (y + j < COLS) && (countsum(arr1, x, y + j - 1) == 0); j++)
		{
			if (arr1[x][y + j] == '0' && arr2[x][y + j] == '*')
			{
				arr2[x][y + j] = countsum(arr1, x, y + j) + '0';
			}
			else break;
		}
		for (i = 1; x - i >= 1; i++)
		{
			if (arr1[x - i][y] == '0' && arr2[x - i][y] == '*')
			{
				arr2[x - i][y] = countsum(arr1, x - i, y) + '0';
				if (arr2[x - i][y] == '0')
				{
					for (j = 1; (y - j >= 1) && (countsum(arr1, x - i, y - j + 1) == 0); j++)
					{
						if (arr1[x - i][y - j] == '0' && arr2[x - i][y - j] == '*')
						{
							arr2[x - i][y - j] = countsum(arr1, x - i, y - j) + '0';
						}
						else break;
					}
					for (j = 1; (y + j < COLS) && (countsum(arr1, x - i, y + j - 1) == 0); j++)
					{
						if (arr1[x - i][y + j] == '0' && arr2[x - i][y + j] == '*')
						{
							arr2[x - i][y + j] = countsum(arr1, x - i, y + j) + '0';
						}
						else break;
					}
				}
				else break;
			}
			else break;
		}
		for (i = 1; x + i < ROWS; i++)
		{
			if (arr1[x + i][y] == '0' && arr2[x + i][y] == '*')
			{
				arr2[x + i][y] = countsum(arr1, x + i, y) + '0';
				if (arr2[x + i][y] == '0')
				{
					for (j = 1; (y - j >= 1) && (countsum(arr1, x + i, y - j + 1) == 0); j++)
					{
						if (arr1[x + i][y - j] == '0' && arr2[x + i][y - j] == '*')
						{
							arr2[x + i][y - j] = countsum(arr1, x + i, y - j) + '0';
						}
						else break;
					}
					for (j = 1; (y + j < COLS) && (countsum(arr1, x + i, y + j - 1) == 0); j++)
					{
						if (arr1[x + i][y + j] == '0' && arr2[x + i][y + j] == '*')
						{
							arr2[x + i][y + j] = countsum(arr1, x + i, y + j) + '0';
						}
						else break;
					}
				}
				else break;
			}
			else break;
		}
	}
}

首先要把传入坐标的周围雷数统计并存往show数组,然后对其进行判断。如果这个值不为0,就说明周边有雷,不需要显示周围一片,如果这个值为0,if判断为真,进行展开显示的判断

 开始两个for循环是在向这个坐标位置的左右方向判断,以下进行向上向下,并每一行向左右的判断

我们向上一行判断(i = 1  x - i),如果周围雷数非零,那么显示这个数到show,停止展开;如果周围雷数为0,显示这个数并且接着向下判断

以上就是对展开区域和周围雷数统计的思路,并且借助for循环使得展开判断能重复进行且保证在雷盘坐标范围之内

到此为止我们实现了对雷盘的排查,和向周围展开的效果,之后需要对su变量进行判断,判断是否需要接着排查,这就用到ifsu函数

e->自定义ifsu函数

统计传入数组(也就是show数组)中'*'字符的个数,再减去雷数,也就是还需要排查的坐标数

3.程序设计全貌

①function.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE 10

void init(char arr[ROWS][COLS], char x);

void putmine(char arr[ROWS][COLS], int x);

void prinarr(char arr[ROWS][COLS], int x, int y);

int countsum(char[ROWS][COLS], int x, int y);

void release(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y);

int ifsu(char arr[ROWS][COLS]);

②function.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "function.h"

void init(char arr[ROWS][COLS], char x)
{
	int i = 0, j = 0;
	for (i = 0; i < ROWS; i++)
	{
		for (j = 0; j < COLS; j++)
		{
			arr[i][j] = x;
		}
	}
}

void putmine(char arr[ROWS][COLS], int x)
{
	int i = 0, j = 0;
	while (x > 0)
	{
		i = rand() % 9 + 1, j = rand() % 9 + 1;
		if (arr[i][j] != '1')
		{
			arr[i][j] = '1';
			x--;
		}
	}
}

void prinarr(char arr[ROWS][COLS], int x, int y)
{
	int i, j;
	for (i = 0; i < x - 1; i++)
	{
		for (j = 0; j < y -1; j++)
		{
			if (i == 0)
				printf("%d_", j);
			else
			{
				if (j == 0)
				{
					printf("%d|", i);
					continue;
				}
				printf("%c ", arr[i][j]);
			}
		}
		printf("\n");
	}
}

int countsum(char arr[ROWS][COLS], int x, int y)
{
	int i = 0, j = 0, sum = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)
		{
			sum += arr[i][j];
		}
	}
	return sum -= 9*'0';
}

void release(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y)
{//					arr1->mine		arr2->show
	arr2[x][y] = countsum(arr1, x, y) + '0';
	//int stx = x, sty = y;
	if (arr2[x][y] == '0')
	{
		int i = 0, j = 0;
		for (j = 1; (y - j >= 1) && (countsum(arr1, x, y - j + 1) == 0); j++)
		{
			if (arr1[x][y - j] == '0' && arr2[x][y - j] == '*')
			{
				arr2[x][y - j] = countsum(arr1, x, y - j) + '0';
			}
			else break;
		}
		for (j = 1; (y + j < COLS) && (countsum(arr1, x, y + j - 1) == 0); j++)
		{
			if (arr1[x][y + j] == '0' && arr2[x][y + j] == '*')
			{
				arr2[x][y + j] = countsum(arr1, x, y + j) + '0';
			}
			else break;
		}
		for (i = 1; x - i >= 1; i++)
		{
			if (arr1[x - i][y] == '0' && arr2[x - i][y] == '*')
			{
				arr2[x - i][y] = countsum(arr1, x - i, y) + '0';
				if (arr2[x - i][y] == '0')
				{
					for (j = 1; (y - j >= 1) && (countsum(arr1, x - i, y - j + 1) == 0); j++)
					{
						if (arr1[x - i][y - j] == '0' && arr2[x - i][y - j] == '*')
						{
							arr2[x - i][y - j] = countsum(arr1, x - i, y - j) + '0';
						}
						else break;
					}
					for (j = 1; (y + j < COLS) && (countsum(arr1, x - i, y + j - 1) == 0); j++)
					{
						if (arr1[x - i][y + j] == '0' && arr2[x - i][y + j] == '*')
						{
							arr2[x - i][y + j] = countsum(arr1, x - i, y + j) + '0';
						}
						else break;
					}
				}
				else break;
			}
			else break;
		}
		for (i = 1; x + i < ROWS; i++)
		{
			if (arr1[x + i][y] == '0' && arr2[x + i][y] == '*')
			{
				arr2[x + i][y] = countsum(arr1, x + i, y) + '0';
				if (arr2[x + i][y] == '0')
				{
					for (j = 1; (y - j >= 1) && (countsum(arr1, x + i, y - j + 1) == 0); j++)
					{
						if (arr1[x + i][y - j] == '0' && arr2[x + i][y - j] == '*')
						{
							arr2[x + i][y - j] = countsum(arr1, x + i, y - j) + '0';
						}
						else break;
					}
					for (j = 1; (y + j < COLS) && (countsum(arr1, x + i, y + j - 1) == 0); j++)
					{
						if (arr1[x + i][y + j] == '0' && arr2[x + i][y + j] == '*')
						{
							arr2[x + i][y + j] = countsum(arr1, x + i, y + j) + '0';
						}
						else break;
					}
				}
				else break;
			}
			else break;
		}
	}
}

int ifsu(char arr[ROWS][COLS])
{
	int x = 0, i, j;
	for (i = 1; i <= ROW; i++)
	{
		for (j = 1; j <= COL; j++)
		{
			if (arr[i][j] == '*')
				x++;
		}
	}
	return x - MINE;
}

③main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "function.h"

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

void game(void)
{
	int su = ROW*COL-MINE;
	system("Cls");
	printf("开始游戏!\n");
	char mine[ROWS][COLS], show[ROWS][COLS];
	init(mine, '0'), init(show, '*');
	prinarr(show, ROWS, COLS);
	putmine(mine,MINE);
	while (su)
	{
		int px, py;
		printf("剩余未排查数:%-2d\n", su);
		printf("请输入你想要排查的坐标:>");
		scanf("%d %d", &px, &py);
		if (px > 0 && px <= COL && py > 0 && py <= ROW && show[px][py] == '*')
		{
			if (mine[px][py] == '1')
			{
				system("Cls");
				printf("很遗憾,你被炸死了。\n");
				prinarr(show, ROWS, COLS);
				prinarr(mine, ROWS, COLS);
				break;
			}
			else
			{
				system("Cls");
				release(mine, show, px, py);
				prinarr(show, ROWS, COLS);
			}
		}
		else
			printf("请输入有效的坐标值!\n");
		su = ifsu(show);
	}
	if (su == 0)
	{
		system("Cls");
		prinarr(show, ROWS, COLS);
		prinarr(mine, ROWS, COLS);
		printf("恭喜你胜利了!\n\n\n");
	}
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 1;
	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;
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值