扫雷游戏小程序

目录

一.文件

1.头文件

2.源文件

二.游戏界面和执行(test.c)

三.函数实现(void game部分,源文件game.c)

1.定义雷二维数组和展示二维数组

2.初始化地雷数组

3.初始化显示的数组

4.显示当前的情况

5.随机放置地雷

6.排雷

ps:深度优先遍历数组

四.结束


一.文件

1.头文件

game.h

用于存放所有源文件需要用的标准库头文件函数的声明。(便于查找和让代码更简洁)

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define COLS COL+2
#define ROWS ROW+2
#define ALLMINE 10
void InitBoard(char board[ROWS][COLS],int row,int col,char set);
void DisplayBoard(char board[ROWS][COLS], int row, int col);
void SetMine(char board[ROWS][COLS], int row, int col);
void FineMine(char mine[ROWS][COLS],char board[ROWS][COLS], int row, int col);

ROW和COL扫雷的行和列,也就是面积

ROWS和ROWS行和列加2,加2是因为我们后面需要统计每个格子四周的8个格子一共含有的雷数,为了避免越界问题,特地+2,左右上下各加一行或者一列嘛。

ALLMINEE所有的雷一共10个

InitBoard,DisplayBoard,SetMine,FineMine为后面需要用到的函数的声明

2.源文件

game.c

test.c

game.c用来写所有自定义函数的代码

test.c用来写游戏界面的执行入口游戏函数执行顺序

如图:

二.游戏界面和执行(test.c)

注意:记得加上自定义头文件game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu() {
	printf("********************************\n");
	printf("********   1.开始游戏   ********\n");
	printf("********   0.退出游戏   ********\n");
	printf("********************************\n");
}
void game() {
	int mine[ROWS][COLS];
	int show[ROWS][COLS];
	InitBoard(mine,ROWS,COLS,'0');//初始化地雷数组
	InitBoard(show, ROWS, COLS,'*');//初始化显示的数组
	DisplayBoard(show,ROW,COL);//显示当前的情况
	/*DisplayBoard(mine, ROW, COL);*/
	SetMine(mine,ROW,COL);//放置地雷,随机
	/*DisplayBoard(mine, ROW, COL);*/
	FineMine(mine,show, ROW, COL);//排雷
}
int main() {
	menu();
	int input = 0;
	srand((unsigned int)time(NULL));//需要标准库头文件stdlib.h和time.h
	do {
		printf("请输入1或0:>\n");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
		}
	} while (input);
	return 0;
}

解释:

1.游戏的进入与退出我们使用do while循环先执行一遍再根据输入的数判断是否再次决定游戏的进入与退出

2.至于srand()函数,void srand(unsigned int seed);是他的原型,srand 函数用于设置随机数生成器的种子。这个种子值决定了 rand 函数(后面会讲到)生成的随机数序列(如果种子为固定值,则随机的数也是固定值)。通常在调用 rand 之前调用 srand,并传入一个无符号整数作为种子值。这里我们使用时间作为种子,因为时间是一直在流逝的嘛,所以其总能够生成随机数。

3.game()函数也就是后面会讲的game.c。

效果如下图:

三.函数实现(void game部分,源文件game.c)

注意:记得加上自定义头文件game.h

1.定义二维数组和展示二维数组

2.初始化地雷数组

给每个格子都初始化为0

void InitBoard(char board[ROWS][COLS], int row, int col,char set){//InitBoard(mine,ROWS,COLS,'0');
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			board[i][j] = set;
		}
		
	}
}

3.初始化显示的数组

注意和初始化地雷数组的区别,这个传入的 实参为show,上面那个传入的是mine

给每个格子初始化为' * '

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROWS][COLS], int row, int col,char set){//InitBoard(show, ROWS, COLS,'*');
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			board[i][j] = set;
		}
		
	}
}

4.显示当前的情况

注意这里的row和col为ROW,COL,而不是ROWS,COLS,我们显示的话只显示9*9的面积就可以了

上面那两个初始化则就是ROWS,COLS,

