【C语言/扫雷】手把手教你写一个扫雷小游戏,可展开

目录

一、制作一个菜单

1.菜单栏

 二、游戏函数的实现

1.雷盘的实现

2.布置雷

3.开始扫雷

1.整体逻辑

2.统计雷的数量

3.递归展开

 4.判断是否排雷成功

 三、代码的优化

四、总结

五、源代码


一、制作一个菜单

1.菜单栏

首先我们需要一个菜单来选择开始游戏或者退出游戏,do...while循环至少会运行一次符合我们对游戏程序的要求

#include <stdio.h>
void mean()
{
	printf("************************\n");
	printf("*****  0.退出游戏  *****\n");
	printf("*****  1.开始游戏  *****\n");
	printf("************************\n");
}
void game()
{
}
int main()
{
	int n = 0;
	do
	{
		mean();
		scanf("%d", &n);
		switch (n)
		{
		case 0:
			break;
		case 1:
			game();
			break;
		default:
			printf("请选择正确的选项\n");
			break;
		}
	} while (n);
}

测试我们的菜单逻辑没有问题 

 二、游戏函数的实现

1.雷盘的实现

 初阶扫雷的棋盘为9x9所以我们需要一个创建一个二维数组作为棋盘,考虑到我们需要在游戏未结束之前隐藏雷的位置和棋盘的内容,为了方便起见我们可以创建两个棋盘。一个用来展示,一个用来存放雷。

我们在选择一个位置后,如果不是雷则需要判断周围8格有几个雷,为了避免数组越界我们创建的存放雷的棋盘要比实际的宽两格,ROW和COL是我们创建的一个宏,值为9.

ROWS和COLS是(ROW+1)和(COL+1)

#define ROW 9
#define COL 9
#define ROWS (ROW+2)
#define COLS (COL+2)

 数组创建之后我们需要将其初始化,考虑到需要,我们将展示的棋盘数组全部初始化为*

存放雷的棋盘全部初始化为0

为了方便后续代码的编写,我们将展示的棋盘也设置为11x11,不过在打印时只打印9x9

初始化完成之后将棋盘打印出来

void game()
{
	char show_board[ROWS][COLS];
	char memory_board[ROWS][COLS];
	init_show(show_board,ROW,COL);//初始化展示的棋盘
	init_memory(memory_board, ROWS, COLS);//初始化存放雷的棋盘
	printf_board(show_board, ROW, COL);
	printf_board(memory_board, ROW, COL);
}

void init_show(char board[][COL],int row,int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = '*';
		}
	}
}
void init_memory(char board[][COLS], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = '0';
		}
	}
}
void printf_board(char board[][COLS], int row, int col)
{
	int i, j;
	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");
	}
}

 

 测试结果符合预期,其中存放雷的棋盘只是为了方便观察和编写程序才将其打印出来,程序完成之后将其删去。

2.布置雷

此时我们已经有了一个符合要求的棋盘,那么我们需要将雷布置到存放雷的棋盘中。

初阶扫雷有10个雷,所以我们需要将10个雷布置到我们的数组当中。

void place_mine(char board[][COLS], int row, int col)
{
	int i = 0;
	while (i<mined)//mined是我们定义的一个宏用来确定放置雷的数量
	{
		int x = rand() %row+1;
		int y = rand() %co+l;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			i++;
		}
	}
}

可以看到我们已经将10个雷分布到了雷盘中

3.开始扫雷

1.整体逻辑

首先我们需要输入一个坐标,然后在在输入之后首先判断是否是雷,如果是雷则游戏结束。

如果不是雷则需要将,一圈八格雷的总数展示出来。

void saolei(char showboard[][COLS],char memoryboard[][COLS])
{
	int x = 0,y=0;
	while (1)
	{
		printf("请输入坐标:\n");
		scanf(" %d%d", &x, &y);
		if (x <= ROW && x > 0&&y > 0 && y <= COL&& showboard[x][y] == '*')
		{
			if (memoryboard[x][y] == '1')
			{
				printf_board(memoryboard, ROW, COL);
				printf("boom*\n");
				printf("you die\n");
				break;
			}
			else
			{
				count(showboard, memoryboard, x, y);
			}
			if (showboard[x][y] == '0' && x > 0 && y > 0)
				ufold(showboard, memoryboard, x, y);
			printf_board(showboard, ROW, COL);
			int win=whether_win(showboard,ROW,COL);
			if (win)
			{
				printf("恭喜排雷成功\n");
				printf_board(showboard, ROW, COL);
				printf_board(memoryboard, ROW, COL);
				break;
			}
		}
		else
			printf("坐标不合法,请重新输入\n");
	}
}

2.统计雷的数量

void count(char showboard[][COLS],char memoryboard[][COLS], int x, int y)
{
	int i = 0, j = 0;
	char sum = '0';
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)
		{
			if (memoryboard[i][j] == '1')
				sum++;
		}
	}
	showboard[x][y] = sum;
}

3.递归展开

在扫雷中如果我们选择的位置周围没有雷,则会展开周围八格,然后展开的格子中如果存在周围没有雷的格子则会继续展开。

所以这里我们可以写一个递归,让它每次识别到没有雷的格子就继续展开。

注意添加限制条件避免数组越界,此处编写过程中条件如果不完善容易陷入死循环,如果在调试运行过程中出现栈溢出的错误,可以仔细检查这里看是否出现死循环。

void ufold(char showboard[][COLS], char memoryboard[][COLS], int x, int y)
{
		int i = 0, j = 0;
		int num = 0;
		for (i = x - 1; i <= x + 1; i++)
		{
			for (j = y - 1; j <= y + 1; j++)
			{
				if (i > 0 && i <= ROW && j > 0 && j <= COL && showboard[i][j] == '*')
				{
					count(showboard, memoryboard, i, j);
					if(showboard[i][j]=='0')
						ufold(showboard, memoryboard, i, j);
				}
			}
		}
}

 测试递归展开逻辑没有问题

 4.判断是否排雷成功

