扫雷-包含空白展开,标记功能,游戏界面优化-控制台全力复刻

目录

引入

思路

涉及头文件索引

主函数

分支函数功能实现

代码总和---CV可游玩

引入

这两天偶然间玩到了扫雷的游戏,下的是微软旗下的扫雷,感觉比起以前简陋的界面好了太多

d55dbbc3433044dab4e7deb8fe494db2.png

感觉扫雷找到规律也可以玩的很有意思,仔细一想,扫雷不就一二维数组,给我也完全可以实现啊。便开始了我的设计扫雷之旅。 

由于本人想兼顾扫雷的灵活性和与原版的功能相似性,我还是花了些时间去完善这些功能,标题也说了,包括空白展开,标记等。以下开始我们的讲解吧!

思路

主要思路是创建两个数组,一个用来记录扫雷的后台数据包括:雷的位置,并记录各个位置周围雷的数量。一个用来展示玩家能看到的界面--展示界面,根据玩家输入展示想给其展示的内容,我画张图来方便大家理解

f16354e5b59c4b5486f3ff8ae321ad81.png

用户输入一个地址,就将后台数组的数据传入展示数组并打印,这样就完成了对格子的探测。

如果选中的是雷,则判断游戏结束并退出,这样实现了失败的判定。

如果 总格子个数-排除的非雷个数=等于雷的个数,则完成了游戏胜利的判断。

如果选中的是0,则用一个递归函数展开,则完成了空白展开的功能。

将展示的内容根据传入地址将*改成$,则完成了对未知位置的标记。

以上便是主要的代码功能概述,下面详细讲解。

涉及头文件索引

在进行讲解之前,我想做一个多数博主都不会做的事,就是,把用到的较生僻头文件和功能都简单介绍下,见代码

#include<stdio.h>
//输入输出头文件,这个都懂

#include<stdlib.h>
//srand生成种子和rand生成随机数的头文件
//rand生成的随机数是与srand生成的种子有关,而srand随机生成的种子又与time(NULL)有关

#include<time.h>
//调用函数time()生成时间戳以及调用Sleep()函数表示停留时间

#include<windows.h>
//调用system("cls");函数,作用是清屏

 以上内容如果不太懂的朋友强烈建议专门去看看相关内容,了解透这些运用之后,相信一定会更容易理解我的调用。那么开始我们的代码内容吧!

主函数

这里直接把代码放到下面,旁边有注释,还是比较好理解的

#define _CRT_SECURE_NO_WARNINGS
#include "mine_sweep.h"//头文件和函数声明太多我就单独创了个头文件放进去了
int main()
{
	int x = 0, y = 0;//关于游戏界面大小——行-列
	char mine[105][105];//后台界面
	char show[105][105];//展示界面
	srand((unsigned int)time(NULL));//随机生成种子
	int input = 0;
	int digit_m = 10;//雷数量
	do {
	input=menu();//打印菜单
	if (input == 1) {
		printf("开始");
		printf("\n请输入扫雷棋盘大小(长:宽):");
		scanf("%d%d", &x, &y);
		printf("\n请输入设置雷的个数:");
		scanf("%d", &digit_m);
		Initboard(x, y, mine, '0');//初始化棋盘--后台区
		Initboard(x, y, show, '*');//初始化棋盘--展示曲
		Init_mine(x, y, mine,show, digit_m);//初始化雷
		playgame(x, y, digit_m, mine, show);//游戏运行函数
		Sleep(15000);	//结束界面展示停留
	}
	else if (input == 0);
	else { printf("输入错误"); Sleep(1000); }
	system("cls");	//清屏
	} while (input);//判断是否继续
	printf("退出游戏");
	return 0;
}

 分支函数功能实现

菜单函数

int menu()
{
	printf("************************\n");
	printf("******欢迎来到扫雷******\n");
	printf("*****   1.开始玩   *****\n");
	printf("*****              *****\n");
	printf("*****    0.退出    *****\n");
	printf("************************\n");
	printf("请选择:");
	int m;
	scanf("%d", &m);
	return m;
}

 也没啥好说的,就展示菜单以及一个返回值,通过返回值判断是否继续游戏

 初始化棋盘函数

