还不会写扫雷游戏吗

本文介绍了如何通过C语言编写一个9x9扫雷游戏,包括模块化代码设计、游戏菜单创建、雷盘初始化、数组操作、随机雷点布置及用户排查过程,展示了C语言的实用性和逻辑结构。

目录

前言

一.模块化代码

二.打造游戏菜单

三.初始化雷盘

1.调用game()函数

2.在game()函数中我们先创建好两个数组

3.对数组进行赋值

四.打印面向用户的数组

五.布置雷点

六.开始我们的排查步骤


前言

相信大家的童年肯定都玩过扫雷小游戏,对于我来说最开始接触电脑就是从电脑系统带的小游戏开始的,对于我印象最深的就是扫雷。这篇文章将带你通过c语言写出9×9模式的扫雷游戏,重温童年的同时感受一下c语言的魅力。

一.模块化代码

当我们需要完成的任务所需代码较多时,如果把所有代码放在一个项目中的一个.c文件中就会让我们代码看起来杂乱无章而且很可能导致很多bug的出现。而且很多大型的项目肯定需要多个程序员共同协作,这个时候如果只有一个.c文件肯定是不合适的,因此我们需要学会模块化代码。

针对于扫雷游戏来说,我认为需要创建出2个源(.c)文件和1个头(.h)文件来完成任务。

其中一个.c文件用于main函数代码的存放。

另一个.c文件则把我们需要的功能性代码存放起来。

其中的.h文件则负责函数的声明以及常量的定义等。

注意:在每个源文件中一定要包含头文件。

二.打造游戏菜单

任何游戏肯定都少不了菜单让我们选择,我们只需要通过循环语句和分支语句来创建即可。(如果对循环和分支语句不够熟悉的小伙伴可以看一下我前一篇文章。)

我这里选择用do-while循环的原因就是不论是玩还是不玩首先肯定要打印一下菜单才能选择而do-while循环刚好有这种特点。这里我将menu()菜单选项放在了另一个.c文件中就是让每个功能都可以单独成为一个函数让bug减少的同时更加有逻辑性和美观。

注意:每个自己创建的函数一定要在头文件中声明一下。

三.初始化雷盘

对于扫雷游戏来说,用户的操作界面是在9×9的雷盘中统一的一个字符来代表该坐标未被探索,一旦输入坐标便会探索该坐标,如果不是雷点则需要在该坐标显示一个数字来表示周围有几个雷点,如果该坐标是雷点则游戏失败。所以一个9×9的雷盘我们需要用数组的方式来创建,而一个数组显然无法满足我们的需要,我们需要创建两个数组,其中一个来面向用户,刚开始为一个字符代表未探索,探索之后该坐标为数字或者雷点,而另一个数组则负责用来布置雷点。

初始化两个雷盘(数组):

1.调用game()函数

2.在game()函数中我们先创建好两个数组

注意:

1.由于我们需要探索每一个坐标是否是雷点,在探索例如坐标(9,8)等边缘坐标的时候由于

当该坐标不是雷点的时候我们需要统计周围一圈的雷点个数,这个时候由于边缘坐标统计的时候会超出9×9的范围,因此我们创建数组的时候创建11×11的数组,来防止超出范围。

2.我们通过‘0’来表示不是雷,‘1’来表示是雷,对于我们布雷的数组便可以很好的布置,同时我们在统计周围的雷点个数的时候可以直接周围一圈相加来表示个数。

3.为了我们后续方便更改雷盘的大小我们可以在头文件中去用#define定义一个常量。

如:

1代表布置雷的数组

2代表用户看到的数组

3.对数组进行赋值

先将布置雷的数组统一赋值为0,用户看到的数组赋值为字符*。

函数声明:

函数调用:

具体函数:

这里值得注意的是我们通过创造一个char ret来代表‘0’和‘*’,这样就不用写两次具体函数了。

四.打印面向用户的数组

前面将两个数组赋值之后,我们需要先打印出来用户操作的界面,也就是游戏的内容(面向用户的数组)。

注意:

1.虽然我们在前面创建数组的时候是11×11的二维数组但是我们打印的时候只需要打印出中间的9×9即可,因为最外一圈只是为了满足我们计算周围雷的个数的需要,在用户界面依然还是9×9的模式。

2.我们只需要打印面向用户的数组,另一个数组只是为了让我们布置雷同时可以计算每个坐标周围的雷的个数。

函数声明:

函数调用:

具体函数:

五.布置雷点

走到这里的时候,一个数组已经全部赋值为‘0’,另一个数组已经全部赋值为‘*’且打印出来了,但是我们的雷点还未布置下来,雷点每次都是随机产生的,所以我们需要可以产生随机坐标,让这个坐标的由‘0’变为‘1’,也就是变成雷点。这里我们就需要用到rand()函数来产生随机值。

首先我们需要在主程序调用一次srand来让我们每次调用rand()函数生成的随机值不一样。

然后进行布置雷点。

函数声明:

函数调用:(这里布置只能在9×9里面布置雷点,因为外层只是一个辅助作用)

具体函数:

六.开始我们的排查步骤

首先我们肯定要选择我们的排查坐标,当该坐标是‘1’的时候游戏失败,而当该坐标是‘0’的时候就需要将面向用户数组里面的‘*”替换成该坐标周围一圈的雷点个数,当只剩下雷点的坐标还没有排查的时候游戏成功。所以我们需要将两个数组都传递给函数。

