1

每个人。生命游戏中的新一代递归/循环计算

下一代在我的Game Of Life应用程序(链接是示例应用程序)正确计算。游戏按预期工作,但每次想要新一代游戏时都必须按“下一步”。我有问题实施“开始”按钮来循环世代。 (请参阅“下一步”和“开始”之间的区别链接。)

很明显,我需要ActionListener类中的某种类型的循环。我试着在actionListener内部recursivly中调用nextGen(),而私有布尔值为true。该程序崩溃。我也尝试过设置某种等待,但没关系。

如果我放置10行nextGen(),它确实会做10次迭代;在听众的内部,所以我猜我在这里需要一些等待。 (这个问题让人难以忘怀。)

希望你能帮我解决这个问题。 :)

下一代是这样计算的。

的ActionListener类:

public class GameOfLifeListener implements ActionListener 
{ 

    // IMPORTANT: GameOfLifeGrid contains the GameOfLife collection! 
    private GameOfLifeGrid gameOfLife; 



    public GameOfLifeListener (GameOfLifeGrid g) 
    { 
     this.gameOfLife = g; 
    } 

    @Override 
    public void actionPerformed (ActionEvent e) 
    { 
     // Get actionCommand 
     String ac = e.getActionCommand(); 

     if (ac.equals("next")) 
     { 
      // Method calculates next generation 
      nextGen(); 
     } 
     if (ac.equals("start")) 
     { 
      // ADDED CODE: See class GameOfLifeGrid in bottom. 
      gameOfLife.start(); 
     } 
    } 

    private void nextGen () 
    { 
     // Get Next generation 
     gameOfLife.getCollection().nextGen(); 

     // Repaint 
     gameOfLife.repaint(); 
    } 
} 

的的ActionListener当键 “下一个” 被按下运行GameOfLife对象上次世代()。如何在下一代航空运输系统()方法的工作并不重要,但在这里它与GameOfLife类

public class GameOfLife extends CellCollection 
{ 
    // Temporary array for new generation . We must add next generations alive cells HERE. 
    // Else the calculations of the current generation will fail. 
    private Cell[][] nextGen = null; 

    public void nextGen () 
    { 
     // Create the new Array holding next generation 
     prepareNextCollection(); 

     // Iterate the whole grid 
     for (int row = 0; row < super.rows; row++) 
     { 
      for (int col = 0; col < super.cols; col++) 
      { 
       ruleOne(row, col); 
      } 
     } 

     // Set the new collection to superClass. 
     // Super class holds the collection that will be drawn 
     super.setCollection(nextGen); 
    } 


    private void ruleOne (int row, int col) 
    { 
     // Calculations not important. It works like expected. 
    } 

    private void prepareNextCollection () 
    { 
     this.nextGen = new Cell[rows][cols]; 
    } 

这一些地区一起被选中GameOfLifeGrid类的部分。它绘制网格和活细胞(细胞阵列)。

public class GameOfLifeGrid extends Grid 
{ 

    private GameOfLife collection = null; 

    // ADDED MEMBERS: Timer, int 
    private Timer timer; 
    private int updateEachMilliSec = 100; // Used in program. Not in this code 

    @Override 
    public void paintComponent (Graphics g) 
    { 
     super.paintComponent(g); 
     drawCells(g); 
    } 

    private void drawCells (Graphics g) 
    { 
     for (int row = 0; row < rows; row++) 
     { 
      for (int col = 0; col < cols; col++) 
      { 
       if (! collection.isEmptyPos(row, col)) 
       { 
        g.fillRect(super.calcX(col), super.calcY(row), cellSize, cellSize); 
       } 
      } 
     } 
    } 

    // ADDED METHOD! 
    public void start() 
    { 
     // Create a timer object. The timer will send events each 100 ms. 
     // The events will be caught by the ActionListener returned from 
     // nextGenlistener(). VOILA! 

     timer = new Timer(100, nextGenlistener()); 

     // Start sending events to be caught! 
     timer.start(); 
    } 

    // ADDED METHOD! The ActionListener who will catch the events sent by timer. 
    private ActionListener nextGenlistener() 
    { 
     return new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       // Get next generation 
       collection.nextGen(); 

       // Repaint 
       repaint(); 
      } 
     }; 
    } 

回答

1

的问题是,当你试图用循环Thread.sleep()方法在actionPerformed方法,你挡住了Event Dispatch Thread。在释放线程控制权之前,没有任何东西可以重新绘制,因此当您的actionPerformed方法完成时,重新绘制请求会立即启动并立即启动。

简单的解决方案是使用一个javax.swing.Timer中以固定时间间隔触发事件,这些方针的东西:

new Timer(5000, new ActionListener(){ 
    public void actionPerformed(ActionEvent e) { 
    panel.repaint(); 
    } 
}).start(); 
+0

我花了很长时间才得到这个权利。我从来没有发现没有一个点在正确的方向。谢谢! – 2012-03-07 04:27:31