Lines 16-39
Link Here
|
16 |
*/ |
16 |
*/ |
17 |
package websocket.snake; |
17 |
package websocket.snake; |
18 |
|
18 |
|
|
|
19 |
import org.apache.catalina.websocket.WsOutbound; |
20 |
|
19 |
import java.io.IOException; |
21 |
import java.io.IOException; |
20 |
import java.nio.CharBuffer; |
22 |
import java.nio.CharBuffer; |
21 |
import java.util.ArrayDeque; |
23 |
import java.util.ArrayDeque; |
22 |
import java.util.Collection; |
24 |
import java.util.Collection; |
23 |
import java.util.Deque; |
25 |
import java.util.Deque; |
24 |
import java.util.Iterator; |
|
|
25 |
|
26 |
|
26 |
import org.apache.catalina.websocket.WsOutbound; |
|
|
27 |
|
28 |
public class Snake { |
27 |
public class Snake { |
29 |
|
28 |
|
30 |
private static final int DEFAULT_LENGTH = 6; |
29 |
private static final int DEFAULT_LENGTH = 5; |
31 |
|
30 |
|
32 |
private final int id; |
31 |
private final int id; |
33 |
private final WsOutbound outbound; |
32 |
private final WsOutbound outbound; |
34 |
|
33 |
|
35 |
private Direction direction; |
34 |
private Direction direction; |
36 |
private Deque<Location> locations = new ArrayDeque<Location>(); |
35 |
private int length = DEFAULT_LENGTH; |
|
|
36 |
private Location head; |
37 |
private Deque<Location> tail = new ArrayDeque<Location>(); |
37 |
private String hexColor; |
38 |
private String hexColor; |
38 |
|
39 |
|
39 |
public Snake(int id, WsOutbound outbound) { |
40 |
public Snake(int id, WsOutbound outbound) { |
Lines 45-58
Link Here
|
45 |
|
46 |
|
46 |
private void resetState() { |
47 |
private void resetState() { |
47 |
this.direction = Direction.NONE; |
48 |
this.direction = Direction.NONE; |
48 |
this.locations.clear(); |
49 |
this.head = SnakeWebSocketServlet.getRandomLocation(); |
49 |
Location startLocation = SnakeWebSocketServlet.getRandomLocation(); |
50 |
this.tail.clear(); |
50 |
for (int i = 0; i < DEFAULT_LENGTH; i++) { |
51 |
this.length = DEFAULT_LENGTH; |
51 |
locations.add(startLocation); |
|
|
52 |
} |
52 |
} |
53 |
} |
|
|
54 |
|
53 |
|
55 |
private void kill() { |
54 |
private synchronized void kill() { |
56 |
resetState(); |
55 |
resetState(); |
57 |
try { |
56 |
try { |
58 |
CharBuffer response = CharBuffer.wrap("{'type': 'dead'}"); |
57 |
CharBuffer response = CharBuffer.wrap("{'type': 'dead'}"); |
Lines 62-69
Link Here
|
62 |
} |
61 |
} |
63 |
} |
62 |
} |
64 |
|
63 |
|
65 |
private void reward() { |
64 |
private synchronized void reward() { |
66 |
grow(); |
65 |
length++; |
67 |
try { |
66 |
try { |
68 |
CharBuffer response = CharBuffer.wrap("{'type': 'kill'}"); |
67 |
CharBuffer response = CharBuffer.wrap("{'type': 'kill'}"); |
69 |
outbound.writeTextMessage(response); |
68 |
outbound.writeTextMessage(response); |
Lines 73-80
Link Here
|
73 |
} |
72 |
} |
74 |
|
73 |
|
75 |
public synchronized void update(Collection<Snake> snakes) { |
74 |
public synchronized void update(Collection<Snake> snakes) { |
76 |
Location firstLocation = locations.getFirst(); |
75 |
Location nextLocation = head.getAdjacentLocation(direction); |
77 |
Location nextLocation = firstLocation.getAdjacentLocation(direction); |
|
|
78 |
if (nextLocation.x >= SnakeWebSocketServlet.PLAYFIELD_WIDTH) { |
76 |
if (nextLocation.x >= SnakeWebSocketServlet.PLAYFIELD_WIDTH) { |
79 |
nextLocation.x = 0; |
77 |
nextLocation.x = 0; |
80 |
} |
78 |
} |
Lines 87-129
Link Here
|
87 |
if (nextLocation.y < 0) { |
85 |
if (nextLocation.y < 0) { |
88 |
nextLocation.y = SnakeWebSocketServlet.PLAYFIELD_HEIGHT; |
86 |
nextLocation.y = SnakeWebSocketServlet.PLAYFIELD_HEIGHT; |
89 |
} |
87 |
} |
90 |
locations.addFirst(nextLocation); |
88 |
if (direction != Direction.NONE) { |
91 |
locations.removeLast(); |
89 |
tail.addFirst(head); |
|
|
90 |
if (tail.size() > length) { |
91 |
tail.removeLast(); |
92 |
} |
93 |
head = nextLocation; |
94 |
} |
92 |
|
95 |
|
93 |
for (Snake snake : snakes) { |
96 |
for (Snake snake : snakes) { |
94 |
if (snake.getId() != getId() && |
97 |
if (snake.getTail().contains(head)) { |
95 |
colliding(snake.getHeadLocation())) { |
98 |
kill(); |
96 |
snake.kill(); |
99 |
if (id != snake.id) { |
97 |
reward(); |
100 |
snake.reward(); |
98 |
} |
101 |
} |
99 |
} |
102 |
} |
100 |
} |
103 |
} |
101 |
|
|
|
102 |
private void grow() { |
103 |
Location lastLocation = locations.getLast(); |
104 |
Location newLocation = new Location(lastLocation.x, lastLocation.y); |
105 |
locations.add(newLocation); |
106 |
} |
104 |
} |
107 |
|
105 |
|
108 |
private boolean colliding(Location location) { |
106 |
public synchronized Collection<Location> getTail() { |
109 |
return direction != Direction.NONE && locations.contains(location); |
107 |
return tail; |
110 |
} |
108 |
} |
111 |
|
109 |
|
112 |
public void setDirection(Direction direction) { |
110 |
public synchronized void setDirection(Direction direction) { |
113 |
this.direction = direction; |
111 |
this.direction = direction; |
114 |
} |
112 |
} |
115 |
|
113 |
|
116 |
public synchronized String getLocationsJson() { |
114 |
public synchronized String getLocationsJson() { |
117 |
StringBuilder sb = new StringBuilder(); |
115 |
StringBuilder sb = new StringBuilder(); |
118 |
for (Iterator<Location> iterator = locations.iterator(); |
116 |
sb.append(String.format("{x: %d, y: %d}", |
119 |
iterator.hasNext();) { |
|
|
120 |
Location location = iterator.next(); |
121 |
sb.append(String.format("{x: %d, y: %d}", |
122 |
Integer.valueOf(location.x), Integer.valueOf(location.y))); |
117 |
Integer.valueOf(head.x), Integer.valueOf(head.y))); |
123 |
if (iterator.hasNext()) { |
118 |
for (Location location : tail) { |
124 |
sb.append(','); |
119 |
sb.append(','); |
|
|
120 |
sb.append(String.format("{x: %d, y: %d}", |
121 |
Integer.valueOf(location.x), Integer.valueOf(location.y))); |
125 |
} |
122 |
} |
126 |
} |
|
|
127 |
return String.format("{'id':%d,'body':[%s]}", |
123 |
return String.format("{'id':%d,'body':[%s]}", |
128 |
Integer.valueOf(id), sb.toString()); |
124 |
Integer.valueOf(id), sb.toString()); |
129 |
} |
125 |
} |
Lines 134-142
Link Here
|
134 |
|
130 |
|
135 |
public String getHexColor() { |
131 |
public String getHexColor() { |
136 |
return hexColor; |
132 |
return hexColor; |
137 |
} |
|
|
138 |
|
139 |
public synchronized Location getHeadLocation() { |
140 |
return locations.getFirst(); |
141 |
} |
133 |
} |
142 |
} |
134 |
} |