天天看点

C语言实现的扫雷游戏

扫雷规则:

自定义大小的方块矩阵中随机布置一定量的雷。由玩家逐个翻开方块,以找出所有地雷为最终游戏目标。如果玩家翻开的方块有地雷,则游戏结束;如果翻开的方块里没雷,则显示以这个方块为中心的九宫格里一共有多少雷。

思路:

假如我们要供用户玩的棋盘大小是10x10,为了显示边界栏上的雷数,我们要设置一个12x12大小的棋盘,这样在统计周围雷的数目时方法也是一样的(具体见代码中 GetMine()子函数)。另外,我们不光要设置一个展示给用户的棋盘,还要设置一个大小一样的用户看不见的棋盘用来种随机数种子(设置雷的分布),注意种的随机数种子是在棋盘二的内部10x10里分布的,边界处均设置成无雷。字符‘1’代表有雷,字符‘0’代表无雷。

难点一:

如何统计雷的数目?这里我们均使用的是char型的,假设被翻开的放块周围有6个‘1’,2个‘0’,那么我们写返回值时可以写成6x‘1’+2x‘0’-7‘0’,这样返回的就是字符型‘6’而非数字型6。6x(‘0’+1)+2x‘0’-7x‘0’=6x’0’+6x1+2x’0’-7x‘0’=‘0’+6=52,这样返回的char就是‘6’了。

难点二:

为什么都要用char型而不用int型,是因为初始化的时候Board[ROW][COL]和Mine[ROW][COL]使用的都是一个接口,为了方便初始化所以就都用char型了,再加上int占4个字节,而char只占一个字节。

难点三:

棋盘的展示,详见子函数ShowBoard()。

代码展示:

头文件mine.h

#ifndef _MINE_H
#define _MINE_H

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

#pragma warning (disable:4996)

#define ROW 12       //行数
#define COL 12       //列数
#define MINE 20      //雷数

void Game();
void InitBoard(char Board[][COL], int row, int col, char elem); 
void ShowBoard(char Board[][COL], int row, int col);
void SetMine(char Mine[][COL], int row, int col);
char GetMine(char Mine[][COL], int x, int y);



#endif
           

主文件部分main.c

#include "mine.h"

void Menu()
{
	printf("####################################\n");
	printf("#########欢迎来到扫雷小游戏#########\n");
	printf("#####1.Start             2.Quit#####\n");
	printf("####################################\n");
	printf("Please enter your select=>");
}

int main()
{
	int quit = 0;
	int select = 0;
	while (!quit)
	{
		Menu();
		scanf("%d", &select);
		switch (select)
		{
		case 1:
			printf("游戏开始,快来排雷吧!\n");
			Game();
			break;
		case 2:
			quit = 1;
			printf("再见!欢迎下次来玩...\n");
			break;
		default:
			printf("Enter Error!Please enter again!\n");
			break;
		}
	}
	system("pause");
	return 0;
}
           

mine.c

#include"mine.h"

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

	}

}
void SetMine(char Mine[][COL], int row, int col)
{
	int n = MINE;
	while (n){
		int x = rand() % (ROW - 2) + 1;
		int y = rand() % (COL - 2) + 1;
		if (Mine[x][y] == '1'){
			continue;
		}
		Mine[x][y] = '1';
		n--;
	}
}
char GetMine(char Mine[][COL], int x, int y)
{
	return Mine[x - 1][y + 1] + Mine[x - 1][y] + Mine[x - 1][y - 1] + \
		Mine[x][y + 1] + Mine[x][y - 1] + \
		Mine[x + 1][y + 1] + Mine[x + 1][y] + Mine[x + 1][y - 1] - 7 * '0';

}
void Game()
{
	srand((unsigned long)time(NULL));   //种随机数种子种子

	char Board[ROW][COL];
	char Mine[ROW][COL];

	InitBoard(Board, ROW, COL,'*');     //初始化两个棋盘
	InitBoard(Mine, ROW, COL,'0');


	SetMine(Mine, ROW, COL);            //设置雷的分布

	int count = (ROW-2)*(COL-2) - MINE;//除了雷之外方块的个数
	while (count>0)          
	{
		system("cls");      //清屏
		int x = 0;
		int y = 0;
		ShowBoard(Board, ROW, COL);         //向用户展示棋盘
		printf("请输入你要扫的坐标:\n");
		scanf("%d %d", &x, &y);
		if (x<1 || x>10 || y<1 || y>10){
			printf("你输入的坐标有误,请重新输入!\n");
			Sleep(1000);            
			continue;
		}
		else if (Board[x][y] != '*'){
			printf("此坐标已被重复输入,请重新输入!\n");
			Sleep(1000);
			continue;
		}
		else if(Mine[x][y] == '0'){
			char num = GetMine(Mine, x, y);//获得周围雷的个数
			Board[x][y] = num;
			count--;
		}
		else {
			printf("你输入的[%d][%d]地方有雷!\n",x,y);
			Sleep(1000);
			break;
		}
	}
	char *result = NULL;
	if (count > 0){     //代表是因为扫到雷了跳出了while循环而不是因为全部扫完了count减到0了
		result = "## 啊哦!你被炸死了!o( ╥ ﹏ ╥ )o ##\n";
		Sleep(1000);
		printf("\n");
	}
	else{
		result = "## 扫雷结束!恭喜!你赢啦!(*^▽^*) ##\n";
		Sleep(1000);
	}
	printf("####################################\n");
	printf("%s", result);
	printf("####################################\n");
	ShowBoard(Mine, ROW, COL);
}
           

继续阅读