简体   繁体   中英

Snake game, How to make a snake move?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM