C语言:实现扫雷游戏简易版

目录

游戏规则

主流程

游戏模块

整体代码


本章设计的C语言知识包括:循环语句,条件语句,数组,函数,宏定义,随机数生成等

游戏规则

扫雷棋盘为9*9方格,玩家目标是避开雷,找出其他非雷的格子。玩家打开格子,如果该方格为雷,则玩家被炸死,游戏结束,如果该方格非雷,则该处显示相邻8格中的雷数,玩家可根据这些信息推导出安全位置。

根据游戏规则,在代码实现过程中应该包含游戏开始&结束主流程,以及单独定义游戏的模块。

主流程

该模块定义用户从开始游戏到退出游戏的整个游戏周期。首先定义menu()函数,展示筛选菜单供用户选择是否开始游戏或退出游戏。

#define _CRT_SECURE_NO_WARNINGS  //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
//游戏开始
menu()
{
	printf("*****************\n");
	printf("******1.play*****\n"); 
	printf("******0.exit*****\n");
	printf("*****************\n");
}

//主流程:
int main()
{
	menu();   //游戏开始&结束菜单
	int input = 0;
	do {
		scanf("%d", &input);
		switch (input)
		{
		case 1:
		{
			printf("游戏开始\n");
			game();  //通过游戏模块实现游戏功能
			break;
		}

		case 0:
			printf("退出游戏");
			break;
		default:
			printf("输入错误");
			break;

		}
	} while (input);
	return 0;
}

游戏模块

游戏模块整体思路可大致拆解为:

  • 生成9*9雷盘;
  • 随机设置雷点
  • 向用户展示雷盘
  • 用户搜索雷点
  • 依据搜索结果,判断输赢

需要注意的是,除了向用户展示隐藏雷的棋盘外,内部后台需要一份记录雷点的数据来对比用户扫雷结果,以判断输赢。因此,可以创建两张二维数组用来存储埋点和扫雷的结果信息。这里,用'1'表示雷点,'0'表示非雷点;'*'表示向用户展示的隐藏雷盘,后续会根据用户搜索结果返回非雷点周围8格中的雷数。

尽管需要展示9*9的雷盘,但是考虑到后续需要统计非雷点周围8格中的雷数,这里可以创建11*11的数组来避免越界问题。

 基本思路以及该注意的细节基本介绍差不多了,话不多说,上代码!!!

  • 初始化棋盘

1。vs2022编译器,数组的大小必须为常量,这里通过宏常量进行定义。宏常量,一般用#define来定义一个符号常量,修改时只需要修改#define这条语句即可,不必处处修改。

2。对于数值或者字符串等常量的定义,一般默认采用全大写的英文字母,单词之间下划线的方式命名。

//游戏模块
#define _CRT_SECURE_NO_WARNINGS  //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9 
#define ROWS ROW+2 
#define COLS COL+2

//棋盘初始化
void initboard(char arr[ROWS][COLS],int rows, int cols, char set)
{
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

game()
{
	char mine[ROWS][COLS];  //创建数组存储雷点信息
	char show[ROWS][COLS];  //创建数组存储扫雷信息
	initboard(mine, ROWS, COLS, '0');  //初始化雷盘,雷点表用'0'填充
	initboard(show, ROWS, COLS, '*');  //初始化雷盘,向用户呈现的雷盘界面用'*'填充
}

  • 随机设置雷点

rand()函数所生成的随机数,并不是真实的随机值,而是伪随机。该函数是通过某个公式计算的随机结果,因此当输入一致时,输入也会保持一样。这里引入srand()函数,生成随机种子,相当于让rand()函数生成随机数的公式随着种子变化而变化。在后面,将srand()函数加入主流程模块中。

//随机设置雷点
#define _CRT_SECURE_NO_WARNINGS  //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9 
#define ROWS ROW+2 
#define COLS COL+2

void setboard(char arr[ROWS][COLS], int row, int col, int mine_count)
{
	while (mine_count)
	{
		int rand1 = rand() % row + 1;
		int rand2 = rand() % col + 1;
		if (arr[rand1][rand2] = '0')  //如果随机设置的雷点坐标处已有雷,则重新随机置雷
		{
			arr[rand1][rand2] = '1';
			mine_count--;
		}
	}

}

  • 打印雷盘交互界面
//打印雷盘交互界面
#define _CRT_SECURE_NO_WARNINGS  //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9 
#define ROWS ROW+2 
#define COLS COL+2
void displayboard(char arr[ROWS][COLS], 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");
	}
}

  • 统计非雷点周围雷数
