扫雷游戏思路代码讲解

为了后续的函数说明,我在这里现将头文件以及函数定义打印如下:

#pragma once
#include <stdio.h>
#include<stdlib.h>
#include<time.h>

//ROW表示行数,SOW表示列数,NUMBER表示雷数,三组数据分别表示三种难度
#define ROW 9
#define SOW 9
#define ROWS ROW + 2
#define SOWS SOW + 2
#define NUMBER 10

//#define ROW 16
//#define SOW 16
//#define ROWS ROW + 2
//#define SOWS SOW + 2
//#define NUMBER 40
//
//#define ROW 16
//#define SOW 30
//#define ROWS ROW + 2
//#define SOWS SOW + 2
//#define NUMBER 99

//初始化棋盘
void InitBorad(char borad[ROWS][SOWS], int row, int sow, char set);

//打印棋盘
void print_borad(char borad[ROWS][SOWS], int row, int sow);

//设置雷
void SetMine(char borad1[ROWS][SOWS], int row, int sow);

//排雷
void FindMine(char borad1[ROWS][SOWS], char borad2[ROWS][SOWS], int row, int sow);

//统计周围雷个数
int GetBorad1Count(char borad1[ROWS][SOWS],int  x, int y);

扫雷游戏的功能要求:

一、

首先,我们需要一个界面,来供玩家进行选择。这里,我选择定义一个meun函数,函数功能简单仅用于打印出 选项,具体的选择,我采用Switch函数,通过识别玩家输入的数字来判断选择,简单的选择仅给出了1、开始游戏与2、退出游戏。具体的代码如下:

void meun1() {
    printf("***********************\n");
    printf("****                     ****\n");
    printf("****  1.进行游戏  ****\n");
    printf("****  2.离开游戏  ****\n");  
    printf("****                      ****\n");
    printf("***********************\n");
}

二、

其次,以上,我们仅做出了简单的定义以及简单的界面设置,想要完成一个扫雷游戏,这样是远远不够的。分析,一个扫雷游戏,会有,扫雷,排雷,统计雷等几个基础功能。

1.扫雷

首先,由于C语言的程序限制,我们只能选择用某一个数字或者符号对雷进行描述与封装。进过短暂的思考 ,我选择使用数字1来表示雷,在打开之前,用*号进行封装,并且没有雷的地方就用0表示 。思考,按照我们对于扫雷的了解,扫雷是一个类似于N宫格的设计,所以我们使用二维数字即可表示。接下来,继续思考我上面所说的,用1表示雷*号进行遮盖,一个为整形,一个为字符型,所以我们考虑使用两个数组,但是在打印棋盘的时候,我们会发现,如果,一个为整形,一个为字符型,我们需要设计两个函数,为了减小麻烦,我们思考后,考虑使用字符型数组,将1用‘1’表示,将0用‘0’表示。这样我们就进行了一个棋盘的初始化定义,再以函数对棋盘进行打印。

具体的代码如下:

棋盘初始化:

void InitBorad(char borad[ROWS][SOWS], int rows, int sows, char set){
    int i = 0,j = 0;
    for (i = 0; i < rows; i++) {
        for (j = 0; j < sows; j++) {
            borad[i][j] = set;
        }
    }
}

棋盘打印:

void print_borad(char borad[ROWS][SOWS], int row, int sow){
    int i = 0;
    int j = 0;
    printf(" ");
    for (j = 1; j <= sow; j++) {
        printf(" %d", j);
        }
    printf("\n");
    printf("-------------------\n");
    for (i = 1; i <= row; i++) {
        printf("%d", i);
        printf("|");
        for (j = 1; j <= sow; j++) {
            printf("%c ", borad[i][j]);
        }
        printf("\n");
    }
    }

2.

在棋盘定义以后,考虑在棋盘中随机插入雷。这里考虑在二维中,行列是可以以坐标的形势表示,这里我们只需要找到两个随机的行列坐标,xy。为了得到两个随机的行列值,使用rand()函数,随机得到两个值,使用rand函数,必须用srand()与time函数。我们在得到坐标以后,将该点的值赋值为‘1’,即为雷。

具体代码如下:

void SetMine(char borad1[ROWS][SOWS], int row, int sow) {
	int count = NUMBER;
	int x = 0;
	int y = 0;
	while (count) {
		x = rand() % row + 1;
		y = rand() % sow + 1;
		if (borad1[x][x] != '1') {
			borad1[x][y] = '1';
			count--;
		}
	}

}

