I am writing a snake game, specifically, is a centipede game. It needs me to draw a snake and that snake will automatically move one line by one line.
I did draw a snake, and it can move from left side to right side. However, the problem is:
I can't make the snake changes line, if it finish the first line, I need it changes to the second line and which starts from the right side.
My code is like this:
private void move()
{
myCentipedes[0] =
new Centipede(Settings.centipedeStartSize, Settings.RIGHT,
Settings.DOWN);
myCentipedes[0].segments = new Point[Settings.centipedeStartSize];
myCentipedes[0].segments[0] = new Point(0, 0);
boolean dr = true;
if (dr == true) {
if (myCentipedes[0].segments[0].x < 30) {
System.out.println(myCentipedes[0].segments[0].x +
" " +
myCentipedes[0].segments[0].y);
myCentipedes[0].segments[0] = new Point(x, 0);
for (int i = 1; i < 10; i++) {
myCentipedes[0].segments[i] =
new Point(myCentipedes[0].segments[i - 1].x - 1,
myCentipedes[0].segments[i - 1].y);
}
x++;
}
}
if (myCentipedes[0].segments[0].x == 29) {
x = 29;
dr = false;
}
if (dr == false) {
if (myCentipedes[0].segments[0].x > 0) {
myCentipedes[0].segments[0] = new Point(x, 1);
for (int i = 1; i < 10; i++) {
myCentipedes[0].segments[i] =
new Point(myCentipedes[0].segments[i - 1].x + 1, 1);
}
x--;
}
}
}
It appears to me that you re-create your entire centipede on every single move:
private void move()
{
myCentipedes[0] =
new Centipede(Settings.centipedeStartSize, Settings.RIGHT,
Settings.DOWN);
Is re-creating the centipede every move()
intentional? Or should move()
run the centipede entirely down the board, from start to finish? (If so, you'll need to add some looping to this method.)
I assume the myCentipedes[0]
is simply a placeholder for future extensions, involving two or more centipedes on the board simultaneously. This sort of over-generic programming can sometimes make the code more difficult to read and write while initially programming, and almost certainly doesn't help matters. You can always re-factor a move()
method that works on one centipede to a move(int centipede)
method that works on a specific centipede and a move()
method that calls move(int)
for every centipede on the board. Or maybe you'll find it easier to place the movement code into the Centipede
class, and need to remove the array indexes then and use class member storage instead.
boolean dr = true;
if (dr == true) {
dr
will always equal true
at this point. You might as well remove the variable and the test.
for (int i = 1; i < 10; i++) {
myCentipedes[0].segments[i] =
new Point(myCentipedes[0].segments[i - 1].x - 1,
myCentipedes[0].segments[i - 1].y);
}
Since you're counting up , you'll actually copy the value from segment[0]
through to all elements in the array, one element at a time. Can't you just assign the Point
objects new array indexes? Starting from i=centipede.segments.length
and counting down , it'll look more like this:
for (int i=myCentipede[0].segments.length; i > 0; i--) {
myCentipede[0].segments[i] = myCentipede[0].segments[i-1];
}
myCentipede[0].segments[0] = new Point(...,...);
Some of your tests can be simplified:
if (myCentipedes[0].segments[0].x == 29) {
x = 29;
dr = false;
}
if (dr == false) {
if (myCentipedes[0].segments[0].x > 0) {
If dr == false
at this point, you might as well have written it like this instead:
if (myCentipedes[0].segments[0].x == 29) {
x = 29;
if (myCentipedes[0].segments[0].x > 0) {
But then the second if
is obviously not needed -- after all, 29 > 0
.
While you're here, clean up all those hard-coded 10
with either a constant ( Settings.centipedeStartSize
) or find the actual length of the centipede ( myCentipedes[0].segments.length
).
Now that I've critiqued your current approach, I'd like to suggest a different tack:
Take a step back and break your problem down into smaller methods.
You've embedded two for
loops that move the centipede one segment at a time by assigning to segment[i]
the values from segment[i-1]
. Instead of duplicating the code, write a new method with the body of the for
loop to move the centipede forward. Make it take a Point
object for the new first element each trip through the function. (Don't forget to make it count down rather than up .)
Once you've broken apart the for
loops, I think it will be easier to make whatever changes are necessary for traveling left-to-right and right-to-left. You will probably want to write it with nested for
loops -- one to control the vertical dimension, and within it, perhaps one or two new for
loops to control the horizontal dimension. Make these loops work with a simple Centipede c
, rather than the complicated expression you've currently got.
Breaking apart the larger function into smaller function will give you a better opportunity to test your functions in isolation -- test movement manually , with simple test methods like this:
move_forward(Centipede c, Point p) {
/* code to move forward one space to occupy `p` */
}
test_right() {
Centipede c = new Centipede(/* ... */);
move_forward(c, new Point(0,0));
move_forward(c, new Point(1,0));
move_forward(c, new Point(2,0));
move_forward(c, new Point(3,0));
move_forward(c, new Point(4,0));
move_forward(c, new Point(5,0));
/* ... */
}
Take it slow, test every method as you write them, and I think you'll find this is an easier problem than it currently looks.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.