蠕虫(蛇)游戏,片断成长/移动

时间:2015-12-30 00:26:42

标签: java move

我正致力于编写类似于Snake的游戏。目前,我正在努力编写我的move()和grow()方法。这个游戏的工作方式是蠕虫从1件开始,每次移动增长1件,直到达到3件。它已达到3件之后,它只能通过吃一个苹果来成长。此游戏中的动作是通过删除第一个部分并添加一个位于蠕虫前进方向的新部分来完成的。 Move()应该将蠕虫移动一片而grow()应该将蠕虫生长一片。但是,当调用grow()时,蠕虫不应该生长,直到调用move()。我添加了一个私有变量" growPiece"调用grow()时存储一个片段,然后在调用move()时添加它。但是,我没有得到我应该得到的结果。

public class Worm {

private int x;
private int y;
private Direction direction;
private List<Piece> pieces;
private Piece growPiece;

public Worm(int originalX, int originalY, Direction originalDirection) {
    this.x = originalX;
    this.y = originalY;
    this.direction = originalDirection;
    this.pieces = new ArrayList<Piece>();
    this.pieces.add(new Piece(this.x, this.y));
    this.growPiece = null;
}

public List<Piece> getPieces() {
    return this.pieces;
}

public void move() {
    if (this.direction == Direction.RIGHT) {
        this.pieces.add(new Piece(this.pieces.get(this.pieces.size() - 1).getX() + 1, this.pieces.get(this.pieces.size() - 1).getY()));
    } else if (this.direction == Direction.LEFT) {
        this.pieces.add(new Piece(this.pieces.get(this.pieces.size() - 1).getX() + 1, this.pieces.get(this.pieces.size() - 1).getY()));
    } else if (this.direction == Direction.DOWN) {
        this.pieces.add(new Piece(this.pieces.get(this.pieces.size() - 1).getX(), this.pieces.get(this.pieces.size() - 1).getY() + 1));
    } else if (this.direction == Direction.UP) {
        this.pieces.add(new Piece(this.pieces.get(this.pieces.size() - 1).getX(), this.pieces.get(this.pieces.size() - 1).getY() - 1));
    }
    if (this.growPiece != null) {
        this.pieces.add(growPiece);
        this.growPiece = null;
    }
    if (this.pieces.size() > 3 && this.growPiece == null) {
        this.pieces.remove(0);
    }
}

public void grow() {
    if (this.direction == Direction.RIGHT) {
        this.growPiece = new Piece(this.pieces.get(this.pieces.size() - 1).getX() + 2, this.pieces.get(this.pieces.size() - 1).getY());
    } else if (this.direction == Direction.LEFT) {
        this.growPiece = new Piece(this.pieces.get(this.pieces.size() - 1).getX() - 2, this.pieces.get(this.pieces.size() - 1).getY());
    } else if (this.direction == Direction.DOWN) {
        this.growPiece = new Piece(this.pieces.get(this.pieces.size() - 1).getX(), this.pieces.get(this.pieces.size() - 1).getY() + 2);
    } else if (this.direction == Direction.UP) {
        this.growPiece = new Piece(this.pieces.get(this.pieces.size() - 1).getX(), this.pieces.get(this.pieces.size() - 1).getY() - 2);
    }
}

我无法在不使用参数的情况下让方法相互交谈。

3 个答案:

答案 0 :(得分:1)

在函数move()中,如果this.growPiece在函数的开头是否为null,则为pieces.size&gt; 3,生长片将被添加,然后立即删除,因为当你到达那个时,如果,growPiece为null。

我的意思是,看看move()末尾的两个if语句。在第一个中,如果已经分配了this.growPiece,则将growPiece添加到件ArrayList中,我必须假设它具有您想要的效果。添加后,将growPiece设为null。

在下一个if中,条件的一部分是growPiece为null,到现在它总是如此。

尝试制作一个其他的if,看看它是否更好。

答案 1 :(得分:0)

所有设置,我使用布尔变量来标记何时增长。

答案 2 :(得分:0)

以下是蠕虫游戏的完整程序代码,练习49,赫尔辛基大学的面向对象编程MOOC。 整个代码中的解释可能看起来过于详细,但它们是针对学习者而不是专业开发人员。 该计划的结构与课程练习中的结构不完全相同,但结果完全相同。 该程序具有以下逻辑:

