学会了C语言的数组和函数,那就来看看扫雷游戏吧

1. 前言

扫雷游戏我们应该都有玩过吧,那么当我们学完了二维数组之后就可以开始自己动手制作一个简易的扫雷游戏了

下面是效果展示

学会了C语言的数组和函数,那就来看看扫雷游戏吧_第1张图片

先来看看完整代码

game.h

#pragma once

#include 
#include 
#include 

#define ROW 9
#define COL 9

#define ROWS 11
#define COLS 11

#define NUMMINE 10  //雷的数量

void meun();

void game();

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 board[ROWS][COLS], int row, int col);

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

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

test.c

#define _CRT_SECURE_NO_WARNINGS 

#include "game.h"

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

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

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

	DisplayBoard(show, ROW, COL);  //展示*

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

	FindMine(mine, show, ROW, COL); //查找雷
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
		meun();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("成功退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

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

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	for (int i = 0; i <= col; i++) {  //给用户显示行
		printf("%d ", i);
	}
	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");
	}
}

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

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x, y;
	int cnt = 0;
	while (cnt < row * col - NUMMINE) {
		printf("请选择你要排查的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) {
			if (mine[x][y] == '1') {
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else {
				int count = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				cnt++;
			}
		}
		else {
			printf("坐标非法,请重新输入\n");
		}
	}
	if (cnt == row * col - NUMMINE) {
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}
int GetMineCount(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y - 1] + board[x][y - 1] + board[x + 1][y - 1] +
		board[x - 1][y] + board[x + 1][y] + board[x - 1][y + 1] +
		board[x][y + 1] + board[x + 1][y + 1] - 8 * '0');
}

2. 游戏的分析

最简单的扫雷是需要一个9*9的棋盘,所以我们可以用一个9*9的二维数组来存放这个棋盘,我们给它全部初始化为0,如果这个位置有雷,那么我们将这个位置变成1

学会了C语言的数组和函数,那就来看看扫雷游戏吧_第2张图片

但是我们排查的时候是需要知道当前排查的位置周围有几个雷的,那么当我们排查到最外围的一圈的时候它的第10行或第10列都没有数据,那么怎么确定这个地方雷的数量?

所以我们要将这个数组设置为11*11的大小,只在中间的9*9的位置布置雷,就可以解决这个问题

学会了C语言的数组和函数,那就来看看扫雷游戏吧_第3张图片

而且我们最好使用两个数组,一个用来展示给用户,一个用来存储雷的分布信息情况

为了保持神秘,我们展示给用户的数组可以展示为字符’*‘,所以为了保持两个数组的一致性我们将两个数组都定义为字符数组比较好

char mine[11][11] = {0};//⽤来存放布置好的雷的信息
char show[11][11] = {0};//⽤来存放排查出的雷的个数信息

3. 文件结构设计

在上一节的函数精解中有写到,我们可以使用多个文件,对于多行代码的处理比较清晰

学会了C语言的数组和函数,那就来看看扫雷游戏吧_第4张图片

game.h用来存放函数的声明、类型的声明放在头文件

game.c和test.c用来存放对函数的实现

4. 游戏的实现

4.1 棋盘的初始化

首先我们需要初始化棋盘,用一个函数来初始化棋盘

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

这个函数的第一个参数是要初始化的棋盘,第二、三个参数是行和列,第四个参数是要初始化的字符

用循环遍历数组,将所有值都赋成set就好了

4.2 棋盘的展示

我们需要输出棋盘到屏幕上,所以我们需要一个函数展示

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	for (int i = 0; i <= col; i++) {  //给用户显示行
		printf("%d ", i);
	}
	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");
	}
}

第一个 for 循环的目的是在第一行输出0-9的数字,第二个 for 循环上来的printf是为了显示列,为了给用户更容易的知道哪个位置是第几行第几列,所以需要这么操作(删掉没影响)

其余的部分计算打印出从下标为1-9的位置,打印出9*9的棋盘(实际上是11*11的棋盘)

4.3 雷的放置

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

NUMMINE在我们的game.h头文件里有用宏定义,表示雷的数量

这里用到了随机数,假设棋盘是9*9,那么随机数 x = rand() % row 的取值范围就是0-8,+1取值范围就是1-9,下面的y同理

cnt控制了循环的次数,雷有多少就布置多少次,每次都让cnt--

4.4 周围雷的数量

int GetMineCount(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y - 1] + board[x][y - 1] + board[x + 1][y - 1] +
		board[x - 1][y] + board[x + 1][y] + board[x - 1][y + 1] +
		board[x][y + 1] + board[x + 1][y + 1] - 8 * '0');
}

直接将周围的8个坐标的元素表示出来再 - 8*’0‘,因为我们这个是字符数组,减去字符0才能知道有多少个整型的雷

具体使用看下面代码

4.5 开始排查雷的位置

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x, y;
	int cnt = 0;
	while (cnt < row * col - NUMMINE) {
		printf("请选择你要排查的坐标\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) {
			if (mine[x][y] == '1') {
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else {
				int count = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				cnt++;
			}
		}
		else {
			printf("坐标非法,请重新输入\n");
		}
	}
	if (cnt == row * col - NUMMINE) {
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

控制第一个循环的次数是 cnt < row * col - NUMMINE,表示的是我们需要排查的次数,如果9*9的棋盘有10个雷,那么我们就需要排查71次

这里使用到了上面的GetMineCount函数,将我们找到雷的数量赋值给count,它的下面一行赋值给show[x][y]的时候需要+上字符0,这一步是必不可少的,因为我们是字符数组,不能存进去一个整型,所以+字符0就解决了

4.6 美化界面

4.6.1 game函数

我们将上面的所有函数都放进game函数,最后在主函数里调用game函数就可以了

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

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

	DisplayBoard(show, ROW, COL);  //展示*

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

	FindMine(mine, show, ROW, COL); //查找雷
}

4.6.2 菜单制作

菜单也是用一个函数,至于里面的内容凭个人自己喜欢制作即可

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

4.7 主函数

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
		meun();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("成功退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

srand是前面随机数所需要的种子,在我之前写的猜数游戏有写到C语言猜数游戏(精讲),你能顺利做成这个游戏并且自己游玩通关吗?-CSDN博客

因为要先进入菜单选择是否进入游戏,所以可以用个do-while循环先使用菜单,用input控制循环的进出

switch选择是否进入游戏,如果input为1则进入游戏,为0则跳出循环

这样扫雷游戏就做完了

感谢观看,希望对你有所帮助

---------------------------------------------------------------------------------------------------------------------------------

你可能感兴趣的:(游戏,c语言,学习)