use crate::data::GameRules; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy)] pub enum BoatDirection { Left, Right, Top, Bottom, } impl BoatDirection { pub fn shift_coordinates(&self, coordinates: Coordinates, nth: usize) -> Coordinates { let shift = match self { BoatDirection::Left => (1, 0), BoatDirection::Right => (-1, 0), BoatDirection::Top => (0, -1), BoatDirection::Bottom => (0, 1), }; Coordinates::new( coordinates.x + shift.0 * nth as i32, coordinates.y + shift.1 * nth as i32, ) } } #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, Eq, PartialEq)] pub struct Coordinates { x: i32, y: i32, } impl Coordinates { pub fn new(x: E, y: E) -> Self where E: Into, { Self { x: x.into(), y: y.into(), } } } #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy)] pub struct BoatPosition { start: Coordinates, len: usize, direction: BoatDirection, } impl BoatPosition { pub fn all_coordinates(&self) -> Vec { let mut positions = Vec::with_capacity(self.len); for i in 0..self.len { positions.push(self.direction.shift_coordinates(self.start, i)); } positions } } #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] pub struct BoatsLayout(Vec); impl BoatsLayout { pub fn gen_random_for_rules(rules: &GameRules) -> Self { todo!() } } #[cfg(test)] mod test { use crate::data::boats_layout::{BoatDirection, BoatPosition, Coordinates}; #[test] fn get_boat_coordinates() { let position = BoatPosition { start: Coordinates { x: 1, y: 1 }, len: 3, direction: BoatDirection::Bottom, }; let coordinates = position.all_coordinates(); assert_eq!( coordinates, vec![ Coordinates::new(1, 1), Coordinates::new(1, 2), Coordinates::new(1, 3), ] ) } }