扫雷游戏的设计与实现

一、扫雷游戏的功能

扫雷功能:
1.通过菜单选择进入游戏还是退出游戏
2.显示9*9的初级棋盘
3.随机布雷十个
4.排查雷
(1).如果位置是雷,被炸死。
(2).如果不是雷,就显示坐标周围有几个雷。
(3).所有雷找出,显示恭喜你排雷成功。

二、多文件实现扫雷游戏

本次扫雷游戏,我们通过多文件来实现,分别用三个文件:
1.test.c,本文件主要为了测试逻辑
2.game.c,本文件主要是为了游戏的实现
3.game.h,本文件主要是实现函数的声明

三、游戏的分析和设计

(一)游戏的分析

初级的扫雷我们要有一个扫雷的棋盘用来放雷,首先我们需要定义二维数组,来存放雷。其次我们需要让棋盘初始化的时候,是雷为1,不是雷为0。然后我们排雷的时候,如果这个位置不是雷的话,那我们就算这个坐标周围有几颗雷。这个时候就会存在冲突,假如选择的位置周围有一颗雷,那么输出1,这个1表示雷还有周围有一颗雷呢?

我认为可以用两个棋盘来存放,用mine数组来存放雷的位置,用show来存放周围雷的个数,我们可以用符号‘1‘,’0’存放在mine数组,符号*存放在show数组。

创建棋盘时,当我们计算周围雷个数时,当计算遇到边缘时,就可能会出现越界问题,那么我们可以创建一个11*11的棋盘,来解决越界问题。
即在头文件中可以如下处理:

#define ROW 9//9行
#define COL 9//9列
#define ROWS ROW+2//11行
#define COLS COL+2//11列

用ROW(行)和COL(列)表示会在后续使用中更方便,而不是一次性代码。

(二)游戏的设计

1.实现游戏界面,以及游戏的选择

我们可以用do while来实现主函数:

#include<stdio.h>
#include"game.h"
void menu()
{
	printf("************************************\n");
	printf("************请选择******************\n");
	printf("***********1.进入游戏***************\n");
	printf("***********0.退出游戏***************\n");
	printf("************************************\n");
	printf("************************************\n");
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();//游戏界面
		scanf("%d", &input);
		switch (input)
		{
		case 1:
		printf("扫雷游戏");
		break;
		case 0:
			printf("退出游戏\n");
            break;
		default:
			printf("输入有误,重新输入\n");
		}

	} while (input);
	return 0;
}

do while可以实现先执行在判断,根据功能我们需要先进入游戏界面。我们利用menu函数,来打印界面,并且配合switch语句来选择是否进入扫雷游戏,如果我们输入不是0/1,那我们就重新输入,如果是1就进入游戏,如果是0就退出游戏。

2.游戏的具体设计

当我们选择1的时候,我们就会进入游戏,所以我们要在case 1:语句的时候定义game函数来调用具体的函数来实现扫雷游戏。

#include<stdio.h>
#include"game.h"

void game()
{
	char mine[ROWS][COLS];//布局棋盘
	char show[ROWS][COLS];//展示棋盘
	InitBoard(mine,ROWS,COLS,'0');//初始化棋盘 全为0
	InitBoard(show,ROWS,COLS,'*');//初始化棋盘 全为*
	//打印棋盘
    //DisplayBoard(mine,ROW,COL);//记录雷的个数
	DisplayBoard(show,ROW, COL);//展示
	//布雷
	SetMine(mine,ROW,COL);
	//DisplayBoard(mine, ROW, COL);//查看布雷结果
	//排雷
	FindMine(mine,show,ROW,COL);
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
	     printf("菜单");//不与上述内容重复
		scanf("%d", &input);
		switch (input)
		{
		case 1:
		game();
		break;
		case 0:
			printf("退出游戏\n");
            break;
		default:
			printf("输入有误,重新输入\n");
		}

	} while (input);
	return 0;

game函数的步骤为:①创建两个二维数组②初始化棋盘③打印棋盘④布雷⑤排查雷

3.在game.c中对游戏的具体实现

(1)初始化棋盘

我们用InitBoard函数定义初始化棋盘,我们要让mine棋盘全为‘0’;让show棋盘全为*。如何解决两个棋盘无法定义两种符号的情况呢?我们可以在函数调用时传入实参‘0’和 *,然后用形参set接收即可。注意:别忘记在头文件中声明InitBoard函数,一个函数的定义,一定要有函数的声明。

void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{//初始化棋盘:让两个棋盘全为0/*
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			board[i][j] = set;//初始化好棋盘
		}
	}
(2)打印棋盘

我们用DisplayBoard函数来表示打印棋盘。注意:我们打印时,一定要打印9* 9的棋盘,因为我们最初设计时,就是9*9(初级难度),但是当我们定义传参时,要与当时创建数组的行列数相同,所以char board[ROWS][COLS]。

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	printf("---------扫雷游戏---------\n");
	for (int j = 0; j <= row; j++)
	{
		printf("%d ", j);//列标
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d ", i);//行号
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("---------扫雷游戏---------\n");

}
(3)布置雷的个数(10个)

我们用SetMine函数来布雷,注意我们布雷要在9*9棋盘内布雷。

void SetMine(char mine[ROWS][COLS],int row,int col)
{
	int count = Easy_Count;
	while (count)
	{
		//随机生成的行列布雷
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
            count--;
		}
	}
}