3.

接下来考虑排雷工作的进行。排雷无非就是两个选项,输入的坐标点的值是表示雷或者不是雷。如果该点事雷,则直接弹出“踩雷了,游戏结束的提示”,并且,回到选择的界面,让玩家选择是否继续进行游戏;如果该点不是雷,则,弹出下一个界面,并且在该点上标明周围八个位置的雷的数量(该功能在下一个介绍上说明),再进行下一个点坐标的输入,如此往复。特别说明,当排雷完成后需要结束游戏,这时候需要一个特别的判断功能,我们只需要判断剩余的点的数量即可。

具体代码如下:

void FindMine(char borad1[ROWS][SOWS], char borad2[ROWS][SOWS], int row, int sow) {
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row*sow-NUMBER) {
		printf("请输入要排查的坐标:");
		scanf_s("%d %d", &x, &y);
		if (x>=1 && x <= row && y>=1 &&y <= sow) {
			if (borad1[x][y] == '1') {
				printf("踩雷了,游戏结束!\n");
				print_borad(borad1, ROW, SOW);
				break;
			}
			else {
				int count = GetBorad1Count(borad1, x, y);
				borad2[x][y] = count + '0';
				print_borad(borad2, ROW, SOW);
				win++;
				}
			}
		else {
			printf("输入的坐标越界,x,y在1~9以内!请重新输入!\n");
		}
	}
	if (win == row * sow - NUMBER) {
		printf("恭喜你排雷完成!\n");
		print_borad(borad1, ROW, SOW);
	}
}

4.

排雷后的雷数统计,让人疑惑。怎样实现这个功能呢?其实还是很简单的,我们需要理清楚该坐标作为点与坐标之间的关系,这里我不做详细说明,大家可以自己看一下。当我们理清楚这些点之间的关系以后,将这些点的进行字符到数字之间的转换(‘1’-‘0’),装换以后将8个点的数字进行求和,求和以后赋予最初点。特别的说明,当点在边界时,我们这个时候统计则会越界,如此,越界后该点的值是不确定的,所以,在一开始,我们的二维数组定义是多了两行两列的,且赋值为‘0’,这样就避免了越界后产生的不确定性,已经程序的危险性。

具体代码如下:

int GetBorad1Count(char borad1[ROWS][SOWS], int  x, int y) {
	int i = 0, j = 0;
	int count = 0;
	for ( i = -1; i <= 1; i++) {
		for (j = -1; j <= 1; j++) {
			count = (borad1[x + i][y + j] - '0');
		}
	}
	return count;
}

三、

最后,写一个函数对游戏功能进行实现,该函数采用循环以及switch来进行,操作也是相当的简单。

具体如下:

void game() {
    char borad1[ROWS][SOWS];//存放雷的信息
    char borad2[ROWS][SOWS];//存放周围雷的数量

    //初始化棋盘
    InitBorad(borad1, ROWS, SOWS, '0');
    InitBorad(borad2, ROWS, SOWS, '*');

    //打印棋盘
    
    print_borad(borad2, ROW, SOW);
    
    //设置雷
    SetMine(borad1, ROW, SOW);
    print_borad(borad1, ROW, SOW);
    //排雷
    FindMine(borad1, borad2, ROW, SOW);
}

void test() {
    srand((unsigned int)time(NULL));
    int input = 0;
    do {
        meun1();
        scanf_s("%d", &input);
        switch (input) {
        case 1:
            game();
            break;
        case 2:
            printf("已退出游戏!\n");
            break;
        default :
            printf("非法输入,请重新选择!\n");
            break;
        }
    } while (input == 1);
}

int main() {
    test();
    return 0;
}

到此我们写完了一个简单的扫雷游戏!因为是使用vscod进行编译,并且包含了多个源文件,所以以上代码如需使用,还需你自己酌情修改,现将完整代码如下展示:

#pragma once
#include <stdio.h>
#include<stdlib.h>
#include<time.h>

//ROW表示行数,SOW表示列数,NUMBER表示雷数,后缀(1,2,3)分别表示三种难度
#define ROW 9
#define SOW 9
#define ROWS ROW + 2
#define SOWS SOW + 2
#define NUMBER 10

