Godot扫雷游戏制作记录3——随机埋雷

本文内容已上传开源仓库:扫雷:一个简单的扫雷游戏,基于Godot4.6 - AtomGit | GitCode

现在,我们来完成随机埋雷的代码。

一、完善tile.gd代码

python 复制代码
extends Control

signal clicked(tile: Node)

@onready var bg: ColorRect = $ColorRect

var is_revealed: bool = false
var is_mine: bool = false  # 新增:标记是否为地雷

func _on_gui_input(event: InputEvent):
	if event is InputEventMouseButton and event.pressed:
		if event.button_index == MOUSE_BUTTON_LEFT:
			clicked.emit(self)

# 修改:更新reveal函数,显示地雷
func reveal():
	if is_revealed:
		return
	is_revealed = true
	
	if is_mine:
		# 如果是地雷,显示紫色
		bg.color = Color(0.926, 0.0, 0.67, 1.0)
	else:
		# 如果不是地雷,显示浅灰色
		bg.color = Color(0.9, 0.9, 0.9)

在这里,我们要做的比较简单,只是添加了一个用于标记该地块是否为雷的变量:

python 复制代码
var is_mine: bool = false  # 新增:标记是否为地雷

并在reveal()函数里更新了显示的颜色,如果是雷,那么翻开后的颜色就是紫色,不是的话,翻开后还是浅灰色:

python 复制代码
	if is_mine:
		# 如果是地雷,显示紫色
		bg.color = Color(0.926, 0.0, 0.67, 1.0)
	else:
		# 如果不是地雷,显示浅灰色
		bg.color = Color(0.9, 0.9, 0.9)

二、完善埋雷逻辑(main.gd)

我们的埋雷逻辑将在main.gd中完成:

python 复制代码
extends Control

const GRID_SIZE = 10
const TILE_SCENE = preload("res://场景/tile.tscn")
const MINE_COUNT = 15  # 新增:地雷数量

var tiles: Array = []

@onready var grid: GridContainer = $grid

func _ready():
	_init_grid()
	_place_mines()  # 新增:放置地雷
	_connect_signals()

func _init_grid():
	for i in range(GRID_SIZE * GRID_SIZE):
		var tile = TILE_SCENE.instantiate()
		tile.custom_minimum_size = Vector2(50, 50)
		grid.add_child(tile)
		tiles.append(tile)

# 新增:随机放置地雷函数
func _place_mines():
	# 创建随机数生成器
	var rng = RandomNumberGenerator.new()
	# 初始化随机种子,确保每次运行结果不同
	rng.randomize()
	
	var placed_mines = 0
	# 循环直到放置完所有地雷
	while placed_mines < MINE_COUNT:
		# 随机选择一个格子索引
		var random_index = rng.randi_range(0, tiles.size() - 1)
		var tile = tiles[random_index]
		
		# 如果这个格子还不是地雷
		if not tile.is_mine:
			# 设置为地雷
			tile.is_mine = true
			placed_mines += 1

func _connect_signals():
	for tile in tiles:
		tile.clicked.connect(_on_tile_clicked)

func _on_tile_clicked(tile: Control):
	tile.reveal()

2.1 定义常量:

我们定义了一个代表地雷数量的常量。

python 复制代码
const MINE_COUNT = 15  # 新增:地雷数量

2.2 随机埋雷函数

接下来,我们编写一个用来埋雷的函数:

python 复制代码
# 新增:随机放置地雷函数
func _place_mines():
	# 创建随机数生成器
	var rng = RandomNumberGenerator.new()
	# 初始化随机种子,确保每次运行结果不同
	rng.randomize()
	
	var placed_mines = 0
	# 循环直到放置完所有地雷
	while placed_mines < MINE_COUNT:
		# 随机选择一个格子索引
		var random_index = rng.randi_range(0, tiles.size() - 1)
		var tile = tiles[random_index]
		
		# 如果这个格子还不是地雷
		if not tile.is_mine:
			# 设置为地雷
			tile.is_mine = true
			placed_mines += 1

在这个函数里,我们做了以下几件事:

2.2.1 创建一个随机种子

