c语言游戏扫雷——二维数组运用解析

二维数组简单应用游戏—扫雷

想必大家都很熟悉扫雷这个游戏其规则简单如下:
  • 在一个雷盘中有定量的雷需要玩家进行排除,不限时间。
  • 玩家踩到雷,游戏结束。
  • 玩家输入坐标不是雷,便将展开坐标周围情况。
  • 玩家第一步走将保证不被炸死。
思路:
  • 创建两个雷盘,一个是设计者雷盘为了实现逻辑,一个是玩家雷盘展示给玩家结果,
  • 雷盘的大小9×9的话,应该初始化11×11的这是考虑到边缘的情况,并且打印雷盘。
  • 布雷,第一步不会被炸死,还要展开显示坐标周围雷的数量。
  • 判断输赢,运用多文件结构game.c,test.h先声明头文件game.h。

先画出游戏的流程图来提供一个清晰思路,往后按流程写代码就不容易混乱。
c语言游戏扫雷——二维数组运用解析
注意:由于本程序用的是多文件结构所以一定要声名头文件game.h
c语言游戏扫雷——二维数组运用解析

头文件game.h
#ifndef _GAME_H_
#define _GAME_H_
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define EASY_COUNT 10//雷的个数
#define ROWS 11//实际雷盘大小
#define COLS 11
#define ROW 9//显示雷盘大小
#define COL 9

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

void display(char mine[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);//排雷且判输赢

void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);//展开坐标周围

void safemine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//保证第一步不被炸死

#endif
游戏测试模块test.c
void test()//游戏测试运行
{
	char mine[ROWS][COLS] = { 0 };//存放雷的信息
	char show[ROWS][COLS] = { 0 };//存放排查出雷的信息
	int input = 0;
	
	do
	{
		printf("请选择:>");
        scanf("%d", &input);
		switch (input)
		{
		case 1:
			init(mine, ROWS, COLS, '0');
			init(show, ROWS, COLS, '*');
			setmine(mine, ROW, COL);
			display(show, ROW, COL);
			safemine(mine, show, ROW, COL);
			findmine(mine, show,ROW, COL);
			break;
		case 0:
			printf("推出游戏!\n");
			break;
		default:
			printf("输入错误,请从新选择:>\n");
			break;
		}
	} while (input);
}

游戏运行模块game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

void init(char mine[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++)
		{
			mine[i][j] = set;
		}
	}
}

void display(char mine[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  ", mine[i][j]);
		}
		printf("\n");
	}
	printf("------------------------------\n");
}

void setmine(char mine[ROWS][COLS], int row, int col) //布雷
{
	int x = 0;
	int y = 0;
	int count = EASY_COUNT;
	
	while (count)
	{
		x = rand() % row+1 ;
		y = rand() % col+1 ;
		 
		if (mine[x][y] == '0')
		{
               mine[x][y] = '1';
			   count--;
		}
	}	
}

int CountMine(char mine[ROWS][COLS], int x, int y)//计算x,y周围的雷数量
{
	int count = 0;
	if (mine[x - 1][y - 1] == '1')  //1表示该位置有雷
	{
		count++;
	}
	if (mine[x - 1][y] == '1')
	{
		count++;
	}
	if (mine[x - 1][y + 1] == '1')
	{
		count++;
	}
	if (mine[x][y - 1] == '1')
	{
		count++;
	}
	if (mine[x][y + 1] == '1')
	{
		count++;
	}
	if (mine[x + 1][y - 1] == '1')
	{
		count++;
	}
	if (mine[x + 1][y] == '1')
	{
		count++;
	}
	if (mine[x + 1][y + 1] == '1')
	{
		count++;
	}
	return count;
}

void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//计算x,y坐标周围坐标的雷数
{
	if (mine[x - 1][y - 1] == '0')  //如果该位置没有雷,则计算出其周围8个区域雷的个数并标记在玩家棋盘对应位置
	{
		show[x - 1][y - 1] = CountMine(mine, x - 1, y - 1) + '0'; //CountMine()函数返回的是数字,而PlayerMine数组存的是字符,所以将数字加上字符零可得数字字符
	}
	if (mine[x - 1][y] == '0')
	{
		show[x - 1][y] = CountMine(mine, x - 1, y) + '0';
	}
	if (mine[x - 1][y + 1] == '0')
	{
		show[x - 1][y + 1] = CountMine(mine, x - 1, y + 1) + '0';
	}
	if (mine[x][y - 1] == '0')
	{
		show[x][y - 1] = CountMine(mine, x, y - 1) + '0'; 
	}
	if (mine[x][y + 1] == '0')
	{
		show[x][y + 1] = CountMine(mine, x, y + 1) + '0';  
	}
	if (mine[x + 1][y - 1] == '0')
	{
		show[x + 1][y - 1] = CountMine(mine, x + 1, y - 1) + '0'; 
	}
	if (mine[x + 1][y] == '0')
	{
		show[x + 1][y] = CountMine(mine, x + 1, y) + '0';
	}
	if (mine[x + 1][y + 1] == '0')
	{
		show[x + 1][y + 1] = CountMine(mine, x + 1, y + 1) + '0'; 
	}
}

void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//扫雷且判输赢
{   
	int x = 0;
	int y = 0;
	int count = 0;
	while (1)
	{
		printf("请输入排查坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row&&y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("抱歉!你踩雷了\n");
				display(mine, row, col);
				break;
			}
			else
			{
				int ret = CountMine(mine, x, y);//计算x,y周围雷数
				show[x][y] = ret+'0';
				OpenMine(mine,show,x,y);
				display(show, row, col);
				count++;
				if ((ROW*COL) - EASY_COUNT == count)
				{
					printf("你赢了!\n");
					display(mine, row, col);
				}

			}
		}
		else
		{
			printf("输入错误,坐标非法!");
		}
	}
}

void safemine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//保证第一步不被炸死
{
	int x = 0;
	int y = 0;
	int ret = 1;
	int ch = 0;
	printf("请输入要排查的坐标:>");
	scanf("%d%d", &x, &y);

	if (mine[x][y] == '1')//如果是雷,去除这个雷从新布一个雷
	{
		mine[x][y] = '0';
		ch = CountMine(mine, x, y);
		show[x][y] = ch + '0';
		while (ret)
		{
			x = rand() % row + 1;
			y = rand() % col + 1;
			if (mine[x][y] == '0')
			{
				mine[x][y] = '1';
			}
			ret--;
		}
	}
	display(show, row, col);
}
游戏主函数模块main( )
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
int main()
{
	srand((unsigned int)time(NULL));//随机数发生器
	menu();
	test();
	//system("pause");
	return 0;
}

总结:

  • 设计是要考虑到用两个雷盘也就是两个二维数组且作用也不相同;
  • 多文件结构注意头文件的声名。
  • 熟练运用#define来定值,是游戏难度变化简单容易。
  • 要理清思维逻辑,切忌提手就敲代码容易卡壳。