zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【C语言】简单实现扫雷游戏

游戏C语言 实现 简单 扫雷
2023-09-11 14:17:48 时间

在实现这种小游戏时,每实现一个功能我们都要先检一下是否有bug,一个功能一个功能的实现起来。


1.实现思路

1.1菜单

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

}
int main()
{
	srand((unsigned int)time(NULL));//电脑随机布置雷的位置
	int input = 0;
	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;
}

1.2初始化棋盘

思路:
(1) 由于要防止棋盘周围雷的提示个数与用1表示雷混淆,所以我们要准备两个棋盘。一个棋盘随机布置雷,另一个棋盘用来排查雷的个数。字符1表示雷,字符0表示不是雷。
(2) 考虑到用户落子于棋盘边缘的时候,我们也要排查雷的个数,如果是99的数组,统计周围8个位置时,就会造成越界,所以我们要准备的是1111的两个棋盘(辅助统计),但是我们展示给用户的还是99的棋盘。
(3)准备两个数组。
一个棋盘全部初始化为字符0(还没布置雷);
一个棋盘全部初始化为字符
(还没排查雷,还没开始游戏)

//这是调用的函数
//初始化两个数组
	//一个初始化为'0'(表示还没布置雷)
	//InitBoard(mine, ROWS, COLS,'0');
	//一个初始化为'*'(表示还没开始排查)
	//InitBoard(show, ROWS, COLS,'*');
//实现初始化棋盘的函数
void InitBoard(char board[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++)
		{
			board[i][j] = set;
		}
	}
}

1.3打印棋盘

注意我们要打印(展示)的棋盘是9x9的,一个打印全是0(还没布雷)的棋盘,一个打印全是*的棋盘。初始化完棋盘后,先打印出来看看能不能实现。

//打印棋盘
	//Display(mine, ROW, COL);
	//Display(show, ROW, COL);
//打印棋盘
void Display(char board[ROWS][COLS], int row, int col)
{
	//我们要打印的是9*9的棋盘
	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 ", board[i][j]);
		}
		printf("\n");
	}
	printf("----------扫雷游戏---------\n");

}

打印结果展示:
在这里插入图片描述

1.4随机布置雷

注意是在9*9的棋盘上布置雷。布置完之后可以把mine数组打印出来看看每次是不是随机布置的

//在9*9的棋盘上布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	//布置10个雷
	int count = boom;
	while (count)
	{
		int x = rand() % 9 + 1;//1-9
		int y = rand() % 9 + 1;//1-9
		if (mine[x][y] == '0')//如果这个位置还没有布置雷,这个坐标才能布置雷
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

1.5排查雷

排查雷我们需要考虑玩家输入的坐标是否合法,是否已经落子,并且我们要从mine数组中获取用户输入坐标周围的雷的个数,即获取雷的个数,然后放在show数组的对应位置中。(注意我们获得的是数字,而我们需要的字符)

1.5.1获取周围雷的个数

int get_Mine(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.5.2转换数字与字符

从ASCII码表中可得’0’的值为48,’1’的值为49,而我们的数字0就是0,1就是1,即数字和字符相差48,即’0’的值。所以如果要把数字转换成字符,就把数字加上’0’,如何以字符的形式打印,若要把字符转换成数字,则减去’0’.

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int win = 0;//赢的情况-排查出ROW*COL-boom
	while (win<ROW*COL-boom)
	{
		printf("请输入你要排查的坐标:");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);//1-9

		

		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
		{
			if (show[x][y] != '*')
			{
				printf("此坐标已排查过了\n");
			}
			else if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				Display(mine, ROW, COL);
				break;
			}
			else
			{
				//统计这个坐标周围有几个雷
				//注意我们得到的是数字3,而我们要的是字符'3',才能存到字符数组show中
				int count= get_Mine(mine, x, y);
				show[x][y] = count + '0';
				Display(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("坐标输入不合法,请重新输入\n");
		}
	}
	if (win == ROW * COL - boom)
	{
		printf("恭喜你!排雷成功!\n");
		Display(mine, ROW, COL);
	}
}

判断用户排雷成功

即排出win==ROW*COL-雷的个数

二、代码的实现

头文件game.h

//头文件
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//展示棋盘
#define ROW 9
#define COL 9
//辅助棋盘
#define ROWS ROW+1
#define COLS COL+2

//想布置几个雷就布置几个雷
#define boom 70

//函数声明
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);
//打印棋盘
void Display(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);

游戏逻辑的实现game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//实现初始化棋盘的函数
void InitBoard(char board[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++)
		{
			board[i][j] = set;
		}
	}
}
//打印棋盘
void Display(char board[ROWS][COLS], int row, int col)
{
	//我们要打印的是9*9的棋盘
	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 ", board[i][j]);
		}
		printf("\n");
	}
	printf("----------扫雷游戏---------\n");

}
//在9*9的棋盘上布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	//布置10个雷
	int count = boom;
	while (count)
	{
		int x = rand() % 9 + 1;//1-9
		int y = rand() % 9 + 1;//1-9
		if (mine[x][y] == '0')//如果这个位置还没有布置雷,这个坐标才能布置雷
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
int get_Mine(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';
}
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int win = 0;//赢的情况-排查出ROW*COL-boom
	while (win<ROW*COL-boom)
	{
		printf("请输入你要排查的坐标:");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);//1-9

		

		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
		{
			if (show[x][y] != '*')
			{
				printf("此坐标已排查过了\n");
			}
			else if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				Display(mine, ROW, COL);
				break;
			}
			else
			{
				//统计这个坐标周围有几个雷
				//注意我们得到的是数字3,而我们要的是字符'3',才能存到字符数组show中
				int count= get_Mine(mine, x, y);
				show[x][y] = count + '0';
				Display(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("坐标输入不合法,请重新输入\n");
		}
	}
	if (win == ROW * COL - boom)
	{
		printf("恭喜你!排雷成功!\n");
		Display(mine, ROW, COL);
	}
}

实现游戏的函数test.c

#include"game.h"
void menu()
{
	printf("********************\n");
	printf("**1.play    0.exit**\n");
	printf("********************\n");

}
void game()
{
	//布置雷的数组
	char mine[ROWS][COLS] = { 0 };
	//排查雷的数组
	char show[ROWS][COLS] = { 0 };
	//初始化两个数组
	//一个初始化为'0'(表示还没布置雷)
	InitBoard(mine, ROWS, COLS,'0');
	//一个初始化为'*'(表示还没开始排查)
	InitBoard(show, ROWS, COLS,'*');
	//打印棋盘
	Display(mine, ROW, COL);
	Display(show, ROW, COL);
	//布置雷
	SetMine(mine, ROW, COL);
	Display(mine, ROW, COL);
	//排查雷
	FindMine(mine, show, ROW, COL);

}
int main()
{
	srand((unsigned int)time(NULL));//电脑随机布置雷的位置
	int input = 0;
	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;
}