如果有人能帮我解决我的代码,我会很高兴。我有一个项目涉及一个人工生命形式(一个臭虫)吃食物和避免障碍。到目前为止,我在地图上随机生成食物。当我点击重置按钮时,所有食物消失并且虫子返回到第一个方格并且不是随机的。谁能告诉我为什么?另外,我如何阻止虫子和食物有时被放在同一个面板上。任何帮助都会很棒,谢谢! 包Javaproject;
import java.lang.Math.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Random;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SpinnerNumberModel;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@SuppressWarnings("serial")
public class JumpinJackFlash extends JPanel implements ActionListener, ChangeListener {
private JPanel gridPanel; //the panel containing the 2D grid
private JPanel cells[][]; //the cells of the 2D grid
private JToolBar toolBar;
private JButton jb_start, jb_stop, jb_reset;
private JTextField jtf_info;
private Timer timer;
private int speed; //cycles per second
private int cycleNum;
private JSpinner jspin_speed;
private final static String RELPATHICONS = "icons" + File.separator; //relative path to icons folder
private final static String RELPATHSOUNDS = "sounds" + File.separator; //relative path to sounds folder
private static Random ran = new Random();
private static final int hsize=10;
private static final int vsize=10;
//the moving item:
private JLabel jack;
private int jack_x, jack_y;
private File boingSoundFile;
private JLabel Food;
private int food_x, food_y;
private static JSlider slider() {
JSlider slider;
slider = new JSlider(JSlider.VERTICAL, 0, 20, 0);
slider.setMajorTickSpacing(5);
slider.setPaintTicks(true);
return slider;
}
/**
* The constructor
*/
public JumpinJackFlash(){
gridPanel = new JPanel(new GridLayout(hsize, vsize));
cells = new JPanel[hsize][vsize];
for(int i=0; i<hsize; i++){
for(int j=0; j<vsize; j++){
cells[i][j] = new JPanel();
cells[i][j].setBackground(Color.white);
cells[i][j].setBorder(BorderFactory.createLineBorder(Color.black));
gridPanel.add(cells[i][j]);
}
}
//{
// cells[i][j] = Food
// }
jack = new JLabel(getImageIcon("download.gif"));
boingSoundFile = new File(RELPATHSOUNDS+File.separator+"boing.wav");
//init position within the 2D grid
int rand1 = (int) (Math.random() * 9);
int rand2 = (int) (Math.random() * 9);
jack_x = rand1;
jack_y= rand2;
cells[jack_x][jack_y].add(jack);
for (int i=0; i<5; i++)
{
int rand3 = (int) (Math.random() * 9);
int rand4 = (int) (Math.random() * 9);
food_x = rand3;
food_y= rand4;
cells[food_x][food_y].add(new JLabel(getImageIcon("food.gif")));
}
//The toolbar
toolBar = new JToolBar();
jb_start = new JButton(getImageIcon("start.gif"));
jb_start.setToolTipText("start");
jb_stop = new JButton(getImageIcon("stop.gif"));
jb_stop.setToolTipText("stop");
jb_reset = new JButton(getImageIcon("back.gif"));
jb_reset.setToolTipText("reset");
toolBar.add(jb_start);
toolBar.add(jb_stop);
toolBar.add(jb_reset);
//Some text for info
jtf_info = new JTextField("cycle "+"<"+cycleNum+">");
jtf_info.setBackground(Color.LIGHT_GRAY);
//The speed
speed = 1; //init speed of the animation (1 cycle per second)
SpinnerNumberModel jsm = new SpinnerNumberModel(speed,1,50,1);
jspin_speed = new JSpinner(jsm);
JLabel jlb_speed = new JLabel("Speed", JLabel.CENTER);
JPanel speedPanel = new JPanel(new BorderLayout());
speedPanel.add(jlb_speed, BorderLayout.NORTH);
speedPanel.add(jspin_speed, BorderLayout.CENTER);
speedPanel.add(new JLabel("(steps per second)", JLabel.CENTER), BorderLayout.SOUTH);
gridPanel.add(slider(), BorderLayout.EAST);
//A panel for the toolbar
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(toolBar, BorderLayout.WEST);
topPanel.add(speedPanel, BorderLayout.EAST);
//Set the layout of the main panel
this.setLayout(new BorderLayout());
add(topPanel, BorderLayout.NORTH);
add(gridPanel, BorderLayout.CENTER);
add(jtf_info, BorderLayout.SOUTH);
//Init the timer and register 'this' as listener
timer = new Timer(1000/speed, this); //create a new Timer object and register 'this' as
//listener for the periodic Timer events
timer.setInitialDelay(500); //in msec
cycleNum = 0;
//Register 'this' listener for the events generated by the jbuttons
//and by the Timer object.
jb_start.addActionListener(this);
jb_stop.addActionListener(this);
jb_reset.addActionListener(this);
//Register 'this' listener for the events generated by the jspinner
jspin_speed.addChangeListener(this);
}
/**
* The call back method for the events generated by the jbuttons
* and for the periodic events generated by the timer.
*/
public void actionPerformed(ActionEvent e){
if(e.getSource() == timer){
cycleNum++; //next step (cycle) of the synchronous animation
gridContent_update(); //update the content of the grid
this.repaint(); //repaint the view
} else if(e.getSource() == jb_start) {
speed = ((SpinnerNumberModel)jspin_speed.getModel()).getNumber().intValue();
timer.setDelay(1000/speed);
timer.start(); //start the animation by starting the timer
} else if(e.getSource() == jb_stop) {
timer.stop();
} else if(e.getSource() == jb_reset) {
timer.stop();
cycleNum = 0;
gridContent_reset();
this.repaint();
} else {
//System.out.println("##### unknown event source #####");
}
}
/**
* The call back method for the events generated by the jspinner,
* which is used to change the animation speed.
*/
public void stateChanged(ChangeEvent e) {
if(e.getSource() == jspin_speed) {
speed = ((SpinnerNumberModel)jspin_speed.getModel()).getNumber().intValue();
timer.setDelay(1000/speed);
}
}
/**
* Set new random coordinates for the moving item.<br>
* It check if the passed new coordinates are valid,
* i.e. within the grid dimensions.
*
* @param coordX
* @param coordY
* @return true if new valid coordinates have been set.
*/
private boolean moveJackTo(int coordX, int coordY){
if((coordX>=0) && (coordX<hsize) && (coordY>=0) && (coordY<vsize)){
if((coordX!=jack_x) || (coordY!=jack_y)){ //valid new coordinates
cells[jack_x][jack_y].removeAll(); //remove jack from start pos
jack_x = coordX;
jack_y = coordY;
cells[jack_x][jack_y].add(jack); //add jack to dest pos
return true;
}
}
return false; //the coordinates have not been changed
}
/**
* This method is used to change the content of the 2D grid,
* i.e. the position of the moving item jack.
*/
private void gridContent_update(){
boolean moved = false;
while(!moved){ //repeat until new valid coordinates have been set
int x = jack_x;
int y = jack_y;
Random rn = new Random();
int answer = rn.nextInt(4) + 1;
switch(answer){
case(1):
{
y++; break;
}
case(2):
{
y--; break;
}
case(3):
{
x++; break;
}
case(4):
{
x--; break;
}
}
moved = moveJackTo(x, y);
}
jtf_info.setText("cycle <"+cycleNum+">");
this.validate(); //should be invoked when this container's subcomponents are modified
}
/**
* This method is used to reset the content of the 2D grid,
* i.e. the initial position of the moving item jack.
*/
private void gridContent_reset(){
for (int i = 0; i < hsize; i++) {
for (int j = 0; j < vsize; j++) {
cells[i][j].removeAll();
cells[i][j].setBackground(Color.white);
}
}
//init position
jack_x=0;
jack_y=0;
cells[jack_x][jack_y].add(jack);
cycleNum = 0;
jtf_info.setText("cycle <"+cycleNum+">");
this.validate(); //should be invoked when this container's subcomponents are modified
}
/**
* Return a ImageIcon with the given icon or generate an error message.
*/
private static ImageIcon getImageIcon(String iconFilename) {
ImageIcon theIcon;
File theImage = new File(RELPATHICONS + iconFilename);
if (theImage.isFile()) {
theIcon = new ImageIcon(theImage.getAbsolutePath());
} else {
// show an error message and quit
theIcon = null;
JOptionPane.showMessageDialog(null, "Error - file not found: "
+ iconFilename);
System.exit(-1);
}
return (theIcon);
}
/**
* Return a ImageIcon with the given icon or a default image
*/
private static ImageIcon getImageIcon(String iconFilename, String std_iconFilename) {
ImageIcon theIcon;
File theImage = new File(RELPATHICONS + iconFilename);
if (theImage.isFile()) {
theIcon = new ImageIcon(theImage.getAbsolutePath());
} else {
theImage = new File(RELPATHICONS + std_iconFilename);
theIcon = new ImageIcon(theImage.getAbsolutePath());
}
return (theIcon);
}
/**
* play a sound
* @param theSoundFile
*/
private static void playSound(File theSoundFile) {
try {
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(theSoundFile);
clip.open(ais);
clip.loop(0);
} catch (Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked by the event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create the container
JFrame wm_frame = new JFrame("Synchronous Animation");
// Quit the application when this frame is closed:
wm_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and add the content panel
JumpinJackFlash wm_panel = new JumpinJackFlash();
wm_frame.add(wm_panel); // OR frame.setContentPane(panel);
// Display the window
wm_frame.pack(); // adapt the frame size to its content
wm_frame.setLocation(10, 10); // in pixels
wm_frame.setVisible(true); // Now the frame will appear on screen
}
public static void main (String args[]){
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
答案 0 :(得分:3)
基本上,当点击“休息”按钮时,您应该restarting
Timer
重新开始。
} else if (e.getSource() == jb_reset) {
timer.stop();
cycleNum = 0;
gridContent_reset();
// Restart the timer...
timer.start();
this.repaint();
}
关于问题的后半部分,基本上,您需要检查JPanel
cells[x][y]
是否包含任何子项,并将x / y值随机化为不存在(或者您达到某种限制,以防止无限循环的可能性)
另一种方法可能是随机化一个列表(可能包含每个单元格的JPanel
),当你想要添加食物时简单地弹出第一个元素,并在没有食物存在时将其添加回来(在该单元格内) )
您应该打破代码,以便至少将模型和视图分开。
模型将包含有关游戏状态的信息,视图将负责渲染它。这将有助于简化大部分逻辑,因为当您想要确定放置食物的位置时,您不应该关心屏幕上的内容。