【初识C11】递归标记版扫雷

本文介绍了如何编写一个基于C语言的游戏程序,包括雷盘初始化、雷的布局、玩家排雷、递归展开标记和胜利条件。通过菜单系统引导玩家进行游戏,展示了核心代码实现和关键函数如计数雷数和标记功能。

主函数

#include"Game.h"

void menu()
{
	printf("****** 1.play   0.exit ******\n");
}

void game()
{
	//两个大小一样的雷盘
	char Mine[ROWS][COLS] = { 0 };//布置雷
	char Pmine[ROWS][COLS] = { 0 };//用作显示排雷信息
	
	//雷盘的初始化
	char set = 0; 	//想要初始化字符数组的元素是什么字符
	InitMine(Mine, ROWS, COLS, '0');	//用0 方便根据该ASCII,进行后续的信息统计。
	InitMine(Pmine, ROWS, COLS, '*');

	//布置雷。
	DecMine(Mine, ROW, COL);	//只用布置在真正玩时的区域。
	//ShowMine(Mine, ROW, COL);		//看一下补完雷后的样子。

	//打印棋盘-只需要显示游戏时的雷盘。
	ShowMine(Pmine, ROW, COL);

	//玩家排雷 -需要把两个数组都传过去
	PlayMove(Mine,Pmine,ROW,COL);
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

Game.h头文件

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

#define ROW 8
#define COL 8
#define ROWS ROW+2   //防止边界排雷时,数组越界
#define COLS COL+2

#define Assmine 10   //布置雷的个数。

void InitMine(char m[ROWS][COLS], int x, int y, char c);

void ShowMine(char m[ROWS][COLS], int x, int y);

void DecMine(char m[ROWS][COLS], int x, int y);

void PlayMove(char m[ROWS][COLS], char p[ROW][COL], int x, int y);

Game.c函数实现

初始化雷盘函数

void InitMine(char m[ROWS][COLS], int x, int y, char c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < ROWS; i++)
	{
		for (j = 0; j < COLS; j++)
		{
			m[i][j] = c;
		}
	}
}

打印雷盘

  • 只需打印玩家排雷时用到的那个雷盘的大小,即行[ROW]列[COL]
void ShowMine(char m[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("------ 雷盘 ------\n");
	//横坐标
	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 ",m[i][j]);
		}
		printf("\n");
	}
	printf("------ 雷盘 ------\n");
}


布置雷

void DecMine(char m[ROWS][COLS], int x, int y)
{
	//布置雷
	int count = Assmine;
	while (count)
	{
		int sx = rand() % ROW + 1;	//1-8的下标
		int sy = rand() % COL + 1;
		if (m[sx][sy] == '0')
		{
			m[sx][sy] = '1';
			count--;
		}
	}
}

统计周围坐标雷的个数

static int CountMine(char board[ROWS][COLS], int x, int y)//计算某个坐标周围的雷数
{
	return (board[x - 1][y] + board[x - 1][y + 1] +
		board[x][y + 1] + board[x + 1][y + 1] +
		board[x + 1][y] + board[x + 1][y - 1] +
		board[x][y - 1] + board[x - 1][y - 1]) - 8 * '0';//数字
}

玩家开始排雷

  • 雷用字符’1`表示。排雷时,修改的时玩家雷盘,修改的信息来自于检测的原始雷盘。
void PlayMove(char m[ROWS][COLS], char p[ROWS][COLS], int row, int col)
{
	int win = 0;		//赢的条件。
	int r = 0;
	int c = 0;
	while (win<row*col-Assmine)
	{
		printf("请输入要排查的坐标:>");
		scanf("%d%d", &r, &c);
		if (r >= 1 && r <= ROW && c >= 1 && c <= COL)
		{
			if (m[r][c] == '1')//是地雷
			{
				printf("很遗憾,您被炸死了!\n");
				ShowMine(m,ROW,COL);
				break;
			}
			else
			{
				int ret = CountMine(m, ROW, COL);
				p[r][c] = ret + '0';
				OpenMine(m, p, ROW, COL, r, c);
				ShowMine(p, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("坐标输入错误,请重新输入!\n");
		}
	}
	if (win==row*col-Assmine)
	{
		printf("恭喜!扫雷成功·!!\n");
		ShowMine(p, ROW, COL);
	}
}

递归展开

static void OpenMine(char m[ROWS][COLS], char p[ROWS][COLS], int row, int col, int x, int y)
{
	int ret = CountMine(m, x, y); 调用统计雷个数的函数。
	if (ret == 0)
	{
		p[x][y] = ' ';
		if (x - 1 >0 && y - 1 >0 && m[x - 1][y - 1] == '0') //要确定周围8个坐标本身不是雷,才递归它周围的。
		{
			OpenMine(m, p, row, col, x - 1, y - 1);
		}
		else if (x > 0 && y - 1 > 0 && m[x][y - 1] == '0') //还要注意递归后坐标的临界值限制条件 比如行列不能大于ROW,COL 都应该大于0
		{
			OpenMine(m, p, row, col, x, y - 1);
		}
		else if (x + 1 <= ROW && y - 1 > 0 && m[x + 1][y - 1] == '0')
		{
			OpenMine(m, p, row, col, x + 1, y - 1);
		}
		else if (x - 1 > 0 && y > 0 && m[x - 1][y] == '0')
		{
			OpenMine(m, p, row, col, x - 1, y);
		}
		else if (x + 1 <= ROW && y > 0 && m[x + 1][y] == '0')
		{
			OpenMine(m, p, row, col, x + 1, y);
		}
		else if (x - 1 > 0 && y + 1 <= COL && m[x - 1][y + 1] == '0')
		{
			OpenMine(m, p, row, col, x - 1, y + 1);
		}
		else if (x > 0 && y + 1 <= COL && m[x][y + 1] == '0')
		{
			OpenMine(m, p, row, col, x, y + 1);
		}
		else if (x + 1 <= ROW && y + 1 <=COL && m[x + 1][y + 1] == '0')
		{
			OpenMine(m, p, row, col, x + 1, y + 1);
		}
	}
	else
	{
		p[x][y] = ret + '0'; 显示该坐标周围有几个雷
	}
}

标记函数

static void SignMine(char show[ROWS][COLS], int row, int col, const int count)
{
    int input = 0;
    int a = 0;
    int b = 0;
    do
    {
        printf("是否需要标记雷: 1.是        0.否\n");
        scanf("%d", &input);
        switch(input)
        {
        case 1:
            printf("请输入要标记的坐标:>");
            scanf("%d%d", &a, &b);
            if(show[a][b]=='\03')
            {
                show[a][b]='*';
                Print(show,row,col); //标记后打印一下棋盘
            }
            else if(show[a][b]=='*')
            {
                printf("该坐标已经被标记\n");
            }
            break;
        case 0:
            break;
        }
    }while(input);
}

GG.

  • 建议写完一个函数,调试一下。如有bug…,断点调试。
  • 有哪些已知,需要哪些数据,如何处理,if,else、while。
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值