C语言初阶-简单实现扫雷游戏

前言:

   在不涉及指针的情况下 ,我们可以通过函数和数组简单的实现一个扫雷游戏(9x9)。

以下我直接给出我们所需要的函数进一步讲解实现。

(同样,我们分成模块文件来完成:game.c   main.c  game .h)

代码分析:

1.实现交互界面,退出or开始游戏。我们直接上代码

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"

int main()
{
	int input = 1;
	while (input)
	{

		menu();
		printf("请输入—>: ");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("已退出游戏\n");
			return;
		default:
			break;
		}

	}


	return 0;
}

2.我们再来看看game.h中几个定义的宏常量

首先我们要定义一个棋盘的大小,但是我们为什么会有一个ROWSCOLS呢?其实这样做是为了方便我们后续在统计了地雷的数目时,因为我们在排查边界的地雷时,就会遇到数组越界的问题,因此我们让行和列大一些,这样我们就不用另外考虑边界的特殊情况,其次就是BOOM_CONUT用来设置地雷的数目

3.我们来看看game()函数的内部

首先我们创建两个数组,一个mine用来记录实际的布雷情况,一个用来展示棋盘给玩家进行游玩 。然后我们依次初始化他们,我们将初始化的内容也设置为参数,这样我们就不用再写一个函数来初始化两个不同要求的数组。初始化后我们可以打印棋盘展示,为了更好地展现棋盘,打印数组的同时,打印棋盘的行列序号


//打印棋盘
void display_board(char board[ROWS][COLS], int row, int col)
{
    
	printf(" |-----Gaming-----|\n");

	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");

	}
	printf(" |-----Gaming-----|\n");



}

注意我给出的game()内部,我也打印了mine数组,这是因为方便我们后续调试 观察,实际情况不需要打印mine棋盘,后面可以注释掉该行,打印show即可。

然后就是设置地雷,使用rand()函数,为了让生成的数更加随机可靠,我们可以在game()中调用srand()函数(我们在进行下标操作时,在1到9进行操作即可,我们要求棋盘时是9x9,而我们的数组大小是11x11,这是用来防止数组越界的,上面的 打印棋盘也是同理,在1到9的下标操作即可),如下

然后关键来了:排雷操作

 前面我们将mine初始化为‘0’(字符0)是有原因的,这样方便我们更好的计算排查坐标周围的地雷个数,直接上代码:

int get_boom_num(char mine[ROWS][COLS],int x,int y)
{
	return
		mine[x - 1][y] + mine[x + 1][y]
		+ mine[x][y - 1] + mine[x][y + 1]
		+ mine[x - 1][y + 1] + mine[x - 1][y - 1]
		+ mine[x + 1][y + 1] + mine[x + 1][y - 1]
		- 8 * 48;
		
}

这段代码是不是看起来很简单,但好像又不知道在干嘛 ?不急慢慢来看,其实我们就是将x,y坐标周围八个值加起来,然后减去8*48;为什么要这样操作呢?我们看看ascII表就知道了因为我们是将数组初始化为了字母‘0’,实际上ascii的值是48,而我们设置的雷是字符‘1’,因此当我们计算地雷的个数,就可以将他们直接相加然后减去48即可得到数字的值,而不是字符的值。然后我们再更新show中的字符

//排雷
void find_boom(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int win =COL*ROW- BOOM_COUNT;
	while (win > 0)
	{
		printf("请输入排雷坐标-->: ");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);

		if (show[x][y] == '*')
		{
			if (mine[x][y] != '1')
			{
				int n = get_boom_num(mine, x, y);
				show[x][y] = n + 48;
				display_board(show,ROW,COL);
				win--;
			}

			else
			{
				printf("你踩雷了!");
				break;
			}
		}

		else
		{
			printf("该坐标已经被排查!\n");
		}

	}
	if (win > 0)
		printf("排雷失败,游戏结束!\n");
	else
		printf("排雷成功,游戏结束!\n");


}

因为我们get_boom_num()的返回类型是int,即为数字的值,而我们要打印的是字符,因此要再n的基础上加上48,得到字符数字,通过ascii表应该能够比较好的理解。然后我们设置一个int win(行x列-设置的地雷,即可得到无雷的坐标个数),用来判断游戏的进行状况 ,逻辑与设置地雷的判断条件类似,每当我们判断成功,win就会减小,知道排完地雷,或者踩雷。

总结

  其中还要很多不足,还请给位大佬多多指正!

  还请大家多多一键三连!

最后是所有代码汇总

//game.c
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"



//菜单
void menu()
{
	printf("-------扫雷游戏-------\n");
	printf("----------------------\n");
	printf("----    1.play    ----\n");
	printf("----------------------\n");
	printf("----    0.exit    ----\n");
	printf("----------------------\n");
	printf("----------------------\n");


}
//初始化棋盘
void init_board(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 display_board(char board[ROWS][COLS], int row, int col)
{
    
	printf(" |-----Gaming-----|\n");

	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");

	}
	printf(" |-----Gaming-----|\n");



}

//设置地雷
void set_boom(char mine[ROWS][COLS],int row, int col)
{
	int x = 0;
	int y = 0;
	int count = BOOM_COUNT;

	while (count> 0)
	{
		x = rand() % row + 1;
		y = rand() % col + 1;
		
		if (mine[x][y] != '1')
		{
			mine[x][y] = '1';
			count--;
		}

	}

}



//排雷
void find_boom(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int win =COL*ROW- BOOM_COUNT;
	while (win > 0)
	{
		printf("请输入排雷坐标-->: ");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);

		if (show[x][y] == '*')
		{
			if (mine[x][y] != '1')
			{
				int n = get_boom_num(mine, x, y);
				show[x][y] = n + 48;
				display_board(show,ROW,COL);
				win--;
			}

			else
			{
				printf("你踩雷了!");
				break;
			}
		}

		else
		{
			printf("该坐标已经被排查!\n");
		}

	}
	if (win > 0)
		printf("排雷失败,游戏结束!\n");
	else
		printf("排雷成功,游戏结束!\n");


}


//判断坐标周围地雷个数

int get_boom_num(char mine[ROWS][COLS],int x,int y)
{
	return
		mine[x - 1][y] + mine[x + 1][y]
		+ mine[x][y - 1] + mine[x][y + 1]
		+ mine[x - 1][y + 1] + mine[x - 1][y - 1]
		+ mine[x + 1][y + 1] + mine[x + 1][y - 1]
		- 8 * 48;
		
}


void game()
{
	char mine[ROWS][COLS] = { 0 };//用于记录雷
	char show[ROWS][COLS] = { 0 };//用于展示棋盘

	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');

	//设置地雷
	srand((unsigned int)time(NULL));
	set_boom(mine, COL, ROW);

	display_board(mine, ROW, COL);
	display_board(show, ROW, COL);

	find_boom(mine, show, ROW, COL);



}

//game.h
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define BOOM_COUNT 70
void menu();//菜单
void game();//游戏主流程
void init_board(char board[ROWS][COLS], int rows, int cols,char set);//初始化棋盘
void display_board(char board[ROWS][COLS], int row, int col);//打印棋盘
void set_boom(char mine[ROWS][COLS], int row, int col);//设置地雷
void find_boom(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//排雷操作
int  get_boom_num(char mine[ROWS][COLS],int x,int y);//获取坐标周围地雷个数
 

//main.c
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"

int main()
{
	int input = 1;
	while (input)
	{

		menu();
		printf("请输入—>: ");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("已退出游戏\n");
			return;
		default:
			break;
		}

	}


	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值