Minesweeper

1. Readme

扫雷

将数字添加到扫雷板上.

扫雷器是一个流行的游戏,其中用户要用数字提示,来找到地雷,这些数字提示指示有多少地雷直接相邻(水平,垂直,对角,总 9 个格),围成一个正方形.

在这个练习中,您必须创建一些代码,这些代码计算与正方形相邻的地雷数量,并且像这样转换地雷板(其中*表示地雷):

    +-----+
    | * * |
    |  *  |
    |  *  |
    |     |
    +-----+

变成:

    +-----+
    |1*3*1|
    |13*31|
    | 2*2 |
    | 111 |
    +-----+

2. 开始你的表演

pub fn annotate(minefield: &[&str]) -> Vec<String> {
   unimplemented!("\nAnnotate each square of the given minefield with the number of mines that surround said square (blank if there are no surrounding mines):\n{:#?}\n", minefield);
}

3. 测试代码查看


# #![allow(unused_variables)]
#fn main() {
fn remove_annotations(board: &[&str]) -> Vec<String> {
   board.iter().map(|r| remove_annotations_in_row(r)).collect()
}

fn remove_annotations_in_row(row: &str) -> String {
   row.chars()
       .map(|ch| match ch {
           '*' => '*',
           _ => ' ',
       })
       .collect()
}

fn run_test(test_case: &[&str]) {
   let cleaned = remove_annotations(test_case);
   let cleaned_strs = cleaned.iter().map(|r| &r[..]).collect::<Vec<_>>();
   let expected = test_case.iter().map(|&r| r.to_string()).collect::<Vec<_>>();
   assert_eq!(expected, annotate(&cleaned_strs));
}

#[test]
fn no_rows() {
   run_test(&[]);
}

#[test]
//#[ignore]
fn no_columns() {
   run_test(&[""]);
}

#[test]
//#[ignore]
fn no_mines() {
   run_test(&["   ", "   ", "   "]);
}

#[test]
//#[ignore]
fn board_with_only_mines() {
   run_test(&["***", "***", "***"]);
}

#[test]
//#[ignore]
fn mine_surrounded_by_spaces() {
   run_test(&["111", "1*1", "111"]);
}

#[test]
//#[ignore]
fn space_surrounded_by_mines() {
   run_test(&["***", "*8*", "***"]);
}

#[test]
//#[ignore]
fn horizontal_line() {
   run_test(&["1*2*1"]);
}

#[test]
//#[ignore]
fn horizontal_line_mines_at_edges() {
   run_test(&["*1 1*"]);
}

#[test]
//#[ignore]
fn vertical_line() {
   run_test(&["1", "*", "2", "*", "1"]);
}

#[test]
//#[ignore]
fn vertical_line_mines_at_edges() {
   run_test(&["*", "1", " ", "1", "*"]);
}

#[test]
//#[ignore]
fn cross() {
   run_test(&[" 2*2 ", "25*52", "*****", "25*52", " 2*2 "]);
}

#[test]
//#[ignore]
fn large_board() {
   run_test(&["1*22*1", "12*322", " 123*2", "112*4*", "1*22*2", "111111"]);
}

#}

4. 答案


# #![allow(unused_variables)]
#fn main() {
struct Board {
   pieces: Vec<Vec<char>>,
   num_rows: usize,
   num_cols: usize
}

impl Board {
   fn annotated(&self) -> Vec<String> {
       (0..self.num_rows).map(|y| self.annotated_row(y)).collect()
   }

   fn annotated_row(&self, y: usize) -> String {
       self.pieces[y]
                 .iter()
                 .enumerate()
                 .map(|(x,&c)| if c == ' ' {self.count_neighbouring_mines_char(x, y)} else {c})
                 .collect::<String>()
   }

   fn count_neighbouring_mines_char(&self, x: usize, y: usize) -> char {
       let mut count = 0;
       for x1 in neighbouring_points(x, self.num_cols) {
           for y1 in neighbouring_points(y, self.num_rows) {
               let piece = self.pieces[y1][x1];
               if piece == '*' {
                   count += 1;
               }
           }
       }
       if count == 0 {
           ' '
       } else {
           (('0' as u8) + count) as char
       }
   }
}

pub fn annotate(pieces: &[&str]) -> Vec<String> {
   if pieces.len() == 0 {
       return Vec::new();
   }
   let pieces_vec = pieces.iter().map(|&r| r.chars().collect()).collect();
   Board {pieces: pieces_vec, num_rows: pieces.len(), num_cols: pieces[0].len()}.annotated()
}

fn neighbouring_points(x: usize, limit: usize) -> Vec<usize> {
   let mut offsets = vec![x];
   if x >= 1 {
       offsets.push(x-1);
   }
   if x+2 <= limit {
       offsets.push(x+1);
   }
   offsets
}

#}



填充/相关