C语言小游戏——扫雷


前言

“扫雷”相信小伙伴们都玩过吧,上机课偷偷玩机房的电脑,只有扫雷,纸牌等小游戏,打磨打磨上课的时间哈哈。
经过自己一段时间的学习后,接下来细讲一下我做的扫雷小程序吧!(附加区域展开效果哦~)


一、效果图(展示)

先展示一下程序运行效果图吧

打印菜单+初始化扫雷界面
在这里插入图片描述
接着扫雷游戏进行,输入排查坐标(如果该坐标附近区域无雷(全为0)即可展开附近一片)
在这里插入图片描述
接着继续输入坐标,如果该坐标是雷,则游戏结束,可选择继续游戏也可选择退出,继续游戏前可以按 2 实现清屏,以防上一局的游戏干扰视线
在这里插入图片描述
游戏结束后会展开所有坐标,查看雷或非雷的区域

二、整体结构及功能介绍

要想扫雷,首先得有一块足够埋雷的空间,扫雷时要想想该如何实现如果该格子周围八个格子都没有雷,该区域就会被清空;踩到雷,即游戏结束。

所以我们理清思路开始逐一实现
1、创建雷盘
2、初始化雷盘
3、打印雷盘
4、随机布置你定义的雷的数量
5、展开式排雷

程序文件还是与三子棋同样思路
test.c;game.c;game.h同三子棋

需要思考的问题

对这上一个小游戏三子棋的思想,想完成一个大的平台,我们可以利用二维数组来存放雷的信息。
首先要电脑实现随机分布各个雷的位置、位置信息只有开发者能看到和游戏结束时能看到

三、功能解析及代码实现

创建雷盘、布置雷盘、初始化、打印
最上面和最左边的数字代表的是列与行坐标,'0'代表没有雷,'1'则为雷,'*'表示的是该点坐标还未进行扫雷;

如果9X9 的平台,当输入坐标为 3,1 时,发现左边有三个位置是超出我们定义的 9X9 数组范围的,那么如果解决这个问题呢?
我们可以让9X9的范围行列都向外扩展一圈,此时9X9就变为 11X11的范围了,接着可以把外围的格子初始化为0然后不显示外围的数据,这样就可以避免后续排查雷的判断了。
在这里插入图片描述

void init_board(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_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0, j = 0;
	printf("----------扫雷游戏----------\n");
	// 列号
	for ( j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	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");
}


void set_mine(char mine[ROWS][COLS], int row, int col)
{
	// 布置10个雷
	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--;
		}
	}
}

接着就是扫雷了,这里我没有添加第一次排雷不被炸死功能,此功能可以先用if判断第一次输入的坐标是否为雷,如果是雷则可以在雷盘上重新找一个非雷的位置将开始的雷移到其他地方,小伙伴可以自行实现哦~
扫雷功能实现:玩家输入一个坐标,如果是雷,则游戏结束,如果不是雷,并且该附近区域无雷,则展开一篇,游戏继续,直到下一次排到雷或者所有非雷位置被排查完,则游戏结束

// 统计
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] + 
		mine[x - 1][y + 1] - 8 * '0');
}

// 递归实现展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	int count_number = get_mine_count(mine, x, y);//排查该坐标附近雷的个数
	if (count_number == 0)
	{
		show[x][y] = ' ';
		if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*')
		{
			Spread(mine, show, x - 1, y - 1);
		}
		if ((x - 1 > 0 && x - 1 < 10) && (y > 0 && y < 10) && show[x - 1][y] == '*')
		{
			Spread(mine, show, x - 1, y);
		}
		if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*')
		{
			Spread(mine, show, x - 1, y + 1);
		}
		if ((x > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*')
		{
			Spread(mine, show, x, y - 1);
		}
		if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*')
		{
			Spread(mine, show, x, y + 1);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*')
		{
			Spread(mine, show, x + 1, y - 1);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*')
		{
			Spread(mine, show, x + 1, y);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*')
		{
			Spread(mine, show, x + 1, y + 1);
		}
	}
	else
	{
		show[x][y] = count_number + '0';
	}
}

void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	// 1. 输入排查的坐标
	// 2. 检查坐标处是不是雷
	//	  (1)是雷     -  boom - game over 
	//	  (2)不是雷    - 统计坐标周围有几个雷  -  存储排查雷的信息到show数组,游戏继续
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - EASY_COUNT)
	{
		printf("请输入要排查雷的坐标:");
		scanf("%d %d", &x, &y);// x -- (1,9)    y -- (1,9)
		//判断坐标的合法性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了!\n");
					display_board(mine, ROW, COL);
					break;
				}
				else
				{
					// 不是雷的情况下,统计x,y坐标周围有几个雷
					int count = get_mine_count(mine, x, y);
					show[x][y] = count + '0';
					Spread(mine, show, x, y);
					//显示排查出的信息
					display_board(show, ROW, COL);
					win++;
				}
			}
			else
			{
				printf("该坐标已排查过\n");
			}
		}
		else
		{
			printf("坐标输入有误,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功!\n");
		display_board(show, ROW, COL);
	}
}

四、完整源码展示

test.c

#define _CRT_SECURE_NO_WARNINGS 1


#include "game.h"


void menu()
{
	printf(" -------------------\n");
	printf("|       1.play      |\n");
	printf("|       2.clear     |\n");
	printf("|       0.exit	    |\n");
	printf(" -------------------\n");
}

