Bootstrap

【c语言】扫雷游戏


扫雷游戏介绍:程序在棋盘内随机生成十个雷,玩家通过输入坐标进行排雷,当输入的坐标下有雷时,游戏结束,并在五秒后关机;如果输入的坐标下不是雷,则显示在该坐标下的九宫格范围内雷的个数。把雷排查完后,游戏胜利。
在这里插入图片描述
在这里插入图片描述

扫雷游戏实现

文件的创建

首先,我们创建两个.c源文件,一个用于函数的声明和实现(game.c),一个用于调用函数(test.c)。还有一个.h头文件:game.h
分两个文件来写,会使得代码美观,有序,易理解。
在这里插入图片描述

棋盘的分析

创建一个9*9的棋盘,在这个范围内存放雷和排查雷。字符‘1’表示雷,字符‘0’表示非雷。
在这里插入图片描述

当扫到非雷时,显示该坐标下的九宫格范围内的雷的个数。
比如我们输入坐标(3,6)检测到九宫格内雷的个数为:1,那么我们将在(3,6)处显示:1。
在这里插入图片描述
但是存在一个问题:当我们输入的坐标是在如上图的(9,7)时,该如何处理呢?我们创建的99的棋盘不就越界了吗?
此时为了防止出现越界的情况,我们创建的棋盘的大小应该是11
11的,这正好与边界坐标可以构成一个九宫格。但是显示出来的范围是棋盘9*9的部分,多出来的部分只是为了防止数组越界,不需要显示出来。

准备工作

以下代码都放在创建的头文件game.h下
在这里插入图片描述

通过宏定义,来控制数组的大小,棋盘的范围,雷的个数,这方便我们以后对程序数据的修改。
宏定义棋盘的行数:

//这是显示给玩家的棋盘
#define ROW 9
#defien COl 9
//这是棋盘实际的行数
#define ROWS ROW+2
#define COLS COL+2

宏定义雷的个数:

#define MINE_COUNT 10

需要用到的头文件:

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

扫雷开始界面

在test.c的文件下,创建一个函数test(),用于开始选择界面。
定义一个choice变量,用于记录玩家输入的值,并通过switch实现分流。将switch放在while循环下,玩家输入1,开始游戏,输入0,退出游戏。当玩家输入的不是0或者1时,则提示“请重新输入”,然后让用户重新选择。

在test()函数下调用菜单函数menu(),提示用户输入。
在这里插入图片描述
将menu()函数创建在game.c的源文件下
在这里插入图片描述

棋盘的初始化

当然,想要实现扫雷,我们得先有两个棋盘,一个用于存放雷和一个用于向玩家展示。
定义两个char类型的数组,一个用于存放雷(mine),一个用于向玩家展示(show)。
在这里插入图片描述
我们再在game.c文件下创建一个inItchess()函数,用于函数的初始化。
在test.c文件下调用,并把数组和行,列数以及初始化的字符传入。
geme.c文件下:
在这里插入图片描述
test.c文件下:
在这里插入图片描述

向这个函数里传入创建好的两个数组、数组的行、列个数以及字符。

show数组:向玩家展示的棋盘是加密的,看不到雷的,所以用‘*’表示。
mine数组:我们规定字符‘1’表示雷,字符‘0’表示非雷;开始先全部赋值‘0’。

//放在test.c文件下
inItchess(show,ROWS,COLS,'*');
inItchess(mine,ROWS,COLS,'0');
//放在game.c文件下
void inItchess(char board[ROWS][COLS],int rows,int cols,char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j=0;j<cols;j++)
		{
			board[i][j] = set;
		}
	}
}

初始化是把棋盘全部都初始化,不只是初始化棋盘9*9的部分

打印棋盘

在玩家输入“1"开始游戏后,我们需要向玩家展示出棋盘。
打印棋盘:

//放在test.c文件下
Display(show,ROW,COL);
//放在game.c的文件下
void Display(char board[ROWS][COLS],int row,int col)
{
	int i = 0;
	for (i = 0; i <= 9; i++)//这里显示的是棋盘横坐标
	{
		printf("%d ",i);
	}
	printf("\n");
	for (i=1;i<=row;i++)
	{
		printf("%d ",i);//这里显示棋盘纵坐标。
		int j = 0;
		for (j=1;j<=col;j++)
		{
			printf("%c ",board[i][j]);
		}
		printf("\n");
	}
	printf("-------------------扫雷-------------------\n");
}

运行效果图:
在这里插入图片描述

布置雷

扫雷当然不能没有雷啦,但是雷该如何布置呢?如果每次雷的位置都是固定的,那玩起来多没意思。
这里我们就可以用随机数进行布雷。
通过时间戳,改变随机数的种子。

//放在test()函数内
srand((unsigned int)time(NULL));

定义一个函数SetMine()进行布雷:

