“扫雷”逻辑简述

前几天做了三子棋的游戏代码,今天弄一个扫雷游戏的代码。我觉得总的思路都是差不多的。上次三子棋是先做了头文件,之后按照顺序将源文件内的代码内容一一补充。我这次打算先编写源代码,编写完毕之后再写头文件。

Menu()
首先 制作刚开始的菜单页面,用printf来简略设定菜单页的外形。使用switch语句来选择,若输入1则开始游戏并进入之后的Game()部分,输入2退出游戏,输入其他显示输入错误。通过此部分设定,菜单页如下图:
在这里插入图片描述
main.c

#include "mine.h"

static void Menu()
{
	printf("==================================\n");
	printf("||         欢迎来到扫雷         ||\n");
	printf("==================================\n");
	printf("||          1.开始游戏          ||\n");
	printf("==================================\n");
	printf("||          2.退出游戏          ||\n");
	printf("==================================\n");
	printf("请输入你的选择: ");
}

int main()
{
	int quit = 0;
	do {
		int select = 0;
		Menu();
		scanf("%d", &select);
		switch (select) {
		case 1:
			Game();
			printf("当前游戏已经结束 ... 再来一把?\n");
			break;
		case 2:
			quit = 1;
			printf("再见 ... 欢迎下次来玩!\n");
			break;
		default:
			printf("选择错误 ... 请重新选择\n");
			break;
		}
	} while (!quit);
	system("pause");
	return 0;
}

mine.c
将此后的代码大致分为几部分,先是初始化面板,随机设定雷所在位置,展示游戏面板,得到某空格周围雷的数量,以及最后将所有代码联系起来的Game()部分。

InitBoard()
该部分使用自定义函数 InitBoard(),为方便修改面板大小以及雷数量,将其定义在头文件部分更为方便,此处不做具体赋值。使用for循环以及赋值语句初始化游戏面板,使面板内空格为0。

#include "mine.h"

void InitBoard(char board[ROW][COL], int row, int col, char elem)
{
	int i = 0;
	for (; i < row; i++) {
		int j = 0;
		for (; j < col; j++) {
			board[i][j] = elem;
		}
	}
}

SetMine()
自定义函数,用rand随机选定位置于(row-2)(col-2)的空格中,若该位置为1,说明此处已设置了雷,继续;若该位置不为1,则将1赋值到该位置,并将n减一,目的是使在此(row-2)*(col-2)的格子中随机生成n个位置的雷(不重复),且用1赋值。

void SetMine(char mine[ROW][COL], int row, int col)
{
	int n = NUM;
	while (n)
	{
		int x = rand() % (row - 2) + 1;
		int y = rand() % (col - 2) + 1;
		if (mine[x][y] == '1')       //若该位置为1 ,说明此位置有雷,继续
		{
			continue;
		}

		mine[x][y] = '1';            //若该位置不为1,则将1赋值到该位置
		n--;
	}                                //最后,使面板中1的数量与规定的NUM值一样
}

ShowBoard()
该部分自定义函数,展示初始化并赋值雷之后的游戏面板。用for循环来规定每个字符所在位置,以此来美化页面。
输出之后的游戏面板如下所示:
在这里插入图片描述
代码如下:

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

GetNum()
随机输入一个位置之后,返回值是它周围的八个格子内所含雷的个数

char GetNum(char mine[ROW][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';
}

Game()
首先初始化board和mine俩个页面,将board内全部赋值为“**”,而mine内全部赋值为“0”。放置雷的时候将雷随机放置在mine中面板中,即将mine中的数字0改为数字1的位置就是雷所存在的位置。
面板内非雷格子数赋值给count,展示board面板,之后输入要扫的位置(x y)。判定位置,第一种情况若x,y不在格子范围内,则显示错误;若所输入位置不为“*”,则说明该位置已被输入过,则输出该位置已被扫过;若输入某位置可执行,则同时将count减一;若输入某位置,该位置有雷,则游戏结束。
最后判定,若count大于0,这说明未把雷扫完,即扫雷失败;若count等于0,这说明将全部雷扫出来了,即扫雷成功。

void Game()
{
	srand((unsigned long)time(NULL));

	char board[ROW][COL];
	char mine[ROW][COL];

	InitBoard(board, ROW, COL, '*'); //'*'
	InitBoard(mine, ROW, COL, '0');  //'0'

	SetMine(mine, ROW, COL);
	//ShowBoard(board, ROW, COL);
	//ShowBoard(mine, ROW, COL);

	int count = (ROW - 2) * (COL - 2) - NUM;
	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) {//[1,10]
			printf("你输入的位置是错误的,请重新输入...\n");
			Sleep(1000);
			continue;
		}
		if (board[x][y] != '*') {             //避免重复输入同一位置
			printf("你输入的位置已经被扫过,请重新输入...\n");
			Sleep(1000);
			continue;
		}
		if (mine[x][y] == '0') {
			count--;
			char num = GetNum(mine, x, y);
			board[x][y] = num;
		}
		else {
			printf("你输入的位置(%d, %d),有雷!\n", x, y);
			break;
		}
	} while (count > 0);

	char* result = NULL;
	if (count > 0) {
		result = "==  扫雷结束, 你被炸死了:<   ==\n";
	}
	else {
		result = "==扫雷结束,恭喜你,成功啦:> ==\n";
	}
	printf("==============================\n");
	printf("%s", result);
	printf("==============================\n");
	ShowBoard(mine, ROW, COL);
}

至此,本代码的大部分内容就已经编写完毕了,最后,总结整个代码然后编写头文件。
mine.h
#ifndef _MINE_H_是防止mine.h被重复引用,之后引用库函数。宏定义扫雷游戏的ROW和COL以及雷的个数,在头文件中宏定义,便于之后修改游戏的难度。需要注意的是游戏中格子的个数是(ROW-2)X(COL-2),所以必须NUM要小于等于(ROW-2)X(COL-2),否则游戏将无法运行。之后声明源文件中的自定义函数。

#ifndef _MINE_H_
#define _MINE_H_

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#pragma warning(disable:4996)

#define ROW 12
#define COL 12

#define NUM 10

void Game();
//初始化面板
void InitBoard(char board[][COL], int row, int col, char elem);
//设置雷位置
void SetMine(char mine[][COL], int row, int col);
//展示面板
void ShowBoard(char board[][COL], int row, int col);
//得到周围雷的数量
char GetNum(char mine[][COL], int x, int y); //'0', '1', '2'

#endif

将头文件中宏定义的数据进行修改,修改之后,面板为6X6的格子,其中含有20个雷。如图所示:
在这里插入图片描述

接着输入要扫的位置就会显示数字或者扫雷失败。修改代码如下:

#define ROW 8
#define COL 8

#define NUM 20

最后,总体来说,都是现将制作游戏代码的整个过程捋一遍,将制作中需要用到的部分自定义出来,最后统筹规划在头文件中总的显示出来。最重要的还是细心的面面俱到吧,无论漏掉哪一部分都会导致游戏制作失败。

加油吧,以后做出来更加难而有意思的游戏!

在这里插入图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值