void game()
{
	// 设计2个数组存放信息
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	// 初始化棋盘
	// mine初始化为全'0'
	// show初始化为全'*'
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');

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

	// 布置雷
	set_mine(mine,ROW,COL);
	// 排雷
	//display_board(mine, ROW, COL);
	display_board(show, ROW, COL);
	find_mine(mine, show, ROW, COL);

}

int main()
{
	srand((unsigned)time(NULL));

	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 2:
			system("cls"); // 清屏
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable : 6031)

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

#define ROW 9
#define COL 9

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

// 默认雷
#define EASY_COUNT 20

// 函数声明

// 初始化
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_mine(char mine[ROWS][COLS], int row, int col);

// 排查雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

// 展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);

game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"


void init_board(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_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0, j = 0;
	printf("----------扫雷游戏----------\n");
	// 列号
	for ( j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	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");
}


void set_mine(char mine[ROWS][COLS], int row, int col)
{
	// 布置10个雷
	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--;
		}
	}
}

// 统计
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] + 
		mine[x - 1][y + 1] - 8 * '0');
}

// 递归实现展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	int count_number = get_mine_count(mine, x, y);//排查该坐标附近雷的个数
	if (count_number == 0)
	{
		show[x][y] = ' ';
		if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*')
		{
			Spread(mine, show, x - 1, y - 1);
		}
		if ((x - 1 > 0 && x - 1 < 10) && (y > 0 && y < 10) && show[x - 1][y] == '*')
		{
			Spread(mine, show, x - 1, y);
		}
		if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*')
		{
			Spread(mine, show, x - 1, y + 1);
		}
		if ((x > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*')
		{
			Spread(mine, show, x, y - 1);
		}
		if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*')
		{
			Spread(mine, show, x, y + 1);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*')
		{
			Spread(mine, show, x + 1, y - 1);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*')
		{
			Spread(mine, show, x + 1, y);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*')
		{
			Spread(mine, show, x + 1, y + 1);
		}
	}
	else
	{
		show[x][y] = count_number + '0';
	}
}

void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	// 1. 输入排查的坐标
	// 2. 检查坐标处是不是雷
	//	  (1)是雷     -  boom - game over 
	//	  (2)不是雷    - 统计坐标周围有几个雷  -  存储排查雷的信息到show数组,游戏继续
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - EASY_COUNT)
	{
		printf("请输入要排查雷的坐标:");
		scanf("%d %d", &x, &y);// x -- (1,9)    y -- (1,9)
		//判断坐标的合法性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了!\n");
					display_board(mine, ROW, COL);
					break;
				}
				else
				{
					// 不是雷的情况下,统计x,y坐标周围有几个雷
					int count = get_mine_count(mine, x, y);
					show[x][y] = count + '0';
					Spread(mine, show, x, y);
					//显示排查出的信息
					display_board(show, ROW, COL);
					win++;
				}
			}
			else
			{
				printf("该坐标已排查过\n");
			}
		}
		else
		{
			printf("坐标输入有误,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功!\n");
		display_board(show, ROW, COL);
	}
}

总结

以上就是C语言实现扫雷小游戏的分析了,还有部分功能期待小伙伴们能补全!
希望该文章能对小伙伴们有所帮助!留个赞👍再走吧~
(如有错误,望指出)

  • 29
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
当然,我可以给你介绍一下C语言扫雷游戏代码。下面是一个简单的C语言扫雷游戏代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 10 #define MINES 10 int board[SIZE][SIZE]; int revealed[SIZE][SIZE]; void initializeBoard() { int i, j; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { board[i][j] = 0; revealed[i][j] = 0; } } } void placeMines() { int count = 0; while (count < MINES) { int x = rand() % SIZE; int y = rand() % SIZE; if (board[x][y] != -1) { board[x][y] = -1; count++; } } } void printBoard() { int i, j; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { if (revealed[i][j]) { if (board[i][j] == -1) { printf("* "); } else { printf("%d ", board[i][j]); } } else { printf(". "); } } printf("\n"); } } int countAdjacentMines(int x, int y) { int count = 0; int i, j; for (i = -1; i <= 1; i++) { for (j = -1; j <= 1; j++) { if (x + i >= 0 && x + i < SIZE && y + j >= 0 && y + j < SIZE) { if (board[x + i][y + j] == -1) { count++; } } } } return count; } void revealCell(int x, int y) { if (x < 0 || x >= SIZE || y < 0 || y >= SIZE) { return; } if (revealed[x][y]) { return; } revealed[x][y] = 1; if (board[x][y] == 0) { int i, j; for (i = -1; i <= 1; i++) { for (j = -1; j <= 1; j++) { revealCell(x + i, y + j); } } } } int main() { srand(time(NULL)); initializeBoard(); placeMines(); int gameOver = 0; while (!gameOver) { printBoard(); int x, y; printf("Enter the coordinates of the cell to reveal (x y): "); scanf("%d %d", &x, &y); if (board[x][y] == -1) { printf("Game Over! You hit a mine.\n"); gameOver = 1; } else { revealCell(x, y); int revealedCount = 0; int i, j; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { if (revealed[i][j]) { revealedCount++; } } } if (revealedCount == SIZE * SIZE - MINES) { printf("Congratulations! You won the game.\n"); gameOver = 1; } } } return 0; } ``` 这是一个简单的命令行扫雷游戏游戏板大小为10x10,总共有10个地雷。你可以根据需要进行修改和扩展。希望对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_NunU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值