C语言实现扫雷游戏详解!

1. test.h

2. main.c

main()

Menu()

3. test.c

InitBoard()

SetMine()

ShowBoard()

GetLei()

Game()

又到了写小游戏的时候,这一次我们实现的是扫雷小游戏,当然,由于我的环境的限制,我不能将它写成彩色的。这一次还是运用了多文件的写法,用test.h声明头文件,main.c写主函数里的东西,再用test.c调用函数,话不多说,上图~

#ifndef _TEST_H_
#define _TEST_H_

#include<stdio.h>
#include<windows.h>
#include<stdlib.h>//生成随机数
#include<time.h>
#pragma warning(disable:4996)

#define ROW 12
#define COL 12
#define LEI 20
void InitBoard(char board[][COL],int row ,int col, char elem);
//elem表示想将其初始化成什么样子
void SetMine(char mine[][COL], int row, int col);
void ShowBoard(char board[][COL], int row, int col);
char GetLei(char mine[][COL],int x, int y);
void Game();
#endif

这儿就是头文件的内容,在这个小游戏里我们要定义行数和列数分别为12行12列,之所以用宏定义,是因为如果后期我们需要改变扫雷的行数和列数就可以直接在头文件里改变,这样子就提高了修改的效率;接着我们需要定义雷的个数,在头文件里定义雷,原因跟刚刚也是一样的;接着需要定义函数,Game()的作用就是控制着整个游戏的正确进行,InitBoard()的作用是初始化我们的游戏面板,SetMine()的作用是定义面板里面雷的位置,ShowBoard()的作用是显示面板,GetLei()的作用是获取雷的位置,接着看下一部分吧~

############################
#####欢迎来到扫雷游戏!#####
###########1.play###########
###########2.exit###########
############################
Please enter the number:

这里是游戏开始的界面,看到这个界面有没有跟我一样想玩呢》?跟我一起看看吧!

在这里插入代码片#include"test.h"

static void Menu()//只在本函数内有效
{
	printf("############################\n");
	printf("#####欢迎来到扫雷游戏!#####\n");
	printf("###########1.play###########\n");
	printf("###########2.exit###########\n");
	printf("############################\n");
	printf("Please enter the number:");

}

这里是main()函数内,首先要引用头文件,因为在头文件里声明了,需要在源文件里引用才能有效。static表示Menu这个函数只在本函数内有效,你看到的这块就是游戏初始界面,玩家可以选择1或者2,但是如果有乱输入的玩家,我也有相应的准备,就像下面这样

int main()
{
	int quit = 0;
	do{
		int number = 0;
		Menu();
		scanf("%d", &number);
		switch (number)
		{
		case 1:
			Game();
			printf("再玩一次?");
			break;
		case 2:
			quit = 1;
			printf("欢迎下次来玩儿!");
			break;
		default:
			break;
			printf("输入有误,再给你一次机会!");
		}
	} while (!quit);

	system("pause");
	return 0;
}

先说quit吧,首先定义它等于0,当玩家选择2时,quit=1,while(!=quit),则循环结束;如果输入1或者其他的数,都不能跳出循环,程序再继续给提示信息!那么会给什么提示信息呢?且跟我看,先定义一个数为0,当玩家输入选择的数字时,将玩家的数字赋值给我定义的数,如果输入1,则进入到Game函数(这也是这个程序最重要的部分),当game()函数结束后,还会提示玩家是否再玩,如果输入2,则跳出循环,如果输入其他的数,系统会提示玩家重新输入。至此,我们的main()部分就编写完了,可以由此进入game部分。

#include"test.h"
void InitBoard(char board[][COL], int row, int col, char elem)
//elem表示想将其初始化成什么样子
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = elem;//初始化成*或者O
		}
	}
}

这里就是我们的另一个源文件所展示的内容,所以我们需要再次引用头文件。用InitBoard()来初始化游戏面板,这里运用了简单的for()循环,分别对每行每列进行初始化。

void SetMine(char mine[][COL], int row, int col)
{
	int n = LEI;
	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--;
	}
}

定义完面板以后我们需要做什么呢?当然是布雷啦,这里我们用了电脑自动生成随机数然后取模的方法,但是这儿要注意一个问题,比如我们定义了12行12列,但是我们现实的是10行10列的数据,因为另外两行两列是辅助我们计算的,所以布雷的时候,只能取到10行10列,即对(row-2)和(col-2)取模后再加1,这才是我们需要布雷的真正位置,每布一个雷以后就减少一个,当雷的数减少到0时,所有雷被分布到面板中。

