【c语言】 扫雷游戏

目录

一、打印菜单

二、创建棋盘

1.初始化数组

2.打印棋盘

三、开始排雷

1.设置雷

2.判断坐标

2.1展开排查

3.设置标记


一、打印菜单

void menu()
{
	printf("******************************\n");
	printf("***********  1.play  *********\n");
	printf("***********  0.exlt  *********\n");
	printf("******************************\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();
        scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			prinft("请重新选择\n");
		}
	} while (input);
	return 0;
}

二、创建棋盘

可以创建两个数组一个用来展示(展示数组),一个用来放雷和排查(雷数组)。两个数组的大小要相同,在排查雷数组坐标后可以在展示数组对应坐标处显示出来。需要创建4个常宏量,两个用来初始化,两个用来打印和排查,初始化的数组要比打印的棋盘大一圈,这个在后面会说用法。

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2

1.初始化数组

雷数组用‘0’表示没雷,‘1’表示雷(使用字符方便一起初始化和打印),初始化时先全部初始化为‘0’,毕竟扫雷游戏没有刚开始就被炸死。

展示数组则可以用‘*’表示没被排查过,先初始化为‘*’。

​​void game()
{
	char Show[ROWS][COLS] = { 0 };//展示数组
	char Fixup[ROWS][COLS] = { 0 };//雷数组
	Init(Show, '*');//初始化
	Init(Fixup, '0');
}
void Init(char board[ROWS][COLS], char a)//初始化数组
{
	int i = 0;
	int j = 0;
	for(i=0;i<ROWS;i++)
	{
		for (j = 0; j < COLS; j++)
			board[i][j] = a;
	}
}

2.打印棋盘

先按三子棋的棋盘打印

void Print(char board[ROWS][COLS])//打印棋盘
{
	int i = 0;
	int j = 0;
	for (i = 1; i <= ROW; i++)
	{
		for (j = 1; j <= COL; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < COL)
				printf("|");
		}
		printf("\n");
		if (i < ROW)
		{
			for (j = 1; j <= COL; j++)
			{
				printf("---");
				if (j < COL)
					printf("|");
			}
		}
		printf("\n");
	}
}

不过我们的扫雷是在终端运行的,只能输入坐标去排查,看这个输出的结果显然是不方便排查。可以将它的行列打印出来方便找到排查的坐标。

void Print(char board[ROWS][COLS])//打印棋盘
{
	int i = 0;
	int j = 0;
	for (i = 0; i <= ROW; i++)//打印列坐标
	{
		printf("%-2d  ", i);//每列坐标都相隔3个字符
	}
	printf("\n\n");
	for (i = 1; i <= ROW; i++)
	{
		printf("%-2d ", i);//打印行坐标
		for (j = 1; j <= COL; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < COL)
				printf("|");
		}
		printf("\n   ");
		if (i < ROW)
		{
			for (j = 1; j <= COL; j++)
			{
				printf("---");
				if (j < COL)
					printf("|");
			}
		}
		printf("\n");
	}
}

打印行列时,打印的数字多一位就需要少打印一个空格,不过一般棋盘的行列不会过百,就不需要考虑这种情况。

三、开始排雷

1.设置雷

打印棋盘使用的数组范围是1-ROW和1-COL,我们在排查时输入的坐标就刚好对应了数组的位置。在输入一次坐标后在设置雷,并且那个坐标不能放雷,防止刚开始就被炸死。雷可以定义一个常宏量来决定数量。

void Settd(char Fixup[ROWS][COLS],int count,int x,int y)//设置雷
{
	while(count)
	{
		int i = rand() % ROW+1;
		int j = rand() % COL+1;
		if (Fixup[i][j] == '0' && (x!=i || y!=j))//生成坐标位置不是雷并且第一次输入不可以放雷
		{
			Fixup[i][j] = '1';
			count--;
		}
	}
}
void Troub(char Show[ROWS][COLS], char Fixup[ROWS][COLS])//排雷
{
	int win = 0;//排查了几个位置
    int a = 0;
	while(win<ROW*COL-COUNT)
	{
		printf("请选择坐标:");
        int x=-1,y=-1;//输入一个数y的值会是上一个输入的值
		scanf("%d.%d", &x, &y);//中间间隔.方便输入
		if(a==0)
        {
			Settd(Fixup,COUNT,x,y);
            a++;
        }
	}
    printf("恭喜你扫雷成功\n");
	Print(Fixup);
}

