扫雷游戏(linux C语言)

1、游戏规则

这款游戏的玩法是在自定义大小的方块矩阵中随机布置一定量的地雷。由玩家逐个翻开方块,以找出所有地雷为最终游戏目标。使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷。如果玩家翻开的方块有地雷,则游戏结束。

在这里插入图片描述

2、程序流程

  1. 建立一个游戏菜单
  2. 创建两个游戏盘(一个用于用户显示,另一个用于放置地雷)
  3. 将两个游戏盘初始化
  4. 将初始化后的游戏盘进行打印
  5. 玩家翻开游戏盘并打印(玩家输入行列坐标的方式来翻开)
  6. 更新游戏信息(翻到地雷则直接游戏,未翻到雷则继续游戏并显示周围八个格子的地雷个数)
  7. 若未翻到雷则回到 4 继续翻雷直至将非地雷的空格全部翻完则游戏胜利。

3、源代码

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

#define MAX_ROW 9//定义一个9x9的游戏盘
#define MAX_COL 9
#define MINE_COUNT 10//定义地雷的数量


//游戏初始化
void init(char showMap[MAX_ROW][MAX_COL],
	char mineMap[MAX_ROW][MAX_COL]) {
	// 1. 初始化 showMap, 全都设为 * 
	for (int row = 0; row < MAX_ROW; row++) {
		for (int col = 0; col < MAX_COL; col++) {
			showMap[row][col] = '*';
		}
	}
	// 2. 初始化 mineMap, 先全设为 '0', 然后随机生成 N 个 '1' 
	//    N 的值就是 MINE_COUNT
	for (int row = 0; row < MAX_ROW; row++) {
		for (int col = 0; col < MAX_COL; col++) {
			mineMap[row][col] = '0';
		}
	}
	int n = MINE_COUNT;
	while (n > 0) {
		// 生成雷的随机位置. 
		int row = rand() % MAX_ROW;
		int col = rand() % MAX_COL;
		if (mineMap[row][col] == '1') {
			// 如果当前位置已经有雷了, 就直接进入下次循环, 重新
			// 产生随机位置. 
			continue;
		}
		mineMap[row][col] = '1';
		n--;//将十个雷都放进去
	}
}
//打印函数(前几次都是打印showMap,游戏结束打印mineMap)
void printMap(char theMap[MAX_ROW][MAX_COL]) {
	// 先打印出第一行, 第一行就是包含所有的列号
	printf("雷|");
	for (int col = 0; col < MAX_COL; col++) {
		printf("%d ", col);
	}
	printf("\n");
	printf("--+------------------\n");
	// 然后在打印下面的每一行的时候再打印行号
	for (int row = 0; row < MAX_ROW; row++) {
		printf(" %d|", row);//行号
		for (int col = 0; col < MAX_COL; col++) {
			printf("%c ", theMap[row][col]);
		}
		printf("\n");
	}
}
//更新信息
void updateShowMap(char showMap[MAX_ROW][MAX_COL],
	char mineMap[MAX_ROW][MAX_COL], int row, int col) {
	// 根据当前 row, col 的位置, 计算出当前位置周围有几个雷并且更新显示到 showMap 中. 
	int count = 0;//统计周围雷数
	//判断他周围3x3的格子有几个雷
	for (int r = row - 1; r <= row + 1; r++) {
		for (int c = col - 1; c <= col + 1; c++) {
			if (r < 0 || r >= MAX_ROW
				|| c < 0 || c >= MAX_COL) {
				// r, c 下标越界, 就直接跳过
				continue;
			}
			if (mineMap[r][c] == '1') {
				count++;
			}
		}
	}
	// 此时 count 里面就已经存好了 row, col 周围 八个格子 的雷的个数
	// 把count的结果写到 showMap 中即可. 
	// 需要把数字 count 转成对应的字符
	showMap[row][col] = count + '0';
}

//游戏函数
void game() {
	// 1. 创建地图并初始化. (两个地图)
	//采用宏定义是为了方便后续代码的修改,可以随意调整游戏盘的大小和地雷数量
	char showMap[MAX_ROW][MAX_COL] = { 0 };
	char mineMap[MAX_ROW][MAX_COL] = { 0 };
	init(showMap, mineMap);//显示棋盘和地雷棋盘
	int noMineSpace = 0;//用来翻开的格子数量
	while (1) {
		// 2. 打印地图 
		printMap(showMap);
		// 3. 程序读取玩家输入的要翻开位置的坐标, 并校验
		int row = 0;
		int col = 0;
		printf("请输入要翻开的坐标(row col): ");
		scanf("%d %d", &row, &col);
		//进行输入值的是否非法判断
		if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) {
			printf("您输入的坐标有误!\n");
			continue;
		}
		//如果这个地方不是地雷则翻开
		if (showMap[row][col] != '*') {
			printf("当前位置已经翻开了!\n");
			continue;
		}
		// 4. 判定该位置的坐标是否是地雷. 如果是地雷, 直接 GameOver
		if (mineMap[row][col] == '1') {
			printf("GameOver!\n");
			// 游戏结束的时候打印一遍地雷的地图, 让玩家知道怎么死的
			printMap(mineMap);
			break;
		}
		// 5. 如果不是地雷, 统计当前位置周围雷的个数, 并显示到地图上. 
		updateShowMap(showMap, mineMap, row, col);
		// 6. 判定游戏是否胜利
		noMineSpace++;//每翻开一次,记录一次,直至非雷地区全部被翻开则游戏胜利
		if (noMineSpace == MAX_ROW * MAX_COL - MINE_COUNT) {
			printf("游戏胜利!\n");
			printMap(mineMap);
			break;
		}
	}
}
//菜单函数
int menu(){
	printf("========================\n");
	printf(" 1. 开始游戏\n");
	printf(" 0. 结束游戏\n");
	printf("========================\n");
	printf(" 请输入您的选择: ");
	int num = -1;
	scanf("%d", &num);//利用键盘输入选项	
	return num;//将选项值返回到主函数中进行判断
}
//主函数
int main(){
	srand((unsigned int)time(0));
	while (1){
		int choice = menu();//调用菜单函数进行游戏选择
		if (choice == 1){//输入1时进入游戏
			game();//游戏函数
		}
		else if (choice == 0) {//输入0时退出程序
			printf("goodbye!\n");
			break;
		}
		else{//输入其他字符进行错误提示并使其再次输入
			printf("您输入的有误请重新输入\n");
		}
	}
	system("pause");
	return 0;
}

转载自:https://blog.csdn.net/qq2977078774/article/details/109510220

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值