简易版扫雷(数组和函数实践)

本文详细介绍了扫雷游戏的设计与实现,包括使用9x9格子、随机布置雷、mine和show数组的使用、数据结构分析、初始化棋盘、显示棋盘、布置雷、排雷以及菜单设计。代码示例展示了如何用C语言实现扫雷游戏的各个步骤。
摘要由CSDN通过智能技术生成

1.扫雷游戏分析

1.1我们设计的是一个9*9的格子

1.2默认随机布置10个雷

1.3排查雷

  • 如果位置是雷,就游戏失败
  • 如果位置不为雷,就显示周围有几颗雷(周边八个网格中)
  • 把不是雷的位置都排查出来,排雷成功,游戏结束

1.4数据的结构分析

  • 首先我们要想如何存储雷的信息,我们需要在9*9的格子中布置雷的信息和排查雷,所以我们首先想到用数组来存储信息,创建一个9*9的数组
空棋盘
​​

 1.5布置雷和排雷

  • 是雷我们这个位置放1,不是雷放0,这个数组我们取为mine数组

  • 假设我们要排查数组下标为 (2,2)这个坐标,(2,2)这个坐标不是雷,接着我们要访问周围一圈8个红色区域

  • (2,2)这个坐标周围有两颗雷,接着我们要把(2,2)中的0改为2,说明周围有两颗雷
  • 这时有个问题,若这个坐标周围只有一颗雷,我们把它改为1,这就存在错误,所以雷和非雷的信息用int类型容易搞混或弄错,这时我们想着用另外有个相同类型的数组show数组来展现周围有几个雷,同时这个数组要保持神秘感,玩家要一个一个排查,所以我们用char类型来表示show数组,里面初始化为字符‘*’

  • 我们要排查数组下标为 (2,2)这个坐标,然后根据mine数组(2,2)这个坐标不是雷,接着求出周围有2颗雷,然后把2转化为char类型的字符‘2’放入show数组(2,2)这个坐标中,接着展示

  • 为了保持两个数组类型的一致,所以mine数组show数组都用char类型mine数组中为雷用字符‘1’表示,不为雷用字符‘0’表示

  • 还有一个问题,就是假设我们排查的是下标是(8,2),我们要访问周围的一圈8个位置,当访问下面三个坐标时会越界,要对(0,?)、(8,?)、(?,8)、(?,0)这些坐标进行特殊处理,还有一种方法是对整个数组扩大一圈,这样就不会出现数组越界的情况了,这里我们选择对数组扩大一圈,扩大的一圈中的数据都为字符‘0’,表示不是雷

                           show数组也扩大一圈,扩大的一圈中的数据都为字符‘*’

2.扫雷游戏实现

2.1文件结构设计

  • 这里我们采用多文件的形式对函数声明和定义
  • 设计三个文件,mine.h(文件中写扫雷游戏需要的数据类型和函数声明等),mine.c(文件中写游戏函数实现等),game.c(文件中写游戏的测试逻辑)

2.2扫雷游戏代码实现

1)定义常量

  • 根据以上分析我们定义一些常量,后面函数会用这些,后面忘了可以回来看看
// 显示出的行
#define ROW 9
// 显示出的列
#define COL 9

// 实际的行
#define ROWS ROW + 2   
// 实际的列
#define COLS COL + 2

// 地雷个数
#define EASY_COUNT 10

2)初始化棋盘

  • 第一步我们先来初始化棋盘,我们要把mine数组和show数组初始化,mine数组初始化为字符‘0’,show数组初始化字符‘*’,不同数组要初始化为不同字符,该怎么写一个函数才能实现呢,这里我们对函数参数多添加一个参数为char set,你调用函数初始化为set字符
// 初始化棋盘
void InitBoard(char arr[ROWS][COLS],char set)
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			arr[i][j] = set;
		}
	}
}

3)显示棋盘

  • 初始化后我们想看看初始化是否成功,这时就要写一个打印函数,显示棋盘
