+170
src/game.rs
+170
src/game.rs
···
···
1
+
use std::{
2
+
fmt::{Display, Formatter},
3
+
ops::{Index, IndexMut},
4
+
};
5
+
6
+
#[derive(Debug, PartialEq, Eq)]
7
+
pub struct Vector2u16 {
8
+
pub x: u16,
9
+
pub y: u16,
10
+
}
11
+
12
+
impl Vector2u16 {
13
+
pub fn new(x: u16, y: u16) -> Self {
14
+
Vector2u16 { x, y }
15
+
}
16
+
}
17
+
18
+
#[derive(Debug, PartialEq, Eq)]
19
+
pub struct Boat {
20
+
pub first_pos: Vector2u16,
21
+
pub last_pos: Vector2u16,
22
+
}
23
+
24
+
impl Boat {
25
+
pub fn new(first_pos: Vector2u16, last_pos: Vector2u16) -> Self {
26
+
Boat {
27
+
first_pos,
28
+
last_pos,
29
+
}
30
+
}
31
+
}
32
+
33
+
#[derive(Debug, PartialEq, Eq)]
34
+
pub struct Board {
35
+
pub cells: [BoardCell; 64],
36
+
}
37
+
38
+
impl Display for Board {
39
+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40
+
writeln!(f, " | A B C D E F G H ")?;
41
+
writeln!(f, "---+-----------------")?;
42
+
43
+
for row in 1..=8 {
44
+
writeln!(
45
+
f,
46
+
" {row} | {} {} {} {} {} {} {} {}",
47
+
self.cells[8 * row - 1],
48
+
self.cells[8 * row],
49
+
self.cells[8 * row + 1],
50
+
self.cells[8 * row + 2],
51
+
self.cells[8 * row + 3],
52
+
self.cells[8 * row + 4],
53
+
self.cells[8 * row + 5],
54
+
self.cells[8 * row + 6],
55
+
)?;
56
+
}
57
+
58
+
Ok(())
59
+
}
60
+
}
61
+
62
+
impl Default for Board {
63
+
fn default() -> Self {
64
+
Self {
65
+
cells: [Default::default(); 64],
66
+
}
67
+
}
68
+
}
69
+
70
+
impl Index<Vector2u16> for Board {
71
+
type Output = BoardCell;
72
+
73
+
fn index(&self, index: Vector2u16) -> &Self::Output {
74
+
&self.cells[index.y as usize * 8 + index.x as usize]
75
+
}
76
+
}
77
+
78
+
impl IndexMut<Vector2u16> for Board {
79
+
fn index_mut(&mut self, index: Vector2u16) -> &mut Self::Output {
80
+
&mut self.cells[index.y as usize * 8 + index.x as usize]
81
+
}
82
+
}
83
+
84
+
impl Board {
85
+
fn new(boats: impl IntoIterator<Item = Boat>) -> Self {
86
+
let mut board = Self::default();
87
+
88
+
for (i, boat) in boats.into_iter().enumerate() {
89
+
let start_x = boat.first_pos.x.min(boat.last_pos.x);
90
+
let start_y = boat.first_pos.y.min(boat.last_pos.y);
91
+
let end_x = boat.first_pos.x.max(boat.last_pos.x);
92
+
let end_y = boat.first_pos.y.max(boat.last_pos.y);
93
+
94
+
for x in start_x..=end_x {
95
+
for y in start_y..=end_y {
96
+
board[Vector2u16 { x, y }] = BoardCell::Boat(i as u8);
97
+
}
98
+
}
99
+
}
100
+
101
+
board
102
+
}
103
+
}
104
+
105
+
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
106
+
pub enum BoardCell {
107
+
#[default]
108
+
Nothing,
109
+
Missed,
110
+
Hit,
111
+
Boat(u8),
112
+
}
113
+
114
+
impl Display for BoardCell {
115
+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
116
+
match self {
117
+
BoardCell::Nothing => write!(f, "."),
118
+
BoardCell::Missed => write!(f, "o"),
119
+
BoardCell::Hit => write!(f, "x"),
120
+
BoardCell::Boat(n) => write!(f, "{n}"),
121
+
}
122
+
}
123
+
}
124
+
125
+
#[cfg(test)]
126
+
mod tests {
127
+
use super::*;
128
+
129
+
#[test]
130
+
fn empty_board() {
131
+
assert_eq!(
132
+
Board::default(),
133
+
Board {
134
+
cells: [Default::default(); 64],
135
+
}
136
+
);
137
+
}
138
+
139
+
#[test]
140
+
fn init_boards_with_boats() {
141
+
let board = Board::new([
142
+
Boat::new(Vector2u16 { x: 2, y: 0 }, Vector2u16 { x: 2, y: 1 }),
143
+
Boat::new(Vector2u16 { x: 3, y: 3 }, Vector2u16 { x: 5, y: 3 }),
144
+
Boat::new(Vector2u16 { x: 1, y: 4 }, Vector2u16 { x: 1, y: 7 }),
145
+
Boat::new(Vector2u16 { x: 3, y: 6 }, Vector2u16 { x: 7, y: 6 }),
146
+
]);
147
+
148
+
let n = BoardCell::Nothing;
149
+
let a = BoardCell::Boat(0);
150
+
let b = BoardCell::Boat(1);
151
+
let c = BoardCell::Boat(2);
152
+
let d = BoardCell::Boat(3);
153
+
154
+
assert_eq!(
155
+
board,
156
+
Board {
157
+
cells: [
158
+
n, n, a, n, n, n, n, n, //
159
+
n, n, a, n, n, n, n, n, //
160
+
n, n, n, n, n, n, n, n, //
161
+
n, n, n, b, b, b, n, n, //
162
+
n, c, n, n, n, n, n, n, //
163
+
n, c, n, n, n, n, n, n, //
164
+
n, c, n, d, d, d, d, d, //
165
+
n, c, n, n, n, n, n, n,
166
+
],
167
+
}
168
+
);
169
+
}
170
+
}
+2
src/main.rs
+2
src/main.rs
+1
-27
src/parser.rs
+1
-27
src/parser.rs
···
1
use std::{fs::File, io::Read, path::Path};
2
3
#[derive(Debug)]
···
14
}
15
}
16
17
-
#[derive(Debug, PartialEq, Eq)]
18
-
pub struct Vector2u16 {
19
-
x: u16,
20
-
y: u16,
21
-
}
22
-
23
-
impl Vector2u16 {
24
-
pub fn new(x: u16, y: u16) -> Self {
25
-
Vector2u16 { x: x, y: y }
26
-
}
27
-
}
28
-
29
-
#[derive(Debug, PartialEq, Eq)]
30
-
pub struct Boat {
31
-
first_pos: Vector2u16,
32
-
last_pos: Vector2u16,
33
-
}
34
-
35
-
impl Boat {
36
-
pub fn new(first_pos: Vector2u16, last_pos: Vector2u16) -> Self {
37
-
Boat {
38
-
first_pos: first_pos,
39
-
last_pos: last_pos,
40
-
}
41
-
}
42
-
}
43
-
44
pub fn parse_file(file_path: &Path) -> Result<[Boat; 4], ParserError> {
45
let mut file = File::open(file_path)?;
46
Ok(parse_ships(&mut file)?)