初始化棋盘函数对后台和展示棋盘都适用,根据传入的参数初始化相应的二维数组,见代码

void Initboard(int x,int y,char arr[105][105],char ch)
{
	for (int i = 0; i <= x+1; i++)
		for (int j = 0; j <= y+1; j++)
			arr[i][j] = ch;//将数组各个元素初始化为ch
}

初始化雷函数

雷的初始化就涉及到随机生成数字和种子了,随机生成种子在主函数中已经提前完成,在这里就只用 生成随机数就行,不过建议也要注意一下生成特定随机数范围的方式,见代码

void Init_mine(int x, int y, char mine[105][105],char show[105][105], int digit)
{
	int mine_x, mine_y;
	for (int i = 0; i < digit; i++) {//随机生成数字
	start:;
		mine_x = rand() % x + 1;
		mine_y = rand() % y + 1;
		if (mine[mine_x][mine_y] == '0')//防止两个雷生成在同一位置
			mine[mine_x][mine_y] = '*';
		else goto start;
	}
	for (int i = 1; i <= x; i++) {//处理雷周围的数字,放到mine中,便于后期调用
		for (int j = 1; j <= y; j++) {
			if (mine[i][j] == '*')continue;
			if (mine[i - 1][j] == '*')mine[i][j]++;
			if (mine[i + 1][j] == '*')mine[i][j]++;
			if (mine[i][j + 1] == '*')mine[i][j]++;
			if (mine[i][j - 1] == '*')mine[i][j]++;
			if (mine[i - 1][j - 1] == '*')mine[i][j]++;
			if (mine[i + 1][j - 1] == '*')mine[i][j]++;
			if (mine[i - 1][j + 1] == '*')mine[i][j]++;
			if (mine[i + 1][j + 1] == '*')mine[i][j]++;
		}
	}
}

建议大家都注意下后台数组的处理方式,对编写扫雷代码很有帮助,方便处理数据 

游戏运行函数

其实也没有多复杂,就是对两个数组的处理而已,见代码

void playgame(int x, int y, int digit_m, char mine[105][105], char show[105][105])
{
	int x1, y1, judge;
	int m = 0;
	int* blank = &m;
	while (*blank < x * y - digit_m) {
		system("cls");
		Showboard(x, y, show);
		printf("或者输入标记的格子(1 行 列)\n");
		printf("请输入要探测格子的位置(0 行 列):");
		scanf("%d%d%d", &judge, &x1, &y1);
		if (mine[x1][y1] == '*'&&judge!=1) { *blank = 0; break; }
		else if (x1<1 && x1>x && y1<1 && y1>y) {
			printf("\n输入错误,请重新输入!");
			continue;
		}
		if (judge == 0) {
			blank_unfold(x, y, x1, y1, mine, show, blank);
		}
		else if (show[x1][y1] != '*' && judge == 1) { printf("已展示格子不可标记!"); Sleep(1500); }
		else if (judge == 1)show[x1][y1] = '$';
		else { printf("输入错误!"); Sleep(1500); }
	}
	system("cls");
	Showboard(x, y, mine);
	if (*blank) { 
		win_maliao();
	}
	else { 
		printf("\n踩到雷了,游戏结束!\n");
		printf("15秒后返回初始界面。\n");
	}
}

其中还涉及到了胜利界面展示,展示界面函数和空白展开函数,下面进行讲解

界面展示函数

 对于界面的展示还是很重要的,有时一个游戏的美观与舒适与否很大程度决定了一个游戏的品质,见代码