// 显示棋盘
void DisplayBoard(char arr[ROWS][COLS])
{
	// 显示的行和列
	for (int i = 1; i <= ROW; i++)
	{
		for (int j = 1; j <= COL; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
	printf("\n");

}

这段代码打印棋盘是可以,但效果不怎么行,总觉得少了些什么,对少了每一行的下标,所以进行优化

// 显示棋盘
void DisplayBoard(char arr[ROWS][COLS])
{
	for (int i = 0; i <= COL; 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");

}

打印效果展示,第一个为mine数组,第二个为show数组

4)布置雷

  • 接下来我们就要进行布置雷了

这是布置完雷的mine数组,外面这一圈黄色部分里面存放的全是是字符‘0’(表示不是雷),这里我们观察一下mine数组,雷放置的位置是行下标为1-9,列下标也为1-9,这就好办了,这里我们用rand函数来产生随机数,用rand函数前要先用srand函数产生一个随机种子,rand函数才能产生真正的随机数,同时srand函数只需要调用一次就行,不要把srand的函数放到自己写的函数中,防止重复调用。

// 布置雷
void SetMine(char arr[ROWS][COLS])
{
	// 定义雷的个数
	int mines = EASY_COUNT;

	while (mines)
	{
		// 产生1-9的随机数
		// 用于数组下标赋值为雷
		int r = rand() % ROW + 1;
		int c = rand() % COL + 1;

		if (arr[r][c] == '0')
		{
			// 把雷设为字符'1',便于运算
			arr[r][c] = '1';
			mines--;
		}
	}
	
}

5)排雷

  • 布置完雷后,我们开始来排雷,这里我们根据1.5布置雷和排雷中的分析进行写

假设我们这里排查的坐标是(3,3),当该位置不是雷时(是雷就结束游戏),显示周围一圈的雷的个数,周围雷的个数为2,所以赋值给show数组,,同时展示show数组

我们知道周围有2颗雷,可计算机不知道,我们要拿出周围八个位置中的字符,拿一个减去一个字符‘0’,把八个都拿出来就减去8个字符‘0’,最后把结果用int接收。(这些字符都有对应的ASCII码表,字符‘1’ - 字符‘0’ == 1)

// 求出它周围一圈的地雷个数
int ItAround(char mine[ROWS][COLS], int r, int c)
{
	// 地雷数组里面放的是字符
	int result = mine[r - 1][c - 1] + mine[r - 1][c] + mine[r - 1][c + 1] +      // 上面三个数据
		mine[r][c - 1] + mine[r][c + 1] +								// 中间两个数据
		mine[r + 1][c - 1] + mine[r + 1][c] + mine[r + 1][c + 1] -		// 下面三个数据
		8 * '0';      // 每个数组数据都要减一个'0',在转换为int类型就为地雷个数
	return result;
}
  • 我们怎么说明排雷成功呢,当我们将不是地雷的位置都排查完了就说明排查结束,所以我们定义一个变量,每排查一次坐标就加加,不是雷的个数有ROW*COL - EASY_COUNT这么多
// 排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS])
{
	int r = 0;
	int c = 0;
	int win = 0;
	while (win < (ROW * COL - 10))
	{
		printf("请输入你要排查的坐标\n");
		scanf("%d %d", &r, &c);
		// 当排查的坐标上为炸弹时
		if (mine[r][c] == '1')
		{
			printf("你踩到地雷了,游戏失败\n");
			DisplayBoard(mine);
			break;
		}
		else
		{
			// 排查的位置不为地雷
			// 要求出它周围一圈的地雷个数
			int num = ItAround(mine, r, c);
			show[r][c] = num + '0';
			win++;
			DisplayBoard(show);

		}
	}
	if (win == (ROW * COL - 10))
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine);
	}

}

6)菜单

  • 这里我们实现一个简单的菜单函数
// 菜单
void Menu()
{
	printf("--------------------------------------\n");
	printf("-------        扫雷游戏       --------\n");
	printf("-------         1.play        --------\n");
	printf("-------         0.exit        --------\n");
	printf("--------------------------------------\n");

}

2.3整体实现

1)mine.h

#pragma once

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


// 显示出的行
#define ROW 9
// 显示出的列
#define COL 9

// 实际的行
#define ROWS ROW + 2   
// 实际的列
#define COLS COL + 2

// 地雷个数
#define EASY_COUNT 10


// 菜单
void Menu();


// 初始化棋盘
void InitBoard(char arr[ROWS][COLS],char set);


// 显示棋盘
void DisplayBoard(char arr[ROWS][COLS]);



// 布置雷
void SetMine(char arr[ROWS][COLS]);

// 求出它周围一圈的地雷个数
int ItAround(char mine[ROWS][COLS], int r, int c);



// 排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS]);

2)mine.c

#include "Mine.h"


// 菜单
void Menu()
{
	printf("--------------------------------------\n");
	printf("-------        扫雷游戏       --------\n");
	printf("-------         1.play        --------\n");
	printf("-------         0.exit        --------\n");
	printf("--------------------------------------\n");

}


// 初始化棋盘
void InitBoard(char arr[ROWS][COLS],char set)
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			arr[i][j] = set;
		}
	}
}


