Java:蛇 - 改变方向

我是编程新手,并且陷入了涉及蛇方向变化的特定部分 . 这款游戏与旧款诺基亚手机相同 . 这很经典 .

目前,每按一次W,A,S或D键,蛇就会移动1平方/ 20像素 . 问题是我希望这个动作是连续的,并且按下其他按键 . 例如,当我按下“S”键时,蛇将向下移动(直到它撞到墙壁),除非我按下W,A或D.在这种情况下,蛇应该将其移动到相应的方向 . 我有一个小小的想法,我将不得不使用循环来继续移动蛇(这个循环我思考将位于方法的一个分支(if / else)内:运动) .

这是我开发的当前源代码 . 这段代码对Java的“Ready to Program”没有任何问题 . 如果不是编写“System.out.println();”,那么写“c.println()”也会有所帮助(但不是必要) . 这是因为我使用的是C控制台 .

我导入了KeyAdapter和KeyEvent . 这就是一个名为SnakeGame的公共类 . keyPressed存在,因为我试图更早地解决这个问题 . 我相信它仍然有用 .

// STORAGE ---- Setting up the variables
public static int life = 1;                     // Sets how many lives the snake has: 1
public static int appleX;                       // The X coordinate of the apple
public static int appleY;                       // The Y coordinate of the apple                
public static int[] jointPosX = new int[400];   // X coordinates of the snake's joints. Stores as an array
public static int[] jointPosY = new int[400];   // Y coordinates of the snake's joints. Stores as an array
public static int jointNum = 3;                 // How many joints the snake starts out with: 3
public static int key;                                                
public static boolean goLeft;
public static boolean goRight;
public static boolean goUp;
public static boolean goDown;
public static char moveInput;                   // The character (w, a, s, d) pressed for direction of movement

public static void board()      // The game board
{
    c.setColor(Color.black);           
    c.drawRect(19, 19, 401, 401);       // These 3 lines make the border thick
    c.drawRect(18, 18, 403, 403);
    c.drawRect(17, 17, 405, 405);
    c.setColor(new Color(72, 232, 75)); // Color: Medium - Dark Green
    c.fillRect(20, 20, 400, 400);       // The actual area where the snake moves

    c.setColor(Color.black);         
    for (int y = 20; y < 420; y+=20)    // Moving the position of the square across the Y axis
    {
        for (int x = 20; x < 420; x+=20)    // Moving the position of the square across the X axis
        {
            c.drawRect(x, y, 20, 20);       // Drawing the individual squares of the grid
        }
    }
}
public static void apple()      // Where the apple will spawn
{
    Random generator = new Random();    // Setting up the randum number generator

    appleX = generator.nextInt(380 - 0 + 1) + 1;    // X coordinate for apple (0 - 380)
    if (appleX % 20 == 0)       // Divisible perfectly by 20. Each square is 20 pixels wide
    {
        appleX = appleX;        // The number is perfect
    }
    else
    {
        int rem = appleX % 20;      // The remainder is assigned a variable
        appleX = appleX - rem;      // The X coordinate is now divisible by 20 (Subtracts the remainder from the indivisible X coordinate)  
    }
    appleX = appleX + 21;   // Adds 21 since board starts 21 pixels to the right

    appleY = generator.nextInt(380 - 0 + 1) + 1;    // Y coordinate for apple (0 - 380)
    if (appleY % 20 == 0)       // Divisible perfectly by 20. Each square is 20 pixels tall
    {
        appleY = appleY;        // The number is perfect
    }
    else
    {
        int rem = appleY % 20;      // The remainder is assigned a variable
        appleY = appleY - rem;      // The Y coordinate is now divisible by 20 (Subtracts the remainder from the indivisible Y coordinate)
    }
    appleY = appleY + 21;   // Adds 21 since board starts 21 pixels downwards
}
public void keyPressed(KeyEvent e)
{
    key = e.getKeyCode();

    if (key == KeyEvent.VK_W)
    {
        goLeft = false;
        goRight = false;
        goUp = true;
        goDown = false; 
    }
    if (key == KeyEvent.VK_A)
    {
        goLeft = true;
        goRight = false;
        goUp = false;
        goDown = false;
    }
    if (key == KeyEvent.VK_S)
    {
        goLeft = false;
        goRight = false;
        goUp = false;
        goDown = true;
    }
    if (key == KeyEvent.VK_D)
    {
        goLeft = false;
        goRight = true;
        goUp = false;
        goDown = false;
    }
}
public static void selfDeath()  // If the snake hits itself
{
    for (int i = jointNum - 1; i > 0; i--)  // Variable i stands for index number
    {
        if (jointPosX[0] == jointPosX[i] && jointPosY[0] == jointPosY[i]) // Checks if X and Y coordinates of head of snake matches any other part of snake 
        {
            life--;     // Loses a life
        }
    }
}
public static void wallDeath()  // If the snake hits the wall
{
    if (jointPosX[0] < 20 || jointPosX[0] > 420 || jointPosY[0] < 20 || jointPosY[0] > 420) // Checks if X and Y coordinates of head of snake is outside border coordinates
    {
        life--;     // Loses a life
    }
} 
public static void movement()   // How the snake moves
{
    c.setColor(new Color(23, 156, 26));             // Color: Dark green
    c.fillRect(jointPosX[0], jointPosY[0], 19, 19); // Initial point of snake

    while(life == 1) {
    moveInput = c.getChar();                // Getting W, A, S, or D from user
    board();                                // Redrawing the board
    c.setColor(Color.red);                  // Color: Red
    c.fillOval(appleX, appleY, 19, 19);     // Drawing the apple
    if (moveInput == 'w')
    {
        for (int i = jointNum - 1; i > 0; i--) {                // Variable i stands for index number
            jointPosY[i] = jointPosY[i - 1];                    // Changing the Y coordinates of the joints to follow
            jointPosX[i] = jointPosX[i - 1];                    // Changing the X ooordinates of the joints to follow
        }

        jointPosY[0] = jointPosY[0] - 20;                       // Changing the vertical position of snake head (User pressed W)

        c.setColor(new Color(23, 156, 26));
        for (int z = 0; z < jointNum; z++) {                    // Moving along the index numbers
            c.fillRect(jointPosX[z], jointPosY[z], 19, 19);     // Drawing each joint
        }
    }
    if (moveInput == 'a')
    {
        for (int i = jointNum - 1; i > 0; i--) {                // Variable i stands for index number
            jointPosX[i] = jointPosX[i - 1];                    // Changing the X ooordinates of the joints to follow
            jointPosY[i] = jointPosY[i - 1];                    // Changing the Y coordinates of the joints to follow
        }

        jointPosX[0] = jointPosX[0] - 20;                       // Changing the horizontal position of snake head (User pressed S)

        c.setColor(new Color(23, 156, 26));
        for (int z = 0; z < jointNum; z++) {                    // Moving along the index numbers
            c.fillRect(jointPosX[z], jointPosY[z], 19, 19);     // Drawing each joint
        }
    }
    if (moveInput == 's')
    {
        for (int i = jointNum - 1; i > 0; i--) {                // Variable i stands for index number
            jointPosY[i] = jointPosY[i - 1];                    // Changing the Y coordinates of the joints to follow
            jointPosX[i] = jointPosX[i - 1];                    // Changing the X ooordinates of the joints to follow
        }

        jointPosY[0] = jointPosY[0] + 20;                       // Changing the vertical position of snake head (User pressed A)

        c.setColor(new Color(23, 156, 26));
        for (int z = 0; z < jointNum; z++) {                    // Moving along the index numbers
            c.fillRect(jointPosX[z], jointPosY[z], 19, 19);     // Drawing each joint
        }
    }
    if (moveInput == 'd')
    {
        for (int i = jointNum - 1; i > 0; i--) {                // Variable i stands for index number
            jointPosX[i] = jointPosX[i - 1];                    // Changing the X ooordinates of the joints to follow
            jointPosY[i] = jointPosY[i - 1];                    // Changing the Y coordinates of the joints to follow
        }

        jointPosX[0] = jointPosX[0] + 20;                       // Changing the horizontal position of snake head (User pressed D)

        c.setColor(new Color(23, 156, 26)); 
        for (int z = 0; z < jointNum; z++) {                    // Moving along the index numbers
            c.fillRect(jointPosX[z], jointPosY[z], 19, 19);     // Drawing each joint
        } 
    }
    addJoint();
    selfDeath();
    wallDeath();
    }
}
public static void addJoint()   // Checks to add a joint to the snake
{
    if (jointPosX[0] == appleX && jointPosY[0] == appleY)   // If X and Y coordinates of head of snake match X and Y coordinates of apple
    {
        jointNum++;     // Adds a joint
        apple();        // Adds another place for the apple to spawn
    }
} 
public static void main(String[] args) 
{
    c = new Console(25, 75);

    jointPosX[0] = 101;
    jointPosY[0] = 101;
    jointPosX[1] = 101;
    jointPosY[1] = 101;
    jointPosX[2] = 101;
    jointPosY[2] = 101;
    board();
    apple();
    movement();
}

}

