典中典—扫雷游戏1.0

前言

扫雷,俄罗斯方块,贪吃蛇,应该算的上是互联网最早的一批小游戏了,我现在还忘不了初中时微机课上总是玩电脑自带的扫雷 。这些游戏时隔多年仍然经久不衰。今天我来尝试一下用C语言编写扫雷程序

实现逻辑

玩法

首先在编写代码之前,我们要先在脑中想好怎么才能实现代码,然后再去想怎么用编程语言去实现。
扫雷
上面就是扫雷的游戏截图。在编写之前我们首先要弄清扫雷的规则。

  • 最开始是一个n*n的格子,每个格子下面都有可能有雷或者没雷。
  • 如果点的格子没有雷,那么这块格子就会被揭开,然后如果周围一圈的格子都没有雷,那么周围格子就会被自动揭开,直到周围的格子至少有一个雷。
  • 排出所有的雷即为获胜,如果点到雷就为失败。

思路

首先我们肯定要生成一个棋盘,对其进行操作,这自然容易让我们联想到二维数组的只是,我的最终代码也确实是用二维数组来实现的。
我们最终想呈现的效果(能力有限,完整的游戏暂时还没能力实现,只能别写一下基本思路)

  • 在终端窗口用打印的二维数组代表棋盘
  • 在键盘上输入坐标,表示翻开的格子
  • 被先开的格子暴露出来,并提示周围还有几个雷
  • 排除所有雷获胜,反之失败
    效果如图
    简陋版扫雷

代码编写

  • 首先我们可以生成一个菜单,让我们的游戏更精致一些
#include <stdio.h>
int main()
{
	printf("开始游戏请按1\n");
	printf("退出游戏请按2\n");
	return 0;
}
  • 然后我们根据设计的菜单进行引导操作
int main()
{
	printf("如果想开始游戏请输入1\n");
	printf("如果想退出游戏请输入2\n");
	int n = 0;//输入一个选项
	do
	{
		scanf("%d", &n);
		switch (n)//这里用switch方便引导
		{
		case 1:
			//开始游戏
			break;
		case 2:
			printf("已退出游戏\n");
			return 0;
			break;
		default://输入1和2以外的数字
			printf("输入错误,请重新输入:\n");
		}
	} while (n != 1 && n != 2);
	return 0;
}
  • 具体实现游戏细节
    首先可以打印一遍没揭开的棋盘
void cover_mint()//打印9*9的棋盘
{
	int i = 0;
	for (i = 0;i < 9;i++)
	{
		int j = 0;
		for (j = 0;j < 9;j++)
		{
			printf("$ ");
		}
		printf("\n");
	}
}

这里用$来遮挡,打印9*9的棋盘

  • 然后如何实现输入坐标揭开棋盘呢
    首先要埋雷,才能够扫雷,我们可以用0代替没有雷,1代替有雷,创建棋盘。但是这里我们最好提前想远一点,到后面我们需要排除所选位置周围8个格子的雷数。我们可以遍历9个格子从而实现
    如图所示
    如图所示
    那么当我们遍历到角落得位置怎么办,我们可以采用扩大棋盘的方式
    (画的很草率,轻喷)
    在这里插入图片描述
    只要我们在周围一圈全都变成0就可以正常遍历了。所以我们在设计棋盘时要设计成11*11的二维数组
    确定好数组的大小后,我们就可以埋雷了。我们在上一篇猜数字游戏中曾经使用过生成随机数的函数。简单说一下用法就是利用srand函数生成种子,rand函数生成随机数
#include <stdlib.h>
#include <time.h>
srand((unsigned int)time(NULL));
rand();

其中srand,rand函数头文件stdlib.h,time函数头文件time.h

srand((unsigned int)time(NULL));
int arr[11][11] = {0}//设置棋盘
int mine = 10;//埋十颗雷
while(mine)
{
	int x = rand()%9+1;//确保下标x从1到8,最后埋的雷都都在中间9*9
	int y = rand()%9+1
	if(arr[x][]y]==0)//确保不会重复埋雷
	{
		arr[x][y] = 1;
		mine--;
	}
}

埋好雷之后就可以挖雷了
最开始棋盘肯定是全覆盖的,每揭开一次棋盘我们就把覆盖棋盘上的那部分换成内层棋盘,并遍历那个位置周围的内容,查看还有几个雷

char arr2[11][11]
int i = 0;
for(i = 0;i<11;i++)
{
	int j = 0;
	for(j = 0;j<11;j++)
	{
		arr2[i][j] = '$';
	}
}//arr2数组用作表面遮盖棋盘
int row = 0;
int col = 0;
scanf("%d %d",&row,&col)//输入坐标
if(arr[row][col]==0)//这里举例一种情况,不是雷的情况
{
	arr2[row][col] = '0'//把arr2的那个位置更改,这样扫过的雷就会保留下来
	int p = 0;
	for(p = 1;p<=9;p++)
	{
		int j = 0;
		for(j = 1;j<9;j++)
		{
			if(i == row&&j == col)//扫过的地方变成0
			{
				printf("%d ",arr[i][j]);
			}
			else
			{
				printf("%c ",arr2[i][j]);//没扫过的地方还是遮盖的
			}
		}
	}
}	

