Skip to content

Commit 3a5be47

Browse files
Extract FieldInfo to table module
1 parent 2183385 commit 3a5be47

File tree

6 files changed

+74
-66
lines changed

6 files changed

+74
-66
lines changed

minesweeper/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod minesweeper_logic;
22
pub use minesweeper_logic::basic_types::SizeType;
3-
pub use minesweeper_logic::field_type::FieldType;
3+
pub use minesweeper_logic::field_info::FieldType;
44
pub use minesweeper_logic::game::{Game, GameLevel};
55
pub use minesweeper_logic::results::{FlagResult, OpenInfo, OpenResult};

minesweeper/src/main.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use minesweeper::{FlagResult, Game, GameLevel, OpenResult, SizeType};
1+
use minesweeper::{FieldType, FlagResult, Game, GameLevel, OpenResult, SizeType};
22

33
use std::io;
44
use std::vec::Vec;
@@ -42,6 +42,14 @@ fn print_fields(fields: &Vec<Vec<char>>) {
4242
print_horizontal_line();
4343
}
4444

45+
fn get_char_repr(field_type: &FieldType) -> char {
46+
match field_type {
47+
FieldType::Empty => ' ',
48+
FieldType::Numbered(x) => std::char::from_digit(*x as u32, 10).unwrap(),
49+
FieldType::Mine => 'X',
50+
}
51+
}
52+
4553
#[derive(Debug)]
4654
enum Action {
4755
Open,
@@ -94,7 +102,7 @@ fn main() {
94102
Ok((Action::Open, r, c)) => {
95103
let open_result = g.open(r, c).expect("Unable to open field");
96104
for (coords, field_type) in &open_result.newly_opened_fields {
97-
fields[coords.0 as usize][coords.1 as usize] = field_type.get_char_repr();
105+
fields[coords.0 as usize][coords.1 as usize] = get_char_repr(field_type);
98106
}
99107
last_result = open_result.result;
100108
}

minesweeper/src/minesweeper_logic/field_type.rs renamed to minesweeper/src/minesweeper_logic/field_info.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
11
use strum_macros::Display;
22

3-
#[repr(C)]
43
#[derive(Clone, Copy, Eq, PartialEq, Display, Debug)]
4+
pub enum FieldState {
5+
Closed,
6+
Opened,
7+
Flagged,
8+
}
9+
10+
impl FieldState {
11+
pub fn is_opened(&self) -> bool {
12+
self == &FieldState::Opened
13+
}
14+
15+
pub fn is_flagged(&self) -> bool {
16+
self == &FieldState::Flagged
17+
}
18+
}
19+
20+
#[repr(C)]
21+
#[derive(Clone, Eq, PartialEq, Display, Debug)]
522
pub enum FieldType {
623
Empty,
724
Numbered(u8),
@@ -26,12 +43,11 @@ impl FieldType {
2643
_ => false,
2744
}
2845
}
46+
}
2947

30-
pub fn get_char_repr(&self) -> char {
31-
match self {
32-
FieldType::Empty => ' ',
33-
FieldType::Numbered(x) => std::char::from_digit(*x as u32, 10).unwrap(),
34-
FieldType::Mine => 'X',
35-
}
36-
}
48+
#[repr(C)]
49+
#[derive(Clone, Eq, PartialEq, Debug)]
50+
pub struct FieldInfo {
51+
pub state: FieldState,
52+
pub field_type: FieldType,
3753
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub mod basic_types;
2-
pub mod field_type;
2+
pub mod field_info;
33
pub mod game;
44
pub mod results;
55
mod table;

minesweeper/src/minesweeper_logic/results.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::basic_types::SizeType;
2-
use super::field_type::FieldType;
2+
use super::field_info::FieldType;
33
use std::collections::HashMap;
44
use strum_macros::Display;
55

minesweeper/src/minesweeper_logic/table.rs

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::basic_types::SizeType;
2-
use super::field_type::FieldType;
2+
use super::field_info::{FieldInfo, FieldState, FieldType};
33
use super::results::{FlagResult, OpenInfo, OpenResult};
44
use indexmap::IndexSet;
55
use mockall::automock;
@@ -15,27 +15,9 @@ static TOO_FEW_MINES_ERROR: &'static str = "Too few mines!";
1515
static MINE_DOES_NOT_HAVE_VALUE_ERROR: &'static str = "Mine does not have value!";
1616
static OPENED_FIELD_CAN_NOT_BE_UPDATED_ERROR: &'static str = "An opened field can not be updated!";
1717

18-
#[derive(Eq, PartialEq, Display, Debug, Clone, Copy)]
19-
enum FieldState {
20-
Closed,
21-
Opened,
22-
Flagged,
23-
}
24-
25-
impl FieldState {
26-
fn is_opened(&self) -> bool {
27-
self == &FieldState::Opened
28-
}
29-
30-
fn is_flagged(&self) -> bool {
31-
self == &FieldState::Flagged
32-
}
33-
}
34-
3518
trait Field {
3619
fn get_field_state(&self) -> FieldState;
3720
fn get_field_type(&self) -> FieldType;
38-
fn get_char_repr(&self) -> char;
3921
}
4022

4123
#[automock]
@@ -58,8 +40,7 @@ enum FieldOpenResult {
5840

5941
#[derive(Debug, Eq, PartialEq)]
6042
struct FieldInner {
61-
field_type: FieldType,
62-
state: FieldState,
43+
field_info: FieldInfo,
6344
}
6445

6546
impl FieldInner {
@@ -69,8 +50,10 @@ impl FieldInner {
6950

7051
fn new_with_field_type(field_type: FieldType) -> FieldInner {
7152
FieldInner {
72-
field_type,
73-
state: FieldState::Closed,
53+
field_info: FieldInfo {
54+
state: FieldState::Closed,
55+
field_type,
56+
},
7457
}
7558
}
7659

@@ -91,60 +74,60 @@ impl FieldInner {
9174
}
9275

9376
fn update_type_to_mine(&mut self) -> Result<(), &'static str> {
94-
if self.state == FieldState::Opened {
77+
if self.field_info.state == FieldState::Opened {
9578
Err(OPENED_FIELD_CAN_NOT_BE_UPDATED_ERROR)
9679
} else {
97-
self.field_type = FieldType::Mine;
80+
self.field_info.field_type = FieldType::Mine;
9881
Ok(())
9982
}
10083
}
10184

10285
fn update_type_to_empty(&mut self) -> Result<(), &'static str> {
103-
if self.state == FieldState::Opened {
86+
if self.field_info.state == FieldState::Opened {
10487
Err(OPENED_FIELD_CAN_NOT_BE_UPDATED_ERROR)
10588
} else {
106-
self.field_type = FieldType::Empty;
89+
self.field_info.field_type = FieldType::Empty;
10790
Ok(())
10891
}
10992
}
11093

11194
fn update_type_with_value(&mut self, value: u8) -> Result<(), &'static str> {
112-
if self.state == FieldState::Opened {
95+
if self.field_info.state == FieldState::Opened {
11396
Err(OPENED_FIELD_CAN_NOT_BE_UPDATED_ERROR)
11497
} else if !FieldInner::is_valid_value(value) {
11598
Err(INVALID_VALUE_ERROR)
11699
} else {
117-
self.field_type = FieldType::Numbered(value);
100+
self.field_info.field_type = FieldType::Numbered(value);
118101
Ok(())
119102
}
120103
}
121104

122105
fn get_open_result_inner(&self) -> FieldOpenResult {
123-
match self.field_type {
106+
match self.field_info.field_type {
124107
FieldType::Empty => FieldOpenResult::MultiOpen,
125108
FieldType::Numbered(_) => FieldOpenResult::SimpleOpen,
126109
FieldType::Mine => FieldOpenResult::Boom,
127110
}
128111
}
129112

130113
fn open(&mut self) -> FieldOpenResult {
131-
if self.get_field_state().is_flagged() {
114+
if self.field_info.state.is_flagged() {
132115
FieldOpenResult::IsFlagged
133-
} else if self.get_field_state().is_opened() {
116+
} else if self.field_info.state.is_opened() {
134117
FieldOpenResult::AlreadyOpened
135118
} else {
136-
self.state = FieldState::Opened;
119+
self.field_info.state = FieldState::Opened;
137120
self.get_open_result_inner()
138121
}
139122
}
140123

141124
fn toggle_flag(&mut self) -> FlagResult {
142-
if self.state.is_flagged() {
143-
self.state = FieldState::Closed;
125+
if self.field_info.state.is_flagged() {
126+
self.field_info.state = FieldState::Closed;
144127
FlagResult::FlagRemoved
145128
} else {
146-
if !self.get_field_state().is_opened() {
147-
self.state = FieldState::Flagged;
129+
if !self.field_info.state.is_opened() {
130+
self.field_info.state = FieldState::Flagged;
148131
FlagResult::Flagged
149132
} else {
150133
FlagResult::AlreadyOpened
@@ -155,21 +138,11 @@ impl FieldInner {
155138

156139
impl Field for FieldInner {
157140
fn get_field_state(&self) -> FieldState {
158-
self.state
141+
self.field_info.state
159142
}
160143

161144
fn get_field_type(&self) -> FieldType {
162-
self.field_type
163-
}
164-
165-
fn get_char_repr(&self) -> char {
166-
if self.state.is_flagged() {
167-
'H'
168-
} else if !self.state.is_opened() {
169-
'O'
170-
} else {
171-
self.field_type.get_char_repr()
172-
}
145+
self.field_info.field_type.clone()
173146
}
174147
}
175148

@@ -407,11 +380,17 @@ impl BasicTable {
407380
}
408381

409382
fn move_mine(&mut self, row: SizeType, col: SizeType) -> Result<(), &'static str> {
410-
if self.fields[row as usize][col as usize].field_type.is_mine() {
383+
if self.fields[row as usize][col as usize]
384+
.get_field_type()
385+
.is_mine()
386+
{
411387
let mut new_place = (0, 0);
412388
let mut visiter = FieldVisiter::new(self.height, self.width, row, col)?;
413389
while let Some((r, c)) = visiter.next() {
414-
if !self.fields[r as usize][c as usize].field_type.is_mine() {
390+
if !self.fields[r as usize][c as usize]
391+
.get_field_type()
392+
.is_mine()
393+
{
415394
new_place = (r, c);
416395
break;
417396
}
@@ -434,7 +413,10 @@ impl BasicTable {
434413
);
435414
fields_to_recalculate.insert((row, col));
436415
for (r, c) in fields_to_recalculate {
437-
if !self.fields[r as usize][c as usize].field_type.is_mine() {
416+
if !self.fields[r as usize][c as usize]
417+
.get_field_type()
418+
.is_mine()
419+
{
438420
let field_value = self.get_field_value(r, c).unwrap();
439421
match field_value {
440422
0 => self.fields[r as usize][c as usize]
@@ -560,7 +542,9 @@ impl Table for BasicTable {
560542
}
561543

562544
if self.number_of_opened_fields == 0
563-
&& self.fields[row as usize][col as usize].field_type.is_mine()
545+
&& self.fields[row as usize][col as usize]
546+
.get_field_type()
547+
.is_mine()
564548
{
565549
self.move_mine(row, col)?;
566550
}

0 commit comments

Comments
 (0)