函数声明:

函数调用:

具体函数:

这里输入的x和y必须是在1~9之间,所以如果不在这区间则坐标不合法,如果排查的坐标已经不是‘*’则代表该坐标已经被排查过了。我们采用了写一个Get函数去计算坐标周围的雷点个数,在计算的时候我们要注意我们赋值的是字符0需要将字符0转换为数字0去计算个数。

函数声明:

函数调用:

具体函数:

七.源代码

头文件:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu();
void game();
#define hang 9
#define pai 9
#define hangs hang+2
#define pais pai+2
#define easy 10
void fuzhi(char s[hangs][pais],int HANG,int PAIS,char ret);//赋值
void yanzhen(char m[hangs][pais], int HANG, int PAIS);//操作模板,显示
void set(char t[hangs][pais], int HANG, int PAIS);//布置雷
void find(char buzhi[hangs][pais], char xianshi[hangs][pais],int HANG,int PAIS );
int Get(char buzhi[hangs][pais],int x, int y);

源文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"ming.h"
void menu()
{
	printf("* * * * * * * * * *\n");
	printf("*  *1. 开始游戏*  *\n");
	printf("*  *0. 退出游戏*  *\n");
	printf("* * * * * * * * * *\n");
}
void game()
{
	char buzhi[hangs][pais] = { 0 };
	char xianshi[hangs][pais] = { 0 };
	fuzhi(buzhi, hangs, pais,'0');
	fuzhi(xianshi, hangs, pais, '*');
	yanzhen(xianshi, hang, pai);
	set(buzhi, hang, pai);
	//yanzhen(buzhi, hang, pai);
	find(buzhi,xianshi,hang,pai);
}
void fuzhi(char s[hangs][pais], int HANG, int PAIS,char ret)//赋值框架
{
	int i = 0;
	for (i = 0;i < hangs; i++)
	{
		int j = 0;
		for (j = 0; j < pais; j++)
		{
			s[i][j] = ret;
		}
	}
}
void yanzhen(char m[hangs][pais], int HANG, int PAIS)//打印框架
{
	int i = 0;
	printf("--------扫雷--------\n");
	for (i = 0; i <= HANG; i++)
	{
		printf(" %d ", i);
	}
	printf("\n");
	for (i = 1; i <= hang; i++)
	{
		int j = 0;
		printf(" %d ", i);
		for (j = 1; j <= pai;j++)
		{
			printf(" %c ", m[i][j]);
		}
		printf("\n");
	}
}
void set(char t[hangs][pais], int HANG, int PAIS)
{
	int count = easy;
	while(count)
	{
		int B = rand() % HANG + 1;
	    int p = rand() % PAIS + 1;
		if (t[B][p] == '0')
		{
			t[B][p] = '1';
			count--;
		}
	}
}
void find(char buzhi[hangs][pais], char xianshi[hangs][pais], int HANG, int PAIS)
{
	int q = 0;
	while (q<HANG*PAIS-easy)
	{
		int x = 0, y = 0;
		printf("请选择你要排查的位置坐标\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= HANG && y >= 1 && y <= PAIS)
		{
			if (buzhi[x][y] == '1')
			{
				printf("很遗憾小丑,你被炸死了\n");
				printf("雷点分布在如下图中,1代表雷的位置\n");
				yanzhen(buzhi, hang, pai);
				break;
			}
			else
			{
				if (xianshi[x][y] != '*')
					printf("该坐标已经被排查过了,请重新输入坐标\n");
				else
				{
					int s = Get(buzhi, x, y);
					xianshi[x][y] = s + '0';
					yanzhen(xianshi, hang, pai);
					q++;
				}
			}
		}
		else
			printf("你输入的坐标不合法请重新输入\n");
	}
	if (q == HANG * PAIS - easy)
	{
		printf("恭喜你,通关了\n");
		
		yanzhen(buzhi, hang, pai);
	}
}
int Get(char buzhi[hangs][pais], int x, int y)
{
	int m = buzhi[x - 1][y] + buzhi[x - 1][y - 1] + buzhi[x][y - 1] + buzhi[x - 1][y + 1] + 
		buzhi[x + 1][y] + buzhi[x + 1][y + 1] + buzhi[x + 1][y - 1] + buzhi[x][y + 1] - 8 * '0';
	return m;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"ming.h"
int main()
{
	int xuanzhe = 0 ;
	srand((unsigned int)time(NULL));
	do
	{
		printf("*****是否开始游戏*****\n");
		menu();
		printf("请选择&&");
		scanf("%d", &xuanzhe);
		switch (xuanzhe)
		{
		case 0:
			printf("*****退出游戏*****\n");
			break;
		case 1:
			printf("*****开始游戏*****\n");
			game();
			break;
		default:
			printf("*****选择错误,请重新选择*****\n");
			break;
		}
	} while (xuanzhe);
	return 0;
}

八.总结

感谢大家的观看,以上就是我所要讲的内容,本文介绍了一下我写扫雷游戏的思路以及代码,当然肯定还有很多不足的地方,请懂哥指教,也希望自己能坚持。如果可以请懂哥温柔一点对待一个初学者,希望每见落日,身上满满的都是成就感。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值