c语言实现简易扫雷

设计思路

首先来谈谈我的设计思路,扫雷这个游戏其实就是棋盘中放雷和非雷,玩家需要将非雷单位全部找出,一旦选中雷,游戏就会结束。于是我就创立了两个二维数组,分别存放雷的信息以及显示给玩家的信息(毕竟如果让玩家看到雷的位置,这个游戏就失去意义了)。
1.打印菜单
2.初始化棋盘
3.玩家下棋
4.判断玩家是否踩雷以及实现扫雷的展开功能
5.游戏结束
由于代码量过大,我分装了game.h和game.c以及test.c三个源文件。

打印菜单

这个功能非常简单,我就不过多赘述了。代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
	printf("##############\n");
	printf("####1.start###\n");
	printf("####0.exit####\n");
	printf("##############\n");
}
void game()
{
	char show[ROWS][COLS] = { 0 };
	char real[ROWS][COLS] = { 0 };
	Initial(show, ROWS, COLS, '*');
	Initial(real, ROWS, COLS, '0');
	set_mine(real, ROW, COL);
	display(show, ROW, COL);
	find_mine(real, show, ROW, COL);
}
int main()
{
	int n = 0;
	do
	{
		menu();
		scanf("%d", &n);
		switch (n)
		{
		case 0:
			printf("退出成功。\n");
			break;
		case 1:
			game();
			break;
		default:
			printf("输入错误,请重试。\n");
			break;
		}
	}while (n);
	return 0;
}

效果图
在这里插入图片描述

初始化棋盘

我将字符‘ 1 ’视为雷,字符‘ 0 ’视为非雷。这个initial函数中的形参 char ch为初始化的字符。代码如下:

void Initial(char arr[ROWS][COLS], int row, int col, char ch)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			arr[i][j] = ch;
		}
	}
}

打印函数的实现用多个个for循环搞定,代码如下:

