forked from BeLuckyDaf/snakes-game-tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Snake.java
122 lines (102 loc) · 3.51 KB
/
Snake.java
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
package snakes;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
/**
* This class implements snake body (the brain is your bot) that
* determines the place of head and body, length of body, etc on the game board
*/
public class Snake implements Cloneable {
public final HashSet<Coordinate> elements; // To quickly check intersections
public final Deque<Coordinate> body; // Instead of ArrayList; this is more efficient and logical
// Those two contain same values, but for different purposes
public final Coordinate mazeSize;
/**
* Construct a snake with the body that defined in elements HashSet
*
* @param mazeSize size of the board
* @param elements Coordinates that define body elements of the snake
* @param body Coordinates that define body elements of the snake
*/
private Snake(Coordinate mazeSize, HashSet<Coordinate> elements, Deque<Coordinate> body) {
this.mazeSize = mazeSize;
this.elements = elements;
this.body = body;
}
/**
* Initialize snake with length 1
*
* @param initialHead coordinate of initial position of snake
* @param mazeSize size of the board
*/
public Snake(Coordinate initialHead, Coordinate mazeSize) {
this(mazeSize, new HashSet<Coordinate>(), new LinkedList<Coordinate>());
body.addFirst(initialHead);
elements.add(initialHead);
}
/**
* Construct snake with predefined length
*
* @param head An initial coordinate of snake's head
* @param tailDirection An initial direction of the snake's tail in which direction snake should grow
* @param size A size of snake after expansion
* @param mazeSize size of the board
*/
public Snake(Coordinate head, Direction tailDirection, int size, Coordinate mazeSize) {
this(head, mazeSize);
Coordinate p = head.moveTo(tailDirection);
for (int i = 0; i < size - 1; i++) {
body.addLast(p);
elements.add(p);
p = p.moveTo(tailDirection);
}
}
/**
* Get head position
*
* @return Coordinates with place of snake's head
*/
public Coordinate getHead() {
return body.getFirst();
}
/**
* Move snake in direction
*
* @param d direction where should snake crawl
* @param grow True - if snake eat an apple
* @return False - if collides with itself or maze bounds
*/
public boolean moveTo(Direction d, boolean grow) {
Coordinate newHead = getHead().moveTo(d);
if (!newHead.inBounds(mazeSize))
return false; // Left maze
if (!grow) {
elements.remove(body.removeLast());
}
if (elements.contains(newHead))
return false; // Collided with itself
body.addFirst(newHead);
elements.add(newHead);
return true;
}
/**
* Check whether head collides with another snake
*
* @param other Snake body of opponent's snake
* @return True - if collides with another snake
*/
public boolean headCollidesWith(Snake other) {
return other.elements.contains(getHead());
}
/**
* Clone snake
*
* @return copy of current snake
*/
@Override
public Snake clone() {
HashSet<Coordinate> newElements = new HashSet<>(elements);
LinkedList<Coordinate> newBody = new LinkedList<>(body);
return new Snake(mazeSize, newElements, newBody);
}
}