C语言小游戏——扫雷

目录

游戏思路 

游戏展示

代码

文件

mine sweeping.h

 mine sweeping.c

初始化

放雷

打印页面

查看坐标附件雷的个数

排雷

text.c

代码优化

展示

mine sweeping.h

mine sweeping.c

查看周围雷数

消除为0雷区

排雷

text.c

总结:


游戏思路 

创建两个相同的数组,一个数组为玩家展示,一个数组个位置区别放置和不放置雷,方便统计玩家所选位置周围雷的个数,返回给玩家显示数组中。

数组的大小比实际展示的大两个长度,在不展示的区域放置非雷标志,在统计所选位置周围雷的个数时,可直接确定此位置无雷。

C语言小游戏——扫雷_第1张图片

游戏展示

C语言小游戏——扫雷_第2张图片

代码

文件

  • mine sweeping.h头文件
  • mine sweeping.c函数实现文件
  • text.c主函数调用文件

mine sweeping.h

#pragma once
#include
#include
#include

#define Row 11
#define Line 11

void Initgame(char lag[Row][Line],char lag1);//初始化
int Putgame(char thunder[Row][Line]);//放雷
void Printchgame(char ch[Row][Line]);//打印玩家猜测雷区
void Removegame(char ch[Row][Line], char thunder[Row][Line], int n);//排雷

 mine sweeping.c

初始化

//初始化   ch—展示数组,thunnder—藏雷数组
void Initgame(char lag[Row][Line],char lag1)
{
	for (int i = 0; i < Row; i++)
	{
		for (int j = 0; j < Line; j++)
		{
			lag[i][j] = lag1;
		}
	}
}

放雷

//放雷
int Putgame(char thunder[Row][Line])
{
	int n = 0;
	printf("请输入藏雷的个数:");
	scanf("%d", &n);

	int i = 0;
	while (i < n)
	{
		int a = rand() % 10;
		int b = rand() % 10;
		if (thunder[a][b] == '0' && a != 0 && b != 0)
		{
			thunder[a][b] = '1';
			i++;
		}
	}
    return n;//返回雷的个数,判断雷是否全部排除
}

打印页面