void DisplayBoard(char board[ROWS][COLS], int row, int col) {//DisplayBoard(show,ROW,COL);
	for (int i = 0; i <= row; i++) {
		printf("%d ", i);//给列显示坐标
	}
	printf("\n");
	for (int i = 1; i <= row; i++) {
		printf("%d ", i);//给行显示坐标
		for (int j = 1; j <= col; j++) {
			
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

效果如图:

5.随机放置地雷

void SetMine(char board[ROWS][COLS], int row, int col) {//SetMine(mine,ROW,COL);
	int n = ALLMINE;//前面在头文件定义了ALLMINE为10,也就是雷的个数
	while (n) {
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '1') {
			continue;
		}//避免了在同一个坐标放置雷
		else {
			board[x][y] = 1 + '0';
			n--;//放好雷之后才n--
		}
	}
}

解释:

1.

rand

rand 函数用于生成一个伪随机数。该函数不需要参数,返回一个在 0RAND_MAX 之间整数(包括 0RAND_MAX)。RAND_MAX 是一个常量,定义在 <stdlib.h> 中,通常是 32767,但这取决于具体的实现。

srand

srand 函数用于设置随机数生成器的种子。这个种子值决定了 rand 函数生成的随机数序列。通常在调用 rand 之前调用 srand,并传入一个无符号整数作为种子值

2.

int x = rand() % row + 1;

int y = rand() % col + 1;

因为row和col都是9,所以我们让这个随机数上一个9,得到的数的范围一定是0~8,此时我们再让他+1,那他的范围就是1~9了,就符合我们的坐标条件了

6.排雷

代码如下:

void FineMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col) {;
	//FineMine(mine,show, ROW, COL);
    int x;
	int y;//x,y为你要排查的坐标,输入
	int count = 0;//你排查了的坐标的个数
	while (1) {//一直循环排雷,直到排到雷,或者是成功通关就结束循环
		printf("请输入你要排查的坐标:>");
		scanf("%d", &x);
		scanf("%d", &y);
		if (mine[x][y] != '1') {
			
			if (show[x][y] = '*') {//
				dfs(mine, show, x, y);//深度优先遍历
				DisplayBoard(show, ROW, COL);//每排查一个坐标就接着显示面板
				count++;//排查了的坐标++
			}
			else
				printf("该坐标已经被占用,请重新输入:>");//如果不为'*'意味着已经排查过这个坐标了
		}
		else {
			printf("很不幸,你被炸死了\n");
			DisplayBoard(mine, ROW, COL);//炸死后显示所有雷的位置
			break;
		}
		if (count == row * col - ALLMINE+1) {
			printf("恭喜你,成功通关了!\n");
			break;
		}
	}
}

至于dfs()函数后面讲

效果如图:

ps:深度优先遍历数组

当然目的就是让其每输入一个坐标都有可能展开一片的操作,极大地减少了工作量。

写这个代码前建议大家刷一下力扣的这道题:

. - 力扣(LeetCode)

代码如下:

上面有注释

void dfs(char mine[ROWS][COLS], char show[ROWS][COLS], int a, int b) {
    //dfs(mine, show, x, y);
	int dx[8] = { -1,-1,-1,0,0,1,1,1 };//每个x都对应着其相同下标的y
	int dy[8] = { -1,0,1,-1,1,-1,0,1 };//输入的x和y所在位置的周围八个位置
	int count = 0;//用来记录(a,b)周围雷的个数
	for (int i = 0; i < 8; i++) {
		int r = a + dx[i];
		int c = b + dy[i];//定位到xy周围的位置
		if (r >= 1 &&r<=9&& c >= 1&&c<=9 && mine[r][c] =='1') {//r >= 1 &&r<=9&& c >= 1&&c<=9这一坨就是判断有没有越界
			count++;//该位置是雷的话,就count++
		}
	}
	if (count == 0) {//周围八个位置没有雷
		show[a][b] = '0';
		for (int i = 0; i < 8; i++) {//在这没有雷的位置扩散开来,直到找到其周围有雷的为止
			int r = a + dx[i];
			int c = b + dy[i];
			if (r >= 1 && r <= 9 && c >= 1 && c <= 9 && show[r][c] == '*') {
             //注意show[r][c] == '*'这个条件,不要遍历到重复的已经遍历过的
				dfs(mine, show, r, c);//从这个坐标开始扩散
			}

		}
	}

效果如图:

可以看到边界都显示有雷的!

四.结束

一键三连哦,感谢大家的阅读!

  • 37
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值