void Showboard(int x, int y, char arr[105][105])
{
	printf("%d |", 0);
	for (int i = 1; i <= y; i++)
		printf(" %d |", i);
	printf("\n");
	for (int i = 0; i <= y; i++)
		printf("----");
	printf("\n");
	for (int i = 1; i <= x; i++) {
		printf("%d ", i);
		
		for (int j = 1; j <= y; j++) {
			if (arr[i][j] == '*' || arr[i][j] == '$')
				printf("| %c ", arr[i][j]);
			else printf("| %d ", arr[i][j] - '0');
		}
		printf("|");
		printf("\n");
		for (int b = 0; b <= y; b++)
			printf("----");
		printf("\n");
	}
}

主要用|和-符号来优化界面,最后的效果是这样的,见下图

71884d0f8000439c9ad310d041cebdff.png

空白展开函数

空白展开在这里算是个拓展功能,不实现的话其实也玩的动,但是有的话会大大提高其可玩性,主要运用到函数的递归,由于有标记功能,这里的代码也需要有一定改动,见代码

void blank_unfold(int x, int y, int x1, int y1, char mine[105][105], char show[105][105], int* blank)
{
	if (x1<1 || x1>x || y1<1 || y1>y)return;//当输入超出范围时返回
	if (show[x1][y1] == '0' || (show[x1][y1] != '*' && show[x1][y1] != '$'))
        return; //在位置已被探测时返回
	else if (mine[x1][y1] != '0') {//在位置不是空白时展开返回
		show[x1][y1] = mine[x1][y1];
		(*blank)++;
		return;
	}
	else {    //递归同时将空白展开
		show[x1][y1] = '0';
		(*blank)++;
		blank_unfold(x, y, x1 - 1, y1, mine, show,blank);
		blank_unfold(x, y, x1 + 1, y1, mine, show,blank);
		blank_unfold(x, y, x1, y1 - 1, mine, show,blank);
		blank_unfold(x, y, x1, y1 + 1, mine, show,blank);
		blank_unfold(x, y, x1 - 1, y1 - 1, mine, show, blank);
		blank_unfold(x, y, x1 - 1, y1 + 1, mine, show, blank);
		blank_unfold(x, y, x1 + 1, y1 - 1, mine, show, blank);
		blank_unfold(x, y, x1 + 1, y1 + 1, mine, show, blank);
	}
}

彩蛋函数(胜利界面展示) 

皮一下,闲着的时候弄得马里奥,胜利的时候免费批发

void win_maliao()
{
	printf("\n恭喜获得胜利!\n");
	printf("送你个马里奥\n");
	printf("                ********\n");
	printf("               ************\n");
	printf("               ####....#.\n");
	printf("             #..###.....##....\n");
	printf("             ###.......######              ###            ###\n");
	printf("                ...........               #...#          #...#\n");
	printf("               ##*#######                 #.#.#          #.#.#\n");
	printf("            ####*******######             #.#.#          #.#.#\n");
	printf("           ...#***.****.*###....          #...#          #...#\n");
	printf("           ....**********##.....           ###            ###\n");
	printf("           ....****    *****....\n");
	printf("             ####        ####\n");
	printf("           ######        ######\n");
	printf("##############################################################\n");
	printf("#...#......#.##...#......#.##...#......#.##------------------#\n");
	printf("###########################################------------------#\n");
	printf("#..#....#....##..#....#....##..#....#....#####################\n");
	printf("##########################################    #----------#\n");
	printf("#.....#......##.....#......##.....#......#    #----------#\n");
	printf("##########################################    #----------#\n");
	printf("#.#..#....#..##.#..#....#..##.#..#....#..#    #----------#\n");
	printf("##########################################    ############\n");
	printf("15秒后返回初始界面。\n");
}

 代码总和---CV可游玩

到这里差不多就要结束了,以上代码涉及了很多头文件,想来整合运行会比较困难,这些工作我就代大家做了,也是希望大家能玩玩我编的扫雷,见代码

