使用Java创建Snake

我决定使用Java重新创建Snake,但我有点卡住了。 目前,我有一个方块,用户可以使用箭头键在屏幕上移动。 当您按下LEFT一次时,方块开始使用计时器向左移动。您不需要按住键或继续按下它; 当您按下任何其他设置的键(右,上,下)时,它会改变方向。 我的目标是使用ArrayList来保存构成蛇的方块。 目前,我创建了一个只包含一个Snake对象的ArrayList,如果我将第二个Snake对象添加到列表中并将其添加到框架(第一个),则只能看到一个Snake对象以及要移动的键它不起作用。 我正在寻找一些关于如何在这个项目上取得进展的想法 – 请不要给我完整的答案,因为我想自己弄清楚它的大部分内容; 我只需要一些方向。 提前致谢 – 代码如下。

import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Snake extends JPanel implements KeyListener, ActionListener { int x = 0, y = 0, velx = 0, vely = 0; Timer t = new Timer(250, this); public Snake(int num1, int num2) { t.start(); addKeyListener(this); setFocusable(true); setFocusTraversalKeysEnabled(true); x = num1; y = num2; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.blue); g.fillRect(x, y, 20, 20); } public void actionPerformed(ActionEvent e) { repaint(); x += velx; y += vely; } public void up() { vely = -20; velx = 0; } public void down() { vely = 20; velx = 0; } public void left() { vely = 0; velx = -20; } public void right() { vely = 0; velx = 20; } public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); if(code == KeyEvent.VK_UP) up(); else if(code == KeyEvent.VK_DOWN) down(); else if(code == KeyEvent.VK_RIGHT) right(); else if(code == KeyEvent.VK_LEFT) left(); } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } } //Driver Class import javax.swing.*; import java.awt.event.*; import java.awt.*; import java.util.*; public class UserClass { private static JFrame frame = new JFrame("Snake"); private static ArrayList mySnake = new ArrayList(); public static void main(String[] args) { frame.setSize(500,500); frame.setBackground(Color.black); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mySnake.add(new Snake(20,20)); frame.add(mySnake.get(0)); } } 

PS当我在Mac上将相同的代码放在Eclipse中时,我的框架的背景是黑色的,但在Windows上它是浅灰色的……任何人都知道为什么? 谢谢。

要回答您的后记,请设置背景颜色或使用彩绘颜色在其他所有内容后面制作JPanel。

要在项目中取得进展,请考虑将其作为MVC框架中的练习。 现在发生的事情是你的模型和视图被链接在同一个类中 – 这使得很难遵循一切背后的逻辑。

您可以做的是首先将Snake与视图分开 – 使用ArrayList segmentLocations或其他东西制作蛇,以表示板上每个段位置的(x,y)您可以定义 – 您可以使用绝对坐标,也可以在视图中创建任意网格并更改为绝对坐标(这更好地代表了MVC关系)。 Snake还应该有一个蛇面朝向的方向 – 我会使用enum Direction {N, S, E, W} ,但是你可以选择它,因为你也可以有一个表示方向或整数的整数其他方式。

那么你的Snake也会有自己更新的方法 – move(),根据初始段的当前方向移动所有段的位置,并使所有其他段跟随之前的段的移动(这如果你考虑几分钟就很容易了。)

您的视图可以是一个带有GridLayout的JFrame,其中包含JPanels,它会轮询您的Snake实例并查看该位置是否存在某个段,如果是,则绘制它或多个其他选项。

您的控制器将是KeyAdapter,当按下箭头键时,它会向Snake方向发送更新。

小提示,让您的生活更轻松:当您添加新细分时,只需将其放在Snake最后一段的位置即可。 下次移动时,新段将位于同一位置,其余的Snake应相应移动。

paintComponent(...)只绘制一个矩形。 相反,如果你想绘制多个矩形或椭圆,或者其他什么,给你的类一个ListList ,并在你的Swing Timer中,从列表中删除尾部并添加一个新头。 然后让paintComponent()使用for循环来遍历列表,绘制列表所持有的所有矩形。

此外,您可能希望使用键绑定而不是KeyListener来获取用户的按键,因为当其他组件窃取焦点时,这将更好地工作。

给定一个定义分段几何的类,

 class Segment { private int x, y, d; public Segment(int x, int y, int r) { this.x = x - r; this.y = y - r; this.d = 2 * r; } } 

考虑一个段的队列,

 Queue snake = new LinkedList(); 

然后每次迭代都很简单

 snake.remove(); snake.add(new Segment(...)); 

paintComponent()包含这个循环

 @Override public void paintComponent(Graphics g) { ... for (Segment s : snake) { g.fillXxxx(sx, sy, sd, sd); } ... }