首页 > 其他分享 >[C语言]还原原版的扫雷

[C语言]还原原版的扫雷

时间:2024-03-14 19:58:17浏览次数:26  
标签:ROWS int void printf COLS C语言 char 扫雷 原版

今天看了b站鹏哥做的扫雷,其中有几点鹏哥没有进行优化,第一个就是没有在进行游戏前不布置雷,在选择第一个方块的时候再布置雷,还有就是如何像原版扫雷一样,点到一个周围为0的方块再检测其周围的方块的取值,鹏哥也暗示了可以用递归的方法,最后一点就是像原版一样进行标记选择,最后一点其实挺容易实现的,所以我这里的代码就没有交代了,大致思想就是,给与输入一个选择1和2,当为1的时候是输入扫雷的位置,当为2的时候是标注,然后要注意标注的地点必须是需要扫雷的地方就好,这点都是很通常的思想,本文就鹏哥前两个问题展开自己的扫雷代码思想。具体代码分别如下:

test.c文件

#include "game.h"

void game()
{
	srand((unsigned int)time(NULL));
	char show[ROWS][COLS] = { 0 };
	char mine[ROWS][COLS] = { 0 };
	//禁忌搜索数组
	int tabu[ROWS][COLS] = { 0 };
	//初始化棋盘
	initialBoard(show, ROWS, COLS, '*');
	initialBoard(mine, ROWS, COLS, '0');
	system("cls");
	//展示棋盘
	Display(show, ROW, COL);
	//第一次点击;
	int x;
	int y;
	printf("要下哪儿呢?\n演示一下如果要下第一行第三列输入1 3就好\n");
	scanf("%d%d", &x, &y);
	system("cls");
	//埋雷
	Setmine(mine,ROW, COL,EASY,x,y);
	//排查第一次雷
	Detect(show,mine,ROW,COL,x,y,tabu);
	Display(show, ROW, COL);
	//排雷
	Play(mine, show, ROW, COL,x,y,tabu);
}


int main()
{
	int input ;
	do {
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("你在输入些什么?\n");
         }
	} while (input);
}

game.c文件