  • 蠕虫会自动移动到每个吃过的苹果上,它的速度会加快。
  • 玩家可以使用箭头键向上,向下,向左和向右移动蠕虫。
  • 当蠕虫短于三片时,它会随着每次移动自动生长,直到达到三片的长度。
  • 如果蠕虫吃了一个苹果,它会在下一步移动时长出一片。
  • 如果蠕虫进入野外框架或自身,游戏就结束了。 /如果添加了几行代码来实现一个计数器,我们可以确定这种类型的事件将在多少次事件后终止./
  • 该字段的标题,即JFrame的标题,用作仪表板显示,显示当前吃过的苹果数量。如果蠕虫进入场地框架或自身,它还会显示有关相应事件的信息。

1

    public enum Direction {
    LEFT, 
    RIGHT,
    DOWN,
    UP;
    }

2

public class Piece {

private int x;
private int y;
private int width;
private int length;
private int numberOfApples;

public Piece(int x, int y, int width, int length) {
    this.x = x;
    this.y = y;
    this.length = length;
    this.width = width;
}

public void setNumberOfApples() {
    this.numberOfApples += 1;
}

public int getNumberOfApples() {
    return this.numberOfApples;
}

public int getX() {
    return this.x;
}

public int getY() {
    return this.y;
}

public int getWidth() {
    return this.width;
}

public int getLength() {
    return this.length;
}

/*we use the following two override methods in order to check when the worm runs into itself.
This checking is done through the method "public boolean runsIntoItself(Piece piece)" in class "Worm"*/
@Override
public boolean equals(Object object) {
    if (this.getClass() == null) {
        return false;
    }

    if (this.getClass() != object.getClass()) {
        return false;
    }

    Piece compared = (Piece) object;
    if (this.x != compared.x || this.y != compared.y
            || this.width != compared.width || this.length != compared.length) {
        return false;
    }
    return true;
}

@Override
public int hashCode() {
    if (this.getClass() == null) {
        return 1;
    }
    return this.x + this.y + this.width + this.length;
}

@Override
public String toString() {
    return "(" + this.x + ", " + this.y + ", " + this.width + ", " + this.length + ")";
  }
}

3

public class Apple extends Piece {
public Apple(int x, int y, int width, int length) {
    super(x, y, width, length);
   }
}

4

import java.util.List;
import java.util.ArrayList;
import javax.swing.JFrame;

public class Worm extends Piece {

private int growth;
Direction direction;
private List<Piece> piecesWorm;
private JFrame frame;

public Worm(int x, int y, int width, int length, Direction originalDirection) {
    super(x, y, width, length);
    this.growth = 0;
    this.direction = originalDirection;
    this.piecesWorm = new ArrayList<Piece>();
    this.piecesWorm.add(new Piece(x, y, width, length));
    frame = new JFrame("Number of Apples: " + super.getNumberOfApples());
}

public JFrame getFrame() {
    return this.frame;
}

public Direction getDirection() {
    return this.direction;
}

public void setDirection(Direction dir) {
    this.direction = dir;
}

public int getLength() {
    return this.piecesWorm.size();
}

public List<Piece> getPieces() {
    return this.piecesWorm;
}

/*this method takes the calculated new piece from method "calculateNewPiece"
and does the following:
# moves the worm(adds an element to the head and substructs an element from the tail) 
# makes the worm grow(only adds an element to the head)
# terminates the game if the worm runs into itself*/
public void move() {
    if (this.runsIntoItself(this.calculateNewPiece()) == false) {
        if (this.piecesWorm.size() < 3) {
            this.piecesWorm.add(this.calculateNewPiece());
        } else if (this.piecesWorm.size() >= 3) {
            if (this.growth == 0) {
                this.piecesWorm.add(this.calculateNewPiece());
                this.piecesWorm.remove(0);
            } else if (this.growth == 1) {
                this.piecesWorm.add(this.calculateNewPiece());
                this.growth = 0;
            }
        }
    } else {
        this.frame.setTitle("The worm has run into itself!!! "
                + "Total Number of Apples: " + (this.getNumberOfApples()));
        try {
            Thread.sleep(10000);
        } catch (Exception ex) {
        }
        System.exit(0);
    }
}
/*this method calculates the next piece of the worm according to its direction*/
public Piece calculateNewPiece() {
    // lpbm stands for "lastPieceBeforeMoving"
    Piece lpbm = null;
    Piece newPiece = null;
    if (this.piecesWorm.size() == 1) {
        lpbm = this.piecesWorm.get(0);
    } else {
        lpbm = this.piecesWorm.get(this.piecesWorm.size() - 1);
    }
    int x = lpbm.getX();
    int y = lpbm.getY();

    if (this.direction.equals(Direction.LEFT)) {
        newPiece = new Piece(x - 1 - super.getWidth(), y, super.getWidth(), super.getLength());

    } else if (this.direction.equals(Direction.RIGHT)) {
        newPiece = new Piece(x + 1 + super.getWidth(), y, super.getWidth(), super.getLength());

    } else if (this.direction.equals(Direction.DOWN)) {
        newPiece = new Piece(x, y + 1 + super.getLength(), super.getWidth(), super.getLength());

    } else if (this.direction.equals(Direction.UP)) {
        newPiece = new Piece(x, y - 1 - super.getLength(), super.getWidth(), super.getLength());
    }
    return newPiece;
}

/*this method sets the conditions that determines whether the worm will grow or not when
the method "move()" is called*/
public void grow() {
    this.growth = 1;
}

/*this method checks whether the worm runs into an apple*/
public boolean runsInto(Piece piece) {
    Piece headPieceOfWorm = this.piecesWorm.get(this.piecesWorm.size() - 1);
    if ((headPieceOfWorm.getX() + (headPieceOfWorm.getWidth())) < piece.getX()) {
        return false;
    } else if (headPieceOfWorm.getX() > (piece.getX() + piece.getWidth())) {
        return false;
    } else if ((headPieceOfWorm.getX() + (headPieceOfWorm.getWidth())) >= piece.getX()
            && (headPieceOfWorm.getX() <= (piece.getX() + piece.getWidth()))) {
        if (headPieceOfWorm.getY() + (headPieceOfWorm.getLength()) < piece.getY()
                || (headPieceOfWorm.getY() > piece.getY() + (piece.getLength()))) {
            return false;
        }
    }
    return true;
}

/*this method checks whether the worm runs into itself*/
public boolean runsIntoItself(Piece piece) {
    if (this.piecesWorm.contains(piece)) {
        return true;
    }
    return false;
}

@Override
public String toString() {
    return "(" + super.getX() + ", " + super.getY() + ", " + super.getWidth()
            + ", " + super.getLength() + ", " + this.getDirection() + ")";
   }
}

5

import java.util.Random;
import java.util.List;

public class AvoidOverlappingPieces {

/*this method calculates the initial position of the apple 
so that the apple is within the field and it does not overlap with the worm*/
public Apple initialApple(Worm worm, int fieldWidth, int fieldLength, int pieceWidth, int pieceLength) {
    Random random = new Random();
    Apple apple = null;
    while (true) {
        int xApple = random.nextInt(fieldWidth - (pieceWidth));
        int yApple = random.nextInt(fieldLength - (pieceLength));
        apple = new Apple(xApple, yApple, pieceWidth, pieceLength);
        if (xApple + (pieceWidth) < worm.getX()) {
            break;
        } else if (xApple > worm.getX() + pieceWidth) {
            break;
        } else if ((xApple + (pieceWidth) >= worm.getX())
                && (xApple <= worm.getX() + pieceWidth)) {
            if (yApple + (pieceLength) < worm.getY()
                    || (yApple > worm.getY() + (pieceLength))) {
                break;
            }
        }
    }
    return apple;
}

/*this method calculates the position of the new apple, after the previous one is eaten
by the worm, so that the apple is within the field and it does not overlap with the worm*/
public Apple replaceEatenApple(Worm worm, List<Piece> piecesWorm, int fieldWidth, int fieldLength, int pieceWidth, int pieceLength) {
    Random random = new Random();
    Apple apple = null;
    while (true) {
        int xApple = random.nextInt(fieldWidth - (pieceWidth));
        int yApple = random.nextInt(fieldLength - (pieceLength));
        Apple newApple = new Apple(xApple, yApple, pieceWidth, pieceLength);
        if (this.fieldExeptWorm(newApple, piecesWorm) == false) {
            apple = newApple;
            break;
        }
    }
    return apple;
}
/*this method calculates the available space, taking account of the current    
position of worm, and it is used in the method "replaceEatenApple(...)"*/
    public boolean fieldExeptWorm(Piece piece, List<Piece> piecesWorm) {
        int counter = 0;
        for (int i = 0; i < piecesWorm.size(); i++) {
        Piece wormPiece = piecesWorm.get(i);
        if ((wormPiece.getX() + (wormPiece.getWidth())) < piece.getX()) {
            counter++;
        } else if (wormPiece.getX() > (piece.getX() + piece.getWidth())) {
            counter++;
        } else if ((wormPiece.getX() + (wormPiece.getWidth())) >= piece.getX()
                && (wormPiece.getX() <= (piece.getX() + piece.getWidth()))) {
            if (wormPiece.getY() + (wormPiece.getLength()) < piece.getY()
                    || (wormPiece.getY() > piece.getY() + (piece.getLength()))) {
                counter++;
            }
        }
    }
    if (counter == piecesWorm.size()) {
        return false;
    }
    return true;
   }
}

6

import java.util.Random;

public class WormGame {

private int fieldWidth;
private int fieldLength;
private int pieceWidth;
private int pieceLength;
private Worm worm;
private Apple apple;
private Random random;
/* class "AvoidOverlappingPieces" contains methods that calculate
the initial spot of the apple and its subsequent positions across the field*/
private AvoidOverlappingPieces properPieces;
protected int applesNumber;

public WormGame(int fieldWidth, int fieldLength) {
    this.fieldWidth = fieldWidth;
    this.fieldLength = fieldLength;
    this.pieceWidth = (this.fieldWidth - 10) / 10;
    this.pieceLength = (this.fieldLength - 10) / 10;
    this.worm = new Worm(0, 0, pieceWidth, pieceLength, Direction.DOWN);
    this.random = new Random();
    this.properPieces = new AvoidOverlappingPieces();
    this.apple = this.properPieces.initialApple(this.worm, this.fieldWidth, this.fieldLength, this.pieceWidth, this.pieceLength);
}

public int getfieldWidth() {
    return this.fieldWidth;
}

public int getfieldLength() {
    return this.fieldLength;
}

public Worm getWorm() {
    return this.worm;
}

public Apple getApple() {
    return this.apple;
}

/*this method accelerates the worm as it grows longer, 
through calculating smaller and smaller values for the number 
of milliseconds that are fed into "Thread.sleep(int number)",
implemented in the method "action()";*/
public int setDelay(Worm worm) {
    int delay = 1500 / worm.getLength();
    return delay;
}

/*this method takes the calculated new piece from method "calculateNewPiece" 
from class "Worm" and does the following:
# checks whether the new piece of the worm is within the confines of the field.
# if the new piece is within these confines the method "move()" from class "Worm" is called.
# if the worm bupms into an apple, the method "grow()" from class "Worm" and 
the method "replaceEatenApple(...)" from class "AvoidOverlappingPieces" are called.
# if the new piece is outside the confines of the field the game is terminated.*/
public void action() {
    int x_nextStep = this.worm.calculateNewPiece().getX();
    int y_nextStep = this.worm.calculateNewPiece().getY();
    if (x_nextStep >= 0 && (x_nextStep + this.pieceWidth) <= this.fieldWidth
            && y_nextStep >= 0 && (y_nextStep + this.pieceLength) <= this.fieldLength) {
        try {
            Thread.sleep(this.setDelay(this.worm));
        } catch (Exception ex) {
        }
        this.worm.move();
        if (this.worm.runsInto(this.apple)) {
            this.worm.setNumberOfApples();
            this.getWorm().getFrame().setTitle("Number of Apples: " + (this.worm.getNumberOfApples()));
            this.worm.grow();
            this.apple = this.properPieces.replaceEatenApple(this.worm, this.worm.getPieces(), this.fieldWidth, this.fieldLength, this.pieceWidth, this.pieceLength);
        }
    } else {
        this.getWorm().getFrame().setTitle("The worm has run into a wall!!! "
                + "Total Number of Apples: " + (this.worm.getNumberOfApples()));
        try {
            Thread.sleep(10000);
        } catch (Exception ex) {
        }
        System.exit(0);
    }
}

public int getNumberOfApples() {
    return this.applesNumber;
   }
}

7

import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;

public class KeyboardListener implements KeyListener {

private WormGame wormGame;

public KeyboardListener(WormGame wormGame) {
    this.wormGame = wormGame;
}

@Override
public void keyPressed(KeyEvent e) {

    if (e.getKeyCode() == KeyEvent.VK_LEFT) {
        this.wormGame.getWorm().setDirection(Direction.LEFT);
    } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
        this.wormGame.getWorm().setDirection(Direction.RIGHT);
    } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
        this.wormGame.getWorm().setDirection(Direction.DOWN);
    } else if (e.getKeyCode() == KeyEvent.VK_UP) {
        this.wormGame.getWorm().setDirection(Direction.UP);
    }
}