#define _CRT_SECURE_NO_WARNINGS  //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9 
#define ROWS ROW+2 
#define COLS COL+2
//统计非雷点雷数
int roudboard(char arr[ROWS][COLS],int row, int col)
{
	int i, j;
	int sum = 0;
	for (i = row - 1; i <= row + 1; i++)
	{
		for (j = col - 1; j <= col + 1; j++)
		{
			sum = sum+arr[i][j]-'0';
		}
	}
	return sum;

}
  • 与用户交互
//与用户交互
#define _CRT_SECURE_NO_WARNINGS  //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9 
#define ROWS ROW+2 
#define COLS COL+2
#define MINE_COUNT 10  //通过宏常量定义雷数为10

void minegame(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int row1, col1;
	int win = row*col-MINE_COUNT;  //所有的方格数减去10个雷点数,则为需要胜利的次数
	printf("请输入坐标\n");
	while (win)
	{
		scanf("%d %d", &row1, &col1);
		if (row1 >= 1 && row1 <= row && col1 >= 1 && col1 <= col)
		{
			if (mine[row1][col1] == '1')
			{
				printf("你被炸死了\n");
				displayboard(mine, ROW, COL);
				break;
			}
			if (mine[row1][col1] == '0')
			{
				int count = roudboard(mine, row1, col1);
				show[row1][col1] = count + '0';
				displayboard(show, ROW, COL);
				win--;
			}
		}
		else
		{
			printf("输入有误,请重新输入\n");
		}
	}
	if (win == 0)
	{
		printf("恭喜顺利通过!");
		displayboard(mine, ROW, COL);
	}
}

 整体代码

#define _CRT_SECURE_NO_WARNINGS  //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9 
#define ROWS ROW+2
#define COLS COL+2
#define MINE_COUNT 10

//扫雷游戏:主流程+游戏模块
//主流程:游戏开始,游戏结束
//游戏模块:初始化棋盘——>埋雷——>展示游戏界面——>扫雷——>返回结果

//游戏开始
menu()
{
	printf("*****************\n");
	printf("******1.play*****\n");
	printf("******0.exit*****\n");
	printf("*****************\n");
}


//棋盘初始化
void initboard(char arr[ROWS][COLS],int rows, int cols, char set)
{
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

//打印雷盘交互界面
void displayboard(char arr[ROWS][COLS], 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 setboard(char arr[ROWS][COLS], int row, int col, int mine_count)
{
	while (mine_count)
	{
		int rand1 = rand() % row + 1;
		int rand2 = rand() % col + 1;
		if (arr[rand1][rand2] = '0')
		{
			arr[rand1][rand2] = '1';
			mine_count--;
		}
	}

}

//统计非雷点周围雷数
int roudboard(char arr[ROWS][COLS],int row, int col)
{
	int i, j;
	int sum = 0;
	for (i = row - 1; i <= row + 1; i++)
	{
		for (j = col - 1; j <= col + 1; j++)
		{
			sum = sum+arr[i][j]-'0';
		}
	}
	return sum;

}

//开始扫雷游戏
void minegame(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int row1, col1;
	int win = row*col-MINE_COUNT;
	printf("请输入坐标\n");
	while (win)
	{
		scanf("%d %d", &row1, &col1);
		if (row1 >= 1 && row1 <= row && col1 >= 1 && col1 <= col)
		{
			if (mine[row1][col1] == '1')
			{
				printf("你被炸死了\n");
				displayboard(mine, ROW, COL);
				break;
			}
			if (mine[row1][col1] == '0')
			{
				int count = roudboard(mine, row1, col1);
				show[row1][col1] = count + '0';
				displayboard(show, ROW, COL);
				win--;
			}
		}
		else
		{
			printf("输入有误,请重新输入\n");
		}
	}
	if (win == 0)
	{
		printf("恭喜顺利通过!");
		displayboard(mine, ROW, COL);
	}
}


//游戏模块
game()
{
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	initboard(mine, ROWS, COLS, '0');
	initboard(show, ROWS, COLS, '*');
	setboard(mine, ROW, COL, MINE_COUNT);
	displayboard(show, ROW, COL);
    //displayboard(mine, ROW, COL);
	minegame(mine,show, ROW, COL);
}

//主流程:
int main()
{
	menu();
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
		scanf("%d", &input);
		switch (input)
		{
		case 1:
		{
			printf("游戏开始\n");
			game();
			break;
		}

		case 0:
			printf("退出游戏");
			break;
		default:
			printf("输入错误");
			break;

		}
	} while (input);
	return 0;
}

写到最后:这里仅实现了扫雷游戏的简易版,仍然有很多地方值得思考和探索,比如当用户选中的方格为非雷点的时候,是否可以展开一片;用户第一次扫雷一定不会遇到雷,来提高用户体验。

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值