#include<stdio.h>//各种头文件
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<string.h>
void Initboard(int x,int y, char arr[105][105],char ch);//初始棋盘函数
void Showboard(int x, int y, char arr[105][105]);//打印界面函数
int menu();//菜单初始化函数
void Init_mine(int x, int y, char arr[105][105],char show[105][105], int digit);//随机初始化雷函数
void playgame(int x,int y,int digit_m, char mine[105][105], char show[105][105]);//游戏运行函数
void blank_unfold(int x, int y, int x1, int y1, char mine[105][105], char show[105][105],int* blank);//空白展开函数
void win_maliao();//胜利界面展示
void Initboard(int x,int y,char arr[105][105],char ch)
{
	for (int i = 0; i <= x+1; i++)
		for (int j = 0; j <= y+1; j++)
			arr[i][j] = ch;
}
void Showboard(int x, int y, char arr[105][105])
{
	printf("%d |", 0);
	for (int i = 1; i <= y; i++)
		printf(" %d |", i);
	printf("\n");
	for (int i = 0; i <= y; i++)
		printf("----");
	printf("\n");
	for (int i = 1; i <= x; i++) {
		printf("%d ", i);
		
		for (int j = 1; j <= y; j++) {
			if (arr[i][j] == '*' || arr[i][j] == '$')
				printf("| %c ", arr[i][j]);
			else printf("| %d ", arr[i][j] - '0');
		}
		printf("|");
		printf("\n");
		for (int b = 0; b <= y; b++)
			printf("----");
		printf("\n");
	}
}
int menu()
{
	printf("************************\n");
	printf("******欢迎来到扫雷******\n");
	printf("*****   1.开始玩   *****\n");
	printf("*****              *****\n");
	printf("*****    0.退出    *****\n");
	printf("************************\n");
	printf("请选择:");
	int m;
	scanf("%d", &m);
	return m;
}
void Init_mine(int x, int y, char mine[105][105],char show[105][105], int digit)
{
	int mine_x, mine_y;
	for (int i = 0; i < digit; i++) {
	start:;
		mine_x = rand() % x + 1;
		mine_y = rand() % y + 1;
		if (mine[mine_x][mine_y] == '0')
			mine[mine_x][mine_y] = '*';
		else goto start;
	}
	for (int i = 1; i <= x; i++) {
		for (int j = 1; j <= y; j++) {
			if (mine[i][j] == '*')continue;
			if (mine[i - 1][j] == '*')mine[i][j]++;
			if (mine[i + 1][j] == '*')mine[i][j]++;
			if (mine[i][j + 1] == '*')mine[i][j]++;
			if (mine[i][j - 1] == '*')mine[i][j]++;
			if (mine[i - 1][j - 1] == '*')mine[i][j]++;
			if (mine[i + 1][j - 1] == '*')mine[i][j]++;
			if (mine[i - 1][j + 1] == '*')mine[i][j]++;
			if (mine[i + 1][j + 1] == '*')mine[i][j]++;
		}
	}
}
void playgame(int x, int y, int digit_m, char mine[105][105], char show[105][105])
{
	int x1, y1, judge;
	int m = 0;
	int* blank = &m;
	while (*blank < x * y - digit_m) {
		system("cls");
		Showboard(x, y, show);
		printf("或者输入标记的格子(1 行 列)\n");
		printf("请输入要探测格子的位置(0 行 列):");
		scanf("%d%d%d", &judge, &x1, &y1);
		if (mine[x1][y1] == '*'&&judge!=1) { *blank = 0; break; }
		else if (x1<1 && x1>x && y1<1 && y1>y) {
			printf("\n输入错误,请重新输入!");
			continue;
		}
		if (judge == 0) {
			blank_unfold(x, y, x1, y1, mine, show, blank);
		}
		else if (show[x1][y1] != '*' && judge == 1) { printf("已展示格子不可标记!"); Sleep(1500); }
		else if (judge == 1)show[x1][y1] = '$';
		else { printf("输入错误!"); Sleep(1500); }
	}
	system("cls");
	Showboard(x, y, mine);
	if (*blank) { 
		win_maliao();
	}
	else { 
		printf("\n踩到雷了,游戏结束!\n");
		printf("15秒后返回初始界面。\n");
	}
}