//#define ROW 16
//#define SOW 16
//#define ROWS ROW + 2
//#define SOWS SOW + 2
//#define NUMBER 40
//
//#define ROW 16
//#define SOW 30
//#define ROWS ROW + 2
//#define SOWS SOW + 2
//#define NUMBER 99

//初始化棋盘
void InitBorad(char borad[ROWS][SOWS], int row, int sow, char set);

//打印棋盘
void print_borad(char borad[ROWS][SOWS], int row, int sow);

//设置雷
void SetMine(char borad1[ROWS][SOWS], int row, int sow);

//排雷
void FindMine(char borad1[ROWS][SOWS], char borad2[ROWS][SOWS], int row, int sow);

//统计周围雷个数
int GetBorad1Count(char borad1[ROWS][SOWS],int  x, int y);

//初始化棋盘
void InitBorad(char borad[ROWS][SOWS], int rows, int sows, char set){
	int i = 0,j = 0;
	for (i = 0; i < rows; i++) {
		for (j = 0; j < sows; j++) {
			borad[i][j] = set;
		}
	}
}

//打印棋盘
void print_borad(char borad[ROWS][SOWS], int row, int sow){
	int i = 0;
	int j = 0;
	printf(" ");
	for (j = 1; j <= sow; j++) {
		printf(" %d", j);
		}
	printf("\n");
	printf("-------------------\n");
	for (i = 1; i <= row; i++) {
		printf("%d", i);
		printf("|");
		for (j = 1; j <= sow; j++) {
			printf("%c ", borad[i][j]);
		}
		printf("\n");
	}
	}

//设置雷
void SetMine(char borad1[ROWS][SOWS], int row, int sow) {
	int count = NUMBER;
	int x = 0;
	int y = 0;
	while (count) {
		x = rand() % row + 1;
		y = rand() % sow + 1;
		if (borad1[x][x] != '1') {
			borad1[x][y] = '1';
			count--;
		}
	}

}

//排查周围雷个数
int GetBorad1Count(char borad1[ROWS][SOWS], int  x, int y) {
	int i = 0, j = 0;
	int count = 0;
	for ( i = -1; i <= 1; i++) {
		for (j = -1; j <= 1; j++) {
			count = (borad1[x + i][y + j] - '0');
		}
	}
	return count;
}

//排雷
void FindMine(char borad1[ROWS][SOWS], char borad2[ROWS][SOWS], int row, int sow) {
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row*sow-NUMBER) {
		printf("请输入要排查的坐标:");
		scanf_s("%d %d", &x, &y);
		if (x>=1 && x <= row && y>=1 &&y <= sow) {
			if (borad1[x][y] == '1') {
				printf("踩雷了,游戏结束!\n");
				print_borad(borad1, ROW, SOW);
				break;
			}
			else {
				int count = GetBorad1Count(borad1, x, y);
				borad2[x][y] = count + '0';
				print_borad(borad2, ROW, SOW);
				win++;
				}
			}
		else {
			printf("输入的坐标越界,x,y在1~9以内!请重新输入!\n");
		}
	}
	if (win == row * sow - NUMBER) {
		printf("恭喜你排雷完成!\n");
		print_borad(borad1, ROW, SOW);
	}
}

void meun1() {
	printf("**********************\n");
	printf("****              ****\n");
	printf("****  1.进行游戏  ****\n");
	printf("****  2.离开游戏  ****\n");
	printf("****              ****\n");
	printf("**********************\n");
}
//难度选项
void meun2() {
	printf("**********************\n");
	printf("***1.初级(10个雷)***\n");
	printf("***2.中级(40个雷)***\n");
	printf("***3.高级(99个雷)***\n");
	printf("**********************\n");
}
//棋盘安排
void game() {
	char borad1[ROWS][SOWS];//存放雷的信息
	char borad2[ROWS][SOWS];//存放周围雷的数量

	//初始化棋盘
	InitBorad(borad1, ROWS, SOWS, '0');
	InitBorad(borad2, ROWS, SOWS, '*');

	//打印棋盘
	
	print_borad(borad2, ROW, SOW);
	
	//设置雷
	SetMine(borad1, ROW, SOW);
    print_borad(borad1, ROW, SOW);
	//排雷
	FindMine(borad1, borad2, ROW, SOW);
}

void test() {
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
		meun1();
		scanf_s("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 2:
			printf("已退出游戏!\n");
			break;
		default :
			printf("非法输入,请重新选择!\n");
			break;
		}
	} while (input == 1);
}

int main() {
	test();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值