首页 > 其他分享 >用C语言写一个扫雷游戏

用C语言写一个扫雷游戏

时间:2024-11-23 21:58:19浏览次数:8  
标签:count 地雷 int C语言 扫雷 数组 printf 我们 游戏


如图这是我们常见的扫雷游戏的界面。为了实现扫雷游戏,我们借助一个二维的数组来实现,我们可以通过在二维数组里填充数字0来表示该处没有雷,填充1来表示该处有地雷。但是如图所示显示界面我们并不能看见此处到底是1或者0,一个数组我们不可能让其既填充0或1又让其填充别的字符来起到遮挡的作用,所以我们应该设计两个一样的数组;一个用来填充地雷应该在的位置,另一个用来显示界面。


当我们开始扫雷游戏时,点击一处就会统计出围绕该位置处其他几个位置雷的总的个数。此时又出现了一个问题:假设我们要创建一个9*9的棋盘,当我们点击中间部分如红框所示,我们需要统计八个格子;当时当我们选择了边界处,如黑框所示,我们只要统计三个格子。这在后面我们写统计一个坐标周围的地雷个数时会很麻烦,所以我们在创建棋盘的时候,我们就往外扩充两行两列,但是在设计地雷位置的时候还是将地雷放置在中间9*9的位置处,这样在统计所选位置周围地雷个数的时候并不会造成影响,而且每个位置都是统计八个元素中的地雷个数,极大方便了我们写函数。

在了解了一些基本设计原理后,现在让我们开始写程序。

由于该程序过程比较复杂,需要创建很多的函数,所以我们写的时候最好分成两个源文件,一个源文件用来写程序测试过程中的主体结构,另一个源文件用来写程序所需的函数,并且用一个头文件来引用。

函数的主题比较简单,首先我们进入游戏肯定是一个菜单选择页面,所以我们先创建一个menu函数来打印菜单,然后通过switch语句就可以实现具体的选择功能,此处比较简单,不过多赘述。具体代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include "game.h"
#include <time.h>
#include <stdlib.h>

menu()
{
	printf("*************************\n");
	printf("*********1.开始游戏******\n");
	printf("*********0.退出游戏******\n");
	printf("*************************\n");
}
test()
{
	int flag = 0;
	do
	{
		menu();
		printf("请输入你想要的选项\n");
		scanf("%d", &flag);
			switch(flag)
			{
			case(1):
					game();
					break;
			case(0):
					printf("游戏已退出\n");
					break;
			default:
				printf("重新输入\n");
					break;
			}
	} 
	while (flag);
}
int main()
{
	test();
	return 0;
}

程序的主题内容就是我们的game()函数,所以我们现在来分析一下扫雷功能怎么实现。

首先,由上文可知我们需要两个二维数组,一个用来存放地雷,一个用来打印出来显示。这里为了方便,我把两个数组都设置成了char型。创建完了数组后我们肯定要对数组进行初始化,显示页面我们用“*”来填充,打印出来的界面就是一个只有“*”的棋盘,实现了遮挡的功能。在存放地雷的数组中我们先统一把每个位置设置为0,以便统计。初始化的方法也很简单,遍历数组,每个元素位置处设置值就行。以下就是数组的建立和初始化,因为我们要把遮挡的页面显示出来,所以这里需要写一个打印游戏界面的函数:

void Border_initialize(char arr[ROWS][COLS], int rows, int cols, char set)//初始化函数
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