上面是举例了扫到不是雷的情况,如果扫到的雷那么游戏结束。如果排除了所有的雷也是为游戏结束。一共81个格子,10颗雷,可以设置一个计次器,每扫完一个雷,计次+1;直到加到71即为获胜。由于可以用到很多函数和头文件,代码较长,可以分装在自己的库函数里。

最终代码

game.h`

`#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define MINE 10;
void print_mint(char arr2[11][11], int row, int col, int n);//打印排雷后的棋盘
void arrange_mine();//布雷函数
void cover_mint();

game.cpp

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void print_mint(char arr2[11][11], int row, int col, int n)//打印排雷后的棋盘
{
	int arr0[11][11] = { 0 };
	int arr1[11][11] = { 1 };
	int i = 0;
	for (i = 1;i <= 9;i++)
	{
		int j = 0;
		for (j = 1;j <= 9;j++)
		{
			if (i == row && j == col && n == 0)//row和col是输入的坐标,输入位置解开遮挡
			{
				printf("%d ", arr0[i][j]);
				arr2[i][j] = '0';
			}
			else if (i == row && j == col && n == 1)
			{
				arr2[i][j] = '1';//修改原先的遮挡棋盘让这个位置不再遮挡
			}
			else//其余位置继续遮挡
				printf("%c ", arr2[i][j]);
		}
		printf("\n");
	}

}




void arrange_mine()//布雷函数
{
	int arr[11][11] = { 0 };//初始化棋盘
	int i = 0;
	int x = 0;
	int y = 0;//x,y是雷的横纵坐标
	int mine = MINE;
	while (mine)//一共埋十个雷
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;//埋雷的横纵坐标小于10
		if (arr[x][y] == 0)//避免重复埋雷
		{
			arr[x][y] = 1;
			mine--;
		}
	}
	/*for (i = 1;i <= 9;i++)
	{
		int j = 0;
		for (j = 1;j <= 9;j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}*/
	int row = 0;
	int col = 0;
	int c = 0;//一共81个位置,10个雷,排查71次没有问题后游戏胜利
	char arr2[11][11];
	for (i = 0;i < 11;i++)//arr2用于遮挡
	{
		int j = 0;
		for (j = 0;j < 11;j++)
		{
			arr2[i][j] = '$';
		}
	}
	while (1)
	{
		printf("请输入想要排除的坐标:");
		scanf("%d %d", &row, &col);//输入想要排除的坐标
		if (arr[row ][col] == 0)//如果不是雷
		{
			print_mint(arr2, row, col, 0);
			int a = 0;
			int b = 0;
			int count = 0;
			for (a = row - 1;a < row + 2;a++)//遍历所选坐标的周围八个坐标,看看还有几个雷
			{
				for (b = col - 1;b < col + 2;b++)
				{
					if (arr[a][b] == 1)
					{
						count++;//count 用于计次雷数
					}
				}
			}
			printf("周围有%d个雷\n", count);
			c++;
			if (c == 71)
			{
				printf("恭喜你,所有的雷都被排除了\n");
			}
		}

		else if (arr[row][col] == 1)
		{
			int i = 0;
			for (i = 1;i < 10;i++)
			{
				int j = 0;
				for (j = 1;j < 10;j++)
				{
					printf("%d ", arr[i][j]);
				}
				printf("\n");
			}
			printf("you lose");
			break;
		}
		else
		{
			printf("非法坐标,请重新输入");
		}
	}
}

void cover_mint()//打印9*9的棋盘
{
	int i = 0;
	for (i = 0;i < 9;i++)
	{
		int j = 0;
		for (j = 0;j < 9;j++)
		{
			printf("$ ");
		}
		printf("\n");
	}
}

源.cpp

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
int main()
{
	srand((unsigned int)time(NULL));//生成种子;
	printf("如果想开始游戏请输入1\n");
	printf("如果想退出游戏请输入2\n");
	int n = 0;
	do
	{
		scanf("%d", &n);
		switch (n)
		{
		case 1:
			printf("游戏开始\n");
			cover_mint();
			arrange_mine();
			break;
		case 2:
			printf("已退出游戏");
			return 0;
			break;
		default:
			printf("输入错误,请重新输入:\n");
		}
	} while (n != 1 && n != 2);
	return 0;
}

最后

耗费了一个下午写出的代码,可能还有很多可以简化或有问题的地方。瑾以此文分享一下我的心得,如果对你有帮助,还请帮忙点赞,评论。如果上面的代码或思路有任何问题,也欢迎在评论区指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值