Skip to content

游戏逻辑

这一步用你选择的编程语言实现游戏规则。

Slint 的总体理念是:在 Slint 中实现用户界面,在你喜欢的编程 语言中实现业务逻辑。

游戏规则规定最多只能有两张牌的帘幕处于打开状态。如果牌匹配,则游戏 认为它们已解开并保持打开。否则,游戏会短暂等待,让玩家记住 图标的位置,然后再次合上帘幕。

在 MainWindow 组件内添加以下代码,以便在用户点击牌时向 Rust 代码发送信号。

export component MainWindow inherits Window {
width: 326px;
height: 326px;
callback check_if_pair_solved(); // Added
in property <bool> disable_tiles; // Added
in-out property <[TileData]> memory_tiles: [
{ image: @image-url("icons/at.png") },

这一改动为 MainWindow 提供了一种方式,通知 Rust 代码它应该 检查玩家是否解开了一对牌。Rust 代码需要一个额外的属性用于切换,以禁用进一步的 牌交互,防止玩家打开超过允许数量的牌。不允许作弊!

代码的最后一项改动是在 MemoryTile 发出玩家点击了它的信号时采取行动。

在 MainWindow 的 for 循环 clicked 处理器中添加以下处理器:

for tile[i] in memory_tiles : MemoryTile {
x: mod(i, 4) * 74px;
y: floor(i / 4) * 74px;
width: 64px;
height: 64px;
icon: tile.image;
open_curtain: tile.image_visible || tile.solved;
// propagate the solved status from the model to the tile
solved: tile.solved;
clicked => {
// old: tile.image_visible = !tile.image_visible;
// new:
if (!root.disable_tiles) {
tile.image_visible = true;
root.check_if_pair_solved();
}
}
}

在 Rust 一侧,你现在可以为 check_if_pair_solved 回调添加一个处理器,检查玩家是否打开了两张牌。 如果它们匹配,代码将模型中的 solved 属性设置为 true。如果它们不匹配, 则启动一个计时器,在一秒后合上牌。计时器运行期间,禁用每一张牌,这样 玩家在这段时间内无法点击任何东西。

在 main_window.run().unwrap(); 调用之前添加这段代码:

let main_window_weak = main_window.as_weak();
main_window.on_check_if_pair_solved(move || {
let mut flipped_tiles =
tiles_model.iter().enumerate().filter(|(_, tile)| tile.image_visible && !tile.solved);
if let (Some((t1_idx, mut t1)), Some((t2_idx, mut t2))) =
(flipped_tiles.next(), flipped_tiles.next())
{
let is_pair_solved = t1 == t2;
if is_pair_solved {
t1.solved = true;
tiles_model.set_row_data(t1_idx, t1);
t2.solved = true;
tiles_model.set_row_data(t2_idx, t2);
} else {
let main_window = main_window_weak.unwrap();
main_window.set_disable_tiles(true);
let tiles_model = tiles_model.clone();
slint::Timer::single_shot(std::time::Duration::from_secs(1), move || {
main_window.set_disable_tiles(false);
t1.image_visible = false;
tiles_model.set_row_data(t1_idx, t1);
t2.image_visible = false;
tiles_model.set_row_data(t2_idx, t2);
});
}
}
});

代码使用了 main_window 的 Weak 指针。这很 重要,因为在回调处理器内部捕获 main_window 本身的副本会导致循环所有权。 MainWindow 拥有回调处理器,而处理器本身又拥有对 MainWindow 的引用,这个引用必须是弱引用 而不是强引用,以避免内存泄漏。

这些就是最后的改动,运行代码会打开一个窗口,让玩家可以按规则进行游戏。


© 2026 SixtyFPS GmbH