C语言实现简易版扫雷

我和我的父亲都是扫雷的狂热粉,小时候我常常因为技术不好而被父亲嘲笑,那么今天我要来做一个简易版扫雷,回头也给他玩一玩。
首先我们要构建好雷盘的样子,我们理所当然想到利用二维数组。那么请注意:因为我们每一次随机生成的雷盘不能展示给用户,所以显示盘与雷盘要分开,那么我们在这里要用到两个二维数组。一个是雷盘,用来记录随机生成雷的布局,另一个是显示盘,初始化全为*,让用户来扫雷。
在这里插入图片描述
具体功能:

  1. 先由电脑随机生成雷的分布。
  2. 玩家通过输入坐标来选择点。
  3. 玩家选择对应点后,对应点将显示周围雷的个数(以该点为中心的一个九宫格)。
  4. 玩家需要根据这个个数,自己推断出有雷的地方,不能输入有雷的对应坐标,只能输入没雷的对应坐标。
  5. 当输入坐标对应点有雷时,炸“死”,游戏结束。当剩下未选中的点的个数等于总共布下的雷的个数时,游戏胜利。

实现功能的函数:
1.菜单函数,必不可少,是展示给用户的第一界面,这个比较简陋,后期可以考虑做一些fashion一点的。

void Menu()
{
	printf("##########################\n");
	printf("#####choose 1 to play#####\n");
	printf("#####choose 0 to exit#####\n");
	printf("Please input your select here:>\n");
}

2.随机生成雷函数,那么对应雷的横竖坐标就是需要随机生成的数。如果大家看过我之前的三子棋就知道,在这里关于随机生成用到了函数GetIndex,算是一个小优化。

void SetMine(char mine_board[][COL], int row, int col)
{
	srand((unsigned long)time(NULL));
	int mine_num = MINES;
	while (mine_num)
	{
		int i_index = GetIndex(1,col-2);//生成1~10的随机数
		int j_index = GetIndex(1,col-2);
		if (mine_board[i_index][j_index] == '0')
		{
			mine_board[i_index][j_index] = '1';
			mine_num--;
		}
	}
}

3.GetIndex函数,这里要注意start和end表示的是生成的随机数的范围。之前我们 如果用rand生成0~10的随机数,就直接rand%10,但是如果是5 ~10呢?所以我们用(end-start+1)得到的是0 ~end的范围,再加一个start,就能到到start ~end的范围。

static int GetIndex(int start, int end)//static修饰 代表该函数只能在本文件内部使用
{
	return rand() % (end - start + 1) + start;
}

4.得到一个点周围雷的数量函数,这里要注意,我写的这个函数的返回值是整型,但得到的mine_board的和是字符型,那么要通过8-'0’来转换一下。

int GetMineNum(char mine_board[][COL], int i, int j)
{
	return mine_board[i-1][j-1]+mine_board[i-1][j]+ mine_board[i-1][j+1]+ \
		mine_board[i][j-1]+ mine_board[i][j+1]+ \
		mine_board[i+1][j-1]+mine_board[i+1][j]+ mine_board[i+1][j+1]-8*'0';//整型
} 

5.显示雷盘函数