2.判断坐标

坐标得在数组范围内。

while(win<ROW*COL-COUNT)
	{
		printf("请选择坐标:");
		scanf("%d.%d", &x, &y);//中间间隔.方便输入
		if(a==0)
		{
			Settd(Fixup, COUNT, x, y);
			a++;
		}
		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
		{

		}
		else if (x == 0 && y == 0)//标记
		{

		}
		else
			printf("坐标非法,请重新输入\n");
	}
}

在数组范围内就判断是否是雷,如果是提醒“游戏失败”并打印雷棋盘;不是雷则排查它周围雷的个数,如果周围没有雷则会展开去排查周围雷的周围雷的个数,排查的位置周围有雷就不会在展开。

if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
		{
			if (Show[x][y]=='*')
			{
				if (Fixup[x][y] == '0')
				{
					Inia(Show, Fixup,&win,x,y);//展开排查
					Print(Show);
				}
				else
				{
					printf("雷炸了,游戏失败\n");
					Print(Fixup);
					return;
				}
			}
			else
			{
				printf("坐标已被排查\n");
				continue;
			}
		}
2.1展开排查

展开排查的坐标可以确定不是雷,先排查它周围雷个数,将这个个数赋值到对应的展示数组内。如果是0则赋值空格,这样打印出来的效果会好些。

void Inia(char Show[ROWS][COLS], char Fixup[ROWS][COLS], int* w,int x,int y)
{
	int a=Around(Fixup,x,y);//排查周围雷的个数
	if (a == 0)
	{
		Show[x][y] = ' ';
	}
	else
		Show[x][y] = a+'0';
}
int Around(char Fixup[ROWS][COLS],int x,int y)
{
	return (Fixup[x][y - 1] +
		Fixup[x + 1][y - 1] +
		Fixup[x + 1][y] +
		Fixup[x + 1][y + 1] +
		Fixup[x][y + 1] +
		Fixup[x - 1][y + 1] +
		Fixup[x - 1][y] +
		Fixup[x - 1][y - 1]) - 8 * '0';
}

这里排查的是它周围8个坐标,如果排查的坐标是在边缘的位置(例:1.1  1.2),创建数组没有扩大就会越界,这也是创建数组范围大的原因。

排查的坐标周围没有雷,就展开排查周围的坐标。

void Inia(char Show[ROWS][COLS], char Fixup[ROWS][COLS], int* w,int x,int y)
{
	int a=Around(Fixup,x,y);//排查周围雷的个数
	(*w)++;
	if (a == 0)
	{
		Show[x][y] = ' ';
		int i = 0;
		int j = 0;
		for (i = -1; i <= 1; i++)
		{
			for (j = -1; j <= 1; j++)
			{
				if (Show[x + i][y + j] == '*' && (x + i) >= 1 && (x + i) <= ROW && (y + j) >= 1 && (y + j) <= COL)
					//只展开没有排查的和在棋盘范围内的
					Inia(Show, Fixup, w, (x+i), (y+j));
			}
		}
	}
	else
		Show[x][y] = a+'0';
}

3.设置标记

输入0.0开始和退出标记

else if (x == 0 && y == 0)//开始标记
		{
			while(1)
			{
				printf("标记坐标:");
                x=-1,y=-1;
				scanf("%d.%d", &x, &y);
				if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
				{
					if (Show[x][y] == '*')//标记
					{
						Show[x][y] = '#';
						Print(Show);
					}
					else if (Show[x][y] == '#')//取消标记
					{
						Show[x][y] = '*';
						Print(Show);
					}
					else
						printf("坐标已被排查,请重新标记\n");
				}
				else if (x == 0 && y == 0)
				{
					printf("退出标记\n");
					break;
				}
				else
					printf("坐标非法,请重新标记\n");
			}
		}

游戏代码

game.h

#pragma once
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define COUNT 8
void Init(char board[ROW][COL], char a);
void Print(char board[ROW][COL]);
void Troub(char Show[ROW][COL], char Fixup[ROW][COL]);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"game.h"
void game()
{
	char Show[ROWS][COLS] = { 0 };//展示数组
	char Fixup[ROWS][COLS] = { 0 };//雷数组
	Init(Show, '*');//初始化
	Init(Fixup, '0');
	Print(Show);//打印棋盘
	Troub(Show, Fixup);
}
void menu()
{
	printf("******************************\n");
	printf("***********  1.play  *********\n");
	printf("***********  0.exlt  *********\n");
	printf("******************************\n");
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("请重新选择\n");
		}
	} while (input);
	return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"game.h"