void ShowBoard(char board[][COL], int row, int col)
{
	int i = 1;
	printf("   ");
	for (i=1; 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");
	}
}

将面板初始化,并且布完雷以后最重要的就是让整个面板显示出来了,这里我们用到了ShowBoard()函数,这儿最重要的就是调试,因为要使整个游戏界面看着美观,所以要不断地运行程序,直到自己满意为止,在调的时候,可以将其他无关代码统统注销,整体要小于等于每行每列-2的原因我已经解释过了,这里不再详细叙述。另外,%-2d和%-2c的作用都是输出的内容靠左,因为没有加负号前是整体靠右的。这块代码整体是用for()循环输出的。

char GetLei(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';
}

这一块代码主要是用来查找雷的个数,这儿我们计算了一个坐标周围的八个位置,然后再进行相加,因为他有返回值,并且我们定义了他的返回值是char类型,所以我们就在最后减了一个7*‘0’,由于‘0’+4=‘4’,所以返回值就成了字符型。

void Game()
{
	srand((unsigned long)time(NULL));//种随机数种子
	char board[ROW][COL];
	char mine[ROW][COL];

	InitBoard(board, ROW, COL, '*');//O面板初始化
	InitBoard(mine, ROW, COL, '0');

	SetMine(mine, ROW, COL);//布雷

	int count = (ROW - 2)*(COL - 2) - LEI;
	do{
		system("cls");//清屏
		int x = 0;
		int y = 0;
		ShowBoard(board,ROW,COL);//显示面板
		printf("请输入坐标:");
		scanf("%d %d", &x, &y);
		if (x<1 || x>10 || y<1 || y>10)
		{
			printf("你输入的坐标有误!请重新输入:\n");	
			Sleep(1000); 
			continue;
		}
		if (board[x][y] != '*')
		{
			printf("你输入的坐标已经被扫过请重新输入:\n");
			Sleep(1000);
			continue;
		}
		if (mine[x][y] == '0')
		{
			count--;
			char num = GetLei(mine, x, y);
			board[x][y] = num;
		}
		else
		{
			printf("你踩雷啦!\n");
			break;
		}
	} while (count>0);//不可能只扫一次

	char *result = NULL;
	if (count > 0)
	{
		result="很遗憾,扫雷失败!\n";
	}
	else
	{
		result="恭喜你,扫雷成功!\n";
	}
    printf("####################\n");
	printf("####################\n");
	printf("%s\n", result);
	printf("####################\n");
	printf("####################\n");
	ShowBoard(mine, ROW, COL);
}

如果说上面各函数是整个程序的身体,那Game()函数就是程序的心脏,我们上面的函数都是由Game()函数发散出去的,因为一个程序,如果只有一个代码块,会显得很臃肿,不够美观,这就是函数的好处,美观大方。

所有被调用的函数都在这各Game()函数中定义了。显示面板后,系统会提示玩家输入坐标,输入坐标后有三种情况,分别为坐标有误、或者坐标已经输入过了,或者坐标正确,在这里,我们都给出了相应的后果,前两者都需要重新输入。这里我们还运用了system(“cls”);表示清屏,这样方便玩家看到最新的游戏情况。如果输入的坐标刚好跟系统设置的雷重合,则显示游戏失败,如果一直没有踩到雷,则扫雷成功。

####################
####################
    1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
-------------------------------------------
 1| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
-------------------------------------------
 2| 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
-------------------------------------------
 3| 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
-------------------------------------------
 4| 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 |
-------------------------------------------
 5| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-------------------------------------------
 6| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-------------------------------------------
 7| 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
-------------------------------------------
 8| 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
-------------------------------------------
 9| 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-------------------------------------------
10| 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-------------------------------------------
再玩一次?############################
#####欢迎来到扫雷游戏!#####
###########1.play###########
###########2.exit###########
############################
Please enter the number:

扫雷失败的界面如上。

至此,我们的扫雷游戏就结束了,但是还可以改进的地方有很多,我也会继续努力,学好这些知识的,到时候再发一个改进后的,就有对比啦,这也能让我看到我在这条路上的点滴,一起努力吧!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值