因为布置雷的时候我们要在9*9的棋盘内,生成随机行列1-9的位置(为什么是1-9?因为从数组的下标来算,0行/0列与10列/10行,是我们防越界时设置的,所以不算在内),所以我们就需要rand函数来生成随机值,在使用rand函数时,我们要在主函数内先定义srand函数(srand函数只用一次,所以我们把它定义在主函数内):srand((unsigned int)time(NULL))。要包含头文件#include<time.h>与#include<stdlib.h>。

扩展:当我们要生成a-b的随机值时,我们可以用固定公式:a+rand()%(b-a+1)
(4)排雷

我们用Findmine函数来实现排雷,在mine数组中找雷,如果不是雷,那么我们计算出雷的个数传入show数组中。

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] + mine[x + 1][y + 1] - 8 * '0');
	//'1'-'0'=1
	//字符1-字符0=数字1,以此类推算出周围还有多少雷
}

void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row,int col)
{
	int i = 0;//行
	int j = 0;//列
	int win = 0;
	while (win<ROW*COL-Easy_Count)
	{
		scanf("%d%d", &i, &j);
		if (show[i][j]!='*')
		{
			printf("重复输入,请重新输入");
			scanf("%d%d", &i, &j);//防止输入相同数值
		}
		if (i > 1 && j > 1 && i <= row && j <= col)
		{
			//输入合法值
			if (mine[i][j] == '1')
			{
				printf("你被炸死了\n");
				DisplayBoard(mine, ROW, COL);//让我看布雷结果
				break;
			}
			else
			{
				int count = GetmineCount(mine,i,j);//count需要返回一个数字
				show[i][j]=count +'0';//例如:返回count为1,1+'0'=49
				//'0'等于ASCII码48
				//'1'等于ASCII码49
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			//不合法
			printf("重新输入");
		}
	}
	if (win == ROW * COL - Easy_Count)
	{
		printf("恭喜你,排雷成功!!");
		DisplayBoard(mine, ROW, COL);
	}
}

其中 GetmineCount函数的作用,计算我输入坐标的周围有几个雷。我们最开始用符号0和符号1来表示是否有雷,那么‘1’-‘0’=1,以此类推,来推算出我周围有多少个雷。例如: 返回count为数字1时,1+‘0’=49
'0’等于ASCII码48
'1’等于ASCII码49

四、扫雷游戏的扩展

1.是否可以选择游戏难度:简单9*9,困难16 *16,地狱30 *16
2.如果排查位置不是雷,周围也没有雷,可以展开周围的⼀⽚
3.是否可以标记雷
4.是否可以加上排雷的时间显⽰

五、代码总体预览

1.test.c

#include<stdio.h>
#include"game.h"

void menu()
{
	printf("************************************\n");
	printf("************请选择******************\n");
	printf("***********1.进入游戏***************\n");
	printf("***********0.退出游戏***************\n");
	printf("************************************\n");
	printf("************************************\n");
}
void game()
{
	char mine[ROWS][COLS];//布局棋盘
	char show[ROWS][COLS];//展示棋盘
	InitBoard(mine,ROWS,COLS,'0');//初始化棋盘 全为0
	InitBoard(show,ROWS,COLS,'*');//初始化棋盘 全为*
	//打印棋盘
    //DisplayBoard(mine,ROW,COL);//记录雷的个数
	DisplayBoard(show,ROW, COL);//展示
	//布雷
	SetMine(mine,ROW,COL);
	//DisplayBoard(mine, ROW, COL);//查看布雷结果
	//排雷
	FindMine(mine,show,ROW,COL);


}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
		game();
		break;
		case 0:
			printf("退出游戏\n");
            break;
		default:
			printf("输入有误,重新输入\n");
		}

	} while (input);
	return 0;
}

2.game.c

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
//游戏实现
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] + mine[x + 1][y + 1] - 8 * '0');
	//'1'-'0'=1
	//字符1-字符0=数字1,以此类推算出周围还有多少雷
}
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row,int col)
{
	int i = 0;//行
	int j = 0;//列
	int win = 0;
	
	while (win<ROW*COL-Easy_Count)
	{
		scanf("%d%d", &i, &j);
		if (show[i][j]!='*')
		{
			printf("重复输入,请重新输入");
			scanf("%d%d", &i, &j);//防止输入相同数值
		}
		if (i > 1 && j > 1 && i <= row && j <= col)
		{
			//输入合法值
			if (mine[i][j] == '1')
			{
				printf("你被炸死了\n");
				DisplayBoard(mine, ROW, COL);//让我看布雷结果
				break;
			}
			else
			{
				int count = GetmineCount(mine,i,j);//count需要返回一个数字
				show[i][j]=count +'0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			//不合法
			printf("重新输入");
		}
	}
	if (win == ROW * COL - Easy_Count)
	{
		printf("恭喜你,排雷成功!!");
		DisplayBoard(mine, ROW, COL);
	}
}

void SetMine(char mine[ROWS][COLS],int row,int col)
{
	int count = Easy_Count;
	while (count)
	{
		//随机生成的行列布雷
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
            count--;
		}
		
	}
}


void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	printf("---------扫雷游戏---------\n");
	for (int j = 0; j <= row; j++)
	{
		printf("%d ", j);//列标
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d ", i);//行号
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("---------扫雷游戏---------\n");

}
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{//初始化棋盘:让两个棋盘全为0/*
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			board[i][j] = set;//初始化好棋盘
		}
	}
	
}

3.game.h

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


#define ROW 9//9行
#define COL 9//9列
#define ROWS ROW+2
#define COLS COL+2
#define Easy_Count 10//十个雷

 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);
 int  GetmineCount(char mine[ROWS][COLS], int x, int y);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值