You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让GameState结构体泛型适配Sure/SometimesSure两种可见性类型?

用泛型适配服务器与客户端的游戏状态复用

要复用GameState结构体适配服务器(全可见)和客户端(部分隐藏)两种场景,核心思路是让MapState、PlayerStates以及GameState都接受一个可见性包装器的泛型参数,用Sure和SometimesSure分别填充这个参数来实现不同场景的适配。

步骤1:修正类型定义并添加泛型约束

首先修正SometimesSure的拼写错误(Visibile改为Visible),然后给MapState、PlayerStates和GameState添加泛型参数V,这个参数代表用于包装数据的可见性类型(Sure或SometimesSure):

// 客户端可见性包装:支持隐藏/显示数据
enum SometimesSure<T> {
    Hidden,
    Visible(T),
}

// 服务器可见性包装:确保数据始终可见
struct Sure<T>(T);

// 泛型地图状态,V 为可见性包装器
struct MapState<V> {
    pub tiles: Vec<V<u8>>,
}

// 泛型玩家状态,V 为可见性包装器
struct PlayerStates<V> {
    pub points: V<bool>,
    pub name: V<String>,
}

// 泛型游戏状态,复用可见性包装器泛型
struct GameState<V> {
    pub map_state: MapState<V>,
    pub player_states: PlayerStates<V>,
}

步骤2:用Trait增强约束(可选)

如果需要统一处理两种包装类型的行为(比如获取内部值、构造实例),可以定义一个trait并让Sure和SometimesSure实现它,给泛型添加更明确的约束:

trait VisibilityWrapper<T> {
    // 从原始值构造包装实例
    fn wrap(value: T) -> Self;
    // 获取内部值(Sure 返回 Some,Hidden 返回 None)
    fn get(&self) -> Option<&T>;
}

impl<T> VisibilityWrapper<T> for Sure<T> {
    fn wrap(value: T) -> Self {
        Sure(value)
    }

    fn get(&self) -> Option<&T> {
        Some(&self.0)
    }
}

impl<T> VisibilityWrapper<T> for SometimesSure<T> {
    fn wrap(value: T) -> Self {
        SometimesSure::Visible(value)
    }

    fn get(&self) -> Option<&T> {
        match self {
            SometimesSure::Visible(val) => Some(val),
            SometimesSure::Hidden => None,
        }
    }
}

// 更新泛型结构体的约束,确保V是合法的可见性包装器
struct MapState<V>
where
    V: for<T> VisibilityWrapper<T>,
{
    pub tiles: Vec<V<u8>>,
}

struct PlayerStates<V>
where
    V: for<T> VisibilityWrapper<T>,
{
    pub points: V<bool>,
    pub name: V<String>,
}

struct GameState<V>
where
    V: for<T> VisibilityWrapper<T>,
{
    pub map_state: MapState<V>,
    pub player_states: PlayerStates<V>,
}

步骤3:实例化不同场景的游戏状态

现在可以分别创建服务器和客户端的游戏状态实例:

服务器端(全可见)

let server_map = MapState {
    tiles: vec![Sure(1), Sure(2), Sure(3)],
};
let server_players = PlayerStates {
    points: Sure(true),
    name: Sure("Alice".to_string()),
};
let server_game_state = GameState {
    map_state: server_map,
    player_states: server_players,
};

客户端(部分隐藏)

let client_map = MapState {
    tiles: vec![
        SometimesSure::Visible(1),
        SometimesSure::Hidden,
        SometimesSure::Visible(3),
    ],
};
let client_players = PlayerStates {
    points: SometimesSure::Hidden, // 隐藏玩家分数
    name: SometimesSure::Visible("Alice".to_string()), // 显示玩家名字
};
let client_game_state = GameState {
    map_state: client_map,
    player_states: client_players,
};

额外:从服务器状态生成客户端状态

可以给服务器端的GameState添加方法,根据游戏逻辑生成对应客户端的可见状态:

impl GameState<Sure> {
    fn to_client_state(&self) -> GameState<SometimesSure> {
        GameState {
            map_state: MapState {
                tiles: self.map_state.tiles.iter()
                    .map(|tile| {
                        // 示例:随机隐藏部分 tiles
                        if rand::random() {
                            SometimesSure::Visible(tile.0)
                        } else {
                            SometimesSure::Hidden
                        }
                    })
                    .collect(),
            },
            player_states: PlayerStates {
                points: SometimesSure::Hidden,
                name: SometimesSure::Visible(self.player_states.name.0.clone()),
            },
        }
    }
}

内容的提问来源于stack exchange,提问作者Tadeo Hepperle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 13:35:18