void blank_unfold(int x, int y, int x1, int y1, char mine[105][105], char show[105][105], int* blank)
{
	if (x1<1 || x1>x || y1<1 || y1>y)return;
	if (show[x1][y1] == '0' || (show[x1][y1] != '*' && show[x1][y1] != '$'))return;
	else if (mine[x1][y1] != '0') {
		show[x1][y1] = mine[x1][y1];
		(*blank)++;
		return;
	}
	else {
		show[x1][y1] = '0';
		(*blank)++;
		blank_unfold(x, y, x1 - 1, y1, mine, show,blank);
		blank_unfold(x, y, x1 + 1, y1, mine, show,blank);
		blank_unfold(x, y, x1, y1 - 1, mine, show,blank);
		blank_unfold(x, y, x1, y1 + 1, mine, show,blank);
		blank_unfold(x, y, x1 - 1, y1 - 1, mine, show, blank);
		blank_unfold(x, y, x1 - 1, y1 + 1, mine, show, blank);
		blank_unfold(x, y, x1 + 1, y1 - 1, mine, show, blank);
		blank_unfold(x, y, x1 + 1, y1 + 1, mine, show, blank);
	}
}
void win_maliao()
{
	printf("\n恭喜获得胜利!\n");
	printf("送你个马里奥\n");
	printf("                ********\n");
	printf("               ************\n");
	printf("               ####....#.\n");
	printf("             #..###.....##....\n");
	printf("             ###.......######              ###            ###\n");
	printf("                ...........               #...#          #...#\n");
	printf("               ##*#######                 #.#.#          #.#.#\n");
	printf("            ####*******######             #.#.#          #.#.#\n");
	printf("           ...#***.****.*###....          #...#          #...#\n");
	printf("           ....**********##.....           ###            ###\n");
	printf("           ....****    *****....\n");
	printf("             ####        ####\n");
	printf("           ######        ######\n");
	printf("##############################################################\n");
	printf("#...#......#.##...#......#.##...#......#.##------------------#\n");
	printf("###########################################------------------#\n");
	printf("#..#....#....##..#....#....##..#....#....#####################\n");
	printf("##########################################    #----------#\n");
	printf("#.....#......##.....#......##.....#......#    #----------#\n");
	printf("##########################################    #----------#\n");
	printf("#.#..#....#..##.#..#....#..##.#..#....#..#    #----------#\n");
	printf("##########################################    ############\n");
	printf("15秒后返回初始界面。\n");
}
int main()
{
	int x = 0, y = 0;
	char mine[105][105];//后台界面
	char show[105][105];//展示界面
	srand((unsigned int)time(NULL));
	int input = 0;
	int digit_m = 10;
	do {
	input=menu();//打印菜单
	if (input == 1) {
		printf("开始");
		printf("\n请输入扫雷棋盘大小(长:宽):");
		scanf("%d%d", &x, &y);
		printf("\n请输入设置雷的个数:");
		scanf("%d", &digit_m);
		Initboard(x, y, mine, '0');//初始化棋盘--后台区
		Initboard(x, y, show, '*');//初始化棋盘--展示曲
		Init_mine(x, y, mine,show, digit_m);//初始化雷
		playgame(x, y, digit_m, mine, show);//游戏运行函数
		Sleep(15000);	//结束界面展示
	}
	else if (input == 0);
	else { printf("输入错误"); Sleep(1000); }
	system("cls");	//清屏
	} while (input);//判断是否继续
	printf("退出游戏");
	return 0;
}

运行截图

 812e7802ac3d4e68b7beed9273b441ae.png

本篇文章已经代码制作编写不易,还请大家在走之前给一个小小的赞啊!!!

如果对你有帮助的话,别忘了放收藏夹关注我哦--比心(> - < )---♥

