@@ -9,35 +9,34 @@ import java.util.ArrayList;
99
1010public class Snake {
1111
12- public Snake () {
13- }
14-
15- private static final int FOOD_COLISION_TOLERANCE = 10 , BODY_COLISION_TOLERANCE = 1 ;
16- private List<SnakeBody > snakeBody = new ArrayList<> ();
12+ private static final byte FOOD_COLISION_TOLERANCE = 10 , BODY_COLISION_TOLERANCE = 1 ;
13+ private short [] bodyX, bodyY;
14+ private short arrIndex;
15+ private SnakeMove [] movements;
1716
18- public List< SnakeBody > getSnakeBody () {
19- return snakeBody ;
17+ public Snake () {
18+ init() ;
2019 }
2120
22- public void setSnakeBody (List<SnakeBody > snakeBody ) {
23- this . snakeBody = snakeBody;
21+ private void init () {
22+ arrIndex = 0 ;
23+ var pieces = piecesPerScreen();
24+ bodyX = new short [pieces];
25+ bodyY = new short [pieces];
26+ movements = new SnakeMove [pieces];
2427 }
2528
26- /**
27- * Get the size of the snake body
28- * @return int the size of the snake body
29- */
30- public int bodySize () {
31- return snakeBody. size();
29+ public int piecesPerScreen () {
30+ return (SnakeGame . W * SnakeGame . H ) / (SnakeGame . SNAKE_SIZE_W * SnakeGame . SNAKE_SIZE_H );
3231 }
3332
3433 /**
3534 * Get the snake body at the specified index
3635 * @param index the index of the snake body
3736 * @return SnakeBody the snake body at the specified index
3837 */
39- public SnakeBody getBody (int index ) {
40- return snakeBody . get( index) ;
38+ public short [] getPosition (int index ) {
39+ return new short []{bodyX[ index], bodyY[index]} ;
4140 }
4241
4342 /**
@@ -46,30 +45,22 @@ public class Snake {
4645 * @return SnakeBody the snake body at the specified index
4746 */
4847 public void updatePosition (SnakeMove movement ) {
49- getSnakeHead(). setMovement(movement);
50- }
51-
52- /**
53- * Adds a new SnakeBody to the snake.
54- * @param body The SnakeBody to be added.
55- */
56- public void addSnakeBody (SnakeBody body ) {
57- snakeBody. add(body);
48+ movements[0 ] = movement;
5849 }
5950
6051 /**
6152 * Gets the first position of the snake.
6253 * @return Position The first position of the snake.
6354 */
64- public int [] getFirstPosition () {
65- return getSnakeHead() . getPosition() ;
55+ public short [] getFirstPosition () {
56+ return new short []{bodyX[ 0 ], bodyY[ 0 ]} ;
6657 }
6758
6859 /**
6960 * Destroys the snake by clearing its body and positions.
7061 */
7162 public void destroySnake () {
72- snakeBody . clear ();
63+ init ();
7364 }
7465
7566 /**
@@ -78,30 +69,32 @@ public class Snake {
7869 * The new body is positioned one movement offset away from the last body.
7970 */
8071 public void newBody () {
81- var lastBody = snakeBody. get(snakeBody. size()- 1 );
82- var positions = lastBody. getPosition();
83- var movement = lastBody. getMovement();
72+ short [] lastPosition = {bodyX[arrIndex], bodyY[arrIndex]};
73+ var movement = movements[arrIndex];
8474 var offset = movement. getOffset();
85- var body = new SnakeBody (movement, positions);
86- body. setX(body. getX() + offset[0 ]);
87- body. setY(body. getY() + offset[1 ]);
88- addSnakeBody(body);
75+ arrIndex++ ;
76+ bodyX[arrIndex] = (short )(lastPosition[0 ] + offset[0 ]);
77+ bodyY[arrIndex] = (short )(lastPosition[1 ] + offset[1 ]);
78+ movements[arrIndex] = movement;
79+ }
80+
81+ public short getSize () {
82+ return (short ) (arrIndex + 1 );
8983 }
9084
85+
9186 /**
9287 * Updates the movement of the snake and checks for collisions with food, borders and body.
9388 * If the snake collides with food, a new food is created and the score is updated.
9489 * If the snake collides with borders or body, the game is over.
9590 */
9691 public void updateMovement () {
97- if (snakeBody. size() > 1 ) {
98- for (int index = snakeBody. size() - 1 ; index > 0 ; index-- ) {
99- var currentBody = snakeBody. get(index);
100- var previousBody = snakeBody. get(index - 1 );
101- currentBody. setX(previousBody. getX());
102- currentBody. setY(previousBody. getY());
103- currentBody. setMovement(previousBody. getMovement());
104- }
92+ if (getSize() > 1 ) {
93+ for (int index = arrIndex; index > 0 ; index-- ) {
94+ bodyX[index] = bodyX[index - 1 ];
95+ bodyY[index] = bodyY[index - 1 ];
96+ movements[index] = movements[index- 1 ];
97+ }
10598 }
10699 updateHeadPosition();
107100 if (checkCollisionWithFood()) {
@@ -118,15 +111,17 @@ public class Snake {
118111 * Starts the snake at the specified position.
119112 * @param position The position to start the snake.
120113 */
121- public void startSnake (int [] position ) {
122- addSnakeBody(new SnakeBody (SnakeMove . UP , position));
114+ public void startSnake (short [] position ) {
115+ bodyX[0 ] = position[0 ];
116+ bodyY[0 ] = position[1 ];
117+ movements[0 ] = SnakeMove . UP ;
123118 }
124119
125120 /**
126121 * Updates the position of all snake pieces of body.
127122 */
128123 private void updateHeadPosition () {
129- getSnakeHead() . doMovement(SnakeGame . VELOCITY );
124+ doMovement(movements[ 0 ], SnakeGame . VELOCITY );
130125 }
131126
132127
@@ -135,44 +130,54 @@ public class Snake {
135130 * @return true if there is a collision, false otherwise.
136131 */
137132 private boolean checkCollisionWithBody () {
138- var firstBody = getSnakeHead();
139133 var result = false ;
140- for (int index = 1 ; index < snakeBody . size (); index++ ) {
141- var body = snakeBody . get( index) ;
142- if (Math . abs(body. getX() - firstBody . getX() ) <= BODY_COLISION_TOLERANCE &&
143- Math . abs(body. getY() - firstBody . getY() ) <= BODY_COLISION_TOLERANCE ) {
134+ for (int index = 1 ; index < getSize (); index++ ) {
135+ short [] body = {bodyX[ index], bodyY[index]} ;
136+ if (Math . abs(body[ 0 ] - bodyX[ 0 ] ) <= BODY_COLISION_TOLERANCE &&
137+ Math . abs(body[ 1 ] - bodyY[ 0 ] ) <= BODY_COLISION_TOLERANCE ) {
144138 result = true ;
145139 break ;
146140 }
147141 }
148142 return result;
149143 }
150144
151- /**
152- * Gets the snake's head.
153- * @return SnakeBody The snake's head.
154- */
155- public SnakeBody getSnakeHead () {
156- return snakeBody. get(0 );
157- }
158-
159145 /**
160146 * Checks if the snake collides with the food.
161147 * @return true if the snake collides with the food, false otherwise.
162148 */
163149 private boolean checkCollisionWithFood () {
164- var bodyPos = getSnakeHead();
165- return (Math . abs(SnakeGame . FOOD_X - bodyPos. getX()) <= FOOD_COLISION_TOLERANCE &&
166- Math . abs(SnakeGame . FOOD_Y - bodyPos. getY()) <= FOOD_COLISION_TOLERANCE );
150+ return (Math . abs(SnakeGame . FOOD_X - bodyX[0 ]) <= FOOD_COLISION_TOLERANCE &&
151+ Math . abs(SnakeGame . FOOD_Y - bodyY[0 ]) <= FOOD_COLISION_TOLERANCE );
167152 }
168153
169154 /**
170155 * Checks if the snake has collided with the game borders.
171156 * @return true if the snake has collided with the borders, false otherwise.
172157 */
173158 private boolean checkCollisionWithBorders () {
174- var body = getSnakeHead();
175- return (body. getX() < SnakeGame . BORDER || body. getX() > SnakeGame . W - SnakeGame . BORDER - SnakeGame . SNAKE_SIZE_W ||
176- body. getY() < SnakeGame . BORDER || body. getY() > SnakeGame . H - SnakeGame . BORDER - SnakeGame . SNAKE_SIZE_H );
159+ return (bodyX[0 ] < SnakeGame . BORDER || bodyX[0 ] > SnakeGame . W - SnakeGame . BORDER - SnakeGame . SNAKE_SIZE_W ||
160+ bodyY[0 ] < SnakeGame . BORDER || bodyY[0 ] > SnakeGame . H - SnakeGame . BORDER - SnakeGame . SNAKE_SIZE_H );
161+ }
162+
163+ /**
164+ * Do a movement in the snake body with a velocity value
165+ * @param velocity short value of velocity
166+ */
167+ public void doMovement (SnakeMove movement , short velocity ) {
168+ switch (movement) {
169+ case UP :
170+ bodyY[0 ] -= velocity;
171+ break ;
172+ case DOWN :
173+ bodyY[0 ] += velocity;
174+ break ;
175+ case LEFT :
176+ bodyX[0 ] -= velocity;
177+ break ;
178+ case RIGHT :
179+ bodyX[0 ] += velocity;
180+ break ;
181+ }
177182 }
178183}
0 commit comments