SetMine(mine,ROW,COL);
//放在game.c文件下
void SetMine(char board[ROWS][COLS],int row,int col)
{
	int x = 0;
	int y = 0;
	int count = MINE_COUNT;
	while(count!=0)
	{
		x = rand()%ROW+1;
		y = rand()%COL+1;
		if (board[x][y] != '1')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

因为玩家游玩的范围是在棋盘9*9的范围内,就是坐标(1,1)到坐标(9,9),所以布置雷只需要在这个范围内布置就可以了。
在这里插入图片描述

排雷

布置完雷后,我们应该如何排雷呢?
先说下扫雷游戏的胜利条件:当把所以不是雷的坐标全部排完,则游戏胜利。
所以我需要定义一个变量win,用来记录排雷的次数。
一下是代码实现:

//在test.c文件下
DelMine(mine,show,ROW,COL);
//在game.c文件下
void DelMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
	int x = 0;
	int y = 0;
	int win = 0;//记录排雷的次数
	printf("请输入坐标:");
	while (win<row*col-MINE_COUNT) //当排雷的次数小于总坐标数减去雷数时,进入循环
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
		{
			if (mine[x][y] == '1')
			{
				break;
			}
			else
			{
				int count = Get_Mine(mine,x,y);
				show[x][y] = count - '0';
				Display(show,row,col);
				win++;
			}
		}
		else
		{
			printf("请重新输入坐标");
		}
	}
	if (win == row * col - MINE_COUNT)
	{
		printf("恭喜你赢了");
	}
	else
	{
		system("cls");
		printf("输了");
		Display(mine,row,col);
		printf("五秒后关机");
		system("shutdown -s -t 5");
		int a = 5;
		while (a)//关机倒计时
		{
			printf("%d\n",a);
			a--;
			Sleep(1000);
			system("cls");
		}
	}
}

扫雷游戏代码实现

以下是在test.c文件下

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"


void game()
{
	char show[ROWS][COLS] = {0};
	char mine[ROWS][COLS] = {0};

	//初始化数组
	inItchess(show,ROWS,COLS,'*');
	inItchess(mine,ROWS,COLS,'0');

	//打印棋盘
	Display(show,ROW,COL);
	

	//布雷
	SetMine(mine,ROW,COL);
	//Display(mine, ROW, COL);

	//排雷
	DelMine(mine,show,ROW,COL);


}



void test()
{
	srand((unsigned int)time(NULL));
	menu();
	int choice = 0;
	scanf("%d",&choice);
	while (1)
	{
		switch (choice)
		{
		case 1:game();
			break;
		case 0:printf("退出游戏");
			break;
		default:
			break;
		}
		break;
	}
}



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

以下是在game.h下


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

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

#define MINE_COUNT 80

以下是在game.c文件下

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"


void menu()
{
	printf("********************************\n");
	printf("***********1.开始游戏***********\n");
	printf("***********0.退出游戏***********\n");
	printf("********************************\n");
}

void inItchess(char board[ROWS][COLS],int rows,int cols,char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j=0;j<cols;j++)
		{
			board[i][j] = set;
		}
	}
}

void Display(char board[ROWS][COLS],int row,int col)
{
	int i = 0;
	for (i = 0; i <= 9; i++)
	{
		printf("%d ",i);
	}
	printf("\n");
	for (i=1;i<=row;i++)
	{
		printf("%d ",i);
		int j = 0;
		for (j=1;j<=col;j++)
		{
			printf("%c ",board[i][j]);
		}
		printf("\n");
	}
	printf("-------------------扫雷-------------------\n");
}

void SetMine(char board[ROWS][COLS],int row,int col)
{
	int x = 0;
	int y = 0;
	int count = MINE_COUNT;
	while(count!=0)
	{
		x = rand()%ROW+1;
		y = rand()%COL+1;
		if (board[x][y] != '1')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

int Get_Mine(char mine[ROWS][COLS],int x,int y)
{
	int count = 0;
	int i = 0;
	for (i=-1;i<=1;i++)
	{
		int j = 0;
		for (j=-1;j<=1;j++)
		{
			count += mine[x+i][y+j] + '0';
		}
	}
	return count;
}


void DelMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	printf("请输入坐标:");
	while (win<row*col-MINE_COUNT) 
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
		{
			if (mine[x][y] == '1')
			{
				break;
			}
			else
			{
				int count = Get_Mine(mine,x,y);
				show[x][y] = count - '0';
				Display(show,row,col);
				win++;
			}
		}
		else
		{
			printf("请重新输入坐标");
		}
	}
	if (win == row * col - MINE_COUNT)
	{
		printf("恭喜你赢了");
	}
	else
	{
		system("cls");
		printf("输了");
		Display(mine,row,col);
		printf("五秒后关机");
		system("shutdown -s -t 5");
		int a = 5;
		while (a)
		{
			printf("%d\n",a);
			a--;
			Sleep(1000);
			system("cls");
		}
	}
}
;