同时如果博主的文章有任何错误,都欢迎在评论区提出来,我会积极去改,也感谢大家对我的支持捏。

  • 27
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
下面是一个简单的控制台版本扫雷游戏C语言代码示例,仅供参考: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <stdbool.h> #define ROWS 10 // 行数 #define COLS 10 // 列数 #define MINE_NUM 10 // 雷数 int minefield[ROWS][COLS]; // 雷区 bool visible[ROWS][COLS]; // 可视区 // 初始化雷区 void initMinefield() { int i, j, count; for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { minefield[i][j] = 0; visible[i][j] = false; } } // 随机生成雷 count = 0; while (count < MINE_NUM) { i = rand() % ROWS; j = rand() % COLS; if (minefield[i][j] == 0) { minefield[i][j] = -1; count++; } } // 计算每个格子周围的雷数 for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { if (minefield[i][j] == -1) { continue; } if (i > 0 && j > 0 && minefield[i-1][j-1] == -1) { minefield[i][j]++; } if (i > 0 && minefield[i-1][j] == -1) { minefield[i][j]++; } if (i > 0 && j < COLS-1 && minefield[i-1][j+1] == -1) { minefield[i][j]++; } if (j > 0 && minefield[i][j-1] == -1) { minefield[i][j]++; } if (j < COLS-1 && minefield[i][j+1] == -1) { minefield[i][j]++; } if (i < ROWS-1 && j > 0 && minefield[i+1][j-1] == -1) { minefield[i][j]++; } if (i < ROWS-1 && minefield[i+1][j] == -1) { minefield[i][j]++; } if (i < ROWS-1 && j < COLS-1 && minefield[i+1][j+1] == -1) { minefield[i][j]++; } } } } // 输出雷区 void printMinefield() { int i, j; printf(" "); for (j = 0; j < COLS; j++) { printf("%d ", j); } printf("\n"); printf(" "); for (j = 0; j < COLS; j++) { printf("- "); } printf("\n"); for (i = 0; i < ROWS; i++) { printf("%d|", i); for (j = 0; j < COLS; j++) { if (visible[i][j]) { if (minefield[i][j] == -1) { printf("* "); } else { printf("%d ", minefield[i][j]); } } else { printf(". "); } } printf("\n"); } } // 检查是否了 bool checkWin() { int i, j, count = 0; for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { if (minefield[i][j] == -1 && visible[i][j]) { return false; } if (minefield[i][j] != -1 && visible[i][j]) { count++; } } } return count == ROWS * COLS - MINE_NUM; } // 处理输入的命令 void handleCommand(char cmd, int row, int col) { if (row < 0 || row >= ROWS || col < 0 || col >= COLS) { printf("Invalid position.\n"); return; } if (cmd == 'o') { // 打开格子 if (visible[row][col]) { printf("This position has already been opened.\n"); return; } visible[row][col] = true; if (minefield[row][col] == -1) { printf("Game over!\n"); printMinefield(); exit(0); } if (minefield[row][col] == 0) { int i, j; for (i = row-1; i <= row+1; i++) { for (j = col-1; j <= col+1; j++) { if (i >= 0 && i < ROWS && j >= 0 && j < COLS && minefield[i][j] != -1) { visible[i][j] = true; } } } } if (checkWin()) { printf("You win!\n"); printMinefield(); exit(0); } } else if (cmd == 'f') { // 标记格子为雷 visible[row][col] = true; } else { printf("Invalid command.\n"); } } int main() { srand(time(NULL)); initMinefield(); printf("Welcome to Minesweeper!\n"); printf("You can enter commands like 'o 3 4' to open the cell at row 3 and column 4.\n"); printf("You can also mark a cell as containing a mine by using the 'f' command.\n"); printf("Good luck!\n"); while (true) { printMinefield(); char cmd; int row, col; printf("Enter command: "); scanf("%c %d %d", &cmd, &row, &col); while (getchar() != '\n'); // 清空输入缓冲区 handleCommand(cmd, row, col); } return 0; } ``` 该代码实现了扫雷游戏的基本功能,包括随机生成雷区、计算每个格子周围的雷数、打开格子、标记格子为雷、检查是否了等。在控制台中运行该程序,便可以体验简单的扫雷游戏了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Forcible Bug Maker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值