```c
void display(char arr[ROW][COL], int row, int col)
{
	int i, j;
	//为了玩家方便找到坐标,打印了列数。
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)//控制行数
	{
		printf("%d ", i);//打印行数
		for (j = 1; j <= col; j++)//控制列数
		{
			printf("%c ", arr[i][j]);//打印棋盘内容。
		}
		printf("\n");
	}
}

紧接着我们就来实现放置雷的函数,代码如下:

void set_mine(char arr[ROW][COL], int row, int col)
{
	int count = easy_count;//放置雷的个数
	while (count)
	{
		int x = rand() % row + 1;//随机生成范围内的数字。
		int y = rand() % col + 1;
		if (arr[x][y] == '0')//判断该坐标是否含有雷,若无雷,就放置一个。
		{
			arr[x][y] = '1';
			count--;//放置成功,雷数自减一。
		}
	}
}

效果图
在这里插入图片描述
ps:为了展示效果,我们将放置雷的棋盘打印出来,但在游戏中不会打印。

玩家下棋

该部分共实现了三个功能
1.返回输入坐标附近的雷数
2.展开效果
3.判断游戏是否结束

首先我们来看判断函数,该函数实现了判断玩家是否踩雷,坐标是否合法,游戏是否结束等功能。代码如下:

void find_mine(char real_arr[ROW][COL],char arr[ROW][COL], int row, int col)
{
	int count = row*col - easy_count;
	int x, y;
	while (count)
	{
		printf("请输入坐标。\n");
		scanf("%d%d", &x, &y);//玩家输入坐标
		if (x > 0 && x <= row && y > 0 && y <= col)//判断坐标是否合法
		{
			if (count == row*col - easy_count)
			{
				save(real_arr, arr, row, col, x, y);//防止玩家第一步踩雷
			}
		    if (real_arr[x][y] == '1')//踩雷
			{
				printf("你被炸死了。\n");
				break; 
			}
			else if (real_arr[x][y] == '0')//未踩雷
			{
				count--;
				arr[x][y] = get_mine(real_arr, x, y)+'0';//+‘ 0 ’为了将整形转变为字符型
				/*open_mine(real_arr, arr, x, y, row, col);*/
				open_mine(real_arr, arr, x, y,ROW,COL);
				display(arr, ROW, COL);
			}
		}
		else
			printf("坐标错误,请重试。\n");
	}
	if (!count)
	{
		printf("游戏成功!\n");//当count为0时说明非雷单位全部排除
	}
}

然后是返回雷数的函数:

int get_mine(char mine[ROW][COL], int x, int y)
{
	return mine[x - 1][y - 1] - '0' +    //减去‘ 0 ’为了将字符转变为整形。
		mine[x - 1][y] - '0' +
		mine[x - 1][y + 1] - '0' +
		mine[x][y + 1] - '0' +
		mine[x + 1][y + 1] - '0' +
		mine[x + 1][y] - '0' +
		mine[x + 1][y - 1] - '0' +
		mine[x][y - 1] - '0';
}

接下来的函数利用递归实现了展开功能,递归条件为:
1.该坐标合法
2.该坐标非雷
3.该坐标为展开
代码如下:

void open_mine(char real_arr[ROW][COL], char show_arr[ROW][COL], int x, int y,int row,int col)
{
	if (show_arr[x][y] == '*' && real_arr[x][y]!='1')
	{
		show_arr[x][y] = get_mine(real_arr, x, y) + '0';
	}
	if (show_arr[x - 1][y - 1] == '*' && real_arr[x - 1][y - 1] != '1' && x > 1 && y > 1)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
	if (show_arr[x - 1][y] == '*' && real_arr[x - 1][y] != '1' && x > 1)
	{
		open_mine(real_arr, show_arr, x - 1, y, row, col);
	}
	if (show_arr[x - 1][y + 1] == '*'  && real_arr[x - 1][y + 1] != '1' && x > 1 && y + 1 <col)
	{
		open_mine(real_arr, show_arr, x - 1, y + 1, row, col);
	}
	if (show_arr[x][y - 1] == '*'  && real_arr[x][y - 1] != '1' && y > 1)
	{
		open_mine(real_arr, show_arr, x, y - 1, row, col);
	}
	if (show_arr[x][y + 1] == '*'  && real_arr[x][y + 1] != '1' && y + 1<col)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
	if (show_arr[x + 1][y + 1] == '*' && real_arr[x + 1][y + 1] != '1' && x + 1<row && y + 1<col)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
	if (show_arr[x + 1][y] == '*'  && real_arr[x + 1][y] != '1' && x + 1<row)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
	if (show_arr[x + 1][y - 1] == '*' && real_arr[x + 1][y - 1] != '1' && x + 1<row && y - 1>0)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
}

game.h

#include<stdio.h>
#include<stdlib.h>
#define easy_count 40
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void Initial(char arr[ROWS][COLS], int row, int col, char ch);
void set_mine(char arr[ROW][COL], int row, int col);
void find_mine(char real_arr[ROW][COL], char arr[ROW][COL], int row, int col);
void display(char arr[ROW][COL], int row, int col);

test.c

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
	printf("##############\n");
	printf("####1.start###\n");
	printf("####0.exit####\n");
	printf("##############\n");
}
void game()
{
	char show[ROWS][COLS] = { 0 };
	char real[ROWS][COLS] = { 0 };
	Initial(show, ROWS, COLS, '*');
	Initial(real, ROWS, COLS, '0');
	set_mine(real, ROW, COL);
	display(show, ROW, COL);
	find_mine(real, show, ROW, COL);
}
int main()
{
	int n = 0;
	do
	{
		menu();
		scanf("%d", &n);
		switch (n)
		{
		case 0:
			printf("退出成功。\n");
			break;
		case 1:
			game();
			break;
		default:
			printf("输入错误,请重试。\n");
			break;
		}
	}while (n);
	return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"

void Initial(char arr[ROWS][COLS], int row, int col, char ch)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			arr[i][j] = ch;
		}
	}
}
void display(char arr[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}
void set_mine(char arr[ROW][COL], int row, int col)
{
	int count = easy_count;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';
			count--;
		}
	}
}
int get_mine(char mine[ROW][COL], int x, int y)
{
	return mine[x - 1][y - 1] - '0' +
		mine[x - 1][y] - '0' +
		mine[x - 1][y + 1] - '0' +
		mine[x][y + 1] - '0' +
		mine[x + 1][y + 1] - '0' +
		mine[x + 1][y] - '0' +
		mine[x + 1][y - 1] - '0' +
		mine[x][y - 1] - '0';
}
void open_mine(char real_arr[ROW][COL], char show_arr[ROW][COL], int x, int y,int row,int col)
{
	if (show_arr[x][y] == '*' && real_arr[x][y]!='1')
	{
		show_arr[x][y] = get_mine(real_arr, x, y) + '0';
	}
	if (show_arr[x - 1][y - 1] == '*' && real_arr[x - 1][y - 1] != '1' && x > 1 && y > 1)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
	if (show_arr[x - 1][y] == '*' && real_arr[x - 1][y] != '1' && x > 1)
	{
		open_mine(real_arr, show_arr, x - 1, y, row, col);
	}
	if (show_arr[x - 1][y + 1] == '*'  && real_arr[x - 1][y + 1] != '1' && x > 1 && y + 1 <col)
	{
		open_mine(real_arr, show_arr, x - 1, y + 1, row, col);
	}
	if (show_arr[x][y - 1] == '*'  && real_arr[x][y - 1] != '1' && y > 1)
	{
		open_mine(real_arr, show_arr, x, y - 1, row, col);
	}
	if (show_arr[x][y + 1] == '*'  && real_arr[x][y + 1] != '1' && y + 1<col)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
	if (show_arr[x + 1][y + 1] == '*' && real_arr[x + 1][y + 1] != '1' && x + 1<row && y + 1<col)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
	if (show_arr[x + 1][y] == '*'  && real_arr[x + 1][y] != '1' && x + 1<row)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
	if (show_arr[x + 1][y - 1] == '*' && real_arr[x + 1][y - 1] != '1' && x + 1<row && y - 1>0)
	{
		open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
	}
}
void save(char arr1[ROW][COL], char arr0[ROW][COL], int row, int col,int x,int y)
{
	if (arr1[x][y] == '1')
	{
		arr1[x][y] = '0';
		while (1)
		{
			int x = rand() % row + 1;
			int y = rand() % col + 1;
			if (arr1[x][y] == '0')
			{
				arr1[x][y] = '1';
				break;
			}
		}
	}
}
void find_mine(char real_arr[ROW][COL],char arr[ROW][COL], int row, int col)
{
	int count = row*col - easy_count;
	int x, y;
	while (count)
	{
		printf("请输入坐标。\n");
		scanf("%d%d", &x, &y);
		if (x > 0 && x <= row && y > 0 && y <= col)
		{
			if (count == row*col - easy_count)
			{
				save(real_arr, arr, row, col, x, y);
			}
		    if (real_arr[x][y] == '1')
			{
				printf("你被炸死了。\n");
				break; 
			}
			else if (real_arr[x][y] == '0')
			{
				count--;
				arr[x][y] = get_mine(real_arr, x, y)+'0';
				/*open_mine(real_arr, arr, x, y, row, col);*/
				open_mine(real_arr, arr, x, y,ROW,COL);
				display(arr, ROW, COL);
			}
		}
		else
			printf("坐标错误,请重试。\n");
	}
	if (!count)
	{
		printf("游戏成功!\n");
	}
}

实现效果

在这里插入图片描述
本人初学c语言,若有bug,还请大佬斧正。最后附上github链接:https://github.com/111q-33/clean_mine-sus.git

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值