C语言实现扫雷


试玩过程,如遇Bug,请给予反馈。 游戏代码GitHub下载链接

思路整理

设计两个二维数组,一个是mine数组,一个是show数组。
在这里插入图片描述
上面展示mine二维数组,因为涉及到需要统计一个位置四周的雷数目,所以需要用到辅助区域,辅助区域不产生雷,是非雷区域,避免越界访问。在这幅图中,用字符0表示非雷,用字符1表示雷,雷式随机产生的,产生雷的位置式核心雷区部分。
在这里插入图片描述
上图是向玩家展示的show二维数组,当一位玩家输入一个坐标时候,对这个坐标判断,如果是,炸死(第一次不会死),如果不是雷,将show数组该位置四周非雷位置的四周的雷数目暴露给玩家。当所有雷排空,玩家胜利,否则循环排雷。

效果展示

开始界面
在这里插入图片描述
被炸死
在这里插入图片描述
运气比较差,第一次就踩雷,免死金牌
在这里插入图片描述
排雷成功
在这里插入图片描述

源文件

游戏实现部分game.c

#include"game.h"

extern char show[ROW][LIST];//这里用extern引入game.h里的show和mine,而game.h里的show和mine引用test.c中的show和mine
extern char mine[ROW][LIST];//保证三个文件中的show和mine是同一个。


int sum = 0;//统计sum不是雷的位置数

void InitBoard()
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < LIST; j++)
		{
			show[i][j] = '*';
			mine[i][j] = '0';
		}
	}
}

void PrintBoard(char board[ROW][LIST])
{
	int k = ROW;
	for (int i = 0; i <LIST-1; i++)//打印第一行的坐标
		printf(" %d |", i);
	printf("\n");
	for (int i = 0; i <LIST-1; i++)//打印第二行的分割线
		printf("----");
	printf("\n");
	for (int i = 1; i < ROW-1; i++)//打印数组1--9,最外围不打印(下标中含有0和11的)
	{
		printf(" %d |", i);
		for (int j = 1; j < LIST-1; j++)
		{
			printf(" %c |", board[i][j]);
		}
		printf("\n");
		if(k)
		{
			for (int i = 0; i <LIST-1; i++)
				printf("----");
			printf("\n");
			k--;
		}
	}
	printf("\n\n\n");
}


void SetMine()
{
	srand((unsigned int)time(NULL));
	int x, y;
	int count = MINE;
	while (count)
	{
		x = (rand() % (ROW-2)) +1;//ROW==11,ROW-2=9,0---8,1---9
		y = (rand() % (LIST-2))+1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}		
	}
}


int CountMine(int x, int y)
{
	int count = 0;
	int i = x-1, j = y-1;
	for (i =x-1; i < x+2; i++)
	{
		for (j = y-1; j < y+2; j++)
		{
			if (!(i==x&&j==y))
			{
				if (mine[i][j] == '1')
					count++;
			}
		}
	}
	return count;
}
void SetShowMap(int x, int y)
{
	int i = x - 1, j = y - 1;
	for (i = x - 1; i < x + 2; i++)
	{
		for (j = y - 1; j < y + 2; j++)
		{
			if (i >0 && i < ROW-1&&j > 0 && j < LIST-1)
			{
				if (!(i == x&&j == y)&&show[i][j] == '*')//
				{
					if (mine[i][j] == '0')
					{
						sum++;
						show[i][j] = CountMine(i, j)+'0';
						SetShowMap(i, j);
					}
					else
					{
						return;
					}
				}
			}
		}
	}
}
void FirstNoDie(x, y)//第一次免死金牌
{
	int i = 1,j = 1;
	mine[x][y] = '0';
	show[x][y] = CountMine(x, y) + '0';
	while (mine[i][j] != '0')
	{
		if (i < ROW - 1)
			i++;
		else
			j++;
	}
	mine[i][j] = '1';//替死鬼
	PrintBoard(mine);
	PrintBoard(show);
}

void ClearMine()
{
	int x, y;//count用来标记不是雷的位置数
	while (sum!=(ROW-2)*(LIST-2)-MINE)
	{
		printf("请输入你想要排除的雷区坐标:>");
		scanf("%d%d", &x, &y);
		if (x > 0 && x <ROW-1 && y > 0 && y < LIST-1)//输入坐标x,y满足1<=x<=9,输入坐标就对应数组小标
		{
			if (mine[x][y] == '1')//踩到雷
			{
				if (sum == 0)//如果排除不是雷的count数值是0,说明是第一次就踩雷了,
				{
					FirstNoDie(x,y);//免死金牌
				}
				else
				{
					printf("很不幸,你被炸死了\n");
					PrintBoard(mine);
					break;
				}
			}
			else
			{
				//不是雷
				sum++;
				show[x][y] = CountMine(x, y)+'0';
				SetShowMap(x, y);
				PrintBoard(show);
			}
		}
		else
		{
			printf("输入坐标不合法\n");
		}
	}
	if (sum==(ROW-2)*(LIST-2)-MINE)
		printf("恭喜你排雷成功!\n");
}

头文件game.h

#ifndef __GAME_H__
#define __GAME_H__

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


#define ROW 11
#define LIST 11

#define MINE 10

extern char show[ROW][LIST];
extern char mine[ROW][LIST];

void InitBoard();
void PrintBoard(char board[ROW][LIST]);
void SetMine();//生成雷区
void ClearMine();//扫雷

int CountMine(int x, int y);//统计x,y附近的雷
void SetShowMap(int x, int y);//扫除一个非雷区,进行重置show数组

#endif//__GAME_H__

测试代码test.c

#include"game.h"

char show[ROW][LIST] = { 0 };
char mine[ROW][LIST] = { 0 };

void menu()
{
	printf("\n\n\n");
	printf("		*******************************************\n");
	printf("		1、play game			0、exit	 \n");
	printf("		*******************************************\n");
}
void game()
{
	InitBoard();
	//PrintBoard(mine);
	PrintBoard(show);
	SetMine();
	PrintBoard(mine);
	//PrintBoard(show);
	ClearMine();
}
void Test()
{
	int input;
	do
	{
		menu();
		printf("\n\n请输入选择>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("输入错误,请重新选择\n");
			break;
		}
	} while (input);
}
int main()
{
	Test();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值