Queen Attack
1. Readme
女王攻击
给定棋盘上的两个皇后的位置,指示在各自位置的它们,是否能互相攻击。
在象棋游戏中,女王可以攻击同一行、列或对角线上的棋子。
棋盘可以用 8 乘 8 的数组来表示。
所以如果你告诉白皇后在(2, 3)和黑皇后在(5, 6),那么设定像这样:
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ W _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ B _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
你也可以回答女王是否可以互相攻击。而在这种情况下,答案是肯定的,他们可以,因为这两个部分共用一个对角线。
资源
J Dalbey 的程序设计实践问题http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html
2. 开始你的表演
#[derive(Debug)] pub struct ChessPosition; #[derive(Debug)] pub struct Queen; impl ChessPosition { pub fn new(rank: i32, file: i32) -> Option<Self> { unimplemented!( "Construct a ChessPosition struct, given the following rank, file: ({}, {}). If the position is invalid return None.", rank, file ); } } impl Queen { pub fn new(position: ChessPosition) -> Self { unimplemented!( "Given the chess position {:?}, construct a Queen struct.", position ); } pub fn can_attack(&self, other: &Queen) -> bool { unimplemented!( "Determine if this Queen can attack the other Queen {:?}", other ); } }
3. 测试代码查看
# #![allow(unused_variables)] #fn main() { #[test] fn chess_position_on_the_board_is_some() { assert!(ChessPosition::new(2, 4).is_some()); } #[test] //#[ignore] fn chess_position_off_the_board_is_none() { assert!(ChessPosition::new(-1, 2).is_none()); assert!(ChessPosition::new(8, 2).is_none()); assert!(ChessPosition::new(5, -1).is_none()); assert!(ChessPosition::new(5, 8).is_none()); } #[test] //#[ignore] fn queen_is_created_with_a_valid_position() { Queen::new(ChessPosition::new(2, 4).unwrap()); } #[test] //#[ignore] 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 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 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 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 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 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 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)); } #}
4. 答案
# #![allow(unused_variables)] #fn main() { #[derive(Debug)] pub struct Queen { position: ChessPosition, } pub trait ChessPiece { fn position(&self) -> &ChessPosition; fn can_attack<T: ChessPiece>(&self, other: &T) -> bool; } impl ChessPiece for Queen { fn position(&self) -> &ChessPosition { &self.position } fn can_attack<T: ChessPiece>(&self, piece: &T) -> bool { self.position.horizontal_from(&piece.position()) || self.position.vertical_from(&piece.position()) || self.position.diagonal_from(&piece.position()) } } impl Queen { pub fn new(position: ChessPosition) -> Queen { Queen { position: position } } } #[derive(Debug)] pub struct ChessPosition { pub rank: i8, pub file: i8, } impl ChessPosition { pub fn new(rank: i8, file: i8) -> Option<Self> { let position = ChessPosition { rank: rank, file: file, }; if position.is_valid() { Some(position) } else { None } } fn is_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 vertical_from(&self, other: &ChessPosition) -> bool { self.file == other.file } fn diagonal_from(&self, other: &ChessPosition) -> bool { self.sum() == other.sum() || self.difference() == other.difference() } fn sum(&self) -> i8 { self.rank + self.file } fn difference(&self) -> i8 { self.rank - self.file } } #}