将向量传递给函数的替代方案?

Alternative to passing a vector to a function?

我目前正在通过编写一个克隆棋盘游戏的项目来学习 Rust "Puerto Rico"。

Game 结构: 我选择 players 成员作为数组切片,因为它只能包含 3、4 或 5 个玩家(据我了解,这是结构内数组切片的完美用例,而不是 Vec)

Game::new函数: Returns 一个新的 Game 实例。它需要一个球员姓名列表和一个空 Vec 并用适当的 Player 实例填充它,然后将其作为数组切片存储在 Game 中。

问题是这种实例化 Game 结构的方法看起来有点麻烦,我觉得有办法绕过它(比如只传递 names 参数并以某种方式创建new 函数内的数组切片)。

那么,有什么办法吗?我是否应该将 players 成员更改为 Vec

我试图将 vec!() 声明移动到 new 函数中,但是,当然,它不起作用,因为它被丢弃在块的末尾。

use super::board::Board;
use super::player::Player;
use super::planatation::ResourceType;

#[derive(Debug)]
pub struct Game<'a> {

    board: Board,
    players: &'a [Player],
    governor: &'a Player
}

impl<'a> Game<'a> {

    pub fn new(names: &[String], players: &'a mut Vec<Player>) -> Self {
        let num_of_players = names.len() as i32;
        let board = Board::new(num_of_players);

        if num_of_players < 3 || num_of_players > 5 {
            panic!("Only 3, 4 or 5 players may play");
        }

        if num_of_players < 5 {
            for (i, name) in names.iter().enumerate() {
                if i < 2 {
                    players.push(Player::new(name.to_string(), ResourceType::Indigo));
                } else {
                    players.push(Player::new(name.to_string(), ResourceType::Corn));
                }
            }
        } else { // num_of_player == 5
            for (i, name) in names.iter().enumerate() {
                if i < 3 {
                    players.push(Player::new(name.to_string(), ResourceType::Indigo));
                } else {
                    players.push(Player::new(name.to_string(), ResourceType::Corn));
                }
            }
        }

        Game {
            board: board,
            players: players,
            governor: &players[0]
        }
    }
}

正如您已经注意到的,切片不拥有它的数据,它只引用它们。这就是为什么您必须在结构之外创建玩家并将它们传递给游戏结构的原因。如果你想让你的结构容纳玩家,他们必须是 Vec 而不是切片。

如果 governor 不是该结构的成员,我建议只使用 Vec(或 ArrayVec)并完成它。然而,这意味着 governor 不能(通常)是对这个完全相同的向量的引用(参见 )。

根据 governor 和其他 "regular" 玩家的确切语义和用例,我将执行以下操作之一:

  • 为 "regular" 名玩家提供 Vec(或 ArrayVec),并为州长提供额外的场地。如果您经常需要对 "regular" 玩家和州长做同样的事情,这可能会很麻烦,但是您可以引入一种方法,returns 一个遍历所有玩家的迭代器 and州长.
  • 为所有玩家提供 Vec(或 ArrayVec),并将索引存储到州长的向量中。作为一种变体,您可以强制规定总督始终是持有所有玩家的 Vecfirst 元素。
  • 做你已经做过的事。 (然而,这可能意味着你不能轻易地改变它们(因为你一次只能有一个可变引用)。你可以通过内部可变性来解决这个问题,但我不确定它是否值得)
  • 只存储一个 Vec<String> 保存玩家名字。从中,您可以得出玩家的数量。如果玩家的种类相当简单,您甚至可以不显式存储玩家,而是通过其索引导出玩家的种类(我认为这可能是可能的,因为您确定 IndigoCorn).缺点是你身边没有玩家,但也许你可以在没有他们的情况下为整个游戏建模。