c语言实现简易扫雷游戏

扫雷游戏很多人都玩过吧,今天就为大家介绍我用c语言制作的简单扫雷程序。
这个游戏的主要功能就是Game()函数的实现,用一个类型为char 的show_map二维数组进行标记一定数量的地雷,不打印给玩家和另一个同类型的名为mine_map的二维数组,用于记录坐标周围的地雷数。玩游戏的功能都是围绕这两个函数操作开展的。
Game()函数思路:

  1. 首先对两个数组定义并初始化,
  2. 然后再植入地雷,
  3. 再输入坐标并判断该坐标下是否触雷,若触雷, 则直接游戏结束。否则继续
  4. 统计该坐标周围的地雷数,并将该坐标元素改为该坐标周围的地雷数,
  5. 打印所有格子(翻开的坐标,打印该坐标周围的地雷数)
  6. 当排除所有地雷时,并且未触雷,游戏成功!
    接下来看一下代码:
//game.h
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MAX_ROW 9
#define MAX_COL 9
#define MAX_COUNT 10
int Menu();//打印菜单并返回选择函数
void Init(char show_map[][MAX_COL], char mine_map[][MAX_COL]);//初始化数组,将show_map全部初始化为*,mine_map全部初始化为0
void ProLand(char mine_map[][MAX_COL],int r ,int c);//初始化地雷函数,在mine_map[][]上随机产生MAX_COUNT个地雷,并将产生地雷的地方修改为1
void Print(char show_map[][MAX_COL]);//打印函数,将传入的数组按格式打印出来
int MineNum(const char mine_map[][MAX_COL], int row, int col);//返回mine_map[row][col]周围的地雷数
int LeapMine(char show_map[][MAX_COL]);//返回未排掉的格子数(包括未排出的地雷)
void Game();//游戏函数
void PrintOver(char mine_map[][MAX_COL]);//踩雷后打印所有雷的位置
//main.c
#include"game.h"
int Menu()
{
	printf("=================================================\n");
	printf("************         1.开始游戏       ***********\n");
	printf("************         0.结束游戏       ***********\n");
	printf("=================================================\n");
	printf("请输入你的选择:");
	int choice = 0;
	scanf("%d", &choice);
	return choice;
}
void Init(char show_map[][MAX_COL], char mine_map[][MAX_COL])
{
	int row = 0;
	int col = 0;
	for (row = 0; row < MAX_ROW; ++row)
	{
		for (col = 0; col < MAX_COL; ++col)
		{
			show_map[row][col] = '*';//初始化show_map[][],即翻开的结果
			mine_map[row][col] = '0';//初始化mine_map[][],初始化地雷
		}
	}
}
void ProLand(char mine_map[][MAX_COL],int r,int c)//在mine_map[][]上随机产生MAX_COUNT个地雷,并将产生地雷的地方修改为1
{
	int count = MAX_COUNT;
	while (count)
	{
		int row = rand() % MAX_ROW;
		int col = rand() % MAX_COL;
		if ((mine_map[row][col] == '0')//初始化雷的分布,但不能在第一次输入的坐标下出现雷
			&& ((row<r-1)
				|| (row>r+1)
				|| (col<c - 1)
				|| (col>c + 1))
			)
		{
			mine_map[row][col] = '1';
			--count;
		}
	}
}
void Print(char show_map[][MAX_COL])//打印
{
	int row = 0;
	int col = 0;
	printf(" |");
	for (int i = 0; i < MAX_COL; ++i)
	{
		printf("%d ", i);
	}
	printf("\n----------------------");
	for (row = 0; row < MAX_ROW; ++row)
	{
		printf("\n%d|", row);
		for (col = 0; col < MAX_COL; ++col)
		{
			printf("%c ", show_map[row][col]);
		}
	}
	printf("\n");
}
void PrintOver(char mine_map[][MAX_COL])
{
	int i, j;
	printf("  |");
	for (i = 0; i < MAX_COL; ++i)
	{
		printf(" %d ", i);
	}
	printf("\n------------------------------");
	for (i = 0; i < MAX_ROW; ++i)
	{
		printf("\n%d |", i);
		for (j = 0; j < MAX_COL; ++j)
		{
			if (mine_map[i][j] == '1')
			{
				printf(" !");
			}
			else
			{
				printf(" O ");
			}
		}
		printf("\n");
	}
}
int MineNum(const char mine_map[][MAX_COL], int row, int col)//返回mine_map[row][col]周围的地雷数
{
	int count = 0;
	if ((row - 1 >= 0) && (col - 1 >= 0) && (mine_map[row - 1][col - 1] == '1'))//坐标左上角
	{
		++count;
	}
	if ((row - 1 >= 0) && (mine_map[row - 1][col] == '1'))//坐标正上方
	{
		++count;
	}
	if ((row - 1 >= 0) && (col + 1 <= MAX_COL) && (mine_map[row - 1][col + 1] == '1'))//坐标右上方
	{
		++count;
	}
	if ((col - 1 >= 0) && (mine_map[row][col - 1] == '1'))//坐标左边
	{
		++count;
	}
	if ((col + 1 <= MAX_COL) && (mine_map[row][col + 1] == '1'))//坐标右边
	{
		++count;
	}
	if ((row + 1<=MAX_ROW) && (col - 1 >= 0) && (mine_map[row + 1][col - 1] == '1'))//坐标左下
	{
		++count;
	}
	if ((row + 1 <= MAX_ROW) && (mine_map[row + 1][col] == '1'))//坐标正下
	{
		++count;
	}
	if ((row + 1 <= MAX_ROW) && (col + 1 <= MAX_COL) && (mine_map[row + 1][col + 1] == '1'))//坐标右下
	{
		++count;
	}
	return count;
}
int LeapMine(char show_map[][MAX_COL])//返回未排掉的格子数(包括未排出的地雷)
{
	int count = 0;
	int row, col;
	for (row = 0; row < MAX_ROW; ++row)
	{
		for (col = 0; col < MAX_COL; ++col)
		{
			if (show_map[row][col] == '*')
			{
				++count;
			}
		}
	}
	return count;
}
void Game()
{
	int row, col;
	srand((unsigned)time(NULL));
	char show_map[MAX_ROW][MAX_COL];//翻开后显示地雷数,翻开前全初始化为*
	char mine_map[MAX_ROW][MAX_COL];//产生地雷的地方修改为‘1’.没有地雷的地方全部初始化为'0'
	Init(show_map, mine_map);
	printf("请输入你要翻开的坐标:");
	while (1)
	{
		scanf("%d%d", &row, &col);
		if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL)
		{
			printf("输入的坐标非法,请重新输入:");
			continue;
		}
		else
		{
			break;
		}
	}
	ProLand(mine_map,row,col);
	show_map[row][col] = MineNum(mine_map, row, col) + '0';
	while (1)
	{
		system("cls");
		Print(show_map);
		printf("\n\n");
		//Print(mine_map);//该行代码用于测试
		printf("请输入你要翻开的坐标:");
		while (1)
		{
			scanf("%d%d", &row, &col);
			if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL)
			{
				printf("输入的坐标非法,请重新输入:");
				continue;
			}
			else if (show_map[row][col] != '*')
			{
				printf("您输入的坐标已被翻开,请重新输入:");
				continue;
			}
			else
			{
				break;
			}
		}
		if (mine_map[row][col] == '1')
		{
			printf("踩雷了,game over!\n");
			PrintOver(mine_map);
			break;
		}
		else
		{
			show_map[row][col] = MineNum(mine_map, row, col) + '0';
		}
		if (LeapMine(show_map) == MAX_COUNT)
		{
			printf("恭喜勇士,成功排掉所有地雷!\n");
			break;
		}
	}
}
int main()
{
	while (1)
	{
		int choice = Menu();
		if (choice == 1)
		{
			Game();
		}
		else if (choice == 0)
		{
			printf("goodbye!\n");
			break;
		}
		else
		{
			printf("您输入有误!\n");
		}
	}
	system("pause");
	return 0;
}

这里需要注意的几点:

  • 为了不让玩家在第一次踩雷,ProLand函数是在输入第一次坐标后开始植入地雷的,并且植入的地雷避开了第一次输入坐标周围的格子。
  • PrintOver函数是在玩家触雷后退出游戏前打印地雷的分布,目的是为了接近真实的扫雷游戏
  • MineNum函数实现返回输入坐标周围的地雷个数,返回值为数值,将该数加上‘0’并赋给该坐标上的字符型元素。
  • LeapMine返回未排掉的格子,当剩余的各自等于植入的格子数时,说明除地雷外所有的格子都已被排完。此时结束游戏。
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值