// 显示棋盘
void DisplayBoard(char arr[ROWS][COLS])
{
	for (int i = 0; i <= COL; 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");

}


// 求出它周围一圈的地雷个数
int ItAround(char mine[ROWS][COLS], int r, int c)
{
	// 地雷数组里面放的是字符
	int result = mine[r - 1][c - 1] + mine[r - 1][c] + mine[r - 1][c + 1] +      // 上面三个数据
		mine[r][c - 1] + mine[r][c + 1] +								// 中间两个数据
		mine[r + 1][c - 1] + mine[r + 1][c] + mine[r + 1][c + 1] -		// 下面三个数据
		8 * '0';      // 每个数组数据都要减一个'0',在转换为int类型就为地雷个数
	return result;
}


// 布置雷
void SetMine(char arr[ROWS][COLS])
{
	// 定义雷的个数
	int mines = EASY_COUNT;

	while (mines)
	{
		// 产生1-9的随机数
		// 用于数组下标赋值为雷
		int r = rand() % ROW + 1;
		int c = rand() % COL + 1;

		if (arr[r][c] == '0')
		{
			// 把雷设为字符'1',便于运算
			arr[r][c] = '1';
			mines--;
		}
	}
	
}


// 排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS])
{
	int r = 0;
	int c = 0;
	int win = 0;
	while (win < (ROW * COL - 10))
	{
		printf("请输入你要排查的坐标\n");
		scanf("%d %d", &r, &c);
		// 当排查的坐标上为炸弹时
		if (mine[r][c] == '1')
		{
			printf("你踩到地雷了,游戏失败\n");
			DisplayBoard(mine);
			break;
		}
		else
		{
			// 排查的位置不为地雷
			// 要求出它周围一圈的地雷个数
			int num = ItAround(mine, r, c);
			show[r][c] = num + '0';
			win++;
			DisplayBoard(show);

		}
	}
	if (win == (ROW * COL - 10))
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine);
	}

}

3)game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Mine.h"

int main()
{

	// 产生随机种子
	srand((unsigned int)time(NULL));
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	int flag = 0;
	do
	{
		Menu();
		printf("请输入相关操作\n");
		scanf("%d", &flag);
		switch (flag)
		{
		case 1:
			printf("玩游戏\n");
			InitBoard(mine, '0');
			InitBoard(show, '*');
			SetMine(mine);
			DisplayBoard(show);
			FindMine(mine, show);
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误请重新输入\n");
			break;
		}
	} while (flag);

	return 0;
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个简单的Python实现扫雷的示例代码: ```python import random # 游戏参数 ROWS = 10 COLUMNS = 10 MINES = 10 # 方格状态 UNREVEALED = -1 MINE = -2 # 创建游戏面板 board = [[UNREVEALED for _ in range(COLUMNS)] for _ in range(ROWS)] # 随机布雷 mines = random.sample(range(ROWS * COLUMNS), MINES) for mine in mines: row, col = divmod(mine, COLUMNS) board[row][col] = MINE # 计算周围地雷数量 for row in range(ROWS): for col in range(COLUMNS): if board[row][col] == MINE: continue count = 0 for r in range(max(0, row - 1), min(row + 2, ROWS)): for c in range(max(0, col - 1), min(col + 2, COLUMNS)): if board[r][c] == MINE: count += 1 board[row][col] = count # 显示游戏面板 def print_board(): print(" ", end="") for col in range(COLUMNS): print(f"{col:2d}", end="") print() for row in range(ROWS): print(f"{row:2d} ", end="") for col in range(COLUMNS): if board[row][col] == UNREVEALED: print(" .", end="") elif board[row][col] == MINE: print(" *", end="") else: print(f" {board[row][col]}", end="") print() # 点击方格 def click(row, col): if board[row][col] == MINE: print("你踩到了地雷,游戏结束!") return False elif board[row][col] == UNREVEALED: board[row][col] = 0 for r in range(max(0, row - 1), min(row + 2, ROWS)): for c in range(max(0, col - 1), min(col + 2, COLUMNS)): if board[r][c] == UNREVEALED: click(r, c) return True else: return True # 开始游戏 print_board() while True: row = int(input("请输入行号:")) col = int(input("请输入列号:")) if not click(row, col): break print_board() ``` 这个简易版扫雷游戏使用的是命令行界面,先随机生成地雷,然后根据地雷数量计算每个方格周围的地雷数量。玩家输入行号和列号来点击方格,如果踩到地雷,则游戏结束,否则会递归地展开周围未点击过的方格,直到点击到有地雷的方格或者所有非地雷方格都被点击为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wrf228

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值