python 复制代码
	# 创建随机数生成器
	var rng = RandomNumberGenerator.new()
	# 初始化随机种子,确保每次运行结果不同
	rng.randomize()
  • RandomNumberGenerator: Godot 的随机数生成器类,专门用来生成各种随机数(比如随机整数、随机小数、随机范围);
  • .new(): 创建一个新的实例------ 相当于 "造一台新的抽奖机";
  • **var rng:**把这台 "抽奖机" 存到变量rng里,后续用rng就能生成随机数了。
  • **rng.randomize():**通过一个数学公式,计算出一个伪随机数,使得每次游戏地雷的位置都不一样。

2.2.2 进行循环埋雷

首先,我们定义了一个用来表示已经埋下雷的数量的变量:

python 复制代码
var placed_mines = 0

接下来,使用while循环嵌套,当已埋雷的数量少于我们之前定义的常数时,选取一个地块作为雷:

python 复制代码
	# 循环直到放置完所有地雷
	while placed_mines < MINE_COUNT:
		# 随机选择一个格子索引
		var random_index = rng.randi_range(0, tiles.size() - 1)
		var tile = tiles[random_index]
  • **randi_range(min,max):**生成一个介于min到max之间的随机整数(包含min和max);
  • 因为我们的所有地块存储在名为tiles的数组里,在数组中,第一个元素是0,那么100个格子,最后一个索引就是99(100 - 1)。所以我们第一个数字是0,第二个数字是tiles.size() - 1。
  • **size():**这个函数用于得到数组的长度,这里不写死是为了方便后续如果可能存在的修改。
  • **var tile = tilesrandom_index:**从tiles数组里,取出索引为random_index的格子。

2.2.3 保护逻辑

因为随机数有重复的情况,如果不加入保护逻辑,那么有可能会把两个雷生成在同一地块上:

python 复制代码
		# 如果这个格子还不是地雷
		if not tile.is_mine:
			# 设置为地雷
			tile.is_mine = true
			placed_mines += 1

如果当前取出的这个地块还不是地雷,那么我们将其设为地雷,并让已埋雷的数量+1,否则什么都不做。

最后,在_ready()函数中调用我们刚写好的随即埋雷函数:

python 复制代码
func _ready():
	_init_grid()
	_place_mines()  # 新增:放置地雷
	_connect_signals()

三、运行测试

现在,我们点击运行游戏,可以看到有部分格子被翻开后变成了紫色,证明我们点到了雷:

关掉窗口重新测试,可以看到地雷的位置发生改变:

相关推荐
java_logo13 小时前
Docker 部署 EmulatorJS:轻松搭建浏览器复古游戏平台
游戏·docker·容器·复古游戏·轩辕镜像·emulatorjs·红白机
淡海水17 小时前
09-04-内存-Unity原生对象生命周期
unity·c#·游戏引擎·gc
寂寞的船1 天前
【Unity Bug挑战】第10期 SerializeReference 内存泄漏之谜
unity·c#·游戏引擎·bug
AI小百科2 天前
AI 进游戏:游戏里的 NPC 开始有自己的性格
人工智能·游戏·ai
云-缩影2 天前
文生图技术落地:从广告到游戏,哪些场景真的能用
人工智能·游戏
hkNaruto3 天前
【AI】游戏大模型智能体OODA过程记忆问题解决方案:AgenticSTS 有界记忆契约:技术分析与流水线改造操作手册
人工智能·游戏·机器学习
tealcwu3 天前
【Unity基础】为什么游戏需要物理按键映射?从 Unity Input Manager 到跨引擎输入设计
java·游戏·unity
沐飞工具箱3 天前
游戏、漫画、视频里的外语怎么实时翻译?从 OCR + AI 原理聊聊 VoriTrans 屏幕翻译
人工智能·游戏·实时互动·音视频·自动翻译
tealcwu4 天前
【Unity高级】Unity URP:构建同时支持 2D 与 3D 场景的项目完全指南
3d·unity·游戏引擎
淡海水4 天前
10-01-互操作-C#与C++边界的内存管理
unity·c#·游戏引擎·.netcore·gc