I'm currently learning rust by writing a project which is a clone of the board game "Puerto Rico".
the Game
struct:
I chose the players
member to be an array slice because it can only contain 3, 4 or 5 players (to my understanding, this is the perfect use case for an array slice inside a struct, instead of a Vec
)
the Game::new
function:
Returns a new Game
instance. It takes a list of the names of the players and an empty Vec
and populates it with the appropriate Player
instances then stores it in the Game
as an array slice.
The problem is that this method of instantiating the Game
struct seems kind of cumbersome and I feel like there is a way around it (as in passing only the names
parameter and somehow creating the array slice inside the new
function).
So, is there a way to do it? Should I just change the players
member to a Vec
?
I tried to move the vec!()
declaration inside the new
function but, of course, it doesn't work becuase it is dropped at the end of the block.
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]
}
}
}