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