最近,在Stack Overflow的人们的帮助下(我非常感谢),我在java中完成了我自己重拍的Tron游戏。然而,发生了一些事情,现在游戏将不会结束,因为我测试的是否是玩家穿越路径的列表在路径交叉时没有返回x和y坐标。这是代码(问题区域评论):
package tron;
import javax.swing.*;
import java.util.Random;
import java.awt.Graphics2D;
import java.awt.*;
import java.awt.BasicStroke;
import java.awt.event.*;
import java.awt.geom.Path2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
public class Tron extends JPanel{
private static Point player = new Point(40, 40);
private static Point lastTurn = new Point(player);
private static Point cpu = new Point(360, 330);
private static Point cpuTurn = new Point(cpu);
static int timer = 0;
static Point RANGE = new Point(400, 400);
public static int size = 1;
public static int move = 1;
public static int dir = 1;
public static int cpu_dir = 2;
public static Path2D path;
public static Path2D path2;
public Random random = new Random();
public Random random2 = new Random();
static List playerlist = new ArrayList();
static List cpulist = new ArrayList();
static final Tron m = new Tron();
static final JFrame frame = new JFrame("1P Tron");
public static void main(String[] args){
frame.setSize(RANGE.x,RANGE.y);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(m);
m.setBackground(Color.black);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
path = new Path2D.Float();
path2 = new Path2D.Float();
path.moveTo(player.x, player.y);
path2.moveTo(cpu.x, cpu.y);
Action actionRight = new AbstractAction(){
public void actionPerformed(ActionEvent actionRightEvent){
dir = 1;
lastTurn = new Point(player);
};
};
Action actionLeft = new AbstractAction(){
public void actionPerformed(ActionEvent actionLeftEvent){
dir = 2;
lastTurn = new Point(player);
};
};
Action actionUp = new AbstractAction(){
public void actionPerformed(ActionEvent actionUpEvent){
dir = 3;
lastTurn = new Point(player);
};
};
Action actionDown = new AbstractAction(){
public void actionPerformed(ActionEvent actionDownEvent){
dir = 4;
lastTurn = new Point(player);
};
};
KeyStroke right = KeyStroke.getKeyStroke("RIGHT");
KeyStroke left = KeyStroke.getKeyStroke("LEFT");
KeyStroke up = KeyStroke.getKeyStroke("UP");
KeyStroke down = KeyStroke.getKeyStroke("DOWN");
InputMap inputMap = m.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(right, "RIGHT");
inputMap.put(left, "LEFT");
inputMap.put(up, "UP");
inputMap.put(down, "DOWN");
m.getActionMap().put("RIGHT", actionRight);
m.getActionMap().put("LEFT", actionLeft);
m.getActionMap().put("UP", actionUp);
m.getActionMap().put("DOWN", actionDown);
}
public void endGame(){ //problems with "if, else if" statements
Component temporaryLostComponent = null;
if(cpulist.contains(player)){
dir = 0;
JOptionPane.showMessageDialog(temporaryLostComponent, "You Lose");
WindowEvent close = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
}else if(playerlist.contains(cpu)){
dir = 0;
JOptionPane.showMessageDialog(temporaryLostComponent, "You Win!");
WindowEvent close = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
}else if(player.x == cpu.x && player.y == cpu.y){
dir = 0;
JOptionPane.showMessageDialog(temporaryLostComponent, "Game Over");
WindowEvent close = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
}
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
draw(g);
try{
p1_move(m);
cpu_move();
}catch(InterruptedException jk){
Component temporaryLostComponent = null;
JOptionPane.showMessageDialog(temporaryLostComponent, "Timer exception, Thread.sleep()");
}
}
@SuppressWarnings("unchecked")
public void p1_move(Tron m) throws InterruptedException{
if(dir == 1){
if(player.x > 390){
player.x = -5;
path.moveTo(0, player.y);
};
Thread.sleep(27);
player.x += 5;
playerlist.add(player);
path.lineTo(player.x, player.y);
path.moveTo(player.x, player.y);
m.repaint();
endGame();
}else if(dir == 2){
if(player.x < 0){
player.x = 395;
path.moveTo(400, player.y);
};
Thread.sleep(27);
player.x -= 5;
playerlist.add(player);
path.lineTo(player.x, player.y);
path.moveTo(player.x, player.y);
m.repaint();
endGame();
}else if(dir == 3){
if(player.y < 0){
player.y = 370;
path.moveTo(player.x, 400);
};
Thread.sleep(27);
player.y -= 5;
playerlist.add(player);
path.lineTo(player.x, player.y);
path.moveTo(player.x, player.y);
m.repaint();
endGame();
}else if(dir == 4){
if(player.y > 369){
player.y = 0;
path.moveTo(player.x, 0);
};
Thread.sleep(27);
player.y += 5;
playerlist.add(player);
path.lineTo(player.x, player.y);
path.moveTo(player.x, player.y);
m.repaint();
endGame();
}
}
@SuppressWarnings("unchecked")
public void cpu_move() throws InterruptedException{
if(cpu_dir == 1){
if(cpu.x > 390){
cpu.x = -5;
path2.moveTo(0, cpu.y);
};
cpu.x += 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
}else if(cpu_dir == 2){
if(cpu.x < 0){
cpu.x = 395;
path2.moveTo(400, cpu.y);
};
cpu.x -= 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
}else if(cpu_dir == 3){
if(cpu.y < 0){
cpu.y = 370;
path2.moveTo(cpu.x, 400);
};
cpu.y -= 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
}else if(cpu_dir == 4){
if(cpu.y > 369){
cpu.y = 0;
path2.moveTo(cpu.x, 0);
};
cpu.y += 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
}else{
cpu_dir = random.nextInt(4) + 1;
};
if(timer == ((cpu_dir * 4) + 25)){
if(cpu_dir == 1){
cpu_dir = random.nextInt(2) + 3;
cpuTurn = new Point(cpu);
timer = 0;
}else if(cpu_dir == 2){
cpu_dir = random.nextInt(2) + 3;
cpuTurn = new Point(cpu);
timer = 0;
}else if(cpu_dir == 3){
cpu_dir = random.nextInt(2) + 1;
cpuTurn = new Point(cpu);
timer = 0;
}else if(cpu_dir == 4){
cpu_dir = random.nextInt(2) + 1;
cpuTurn = new Point(cpu);
timer = 0;
}else{
cpu_dir = random.nextInt(4) + 1;
cpuTurn = new Point(cpu);
timer = 0;
};
}
}
public void draw(Graphics g){
Graphics2D g2 = (Graphics2D) g.create();
g.setColor(Color.BLUE);
g.fillRect(player.x, player.y, size, size);
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(5));
g2.draw(path);
g2.draw(new Line2D.Float(lastTurn, player));
g.setColor(Color.ORANGE);
g.fillRect(cpu.x, cpu.y, size, size);
g2.setColor(Color.ORANGE);
g2.draw(path2);
g2.draw(new Line2D.Float(cpuTurn, cpu));
}
}
我根据您的建议和其他人对我的代码做了一些(好的,很多)更改:
//package Tron.Stable;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Tron {
public static void main(String[] args) {
new Tron();
}
public Tron() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Tron");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private int cpu_xVelocity;
private int cpu_yVelocity;
private int xVelocity;
private int yVelocity;
protected static int CPU_DIR = 1;
protected static final int PLAYER_SIZE = 0;
protected static final int DELTA = 4;
protected static int CPU_DELTA = -4;
public static int timer = 0;
private Point player;
private Point cpu;
private Point lastTurn;
private Point cpuTurn;
private Path2D playerPath;
private Path2D cpuPath;
private final Random random = new Random();
static CpuVelocityAction cpu_Vel;
public TestPane(){
setBackground(Color.BLACK);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");
am.put("left", new VelocityAction(-DELTA, 0));
am.put("right", new VelocityAction(DELTA, 0));
am.put("up", new VelocityAction(0, -DELTA));
am.put("down", new VelocityAction(0, DELTA));
cpu_xVelocity = CPU_DELTA;
xVelocity = DELTA;
player = new Point(40, 40);
cpu = new Point(360, 360);
lastTurn = new Point(player);
cpuTurn = new Point(cpu);
playerPath = new Path2D.Float();
cpuPath = new Path2D.Float();
playerPath.moveTo(40, 40);
cpuPath.moveTo(360, 360);
Timer playerTimer = new Timer(20, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
player.x += xVelocity;
if (player.x > getWidth()){
playerPath.lineTo(getWidth(), player.y);
playerPath.moveTo(0, player.y);
player.x = 0;
lastTurn = new Point(player);
}
if (player.x + PLAYER_SIZE < 0){
playerPath.lineTo(0, player.y);
playerPath.moveTo(getWidth() - 1, player.y);
player.x = getWidth() - 1;
lastTurn = new Point(player);
}
player.y += yVelocity;
if (player.y > getHeight()){
playerPath.lineTo(player.x, getHeight());
playerPath.moveTo(player.x, 0);
player.y = 0;
lastTurn = new Point(player);
}
if (player.y + PLAYER_SIZE < 0){
playerPath.lineTo(player.x, 0);
playerPath.moveTo(player.x, getHeight() - 1);
player.y = getHeight() - 1;
lastTurn = new Point(player);
}
if(CPU_DIR == 1){
cpu_Vel = new CpuVelocityAction(CPU_DELTA, 0);
cpu_xVelocity = cpu_Vel.cpu_xDelta;
cpu_yVelocity = cpu_Vel.cpu_yDelta;
}else if(CPU_DIR == 2){
cpu_Vel = new CpuVelocityAction(-CPU_DELTA, 0);
cpu_xVelocity = cpu_Vel.cpu_xDelta;
cpu_yVelocity = cpu_Vel.cpu_yDelta;
}else if(CPU_DIR == 3){
cpu_Vel = new CpuVelocityAction(0, CPU_DELTA);
cpu_xVelocity = cpu_Vel.cpu_xDelta;
cpu_yVelocity = cpu_Vel.cpu_yDelta;
}else if(CPU_DIR == 4){
cpu_Vel = new CpuVelocityAction(0, -CPU_DELTA);
cpu_xVelocity = cpu_Vel.cpu_xDelta;
cpu_yVelocity = cpu_Vel.cpu_yDelta;
};
if(timer == (CPU_DIR + 25)){
if((CPU_DIR == 1) | (CPU_DIR == 2)){
CPU_DIR = ((random.nextInt(2)) + 3);
}else if((CPU_DIR == 3) | (CPU_DIR == 4)){
CPU_DIR = ((random.nextInt(2)) + 1);
}
};
timer += 1;
cpu.x += cpu_xVelocity;
if (cpu.x > getWidth()){
cpuPath.lineTo(getWidth(), cpu.y);
cpuPath.moveTo(0, cpu.y);
cpu.x = 0;
cpuTurn = new Point(cpu);
}
if (cpu.x + PLAYER_SIZE < 0){
cpuPath.lineTo(0, cpu.y);
cpuPath.moveTo(getWidth() - 1, cpu.y);
cpu.x = getWidth() - 1;
cpuTurn = new Point(cpu);
}
cpu.y += cpu_yVelocity;
if (cpu.y > getHeight()){
cpuPath.lineTo(cpu.x, getHeight());
cpuPath.moveTo(cpu.x, 0);
cpu.y = 0;
cpuTurn = new Point(cpu);
}
if (cpu.y + PLAYER_SIZE < 0){
cpuPath.lineTo(cpu.x, 0);
cpuPath.moveTo(cpu.x, getHeight() - 1);
cpu.y = getHeight() - 1;
cpuTurn = new Point(cpu);
}
repaint();
}
});
playerTimer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setStroke(new BasicStroke(6));
g2d.setColor(Color.BLUE);
g2d.draw(playerPath);
g2d.draw(new Line2D.Float(lastTurn, player));
g2d.drawRect(player.x - (PLAYER_SIZE / 2), player.y - (PLAYER_SIZE / 2), PLAYER_SIZE, PLAYER_SIZE);
g2d.setColor(Color.ORANGE);
g2d.draw(cpuPath);
g2d.draw(new Line2D.Float(cpuTurn, cpu));
g2d.drawRect(cpu.x - (PLAYER_SIZE / 2), cpu.y - (PLAYER_SIZE / 2), PLAYER_SIZE, PLAYER_SIZE);
}
public class VelocityAction extends AbstractAction{
private final int xDelta;
private final int yDelta;
public VelocityAction(int xDelta, int yDelta){
this.xDelta = xDelta;
this.yDelta = yDelta;
};
@Override
public void actionPerformed(ActionEvent e){
xVelocity = xDelta;
yVelocity = yDelta;
lastTurn = new Point(player);
playerPath.lineTo(player.x, player.y);
}
}
public class CpuVelocityAction extends AbstractAction{
private final int cpu_xDelta;
private final int cpu_yDelta;
public CpuVelocityAction(int cpu_xDelta, int cpu_yDelta){
this.cpu_xDelta = cpu_xDelta;
this.cpu_yDelta = cpu_yDelta;
};
@Override
public void actionPerformed(ActionEvent e){
cpu_xVelocity = cpu_xDelta;
cpu_yVelocity = cpu_yDelta;
cpuTurn = new Point(cpu);
cpuPath.lineTo(cpu.x, cpu.y);
}
}
}
}
虽然我还没有实现一个系统来测试与对手线的碰撞,但正如我原来问题的主题那样,我在将cpu播放器转换为使用摆动计时器时遇到了一些问题(I讨厌使用那些,顺便说一句,这就是为什么我试图让Thread.sleep()
在原始代码中工作的原因)。基本上,cpu只是不起作用。它要么完全吓坏了,要么把所有这些对角线都放在一边,要么只是保持直线而不会转弯。我几乎是肯定的,这与我的随机数发生器无关,我把它设置为使cpu决定如何转动,那么在写这个时我还搞砸了什么呢?谢谢你的帮助。
答案 0 :(得分:2)
我在endGame
例程中放了一个简单的print语句,在任何给定时间打印出CPU的坐标,我发现:
cpu coordiantes = [java.awt.Point[x=340,y=330], java.awt.Point[x=340,y=330],java.awt.Point[x=340,y=330], java.awt.Point[x=340,y=330]]
所有CPU的访问坐标都是当前坐标!这是一个错误。在更新位置的任何情况下,您都可以将其追踪到cpu_move
,例如:
else if(cpu_dir == 2){
if(cpu.x < 0){
cpu.x = 395;
path2.moveTo(400, cpu.y);
}
cpu.x -= 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
更新X坐标并将其重新添加到列表中。您想要创建一个新的不同Point
对象,并为其分配cpu.x - 5的值,并将其添加到列表中。一般来说,这段代码编写得很糟糕,但是如果你解决了这个问题,我认为它应该可行。
值得注意的是,在这种情况下使用Set
会更好,因为查找会更快,特别是随着游戏的进行和当前列表的增长。
注意:了解如何在调试器中单步调试代码,否则永远不会成为优秀的程序员。