事情太多了,更新迟了点。
上周学习了二维数组的知识,就写一个简单扫雷锻炼一下。
因为把之前写的简单小游戏(共3个)整合成为了一个简单游戏大厅的样子,方便以后继续向里面添加类似的游戏,所以主程序里面有一些与扫雷不相关的代码。
游戏逻辑
大家看看简单扫雷的逻辑就ok了。
1.首先要创建两个大小二维数组,把展示给玩家的数组称为面板,电脑用来布雷和数雷的面板称为雷板。
2.现假设面板的规格是n*n,那我们的两个板的规格要设置为(n+2)*(n+2)。
因为这样设置,检雷时不管输入的位置是啥,我们都可以绕一圈数雷,而不用特意处理雷板的边界和4个角。
3.宏定义面板大小和雷的数目。通过随机数让雷随机存在雷板里。
4.当用户输入位置时,需要检测用户输入的位置是否合法?越界和重复位置要让用户重复输入。若输入位置是雷,立即跳出,把雷板展示给用户,不能让用户输的不明不白。
5.数雷:把雷板初始为‘ ’,然后让‘#’代表雷。根据输入位置,检测以当前位置为中心的9个格子,数‘#’的数目,然后填入面板(不是雷板)。
以上,大概就是最简单的扫雷了。
代码实现
Clearmine.h 如下所示:
#ifndef __CLEARMINE_H__
#define __CLEARMINE_H__
#include <stdio.h>
#include <time.h>
#include <windows.h>
#pragma warning(disable:4996)
#define Size 10 //宏定义展示给人的面板的大小
#define DeathNum 35 //宏定义雷的数目
void ClearMine();
void SetMine(char arr[][Size + 2]);
void table(char arr[][Size + 2]);
void CountD(char arr[][Size + 2], char arr1[][Size + 2], int x, int y);
#endif
#endif
游戏逻辑Clearmine.c 如下所示:
#include "Clearmine.h"
void SetMine(char arr[][Size + 2])
{
int cnt = DeathNum;
while (cnt) {
int x = rand() % Size + 1;
int y = rand() % Size + 1;
if (arr[x][y] == ' ') { //当前位置可以布雷
arr[x][y] = '#';
}
cnt--;
}
}
void table(char arr[][Size + 2])
{ //要好看的面板:试or计算
printf(" |");
for (int i = 0; i < Size; i++) {
printf("%2d |", i + 1);
}
printf("\n--------------------------------------------\n");
for (int i = 1; i <= Size; i++) {
printf("%2d |", i);
for (int j = 1; j <= Size; j++) {
printf(" %c |", arr[i][j]);
}
printf("\n--------------------------------------------\n");
}
}
void CountD(char arr[][Size + 2], char arr1[][Size + 2], int x, int y)
{
int k = 0;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j <= y + 1; j++) {
if (arr[i][j] == '#') {
k++; //发现雷则自增1
}
}
}
arr1[x][y] = k + '0'; //将雷的数目填入面板相应位置
}
void ClearMine()
{
srand((unsigned long)time(NULL)); //设置随机种子
char showboard[Size + 2][Size + 2]; //面板:展示的数组
char mineboard[Size + 2][Size + 2]; //布雷/检雷的面板
memset(showboard, '*', sizeof(showboard)); //面板数组初始化
memset(mineboard, ' ', sizeof(mineboard)); //雷板数组初始化
SetMine(mineboard); //布雷
int cnt = Size * Size - DeathNum; //设置安全位置的数目,控制游戏循环
int x = 0,y = 0;
do {
system("cls"); //清空显示界面
table(showboard); //展示面板
printf("请输入清扫位置# ");
scanf("%d %d", &x, &y);
if (x < 1 || x > Size || y < 1 || y > Size) {
printf("输入位置越界,请重新输入!\n");
continue;
}
if (showboard[x][y] != '*') {
printf("该位置已经被排除!\n");
continue;
}
if (mineboard[x][y] == '#') { //踩雷即跳出
break;
}
CountD(mineboard, showboard, x, y); //计算输入位置附近雷的数目,并填入面板
cnt--; //安全位置减1
} while (cnt >= 0);
if (cnt > 0) { //cnt>0则说明跳出循环时安全位置并没有被找完,只有一个原因:踩雷
system("cls");
printf("你被炸死了!你刚才输入的位置为(%d,%d)\n",x,y);
table(mineboard);
}
else {
printf("恭喜,你通过游戏!\n");
}
Sleep(1000);
}
因为自己搞成了大厅,所以主函数就不展示了,要不然又得贴好多代码。主函数就写个简单菜单,用循环写一下就ok,能让用户进入游戏与退出游戏就行。
说明
这个扫雷代码没有实现那个达到某个条件就可以排除大片区域的逻辑,也没有难度的设置,后续有时间我再来更新。