【c语言】扫雷游戏实现

这篇博客介绍了如何使用C语言设计一个简单的扫雷游戏。通过多文件管理,将函数声明和定义分开,实现了游戏主循环、菜单显示、棋盘初始化、布雷、扫雷逻辑等功能。玩家可以输入坐标进行游戏,当所有非雷格子被翻开即获胜,踩到雷则游戏结束。博客详细阐述了每个函数的实现细节,包括如何计算周围雷的数量以及如何防止数组越界。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计思路

  • 由于这个代码相较于平常所写的,代码比较多,故我采用多文件管理,减少维护成本
    • 函数声明放在game.h头文件
    • 与游戏有关函数定义放在game.c源文件
    • main函数单独放在main.c中
  • 设计代码时,先写出主体逻辑,然后边测试逻辑的正确性边进行代码的具体实现
如下:
主函数
int main(void)
{
	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;
}
菜单
void menu()
{
	printf("****************************************\n");
	printf("*******     1.play    0.exit   *********\n");
	printf("****************************************\n");
}
game函数的逻辑
  • 设计时需要一个棋盘布置雷,我们把雷设置为字符1(后续好计算雷的个数),其他设置为字符0,此时若要显示你所输入的坐标周围雷的个数,若有一个雷,就会与雷冲突,所以我们设置两个数组一个布置雷,一个显示周围雷的数量
  • 由于后面要检查周围8个位置的雷个数,在边界时防止数组越界,故数组扩大一圈
  • 初识化棋盘,将初始化的字符作为参数传递
  • 设置雷
  • 打印显示雷数量的棋盘
  • 开始排雷
void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	srand((unsigned)time(NULL));

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

	SetMine(mine, ROW, COL, DIGIT_MINE);

	PrintBoard(show, ROW, COL);

	CheckMine(mine, show, ROW, COL, DIGIT_MINE);
}
初始化棋盘
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 SetMine(char mine[ROWS][COLS], int row, int col, int digitMine)
{
	int x = 0;
	int y = 0;
	while (digitMine > 0)
	{
		x = rand() % row + 1;
		y = rand() % col + 1;

		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			digitMine--;
		}
	}
}
打印棋盘
void PrintBoard(char board[ROWS][COLS], int row, int col)
{
	int  i = 0;
	int j = 0;

	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");
	}
}
排查雷
void CheckMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int digitMine)
{
	int x = 0;
	int y = 0;
	int ret = 0;

	int count = 0;
	while (row * col - digitMine > count)
	{
		printf("请输入坐标:");
		scanf("%d %d", &x, &y);

		if (mine[x][y] == '1')
		{
			printf("你已被炸死!\n");
			PrintBoard(mine, ROW, COL);

			break;
		}
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				ret = GetMine(mine, x, y);
				show[x][y] = ret + '0';
				count++;
				PrintBoard(show, ROW, COL);

			}
			else
			{
				printf("该坐标已被排查!\n");
			}
		}
		else
		{
			printf("输入错误,请重新输入!\n");
		}
	}
	if (count == row * col - digitMine)
	{
		printf("恭喜你排雷成功!\n");
		PrintBoard(mine, ROW, COL);
	}
}
坐标周围雷的数量

由于雷是用字符1表示,故把周围的字符都相加减去8个字符0,就会得到周围雷的个数

int GetMine(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 * '0';
}
全部代码
#define _CRT_SECURE_NO_WARNINGS 1

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define DIGIT_MINE 10
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void PrintBoard(char board[ROWS][COLS], int row, int col);

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col, int digitMine);
//扫雷
void CheckMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int digitMine);

\
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

int GetMine(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 * '0';
}
//初始化棋盘
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 PrintBoard(char board[ROWS][COLS], int row, int col)
{
	int  i = 0;
	int j = 0;

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

void SetMine(char mine[ROWS][COLS], int row, int col, int digitMine)
{
	int x = 0;
	int y = 0;
	while (digitMine > 0)
	{
		x = rand() % row + 1;
		y = rand() % col + 1;

		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			digitMine--;
		}
	}
}


void CheckMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int digitMine)
{
	int x = 0;
	int y = 0;
	int ret = 0;

	int count = 0;
	while (row * col - digitMine > count)
	{
		printf("请输入坐标:");
		scanf("%d %d", &x, &y);

		if (mine[x][y] == '1')
		{
			printf("你已被炸死!\n");
			PrintBoard(mine, ROW, COL);

			break;
		}
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				ret = GetMine(mine, x, y);
				show[x][y] = ret + '0';
				count++;
				PrintBoard(show, ROW, COL);

			}
			else
			{
				printf("该坐标已被排查!\n");
			}
		}
		else
		{
			printf("输入错误,请重新输入!\n");
		}
	}
	if (count == row * col - digitMine)
	{
		printf("恭喜你排雷成功!\n");
		PrintBoard(mine, ROW, COL);
	}
}


#define _CRT_SECURE_NO_WARNINGS 1

#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 };
	srand((unsigned)time(NULL));

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

	SetMine(mine, ROW, COL, DIGIT_MINE);

	PrintBoard(show, ROW, COL);

	CheckMine(mine, show, ROW, COL, DIGIT_MINE);
}
int main(void)
{
	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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值