回答(1)

3 years ago

嗯,首先,你希望每次重绘帧时让它在正确的方向上移动一点,而不仅仅是当用户按下箭头键时 .

当用户按下某个键时,不是告诉它移动的时间,而是修改存储头节点当前方向的变量的时间 . 真正的诀窍在于保留蛇的形状,为了达到这个目的,你不希望每个节点在同一方向上移动,而是让每个节点移动到前一个节点的位置 .

例如,如果这是你的蛇(1是你开始的头,7是你最后吃的尾巴)

1)The game is in the current Position
xxxxxxxxxxxxxxxxxx
x                x   2) User presses the Right Arrow (=>)
x    76          x   
x     543        x   3) Direction is adjusted 
x       2        x      Var Direction_X = 1
x       1        x      Var Direction_Y = 0
x                x
xxxxxxxxxxxxxxxxxx

4) Head node moves per Direction_X and Direction_Y
xxxxxxxxxxxxxxxxxx
x                x   
x    76          x   
x     543        x  
x       2        x    
x        1       x      
x                x
xxxxxxxxxxxxxxxxxx

5) Node 2 moves to where node 1 was
xxxxxxxxxxxxxxxxxx
x                x   
x    76          x   
x     543        x  
x                x    
x       21       x      
x                x
xxxxxxxxxxxxxxxxxx

6) Node 3 moves to where node 2 was
xxxxxxxxxxxxxxxxxx
x                x   
x    76          x   
x     54         x  
x       3        x    
x       21       x      
x                x
xxxxxxxxxxxxxxxxxx

7) Nodes 4 to 7 follow the same pattern
xxxxxxxxxxxxxxxxxx
x                x   
x     7          x   
x     654        x  
x       3        x    
x       21       x      
x                x
xxxxxxxxxxxxxxxxxx

8) The frame is repainted with everything in the new position.

A Note on implementation:

上面的图表是我能想到的最好的方式,以显示算法的意图清晰,但实际编码时,你可能想要从后面开始,而不是替换节点(位置6,6,6,6,5 ,5在4,...,2在1,每当前方向变量移动1) . 这是因为下一个位置已经存储在您的列表中 .