[c]扫雷

    写过的一个简单版的扫雷, 逻辑也比较简单, 里面注释写的比较清楚, 直接上代码.

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

#define ROW 9
#define COL 9
#define M_count 10

int menu()    //搞一个菜单
{
	printf("***********************************\n");
	printf("************1.开始游戏*************\n");
	printf("************0.退出游戏*************\n");
	printf("***********************************\n");
	int choice = 0;
	printf("请输入你的选择:");
	scanf("%d", &choice);
	return choice;
}
void init(char m_map[ROW + 2][COL + 2], char s_map[ROW + 2][COL + 2]) //初始化
{
	for (int row = 0; row < ROW + 2; ++row)
	{
		for (int col = 0; col < COL + 2; ++col)
		{
			s_map[row][col] = '*';
		}
	}
	for (int row = 0; row < ROW + 2; ++row)
	{
		for (int col = 0; col < COL + 2; ++col)
		{
			m_map[row][col] = '0';
		}
	}
	//1.s_map  *
	//2.m_map  先初始化为 '0'
	//3.对m_map进行雷阵的布置
	//布雷
	int m_count = M_count;   //设置一个临时变量存储
	while (m_count > 0)
	{
		//进行布置雷, 每布置一个, m_count--;
		int row = rand() % ROW + 1;
		int col = rand() % COL + 1;
		if (m_map[row][col] == '1')
		{
			continue;
		}
		//当前位置可以设置;
		m_map[row][col] = '1';
		--m_count;
	}
}
void display(char map[ROW + 2][COL + 2])   //打印
{
	//打印四个空格
	printf(" ");  //左上角
	//列坐标([1,COL])
	printf("|");
	for (int i = 1; i <= COL; ++i)
	{
		printf("%d ", i);
	}
	//上边框
	printf("\n");
	for (int i = 0; i < COL; ++i)
	{
		if (i == 0)
		{
			printf("-|");
		}
		printf("--");
	}
	printf("\n");

	//打印每一行(带行号)
	for (int row = 1; row <= ROW; ++row)
	{
		printf("%d|", row);
		for (int col = 1; col <= COL; ++col)
		{
			printf("%c ", map[row][col]);
		}
		printf("\n");
	}
}

int leishu(char m_map[ROW + 2][COL + 2], int row, int col)//计算当前位置的周围八个中有几个雷
{
	//每次翻开一个,不是雷,就更新 s_map
	//当前位置替换成一个数字(代表8个中有几个雷)
	int m_count =
		(m_map[row - 1][col - 1] - '0')
		+ (m_map[row - 1][col] - '0')
		+ (m_map[row - 1][col + 1] - '0')
		+ (m_map[row][col - 1] - '0')
		+ (m_map[row][col + 1] - '0')
		+ (m_map[row + 1][col - 1] - '0')
		+ (m_map[row + 1][col] - '0')
		+ (m_map[row + 1][col + 1] - '0');
	return m_count;
}
//row => [1,ROW]
void updateshowmap(char m_map[ROW + 2][COL + 2],
	char s_map[ROW + 2][COL + 2], int row, int col)   //更新雷阵
{
	int ret = 0;
	ret = leishu(m_map, row, col);
	if (ret == 0)
	{
		s_map[row][col] = '0';
		if (row - 1 > 0 && col > 0 && s_map[row - 1][col] == '*')
		{
			updateshowmap(m_map, s_map, row - 1, col);
		}
		if (row - 1 > 0 && col + 1 > 0 && s_map[row - 1][col + 1] == '*')
		{
			updateshowmap(m_map, s_map, row - 1, col + 1);
		}
		if (row > 0 && col + 1 > 0 && s_map[row][col + 1] == '*')
		{
			updateshowmap(m_map, s_map, row, col + 1);
		}
		if (row + 1 > 0 && col + 1 > 0 && s_map[row + 1][col + 1] == '*')
		{
			updateshowmap(m_map, s_map, row + 1, col + 1);
		}
		if (row + 1 > 0 && col > 0 && s_map[row + 1][col] == '*')
		{
			updateshowmap(m_map, s_map, row + 1, col);
		}
		if (row + 1 > 0 && col - 1 > 0 && s_map[row + 1][col - 1] == '*')
		{
			updateshowmap(m_map, s_map, row + 1, col - 1);
		}
		if (row > 0 && col - 1 > 0 && s_map[row][col - 1] == '*')
		{
			updateshowmap(m_map, s_map, row, col - 1);
		}
		if (row - 1 > 0 && col - 1 > 0 && s_map[row - 1][col - 1] == '*')
		{
			updateshowmap(m_map, s_map, row - 1, col - 1);
		}

	}
	else
	{
		//由于 s_map 中都是字符 要转换
		s_map[row][col] = ret + '0';
	}
}
int finish(char s_map[ROW + 2][COL + 2])  //判断是否结束
{
	int count = 0;
	for (int row = 1; row <= ROW; ++row)
	{
		for (int col = 1; col <= COL; ++col)
		{
			if (s_map[row][col] == '*')
			{
				++count;
			}
		}
	}
	return count;
}
void game()   //开始一局游戏
{
	//1.设定一个二维数组,作为表示地雷的地图,0表示没有雷,1表示有雷
	//  设定一个二维数组,作为给玩家看的地图,每个位置是否被掀开,如果翻开
	//此处加了一圈边框,后面有解释
	char m_map[ROW + 2][COL + 2];
	char s_map[ROW + 2][COL + 2];
	//2.对地图进行初始化(包含布置地雷的过程)
	init(m_map, s_map);
	int open_count = 0;
	//先打印下初始地图
	display(s_map);
	while (1)
	{
		//3.提示玩家输入一组坐标,并且对玩家输入进行合法性检查(注意有效范围) (continue)
		printf("输入坐标, 逗号隔开(row,col):");
		int row = 0;
		int col = 0;
		scanf("%d,%d", &row, &col);
		//有效范围(判断是否在范围之中)
		if (row < 1 || row > ROW || col < 1 || col > COL)
		{
			printf("你的坐标违法:\n");
			continue;
		}
		//4.判定玩家翻开的位置是否是地雷,如果是,游戏结束,玩家失败;
		if (m_map[row][col] == '1')
		{
			printf("\n您踩雷了,游戏结束,地雷分布如下 : !\n");
			//告诉玩家哪些位置是雷;
			display(m_map);
			break;
		}
		if (s_map[row][col] != '*')
		{
			printf("此位置已经揭开!\n");
			continue;
		}
		//5.把这个位置翻开,并且计算当前位置周围的8个格子中包含几个雷
		updateshowmap(m_map, s_map, row, col);
		display(s_map);
		//6.如果当前位置已经把最后一个不是雷的位置翻开了,游戏结束,玩家胜利
		if (finish(s_map) == M_count)
		{
			printf("^_^恭喜您,扫雷成功^_^\n");
			display(m_map);
			break;
		}
		// 回到3,循环执行
	}
}

int main()
{
	srand((unsigned int)time(0));
	while (1)
	{
		int choice = menu();
		if (choice == 1)
		{
			game();
		}
		else if (choice == 0)
		{
			printf("byebye\n");
			break;
		}
		else
		{
			printf("输入错误!\n");
			continue;
		}
	}
	system("pause");
	return 0;
}

    运行结果如图 :

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值