@Override
public void keyReleased(KeyEvent e) {
}

@Override
public void keyTyped(KeyEvent e) {
   }
}

8

import java.awt.Color;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.Timer;

public class DrawingBoard extends JPanel implements ActionListener {

private WormGame wormGame;
/*"Timer" sets the speed with which the worm moves.
Since in our case the worm accelerates with every eaten apple through 
"Thread.sleep()" applied in method "action()", class "WormGame", the "Timer" here 
sets the maximum speed. 
In other words:
the initial speed (i.e. delay in the movement of the worm) is the sum of 
the value of the integer in "Timer", which is 400, plus the value of the integer in 
"Thread.sleep", which is 1500, totalling to 1900.   
So, theoretically the value in "Thread.sleep" could be reduced to nearly zero, thus 
the maximum speed of 400 milliseconds delay remains the upper speed limit. 
Of course these values could be changed as per the desire of the player.*/
Timer tm = new Timer(400, this);

public DrawingBoard(WormGame wormGame) {
    this.wormGame = wormGame;
    super.setBackground(Color.WHITE);
}
/*this method paints the initial positions of the apple and the worm*/
@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.BLACK);
    for (Piece w : this.wormGame.getWorm().getPieces()) {
        g.fill3DRect(w.getX(), w.getY(), w.getWidth(), w.getLength(), true);
    }
    g.setColor(Color.RED);
    g.fillOval(this.wormGame.getApple().getX(), this.wormGame.getApple().getY(),
            this.wormGame.getApple().getWidth(), this.wormGame.getApple().getLength());
    tm.start();
}
/*this method paints the positions of the apple and the worm as they move across the board*/
public void actionPerformed(ActionEvent event) {
    this.wormGame.action();
    repaint();
   }
}

9

import java.awt.Container;
import java.awt.Dimension;
import javax.swing.WindowConstants;
import javax.swing.JFrame;

public class UserInterface implements Runnable {

private JFrame frame;
private WormGame wormGame;

public UserInterface(WormGame wormGame) {
    this.wormGame = wormGame;
}

public void run() {
    frame = this.wormGame.getWorm().getFrame();
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    this.createCompoent(frame.getContentPane());
    frame.pack();
    frame.setVisible(true);
}

private void createCompoent(Container container) {
    DrawingBoard board = new DrawingBoard(this.wormGame);
    container.add(board);
    KeyboardListener kL = new KeyboardListener(this.wormGame);
    frame.addKeyListener(kL);
    container.setPreferredSize(new Dimension(this.wormGame.getfieldWidth(), this.wormGame.getfieldLength()));
   }
}

10

import javax.swing.SwingUtilities;

public class Run {

public static void main(String[] args) {
    WormGame game = new WormGame(510, 510);
    UserInterface ui = new UserInterface(game);
    SwingUtilities.invokeLater(ui);
   }
}