void ShowBoard(char show_board[][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("    ");
	for (i = 1; i <= col-2; i++)
	{
		printf("%d   ", i);
	}
	printf("\n");
	for (i = 1; i <= col - 1; i++)
	{
		printf("----");
	}
	printf("\n");
	for (i = 1; i <=row - 2; i++)
	{
		printf("%-2d|", i);
		for (j = 1; j <=col - 2; j++)
		{
			printf(" %c |", show_board[i][j]);
		}
		printf("\n");
		int k = 1;
		for (k = 1; k <= col - 1; k++)
		{
			printf("----");
		}
		printf("\n");
	}
}

6.进行游戏函数,以total作为一个衡量标准。输入坐标,判断是否为雷的位置,是则游戏结束,不是则总的方块数减1,继续输入坐标。

void PlayGame(char show_board[][COL], char mine_board[][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	int total = (ROW - 2)*(COL - 2);
	while (1)
	{
		ShowBoard(show_board, row, col);
		printf("Please enter your pos<x,y>");
		scanf("%d%d", &i, &j);
		if (i >= 1 && i < row - 2 && j >= 1 && j < col - 2)
		{
			if (mine_board[i][j] == '0')
			{
				int num = GetMineNum(mine_board, i, j);
				show_board[i][j] = num + '0';
				total--;
			}
			else
			{
				ShowBoard(mine_board, row, col);
				printf("Game over!you lose!:(\n");
				break;
			}
		}
		else
		{
			printf("Error!Try again!\n");
			continue;
		}
		if (total == MINES)
		{
			printf("You win:)!\n");
			break;
		}
	}
}

7.Game函数,初始化两个盘,主要调用了前面的函数,对函数的一个整合,来贯穿一下整个流程。

void Game()
{
	char show_board[ROW][COL];
	char mine_board[ROW][COL];
	memset(show_board, '*', sizeof(show_board));
	memset(mine_board, '0', sizeof(mine_board));

	SetMine(mine_board, ROW, COL);
	PlayGame(show_board, mine_board, ROW, COL);
}

这里还是采用了文件的形式,分为函数声明,函数定义,主函数。
函数声明 Mine.h

#ifndef _MINE_H_
#define _MINE_H_

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

#define ROW 12
#define COL 12
#define MINES 20
void Menu();
void Game();
int GetIndex(int start, int end);
void SetMine(char mine_board[][COL], int row, int col);
int GetMineNum(char mine_board[][COL], int i, int j);
void ShowBoard(char show_board[][COL], int row, int col);
void PlayGame(char show_board[][COL], char mine_board[][COL], int row, int col);
#endif 

函数定义 Mine.c

#include"Mine.h"

void Menu()
{
	printf("##########################\n");
	printf("#####choose 1 to play#####\n");
	printf("#####choose 0 to exit#####\n");
	printf("Please input your select here:>\n");
}

static int GetIndex(int start, int end)//static修饰 代表该函数只能在本文件内部使用
{
	return rand() % (end - start + 1) + start;
}

//随机生成雷
void SetMine(char mine_board[][COL], int row, int col)
{
	srand((unsigned long)time(NULL));
	int mine_num = MINES;
	while (mine_num)
	{
		int i_index = GetIndex(1,col-2);
		int j_index = GetIndex(1,col-2);
		if (mine_board[i_index][j_index] == '0')
		{
			mine_board[i_index][j_index] = '1';
			mine_num--;
		}
	}
}
//得到一个点周围雷的数量
int GetMineNum(char mine_board[][COL], int i, int j)
{
	return mine_board[i-1][j-1]+mine_board[i-1][j]+ mine_board[i-1][j+1]+ \
		mine_board[i][j-1]+ mine_board[i][j+1]+ \
		mine_board[i+1][j-1]+mine_board[i+1][j]+ mine_board[i+1][j+1]-8*'0';//整型
} 
//显示雷盘
void ShowBoard(char show_board[][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("    ");
	for (i = 1; i <= col-2; i++)
	{
		printf("%d   ", i);
	}
	printf("\n");
	for (i = 1; i <= col - 1; i++)
	{
		printf("----");
	}
	printf("\n");
	for (i = 1; i <=row - 2; i++)
	{
		printf("%-2d|", i);
		for (j = 1; j <=col - 2; j++)
		{
			printf(" %c |", show_board[i][j]);
		}
		printf("\n");
		int k = 1;
		for (k = 1; k <= col - 1; k++)
		{
			printf("----");
		}
		printf("\n");
	}
}
void PlayGame(char show_board[][COL], char mine_board[][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	int total = (ROW - 2)*(COL - 2);
	while (1)
	{
		ShowBoard(show_board, row, col);
		printf("Please enter your pos<x,y>");
		scanf("%d%d", &i, &j);
		if (i >= 1 && i < row - 2 && j >= 1 && j < col - 2)
		{
			if (mine_board[i][j] == '0')
			{
				int num = GetMineNum(mine_board, i, j);
				show_board[i][j] = num + '0';
				total--;
			}
			else
			{
				ShowBoard(mine_board, row, col);
				printf("Game over!you lose!:(\n");
				break;
			}
		}
		else
		{
			printf("Error!Try again!\n");
			continue;
		}
		if (total == MINES)
		{
			printf("You win:)!\n");
			break;
		}
	}
}
void Game()
{
	char show_board[ROW][COL];
	char mine_board[ROW][COL];
	memset(show_board, '*', sizeof(show_board));
	memset(mine_board, '0', sizeof(mine_board));

	SetMine(mine_board, ROW, COL);
	PlayGame(show_board, mine_board, ROW, COL);
}

主函数 main.c

#include"Mine.h"

int main()
{
	int select = 0;
	int quit = 0;
	while (!quit)
	{
		Menu();
		scanf("%d", &select);
		switch (select)
		{
		case 1:
			Game();
			break;
		case 0:
			printf("OK,byebye!\n");
			quit = 1;
			break;
		default:
			printf("Error!input again!\n");
			break;
		}
	}
	system("pause");
	return 0;
}

运行展示界面:
在这里插入图片描述
在这里插入图片描述
这是简易版的扫雷,过过干瘾还是可以,但和电脑里的扫雷还是有一定的差别,后期还要做一些优化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值