#include "game.h"
void menu()
{
	printf("***********    扫雷    ***********\n");
	printf("***********   1.play   ***********\n");
	printf("***********   0.exit   ***********\n");
	printf("**********************************\n");
}
void initialBoard(char Board[ROWS][COLS], int row, int col, char set)
{
	int i;
	int j;
	for (i=0;i<row;i++)
		for (j = 0; j < col; j++)
		{
			Board[i][j] = set;
		}
	return 0;
}
void Display(char Board[ROWS][COLS], int row, int col)
{
	int i;
	int j;
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
    printf("\n");
	for (i = 1; i <= row; i++)
	{
			printf("%d ", i );
			for (j = 1; j <= col; j++)
			{
				printf("%c ", Board[i][j]);
			}
			printf("\n");
	}

}
void Setmine(char Board[ROWS][COLS], int row, int col, int Difficult,int first_x,int first_y)
{
	int a;
	int b;
	int i = 0;
	for (i = 0; i < Difficult; i++)
	{
		flag:
		a = (rand()%row)+1;
		b = (rand()%col)+1;
		if ((Board[a][b] == '0')&&((a != first_x)||(b != first_y)))
		{
			Board[a][b] = '1';
		}
		else
		{
			goto flag;
		}
	}
	
}
void Detect(char Boardshow[ROWS][COLS], char Boardmine[ROWS][COLS], int row, int col, int Detect_x, int Detect_y,int tabu[ROWS][COLS])
{
	if ((Detect_x >= 1) && (Detect_x <= row) && (Detect_y >= 1) && (Detect_y <= col)&&tabu[Detect_x][Detect_y]==0)
	{
		Boardshow[Detect_x][Detect_y] = Boardmine[Detect_x - 1][Detect_y + 1] + Boardmine[Detect_x][Detect_y + 1]
			+ Boardmine[Detect_x + 1][Detect_y + 1] + Boardmine[Detect_x - 1][Detect_y]
			+ Boardmine[Detect_x - 1][Detect_y - 1] + Boardmine[Detect_x + 1][Detect_y]
			+ Boardmine[Detect_x][Detect_y - 1] + Boardmine[Detect_x + 1][Detect_y - 1] - 7 * '0';
		tabu[Detect_x][Detect_y] = 1;
		if ((Boardshow[Detect_x][Detect_y] == '0'))
		{
			Detect(Boardshow, Boardmine, row, col, Detect_x - 1, Detect_y + 1, tabu);
			Detect(Boardshow, Boardmine, row, col, Detect_x , Detect_y + 1, tabu);
			Detect(Boardshow, Boardmine, row, col, Detect_x + 1, Detect_y + 1, tabu);
			Detect(Boardshow, Boardmine, row, col, Detect_x - 1, Detect_y , tabu);
			Detect(Boardshow, Boardmine, row, col, Detect_x + 1, Detect_y , tabu);
			Detect(Boardshow, Boardmine, row, col, Detect_x - 1, Detect_y - 1, tabu);
			Detect(Boardshow, Boardmine, row, col, Detect_x , Detect_y - 1, tabu);
			Detect(Boardshow, Boardmine, row, col, Detect_x + 1, Detect_y - 1, tabu);
		}
	}
}
void Play(char Boardmine[ROWS][COLS], char Boardshow[ROWS][COLS], int row, int col, int a, int b, int tabu[ROWS][COLS])
{
	int x1= 0;
	int x2= 0;
	int i = 0;
	int j = 0;
	while (1)
	{
		while (1)
		{
			printf("请输入:");
			scanf("%d%d", &x1, &x2);
			if ((x1 <= row && x1 >= 1) && (x1 <= col && x2 >= 1) && (Boardshow[x1][x2] == '*'))
			{
				break;
			}
			else
				printf("请输入没有下过的位置\n");

		}
		if (Boardmine[x1][x2] == '1')
		{
			printf("BOOM!\n");
			break;
		}
		else
		{
			Detect(Boardshow, Boardmine, row, col, x1, x2,tabu);
		}
		system("cls");
		Display(Boardshow, ROW, COL);
		int count = 0;
		for (i = 1; i <= row; i++)
		{
			for (j = 1; j <= col; j++)
			{
				if (Boardshow[i][j] == '*')
				{
					count += 1;
					if (count > EASY)
					{
						goto flag;
					}
			    }
			}
		}
		if (count == EASY)
		{
			printf("恭喜胜利\n");
			break;
		}
		flag:
		;
	}
}

game.h文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#define ROWS 11
#define COLS 11
#define ROW ROWS-2
#define COL COLS-2
#define EASY ((ROWS-1)*(COLS-1))/10
#include <time.h>
#include <stdlib.h>

void menu();
void initialBoard(char Board[ROWS][COLS], int row, int col,char set );
void Display(char Board[ROWS][COLS], int row, int col);
void Setmine(char Board[ROWS][COLS], int row, int col, int Difficult ,int first_x,int first_y);
void Detect(char Boardshow[ROWS][COLS], char Boardmine[ROWS][COLS], int row, int col, int Detect_x, int Detect_y, int tabu[ROWS][COLS]);
void Play(char Boardmine[ROWS][COLS], char Boardshow[ROWS][COLS],int row, int col ,int a,int b, int tabu[ROWS][COLS]);

运行代码如下

输入1后

如下棋盘1 3的位置

可以看到与鹏哥不同的点在于像原版扫雷一样遍历出来了很多区域

说一下我的思路,遍历查找的思想,利用递归的方式就好,但是呢这里要防止他反复递归,就是有些递归过的点要让他不参与递归,所以在主函数一开始我用到了一个tabu的禁忌递归矩阵,就是如果里面有坐标递归过了,令其里面等于1,如果没有那就还是初始值0,按照这个思想就可以完成扫雷区域的扩充。

其次就是如何实现第一次点击不会点到炸弹,只需要再游戏没进入play循环前,提前输入一次就好,然后再设置地雷的时候,不让那个坐标参与设置就行,如这行代码的条件

这里的xy就是排除上面输入的坐标设置的参数,具体可以在函数里看到