int whether_win(char showboard[][COLS], int row, int col)
{
	int sum = 0;
	int i = 0, j = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (showboard[i][j] == '*')
				sum++;
			if (sum > mined)
				return 0;
		}
	}
	return 1;
}

在这里为了节省时间提高效率,我们可以将雷数量mine改为2进行测试。测试完毕没有问题。

#define mined 2//雷的数量

 三、代码的优化

1.删去      printf_board(memory_board, ROW, COL);这个是我们存放雷的棋盘,为了方便观察才打印出来的。

2.美化雷盘,美化到自己满意即可,此处不做过多演示

void printf_board(char board[][COLS], int row, int col)
{
	int i, j;
	printf(" ");
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 0; i <= col; i++)
	{
		printf("--");
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d |", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

3.在合适位置添加清屏函数提升界面美观度

windows系统下可以使用system("cls"),头文件为stdlib.h

四、总结

    代码整体难度较低,所用到的知识非常基础,在编写时保证头脑清晰冷静可以较快完成。

五、源代码

头文件

#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 9
#define COL 9
#define ROWS (ROW+2)
#define COLS (COL+2)
#define mined 10//雷的数量
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void init_show(char board[][COLS], int row, int col);//初始化展示的棋盘
void init_memory(char board[][COLS], int row, int col);//初始化存放雷的棋盘
void printf_board(char board[][COLS], int row, int col);//打印棋盘
void place_mine(char board[][COLS], int row, int col);//布置雷
void saolei(char showboard[][COLS], char memoryboard[][COLS]);//扫雷
void count(char showboard[][COLS], char memoryboard[][COLS], int x, int y);//计算雷的数量
void ufold(char showboard[][COLS], char memoryboard[][COLS], int x, int y);//递归展开没有雷的格子
int whether_win(char showboard[][COLS], int row, int col);//判断是否成功

test.c

#include "game.h"
void mean()
{
	printf("************************\n");
	printf("*****  0.退出游戏  *****\n");
	printf("*****  1.开始游戏  *****\n");
	printf("************************\n");
}
void game()
{
	char show_board[ROWS][COLS];
	char memory_board[ROWS][COLS];
	init_show(show_board,ROWS,COLS);
	init_memory(memory_board, ROWS, COLS);
	place_mine(memory_board, ROW, COL);
	printf_board(show_board, ROW, COL);
	saolei(show_board, memory_board);
}
int main()
{
	srand((unsigned int)time(NULL));
	int n = 0;
	do
	{
		mean();
		scanf("%d", &n);
		switch (n)
		{
		case 0:
			break;
		case 1:
			game();
			break;
		default:
			printf("请选择正确的选项\n");
			break;
		}
	} while (n);
}

game.c

#include "game.h"

void init_show(char board[][COLS],int row,int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = '*';
		}
	}
}
void init_memory(char board[][COLS], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = '0';
		}
	}
}
void printf_board(char board[][COLS], int row, int col)
{
	int i, j;
	printf("   ");
	for (i = 1; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 0; i <= col; i++)
	{
		printf("--");
	}
	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 place_mine(char board[][COLS], int row, int col)
{
	int i = 0;
	while (i<mined)
	{
		int x = rand()%row+1;
		int y = rand()%col+1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			i++;
		}
	}
}
void ufold(char showboard[][COLS], char memoryboard[][COLS], int x, int y)
{
		int i = 0, j = 0;
		int num = 0;
		for (i = x - 1; i <= x + 1; i++)
		{
			for (j = y - 1; j <= y + 1; j++)
			{
				if (i > 0 && i <= ROW && j > 0 && j <= COL && showboard[i][j] == '*')
				{
					count(showboard, memoryboard, i, j);
					if(showboard[i][j]=='0')
						ufold(showboard, memoryboard, i, j);
				}
			}
		}
}
void count(char showboard[][COLS],char memoryboard[][COLS], int x, int y)
{
	int i = 0, j = 0;
	char sum = '0';
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)
		{
			if (memoryboard[i][j] == '1')
				sum++;
		}
	}
	showboard[x][y] = sum;
}
int whether_win(char showboard[][COLS], int row, int col)
{
	int sum = 0;
	int i = 0, j = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (showboard[i][j] == '*')
				sum++;
			if (sum > mined)
				return 0;
		}
	}
	return 1;
}
void saolei(char showboard[][COLS],char memoryboard[][COLS])
{
	int x = 0,y=0;
	while (1)
	{
		printf("请输入坐标:\n");
		scanf(" %d%d", &x, &y);
		system("cls");
		if (x <= ROW && x > 0&&y > 0 && y <= COL&& showboard[x][y] == '*')
		{
			if (memoryboard[x][y] == '1')
			{
				printf_board(memoryboard, ROW, COL);
				printf_board(showboard, ROW, COL);
				printf("boom*\n");
				printf("you die\n");
				break;
			}
			else
			{
				count(showboard, memoryboard, x, y);
			}
			if (showboard[x][y] == '0' && x > 0 && y > 0)
				ufold(showboard, memoryboard, x, y);
			printf_board(showboard, ROW, COL);
			int win=whether_win(showboard,ROW,COL);
			if (win)
			{
				printf("恭喜排雷成功啦>>>>>>>>>>>\n");
				printf_board(showboard, ROW, COL);
				printf_board(memoryboard, ROW, COL);
				break;
			}
		}
		else
			printf("坐标不合法,请重新输入\n");
	}
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值