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
   }
}

#}



填充/相关