其他的代码和鹏哥的思路大差不差。

标签:ROWS,int,void,printf,COLS,C语言,char,扫雷,原版
From: https://blog.csdn.net/azurehan01/article/details/136635167

相关文章

  • C语言const 和 *的爱恨情仇
    相信所有在学C的人都对const和*这对小情侣非常熟悉,实在是太烦了。他们中间还时不时得加个第三者什么int,char啥的。看了很多资料再加上我自身的总结提炼理解以后,我终于把他们理清了。首先const这个关键字是用来修饰常量的,我们就简称它为常量。定义指针的时候都会用到*,int*p......
  • 实验1 c语言开发环境使用和数据类型、运算符、表达式
    task1`#include<stdio.h>intmain(){printf("o\n");printf("\n");printf("II\n");printf("o\n");printf("<H>\n");printf("II\n");return0;}``#include<stdio......
  • 实验1_C语言输入输出和简单程序编写
    task1_11#include<stdio.h>2#include<stdlib.h>3intmain()4{5printf("O\n");6printf("<H>\n");7printf("II\n");8printf("O\n");9printf("<H>\n");10p......
  • C语言:洛谷数组题目(2)(冰雹猜想,校门外的树,旗鼓相当的对手)
    目录1.前言2.三则题目1.冰雹猜想1.题目描述2.输入格式3.输出格式4.题解2.校门外的树1.题目描述2.输入格式3.输出格式4.题解3.旗鼓相当的对手1.题目描述2.输入格式3.输出格式4.题解3.小结1.前言今天小蒟蒻继续为大家分享洛谷数组题单题解,一共三道题,希望大......
  • 滴水逆向笔记系列-c语言总结6-20.多级指针 数组指针 函数指针-21.位运算-22.内存分配
    第二十课c语言13多级指针数组指针函数指针1.多级指针反汇编一二级指针可以看到p1==*(p1+0)==p1[0]本来一直没想懂为什么是movsxecx,byteptr[eax],是byte,才发现p1是char类型,所以才得用movsx拓展(p1+2)==p1[2],指针可以用和[]取值,他们是一样的(((p3+1)+2)+3)==p3[......
  • 深入C语言指针,使代码更加灵活(二)
    一、数组名的理解前面我们在使用指针访问数组内容的时候,有这样的代码:intarr[10]={1,2,3,4,5,6,7,8,9,10};int*p=&arr[0];在这里我们使用&arr[0]的方式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,而且是数组首元素的地址。我们来进行测试:#d......
  • 滴水逆向笔记系列-c语言总结4-15.switch语句反汇编-16.指针1-17.指针2
    第十五课c语言8switch语句初步测试感觉switch在反汇编的语句和if语句的唯一差别就是jcc语句比较集中当分支大于四条时,switch的反汇编开始变3为switch传入的值,1是case最小值,4是case最大值减1,算出偏移量后通过偏移量4加上基址就可以在大表中获取要输出的case语句的地址当现在case......
  • 滴水逆向笔记系列-c语言总结5-
    第十八课c语言11字符串与数组这一节课b站缺失了,参考一下大佬的笔记学习,链接:https://blog.csdn.net/Edimade/article/details/124446533?spm=1001.2014.3001.55021.字符数组:::infochararr[10]={'A','B','C','D','E','F'};//编译器默认在结尾添加......
  • C语言冒泡排序
            冒泡排序是一种简单的排序算法,通过重复遍历要排序的数列,依次比较两个相邻的元素,如果它们的顺序错误则交换它们。这个过程会重复进行,直到没有相邻的元素需要交换,也就是数列已经排序完成。        冒泡排序的名字来源于其工作方式,因为较小的元素会像气......
  • C语言从入门到实战————数组和指针的深入理解
    前言在C语言中,数组和指针有的密切得联系,因为数组名本身就相当于一个指针常量。指针是一个变量,专门用来存储另一个变量的内存地址,通过这个地址可以访问和操作该变量的值,同时也包括数组。数组是一组连续存储的同类型数据的集合,它允许通过索引快速访问各个元素。同时数组名也是数......