From 275919a4632eae2662adbd5206032b538295e4b4 Mon Sep 17 00:00:00 2001 From: Ian Whitney Date: Fri, 29 Apr 2016 19:53:41 -0500 Subject: [PATCH] Queen Attack: Replace tuple with ChessPosition Fixes #118 `Queen::new` now expects a `ChessPosition` instead of a tuple. `ChessPosition::new` returns a Result, indicating if the position is valid or not. I've added a few tests at the start to capture the behavior of `ChessPosition`. The tests of Queen have their API usage updated, and have been renamed for readability. --- exercises/queen-attack/example.rs | 99 +++++++++----------- exercises/queen-attack/tests/queen-attack.rs | 75 ++++++++------- 2 files changed, 85 insertions(+), 89 deletions(-) diff --git a/exercises/queen-attack/example.rs b/exercises/queen-attack/example.rs index ff89dc050..70ae5eb37 100644 --- a/exercises/queen-attack/example.rs +++ b/exercises/queen-attack/example.rs @@ -1,78 +1,69 @@ -#[derive(Debug, PartialEq)] -pub struct Queen { position: ChessPosition } - -impl Queen { - pub fn new(position: (i8, i8)) -> Result { - let position = ChessPosition::new(position); - if position.valid() { - Ok(Queen { position: position }) - } else { - Err(()) - } - } - - pub fn can_attack(&self, piece: &Queen) -> bool { - self.horizontal_from(&piece) || - self.vertical_from(&piece) || - self.diagonal_from(&piece) - } - - fn horizontal_from(&self, piece: &Queen) -> bool { - self.rank() == piece.rank() - } - - fn vertical_from(&self, piece: &Queen) -> bool { - self.file() == piece.file() - } - - fn diagonal_from(&self, piece: &Queen) -> bool { - self.sum() == piece.sum() || - self.difference() == piece.difference() - } +pub struct Queen { + position: ChessPosition, +} +pub trait ChessPiece { + fn position(&self) -> &ChessPosition; + fn can_attack(&self, other: &T) -> bool; +} - fn rank(&self) -> i8 { - self.position.rank() +impl ChessPiece for Queen { + fn position(&self) -> &ChessPosition { + &self.position } - fn file(&self) -> i8 { - self.position.file() - } - - fn sum(&self) -> i8 { - self.position.sum() + fn can_attack(&self, piece: &T) -> bool { + self.position.horizontal_from(&piece.position()) || + self.position.vertical_from(&piece.position()) || + self.position.diagonal_from(&piece.position()) } +} - fn difference(&self) -> i8 { - self.position.difference() +impl Queen { + pub fn new(position: ChessPosition) -> Queen { + Queen { position: position } } } -#[derive(Debug, PartialEq)] -struct ChessPosition { coordinates: (i8, i8) } +pub struct ChessPosition { + pub rank: i8, + pub file: i8, +} impl ChessPosition { - fn new(coordinates: (i8, i8)) -> ChessPosition { - ChessPosition {coordinates: coordinates} + pub fn new(rank: i8, file: i8) -> Result { + let position = ChessPosition { + rank: rank, + file: file, + }; + + if position.is_valid() { + Ok(position) + } else { + Err(String::from("Invalid Position")) + } + } + + fn is_valid(&self) -> bool { + self.rank >= 0 && self.rank <= 7 && self.file >= 0 && self.file <= 7 } - fn valid(&self) -> bool { - (self.rank() >= 0 && self.rank() <= 7) && - (self.file() >= 0 && self.file() <= 7) + fn horizontal_from(&self, other: &ChessPosition) -> bool { + self.rank == other.rank } - fn rank(&self) -> i8 { - self.coordinates.0 + fn vertical_from(&self, other: &ChessPosition) -> bool { + self.file == other.file } - fn file(&self) -> i8 { - self.coordinates.1 + fn diagonal_from(&self, other: &ChessPosition) -> bool { + self.sum() == other.sum() || self.difference() == other.difference() } fn sum(&self) -> i8 { - self.rank() + self.file() + self.rank + self.file } fn difference(&self) -> i8 { - self.rank() - self.file() + self.rank - self.file } } diff --git a/exercises/queen-attack/tests/queen-attack.rs b/exercises/queen-attack/tests/queen-attack.rs index 6f552ab95..73fb1154e 100644 --- a/exercises/queen-attack/tests/queen-attack.rs +++ b/exercises/queen-attack/tests/queen-attack.rs @@ -3,79 +3,84 @@ extern crate queen_attack; use queen_attack::*; #[test] -fn test_queen_creation_with_valid_position() { - let white_queen = Queen::new((2,4)); - assert!(white_queen.is_ok()); +fn chess_position_on_the_board_is_ok() { + assert!(ChessPosition::new(2, 4).is_ok()); } #[test] #[ignore] -fn test_queen_creation_with_incorrect_positions() { - let white_queen = Queen::new((-1,2)); - assert!(white_queen.is_err()); - - let white_queen = Queen::new((8,2)); - assert!(white_queen.is_err()); +fn chess_position_off_the_board_is_err() { + assert!(ChessPosition::new(-1, 2).is_err()); + assert!(ChessPosition::new(8, 2).is_err()); + assert!(ChessPosition::new(5, -1).is_err()); + assert!(ChessPosition::new(5, 8).is_err()); +} - let white_queen = Queen::new((5,-1)); - assert!(white_queen.is_err()); +#[test] +#[ignore] +fn queen_is_created_with_a_ok_position() { + Queen::new(ChessPosition::new(2, 4).unwrap()); +} - let white_queen = Queen::new((5,8)); - assert!(white_queen.is_err()); +#[test] +#[ignore] +#[should_panic(expected = "Invalid Position")] +fn queen_panics_with_err_position() { + Queen::new(ChessPosition::new(-1, 4).unwrap()); } #[test] #[ignore] -fn test_can_not_attack() { - let white_queen = Queen::new((2,4)).unwrap(); - let black_queen = Queen::new((6,6)).unwrap(); - assert_eq!(false, white_queen.can_attack(&black_queen)); +fn queens_that_can_not_attack() { + let white_queen = Queen::new(ChessPosition::new(2, 4).unwrap()); + let black_queen = Queen::new(ChessPosition::new(6, 6).unwrap()); + assert!(!white_queen.can_attack(&black_queen)); } #[test] #[ignore] -fn test_can_attack_on_same_rank() { - let white_queen = Queen::new((2,4)).unwrap(); - let black_queen = Queen::new((2,6)).unwrap(); +fn queens_on_the_same_rank_can_attack() { + let white_queen = Queen::new(ChessPosition::new(2, 4).unwrap()); + let black_queen = Queen::new(ChessPosition::new(2, 6).unwrap()); assert!(white_queen.can_attack(&black_queen)); } #[test] #[ignore] -fn test_can_attack_on_same_file() { - let white_queen = Queen::new((4,5)).unwrap(); - let black_queen = Queen::new((3,5)).unwrap(); +fn queens_on_the_same_file_can_attack() { + let white_queen = Queen::new(ChessPosition::new(4, 5).unwrap()); + let black_queen = Queen::new(ChessPosition::new(3, 5).unwrap()); assert!(white_queen.can_attack(&black_queen)); } #[test] #[ignore] -fn test_can_attack_on_first_diagonal() { - let white_queen = Queen::new((2,2)).unwrap(); - let black_queen = Queen::new((0,4)).unwrap(); +fn queens_on_the_same_diagonal_can_attack_one() { + let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap()); + let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap()); assert!(white_queen.can_attack(&black_queen)); } #[test] #[ignore] -fn test_can_attack_on_second_diagonal() { - let white_queen = Queen::new((2,2)).unwrap(); - let black_queen = Queen::new((3,1)).unwrap(); +fn queens_on_the_same_diagonal_can_attack_two() { + let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap()); + let black_queen = Queen::new(ChessPosition::new(3, 1).unwrap()); assert!(white_queen.can_attack(&black_queen)); } #[test] #[ignore] -fn test_can_attack_on_third_diagonal() { - let white_queen = Queen::new((2,2)).unwrap(); - let black_queen = Queen::new((1,1)).unwrap(); +fn queens_on_the_same_diagonal_can_attack_three() { + let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap()); + let black_queen = Queen::new(ChessPosition::new(1, 1).unwrap()); assert!(white_queen.can_attack(&black_queen)); } #[test] #[ignore] -fn test_can_attack_on_fourth_diagonal() { - let white_queen = Queen::new((2,2)).unwrap(); - let black_queen = Queen::new((5,5)).unwrap(); +fn queens_on_the_same_diagonal_can_attack_four() { + let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap()); + let black_queen = Queen::new(ChessPosition::new(5, 5).unwrap()); assert!(white_queen.can_attack(&black_queen)); }