void Init(char board[ROWS][COLS], char a)//初始化数组
{
	int i = 0;
	int j = 0;
	for(i=0;i<ROWS;i++)
	{
		for (j = 0; j < COLS; j++)
			board[i][j] = a;
	}
}


void Print(char board[ROWS][COLS])//打印棋盘
{
	int i = 0;
	int j = 0;
	for (i = 0; i <= ROW; i++)//打印列坐标
	{
		printf("%-2d  ", i);//每列坐标都相隔3个字符
	}
	printf("\n\n");
	for (i = 1; i <= ROW; i++)
	{
		printf("%-2d ", i);//打印行坐标
		for (j = 1; j <= COL; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < COL)
				printf("|");
		}
		printf("\n   ");
		if (i < ROW)
		{
			for (j = 1; j <= COL; j++)
			{
				printf("---");
				if (j < COL)
					printf("|");
			}
		}
		printf("\n");
	}
}

void Settd(char Fixup[ROWS][COLS],int count,int x,int y)//设置雷
{
	while(count)
	{
		int i = rand() % ROW+1;
		int j = rand() % COL+1;
		if (Fixup[i][j] == '0' && (x!=i || y!=j))//生成坐标位置不是雷并且第一次输入不可以放雷
		{
			Fixup[i][j] = '1';
			count--;
		}
	}
}
int Around(char Fixup[ROWS][COLS],int x,int y)
{
	return (Fixup[x][y - 1] +
		Fixup[x + 1][y - 1] +
		Fixup[x + 1][y] +
		Fixup[x + 1][y + 1] +
		Fixup[x][y + 1] +
		Fixup[x - 1][y + 1] +
		Fixup[x - 1][y] +
		Fixup[x - 1][y - 1]) - 8 * '0';
}
void Inia(char Show[ROWS][COLS], char Fixup[ROWS][COLS], int* w,int x,int y)
{
	int a=Around(Fixup,x,y);//排查周围雷的个数
	(*w)++;
	if (a == 0)
	{
		Show[x][y] = ' ';
		int i = 0;
		int j = 0;
		for (i = -1; i <= 1; i++)
		{
			for (j = -1; j <= 1; j++)
			{
				if (Show[x + i][y + j] == '*' && (x + i) >= 1 && (x + i) <= ROW && (y + j) >= 1 && (y + j) <= COL)
					//只展开没有排查的和在棋盘范围内的
					Inia(Show, Fixup, w, (x+i), (y+j));
			}
		}
	}
	else
		Show[x][y] = a+'0';
}
void Troub(char Show[ROWS][COLS], char Fixup[ROWS][COLS])//排雷
{
	int win = 0;//排查了几个位置
	int a = 0;
	while(win<ROW*COL-COUNT)
	{
		printf("请选择坐标:");
		int x = -1, y = -1;//输入一个数y的值会是上一个输入的值
		scanf("%d.%d", &x, &y);//中间间隔.方便输入
		if(a==0)
		{
			Settd(Fixup, COUNT, x, y);
			a++;
		}
		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
		{
			if (Show[x][y]=='*')
			{
				if (Fixup[x][y] == '0')
				{
					Inia(Show, Fixup,&win,x,y);//展开排查
					Print(Show);
				}
				else
				{
					printf("雷炸了,游戏失败\n");
					Print(Fixup);
					return;
				}
			}
			else
			{
				printf("坐标已被排查\n");
				continue;
			}
		}
		else if (x == 0 && y == 0)//开始标记
		{
			while(1)
			{
				printf("标记坐标:");
				x = -1, y = -1;
				scanf("%d.%d", &x, &y);
				if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
				{
					if (Show[x][y] == '*')//标记
					{
						Show[x][y] = '#';
						Print(Show);
					}
					else if (Show[x][y] == '#')//取消标记
					{
						Show[x][y] = '*';
						Print(Show);
					}
					else
						printf("坐标已被排查,请重新标记\n");
				}
				else if (x == 0 && y == 0)
				{
					printf("退出标记\n");
					break;
				}
				else
					printf("坐标非法,请重新标记\n");
			}
		}
		else
			printf("坐标非法,请重新输入\n");
	}
	printf("恭喜你扫雷成功\n");
	Print(Fixup);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值