//打印雷区
void Printchgame(char ch[Row][Line])
{
	for (int i = 0; i < Line-1; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i < Row-1; i++)
	{
		printf("%d ", i );
		for (int j = 1; j < Line-1; j++)
		{
			printf("%c ", ch[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

查看坐标附件雷的个数

//查看坐标周围有多少个雷1
//思路1:输入坐标此时一定不是雷,将周围看作一个3*3数组,查看有多少个'1'
int sumth1(char thunder[Row][Line], int a, int b)
{
	int count = 0;
	for (int i=0;i<3;i++)
	{
		for (int j = 0; j < 3; j++)
		{
			if (thunder[a+i][b+j] == '1')
			{
				count++;
			}
		}
	}
	return count;
}

//查看坐标周围有多少个雷2
//思路2:挨个字符相加,相当于把坐标对应的字符Ascll码值相加最终减去'0'倍个相加个数,得到数字'1'的个数
int sumth2(char thunder[Row][Line], int a, int b)
{
	return thunder[a][b] + thunder[a][b + 1] + thunder[a][b + 2] + thunder[a + 1][b] + thunder[a + 1][b + 2] +
		thunder[a + 2][b] + thunder[a + 2][b + 1] + thunder[a + 2][b + 2] - 8 * '0';
}

排雷

//排雷
void Removegame(char ch[Row][Line], char thunder[Row][Line],int n)
{
	int a = 0;
	int b = 0;
	int win = 0;
	int num = (Row-2) * (Line-2) - n;

	while (win < num)
	{
		printf("请输入坐标:");
		scanf("%d %d", &a, &b);

		if (a >= 1 && a <= Row && b >= 1 && b <= Line)
		{
			if (thunder[a][b] == '1')
			{
				printf("扫雷失败!\n");
				Printchgame(thunder);
				return;
			}
			else
			{
				int c = sumth1(thunder, a - 1, b - 1 );//查看周围雷个数
				ch[a][b] = c + '0';
				Printchgame(ch);//打印 ch
				//Printchgame(thunder);
			}
			win++;
		}
		else
		{
			printf("坐标非法!\n");
		}
	}
	printf("游戏成功!\n");
	Printchgame(thunder);//打印 ch
}

text.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "mine sweeping.h"

void menu()
{
	printf("*************************\n");
	printf("       1.开始游戏        \n");
	printf("       0.退出游戏        \n");
	printf("*************************\n");
}

void game()
{
	char ch[Row][Line] = { 0 };//展示数组
	char thunder[Row][Line] = { 0 };//藏雷数组
	
	Initgame(ch, '*');//初始化  玩家
	Initgame(thunder,'0');//初始化  电脑

	int n = Putgame(thunder);//放雷

	Printchgame(ch);//打印 ch
	//Printchgame(thunder);//打印  thunder

	Removegame(ch, thunder,n);//排雷
}

int main()
{
	int flag = 1;
	srand((unsigned)time(NULL));

	while(flag)
	{
		menu();//菜单

		int input = 0;
		printf("请选择:");
		scanf("%d", &input);

		switch (input)
		{
		case 1:
			game();//游戏
			break;
		case 0:
			printf("欢迎下次使用!\n");
			flag = 0;
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}
		system("pause");
		system("cls");
	}

	return 0;
}

代码优化

若所选位置周围雷数为0,则向四周发散,清楚为0的雷区,直到可以连接的雷区清除干净。

展示

C语言小游戏——扫雷_第3张图片

 增加和修改代码如下:

mine sweeping.h

#pragma once
#include
#include
#include

#define Row 11
#define Line 11

void Initgame(char lag[Row][Line],char lag1);//初始化
int Putgame(char thunder[Row][Line]);//放雷
void Printchgame(char ch[Row][Line]);//打印玩家猜测雷区
void Removegame(char thunder[Row][Line], char ch[Row][Line],char flag[Row][Line],int n);//排雷//排雷
void Minihunt(char thunder[Row][Line], char ch[Row][Line], int a, int b);//消除周围为0的位置
void JudgeRemove(char thunder[Row][Line], char ch[Row][Line], int a, int b);//判断四周是否有雷

增加了两组函数,用于排查周围为0的雷区

mine sweeping.c

查看周围雷数

//查看坐标周围有多少个雷1
//思路1:输入坐标此时一定不是雷,将周围看作一个3*3数组,查看有多少个'1'
int sumth1(char thunder[Row][Line], int a, int b)
{
	int count = 0;
	for (int i=-1;i<2;i++)
	{
		for (int j = -1; j < 2; j++)
		{
			if (thunder[a+i][b+j] == '1')
			{
				count++;
			}
		}
	}
	return count;
}

//查看坐标周围有多少个雷2
//思路2:挨个字符相加,相当于把坐标对应的字符Ascll码值相加最终减去'0'倍个相加个数,得到数字'1'的个数
int sumth2(char thunder[Row][Line], int a, int b)
{
	return thunder[a-1][b-1] + thunder[a-1][b] + thunder[a-1][b + 1] + thunder[a][b-1] + thunder[a][b + 1] +
		thunder[a + 1][b-1] + thunder[a + 1][b ] + thunder[a + 1][b + 1] - 8 * '0';
}

对这两个查雷数的函数做了修改,在使用时之间调用即可,不需要再对输入的数字在函数内部进行修改

消除为0雷区

//判断所选位置的周围位置
void JudgeRemove(char thunder[Row][Line],  char ch[Row][Line], char flag[Row][Line], int a, int b)
{
	if (thunder[a][b] != '1')
	{
		int m = sumth2(thunder, a, b);
		
		if (m == 0 && flag[a][b] != '+')
		{
			flag[a][b] = '+';
			ch[a][b] = ' ';
			Minihunt(thunder, ch, flag, a, b);
		}
		if (m != 0 && flag[a][b] != '+')
		{
			flag[a][b] = '+';
			ch[a][b] = m + '0';
		}
	}
	return;
}

//当所选位置为0时,判断周围位置
void Minihunt(char thunder[Row][Line],  char ch[Row][Line], char flag[Row][Line], int a, int b)
{
	if (a < 1 || b>Line-2)
	{
		return;
	}

	if (a - 1 >= 0 && b + 1 <= 10 && b-1>=0 && a+1<=10)
	{
		for (int i = -1; i < 2; i++)
		{
			for (int j = -1; j < 2; j++)
			{
				JudgeRemove(thunder,  ch, flag, a + i, b + j);
			}
		}
	}
	return;
}

首先确定所给位置的正确性,不能超出范围

使用循环,以此探查为0的位置周围各位置的雷数,若非0,停止探索,若为0,使用递归继续探查

另外增加了标志数组flag,若此位置已经探查过则不再探查,防止代码进入死循环。(此方法类似于数据结构中的标志变量)

排雷

//排雷
void Removegame(char thunder[Row][Line], char ch[Row][Line], char flag[Row][Line], int n)
{
	int a = 0;
	int b = 0;
	int win = 0;
	//int num = (Row-2)*(Line-2)-n;

	while (win != n)
	{
		printf("请输入坐标:");
		scanf("%d %d", &a, &b);

		if (a >= 1 && a <= Row && b >= 1 && b <= Line)
		{
			if (thunder[a][b] == '1')
			{
				printf("扫雷失败!\n");
				Printchgame(thunder);
				return;
			}
			else
			{
				int c = sumth1(thunder, a, b );//查看周围雷个数
				
				if (c == 0)//排除周边非雷区
				{
					ch[a][b] = ' ';
					Minihunt(thunder, ch,flag, a, b );
				}
				else
				{
					ch[a][b] = c + '0';
				}
				
				Printchgame(ch);//打印 ch
				//Printchgame(thunder);
			}
			win = 0;
			for (int i = 1; i <= Row - 2; i++)
			{
				for (int j = 1; j <= Line - 2; j++)
				{
					if (ch[i][j] == '*')
					{
						win++;
					}
				}
			}
		}
		else
		{
			printf("坐标非法!\n");
		}
	}
	printf("游戏成功!\n");
	Printchgame(thunder);//打印 ch
}

修改了对win变量的使用,当win值==n值时,雷全部排出,结束游戏

当所选位置雷数为零时,进入Minihunt函数,判断周围各位置雷数,并打印

text.c

void game()
{
	char ch[Row][Line] = { 0 };//展示数组
	char thunder[Row][Line] = { 0 };//藏雷数组
	char flag[Row][Line] = { 0 };//判断此位置是否已经经过判断
	
	Initgame(ch, '*');//初始化  玩家
	Initgame(thunder,'0');//初始化  电脑
	Initgame(flag, '-');// '-'表示没有被判断   标志数组

	int n = Putgame(thunder);//放雷

	Printchgame(ch);//打印 ch
	//Printchgame(thunder);//打印  thunder

	Removegame(thunder,ch,flag,n);//排雷
}

增加了标志数组,判断对应位置是否被探查过

总结:

  • 使用简单C语言循环、判断做出的小游戏,可以尝试增加功能,如标识雷的位置,计时功能等
  • 可以尝试扩大雷区,给出不同的游戏等级
  • 在消除周围雷区的函数中使用了递归的思想

你可能感兴趣的:(小游戏,c语言)