void Border_output(char arr[ROWS][COLS], int row, int col)//打印数组函数
{
	printf("-------------------扫雷---------------------\n");
	for (int i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
	printf("---------------------------------------------\n");
}

现在我们手里有一个初始化后的数组,现在我们就要来放置地雷,地雷的位置肯定是随机的,而且行和列的坐标都是1~9,只有中间9*9的棋盘才是有效的棋盘。假设此处我们要埋十个地雷,我们就要找十个数组的位置,将里面的元素从0改成1,就实现了地雷的布置。随机数的设置也很好实现,因为坐标只能是1~9,所以我们对9取模后加1就是1~9.此处还有一个容易被忽视的问题就是可能会有几次产生的随机坐标都是同一个,为了解决这一个问题,我们就还需再借助一个变量count,当我们每次进入循环时,判断产生的随机坐标处的元素是否为1,如果为0我们的count就减1,说明此次的设置地雷的操作是有效的,当count为0时,就跳出循环,这样子我们就可以得到一个埋藏着10个地雷的数组了。具体代码如下:

void Border_set(char arr[ROWS][COLS], int row, int col)//设置雷所在位置
{
	//雷所在位置在数组中从一开始,到九结束
	srand((unsigned int)time(NULL));
	int x, y = 0;
	//有十颗雷我们就应该将原来数组中的十个位置由0变为1来表示此处有雷
	int count = 10;
	do
	{
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (arr[x][y] != '1')
		{
			arr[x][y] = '1';
			count--;
		}
	} 
	while (count);
}

设置完地雷的值后我们就要开始实现扫雷操作了。我们此处肯定需要一个输入端来接受元素坐标,如果此处元素里的值为1,我们就提醒踩雷了,并退出游戏,返回主菜单界面。如果不为0的话,我们就需要在显示的数组处将那个地方的元素内容替换成周围八个位置处的地雷总数,于是在此处我们就要另外再设计一个Mine_count()函数来统计数字,已知ACSII码表中字符1和字符0差一,我们已知的元素坐标为(x,y),所以以(x,y)为中心的九个元素的行坐标范围是(x-1)~(x+1),列坐标范围是(y-1)~(y+1),我们将每个元素里面的存的字符减去字符0,然后再相加,用一个变量来存储并返回,我们就可以得到一个元素周围一圈位置所包含的地雷个数,此处我用循环来实现,一个位置一个位置相加也能实现。除此以外我们还要返回游戏成功的界面,因为一共由9*9个位置,由10个位置埋藏着地雷,所以我们只要猜出剩下的71个位置就能完成游戏,所以,我们再设置一个变量,用来统计成功次数,每次成功没有踩雷就减一,直至为0,跳出循环游戏成功。综上,代码如下:

int Mine_count(char arr[ROWS][COLS], int m, int n)//统计周围雷的个数
{
	int count = 0;
	for (int i = -1; i <= 1; i++)
	{
		for (int j = -1; j <= 1; j++)
		{
			count = count+(arr[m + i][n + j] - '0');//字符1和字符0在ASCII码表上差一,所以可以实现统计地雷出现的个数
		}
	}
	return count;
}

void Border_function(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col)//实现扫雷功能
{
	int x, y = 0;//实现我们要扫雷的位置
	int d = 71;
	while (d)
	{
		printf("请输入你想要扫的坐标\n");
		scanf("%d %d", &x, &y);
		if (x > row || x<0 || y>col || y < 0)
		{
			printf("输入坐标超出限制请重新输入\n");
			continue;
		}
		else
		{
			if (arr1[x][y] == '1')
			{
				printf("哎呀,踩到雷了!游戏失败\n");
				break;
			}
			else
			{
				int c = Mine_count(arr1, x, y);//此处需要一个功能来实现扫完某个位置会显示周围一圈雷的个数
				arr2[x][y] = '0' + c;//字符0加上数字c就可以得到字符c
				Border_output(arr2, row, col);//显示改变后的数组显示
				d--;
			}
		}
	}
	if (d == 0)
	{
		printf("恭喜你扫雷成功!\n");
	}
}

以上就是整个扫雷小游戏,注意记得拆开写,会更加简洁明了!

标签:count,地雷,int,C语言,扫雷,数组,printf,我们,游戏
From: https://blog.csdn.net/spikezqq/article/details/143926256

相关文章

  • C语言基础之m,n互换位置
    好久不见甚是想念,又是一期C语言,上一期C语言博客说我质量低,所以今天多说一些废话m.n换位,要借助第三方tt=m把m的值赋给tm=n 把n的值赋给mn=t 把t的值赋给m#include<stdio.h>#include<stdlib.h>intmain(){intm,n;printf("输入两个整数值:");scanf("%d......
  • 【Solution】用C语言代码绘制线性函数包围图
    题目:绘制左边图的众多*输出图像,函数已给出:y=1,y=-x+2n,y=x。解决方案: 思路对于原来的坐标几何图形,2<=n,y<=x<=2n-y,1<=y<=x。我们用来写C代码的函数首先要确定三角形高的范围,至少要2。将图形分隔成上下两部分。从最高的顶点到三角形高的部分,和其下面的部分。使用line......
  • 前端游戏网站【GAME】大学生web期末大作业 html+css+js
    目录1.项目介绍2项目展示3.代码部分4.联系我 1.项目介绍这是大一时候写的一个前端游戏网站,包括了火影忍者,原神,蛋仔派对(没有写完),英雄联盟(没有写完),现在才想起来有怎么一个项目可以分享出来可以练练手。2项目展示前面使用html+css+js:Div、导航栏、图片轮翻效果、视频......
  • 网络游戏的状态同步
    在网络游戏中,移动同步是确保玩家体验流畅和准确的关键因素。为了应对不稳定网络带来的挑战,我们可以采用多种技术和策略来优化数据同步。以下是一些有效的方法和思路:1.客户端预测客户端预测是指在客户端上预测玩家的移动,而不是完全依赖服务器的更新。这可以通过以下方式实......
  • C语言_数据类型及运算符_PAGE3
    顺序程序设计例题华氏度转化为摄氏度#include<stdio.h>intmain() { floatf,c;//定义f和c为单精度浮点型变量 f=64.0; c=(5.0/9)*(f-32); printf("f=%f\n",f,c); return0; }计算存款利息#include<stdio.h>intmain() { floatp0=1000,r1=0.0036,r2=0.022......
  • c语言程序块中初始化变量对同名变量作用域的影响
     001、[root@PC1test1]#lstest1.ctest2.c[root@PC1test1]#cattest1.c#include<stdio.h>intmain(void){inti;intx=10000;for(i=0;i<4;i++){intx=i*5;printf(......
  • C++游戏开发
    C++是一种常用的编程语言,广泛应用于游戏开发领域。在使用C++进行游戏开发时,可以利用C++的面向对象特性、高性能和可移植性来创建游戏。以下是C++游戏开发的详细步骤:设计游戏的概念和目标:在开始游戏开发之前,你需要明确游戏的概念和目标,包括游戏的类型、玩法、关卡设计等。这......
  • C语言数据结构与算法--简单实现栈的出栈与入栈
     目录(一)栈的基本概念(二)栈的的表现形式1.栈的表示和实现2.栈的链式表示(三)栈的链式表示时元素压入、弹出 算法实现思路1.栈的线性链表的压入算法2.栈的线性链表的弹出算法(四)算法的实现(一)栈的基本概念        栈(Stack)是限定仅在表尾进行插入和删除操作的线......
  • C语言:函数指针精讲
    1、函数指针一个函数总是占用一段连续的内存区域,函数名在表达式中有事也会被转换为该函数所在内存区域的首地址,这和数组名非常类似,我们可以把函数这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就......
  • c语言:动态内存管理中的malloc和free,calloc和realloc
    为什么要有动态内存分配?通过之前的学习,我们已经掌握的内存开辟方式有:inta=20;//在栈空间上开辟四个字节chararr[10]={0};//在栈空间上开辟10个字节的连续空间上述空间的开辟的大小是固定的数组在申明的时候,必须指定数组的长度,数组空间一旦确定了大小不能进行调整。......