-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsnake.rs
134 lines (116 loc) · 3.25 KB
/
snake.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use piston_window::types::Color;
use piston_window::{Context, G2d};
use std::collections::LinkedList;
use crate::draw::draw_block;
const SNAKE_COLOR: Color = [0.00, 0.80, 0.00, 1.0];
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Direction {
Up,
Down,
Left,
Right,
}
impl Direction {
pub fn opposite(&self) -> Direction {
match *self {
Direction::Up => Direction::Down,
Direction::Down => Direction::Up,
Direction::Left => Direction::Right,
Direction::Right => Direction::Left,
}
}
}
#[derive(Debug, Clone)]
struct Block {
x: i32,
y: i32,
}
pub struct Snake {
direction: Direction,
body: LinkedList<Block>,
tail: Option<Block>,
}
impl Snake {
pub fn new(x: i32, y: i32) -> Self {
let mut body = LinkedList::new();
body.push_back(Block { x: x + 2, y });
body.push_back(Block { x: x + 1, y });
body.push_back(Block { x, y });
Snake {
direction: Direction::Right,
body,
tail: None,
}
}
pub fn draw(&self, con: &Context, g: &mut G2d) {
for block in &self.body {
draw_block(SNAKE_COLOR, block.x, block.y, con, g);
}
}
pub fn head_position(&self) -> (i32, i32) {
let head_block = self.body.front().unwrap();
(head_block.x, head_block.y)
}
pub fn move_forward(&mut self, dir: Option<Direction>) {
match dir {
Some(d) => self.direction = d,
None => (),
}
let (last_x, last_y) = self.head_position();
let new_block = match self.direction {
Direction::Up => Block {
x: last_x,
y: last_y - 1,
},
Direction::Down => Block {
x: last_x,
y: last_y + 1,
},
Direction::Left => Block {
x: last_x - 1,
y: last_y,
},
Direction::Right => Block {
x: last_x + 1,
y: last_y,
},
};
self.body.push_front(new_block);
let removed_block = self.body.pop_back().unwrap();
self.tail = Some(removed_block);
}
pub fn head_direction(&self) -> Direction {
self.direction
}
pub fn next_head(&self, dir: Option<Direction>) -> (i32, i32) {
let (head_x, head_y) = self.head_position();
let mut moving_dir = self.direction;
match dir {
Some(d) => moving_dir = d,
None => {}
}
match moving_dir {
Direction::Up => (head_x, head_y - 1),
Direction::Down => (head_x, head_y + 1),
Direction::Left => (head_x - 1, head_y),
Direction::Right => (head_x + 1, head_y),
}
}
pub fn restore_tail(&mut self) {
let blk = self.tail.clone().unwrap();
self.body.push_back(blk);
}
pub fn overlap_tail(&self, x: i32, y: i32) -> bool {
let mut ch = 0;
for block in &self.body {
if x == block.x && y == block.y {
return true;
}
ch += 1;
if ch == self.body.len() - 1 {
break;
}
}
false
}
}