2013-07-22 56 views
0

我開始重構這個程序,我正在努力工作,並且遇到了一個主要障礙......我有一個類作爲一個核心,有大約6個其他較小(但仍然重要)的類一起工作來運行程序......我採用了一種方法[稱爲'填充()']出核類,並用它[稱爲'PopulationGenerator']創建了一個全新的類,但是當我嘗試創建一個對象找不到意外循環的來源

:在覈級試圖創建對象之前......這裏的重構前的核上課的時候我會停留在新課改

我從來沒有過這個問題永無止境的循環新創建的類的任何地方

public class Simulator 
{ 
    // Constants representing configuration information for the simulation. 
    // The default width for the grid. 
    private static final int DEFAULT_WIDTH = 120; 
    // The default depth of the grid. 
    private static final int DEFAULT_DEPTH = 80; 
    // The probability that a fox will be created in any given grid position. 
    private static final double FOX_CREATION_PROBABILITY = 0.02; 
    // The probability that a rabbit will be created in any given grid position. 
    private static final double RABBIT_CREATION_PROBABILITY = 0.08;  

    // List of animals in the field. 
    private List<Animal> animals; 
    // The current state of the field. 
    private Field field; 
    // The current step of the simulation. 
    private int step; 
    // A graphical view of the simulation. 
    private SimulatorView view; 

    /** 
    * Construct a simulation field with default size. 
    */ 
    public Simulator() 
    { 
     this(DEFAULT_DEPTH, DEFAULT_WIDTH); 
    } 

    /** 
    * Create a simulation field with the given size. 
    * @param depth Depth of the field. Must be greater than zero. 
    * @param width Width of the field. Must be greater than zero. 
    */ 
    public Simulator(int depth, int width) 
    { 
     if(width <= 0 || depth <= 0) { 
      System.out.println("The dimensions must be greater than zero."); 
      System.out.println("Using default values."); 
      depth = DEFAULT_DEPTH; 
      width = DEFAULT_WIDTH; 
     } 

     animals = new ArrayList<Animal>(); 
     field = new Field(depth, width); 

     // Create a view of the state of each location in the field. 
     view = new SimulatorView(depth, width); 
     view.setColor(Rabbit.class, Color.orange); 
     view.setColor(Fox.class, Color.blue); 

     // Setup a valid starting point. 
     reset(); 
    } 

    /** 
    * Run the simulation from its current state for a reasonably long period, 
    * (4000 steps). 
    */ 
    public void runLongSimulation() 
    { 
     simulate(4000); 
    } 

    /** 
    * Run the simulation from its current state for the given number of steps. 
    * Stop before the given number of steps if it ceases to be viable. 
    * @param numSteps The number of steps to run for. 
    */ 
    public void simulate(int numSteps) 
    { 
     for(int step = 1; step <= numSteps && view.isViable(field); step++) { 
      simulateOneStep(); 
     } 
    } 

    /** 
    * Run the simulation from its current state for a single step. 
    * Iterate over the whole field updating the state of each 
    * fox and rabbit. 
    */ 
    public void simulateOneStep() 
    { 
     step++; 

     // Provide space for newborn animals. 
     List<Animal> newAnimals = new ArrayList<Animal>();   
     // Let all rabbits act. 
     for(Iterator<Animal> it = animals.iterator(); it.hasNext();) { 
      Animal animal = it.next(); 
      animal.act(newAnimals); 
      if(! animal.isAlive()) { 
       it.remove(); 
      } 
     } 

     // Add the newly born foxes and rabbits to the main lists. 
     animals.addAll(newAnimals); 

     view.showStatus(step, field); 
    } 

    /** 
    * Reset the simulation to a starting position. 
    */ 
    public void reset() 
    { 
     step = 0; 
     animals.clear(); 
     populate(); 

     // Show the starting state in the view. 
     view.showStatus(step, field); 
    } 

    /** 
    * Randomly populate the field with foxes and rabbits. 
    */ 
    private void populate() 
    { 
     Random rand = Randomizer.getRandom(); 
     field.clear(); 
     for(int row = 0; row < field.getDepth(); row++) { 
      for(int col = 0; col < field.getWidth(); col++) { 
       if(rand.nextDouble() <= FOX_CREATION_PROBABILITY) { 
        Location location = new Location(row, col); 
        Fox fox = new Fox(true, field, location); 
        animals.add(fox); 
       } 
       else if(rand.nextDouble() <= RABBIT_CREATION_PROBABILITY) { 
        Location location = new Location(row, col); 
        Rabbit rabbit = new Rabbit(true, field, location); 
        animals.add(rabbit); 
       } 
       // else leave the location empty. 
      } 
     } 
    } 
} 

編輯:

下面是這同一類之後重構......

import java.util.Random; 
import java.util.List; 
import java.util.ArrayList; 
import java.util.Iterator; 
import java.awt.Color; 

/** 
* A simple predator-prey simulator, based on a rectangular field 
* containing rabbits and foxes. 
* 
* Update 10.40: 
* Now *almost* decoupled from the concrete animal classes. 
* 
* @TWiSTED_CRYSTALS 
*/ 
public class Simulator 
{ 
    // Constants representing configuration information for the simulation. 
    // The default width for the grid. 
    private static final int DEFAULT_WIDTH = 120; 
    // The default depth of the grid. 
    private static final int DEFAULT_DEPTH = 80; 

    // The current state of the field. 
    private Field field; 
    // The current step of the simulation. 
    private int step; 
    // A graphical view of the simulation. 
    private SimulatorView view; 
    //Population Generator class... coupled to fox and rabbit classes 
    private PopulationGenerator popGenerator; 
    // Lists of animals in the field. Separate lists are kept for ease of iteration. 
    private List<Animal> animals; 

    /** 
    * Construct a simulation field with default size. 
    */ 
    public Simulator() 
    {  
     this(DEFAULT_DEPTH, DEFAULT_WIDTH); 

    } 

    /** 
    * Create a simulation field with the given size. 
    * @param depth Depth of the field. Must be greater than zero. 
    * @param width Width of the field. Must be greater than zero. 
    */ 
    public Simulator(int depth, int width) 
    { 

     if(width <= 0 || depth <= 0) { 
      System.out.println("The dimensions must be greater than zero."); 
      System.out.println("Using default values."); 
      depth = DEFAULT_DEPTH; 
      width = DEFAULT_WIDTH; 
     } 

     animals = new ArrayList<Animal>(); 
     field = new Field(depth, width); 

     // Create a view of the state of each location in the field. 
     // 
     //   view.setColor(Rabbit.class, Color.orange); // PG 
     //   view.setColor(Fox.class, Color.blue); // PG 

     // Setup a valid starting point. 
     reset(); 
    } 

    /** 
    * Run the simulation from its current state for a reasonably long period, 
    * (4000 steps). 
    */ 
    public void runLongSimulation() 
    { 
     simulate(4000); 

    } 

    /** 
    * Run the simulation from its current state for the given number of steps. 
    * Stop before the given number of steps if it ceases to be viable. 
    * @param numSteps The number of steps to run for. 
    */ 
    public void simulate(int numSteps) 
    { 
     for(int step = 1; step <= numSteps && view.isViable(field); step++) { 
      simulateOneStep(); 
     } 
    } 

    /** 
    * Run the simulation from its current state for a single step. 
    * Iterate over the whole field updating the state of each 
    * fox and rabbit. 
    */ 
    public void simulateOneStep() 
    { 
     step++; 

     // Provide space for animals. 
     List<Animal> newAnimals = new ArrayList<Animal>();   
     // Let all animals act. 
     for(Iterator<Animal> it = animals.iterator(); it.hasNext();) { 
      Animal animal = it.next(); 
      animal.act(newAnimals); 
      if(! animal.isAlive()) { 
       it.remove(); 
      } 
     } 

     animals.addAll(newAnimals); 

    } 

    /** 
    * Reset the simulation to a starting position. 
    */ 
    public void reset() 
    { 
     PopulationGenerator popGenerator = new PopulationGenerator(); 

     step = 0; 

     animals.clear(); 

     popGenerator.populate(); 

     // Show the starting state in the view. 
     view.showStatus(step, field); 
    } 

    public int getStep() 
    { 
     return step; 
    } 

} 

...和新的類

import java.util.ArrayList; 
import java.util.Random; 
import java.util.List; 
import java.awt.Color; 

public class PopulationGenerator 
{ 
    // The default width for the grid. 
    private static final int DEFAULT_WIDTH = 120; 
    // The default depth of the grid. 
    private static final int DEFAULT_DEPTH = 80; 

    // The probability that a fox will be created in any given grid position. 
    private static final double FOX_CREATION_PROBABILITY = 0.02; 
    // The probability that a rabbit will be created in any given grid position. 
    private static final double RABBIT_CREATION_PROBABILITY = 0.08; 

    // Lists of animals in the field. Separate lists are kept for ease of iteration. 
    private List<Animal> animals; 
    // The current state of the field. 
    private Field field; 
    // A graphical view of the simulation. 
    private SimulatorView view; 

    /** 
    * Constructor 
    */ 
    public PopulationGenerator() 
    { 
     animals = new ArrayList<Animal>(); 

     field = new Field(DEFAULT_DEPTH, DEFAULT_WIDTH); 

    } 

    /** 
    * Randomly populate the field with foxes and rabbits. 
    */ 
    public void populate() 
    { 
     // Create a view of the state of each location in the field. 
     view = new SimulatorView(DEFAULT_DEPTH, DEFAULT_WIDTH); 

     view.setColor(Rabbit.class, Color.orange); // PG 
     view.setColor(Fox.class, Color.blue); // PG 

     Simulator simulator = new Simulator(); 
     Random rand = Randomizer.getRandom(); 
     field.clear(); 
     for(int row = 0; row < field.getDepth(); row++) { 
      for(int col = 0; col < field.getWidth(); col++) { 
       if(rand.nextDouble() <= FOX_CREATION_PROBABILITY) { 
        Location location = new Location(row, col); 
        Fox fox = new Fox(true, field, location); 
        animals.add(fox); 
       } 
       else if(rand.nextDouble() <= RABBIT_CREATION_PROBABILITY) { 
        Location location = new Location(row, col); 
        Rabbit rabbit = new Rabbit(true, field, location); 
        animals.add(rabbit); 
       } 
       // else leave the location empty. 
      } 
     } 
     view.showStatus(simulator.getStep(), field); 
    } 
} 

這裏的Field類的PopulationGenerator電話...我沒有以任何方式改變這個班級

import java.util.Collections; 
import java.util.Iterator; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Random; 

/** 
* Represent a rectangular grid of field positions. 
* Each position is able to store a single animal. 
* 
* @TWiSTED_CRYSTALS 
*/ 
public class Field 
{ 
    // A random number generator for providing random locations. 
    private static final Random rand = Randomizer.getRandom(); 

    // The depth and width of the field. 
    private int depth, width; 
    // Storage for the animals. 
    private Object[][] field; 

    /** 
    * Represent a field of the given dimensions. 
    * @param depth The depth of the field. 
    * @param width The width of the field. 
    */ 
    public Field(int depth, int width) 
    { 
     this.depth = depth; 
     this.width = width; 
     field = new Object[depth][width]; 
    } 

    /** 
    * Empty the field. 
    */ 
    public void clear() 
    { 
     for(int row = 0; row < depth; row++) { 
      for(int col = 0; col < width; col++) { 
       field[row][col] = null; 
      } 
     } 
    } 

    /** 
    * Clear the given location. 
    * @param location The location to clear. 
    */ 
    public void clear(Location location) 
    { 
     field[location.getRow()][location.getCol()] = null; 
    } 

    /** 
    * Place an animal at the given location. 
    * If there is already an animal at the location it will 
    * be lost. 
    * @param animal The animal to be placed. 
    * @param row Row coordinate of the location. 
    * @param col Column coordinate of the location. 
    */ 
    public void place(Object animal, int row, int col) 
    { 
     place(animal, new Location(row, col)); 
    } 

    /** 
    * Place an animal at the given location. 
    * If there is already an animal at the location it will 
    * be lost. 
    * @param animal The animal to be placed. 
    * @param location Where to place the animal. 
    */ 
    public void place(Object animal, Location location) 
    { 
     field[location.getRow()][location.getCol()] = animal; 
    } 

    /** 
    * Return the animal at the given location, if any. 
    * @param location Where in the field. 
    * @return The animal at the given location, or null if there is none. 
    */ 
    public Object getObjectAt(Location location) 
    { 
     return getObjectAt(location.getRow(), location.getCol()); 
    } 

    /** 
    * Return the animal at the given location, if any. 
    * @param row The desired row. 
    * @param col The desired column. 
    * @return The animal at the given location, or null if there is none. 
    */ 
    public Object getObjectAt(int row, int col) 
    { 
     return field[row][col]; 
    } 

    /** 
    * Generate a random location that is adjacent to the 
    * given location, or is the same location. 
    * The returned location will be within the valid bounds 
    * of the field. 
    * @param location The location from which to generate an adjacency. 
    * @return A valid location within the grid area. 
    */ 
    public Location randomAdjacentLocation(Location location) 
    { 
     List<Location> adjacent = adjacentLocations(location); 
     return adjacent.get(0); 
    } 

    /** 
    * Get a shuffled list of the free adjacent locations. 
    * @param location Get locations adjacent to this. 
    * @return A list of free adjacent locations. 
    */ 
    public List<Location> getFreeAdjacentLocations(Location location) 
    { 
     List<Location> free = new LinkedList<Location>(); 
     List<Location> adjacent = adjacentLocations(location); 
     for(Location next : adjacent) { 
      if(getObjectAt(next) == null) { 
       free.add(next); 
      } 
     } 
     return free; 
    } 

    /** 
    * Try to find a free location that is adjacent to the 
    * given location. If there is none, return null. 
    * The returned location will be within the valid bounds 
    * of the field. 
    * @param location The location from which to generate an adjacency. 
    * @return A valid location within the grid area. 
    */ 
    public Location freeAdjacentLocation(Location location) 
    { 
     // The available free ones. 
     List<Location> free = getFreeAdjacentLocations(location); 
     if(free.size() > 0) { 
      return free.get(0); 
     } 
     else { 
      return null; 
     } 
    } 

    /** 
    * Return a shuffled list of locations adjacent to the given one. 
    * The list will not include the location itself. 
    * All locations will lie within the grid. 
    * @param location The location from which to generate adjacencies. 
    * @return A list of locations adjacent to that given. 
    */ 
    public List<Location> adjacentLocations(Location location) 
    { 
     assert location != null : "Null location passed to adjacentLocations"; 
     // The list of locations to be returned. 
     List<Location> locations = new LinkedList<Location>(); 
     if(location != null) { 
      int row = location.getRow(); 
      int col = location.getCol(); 
      for(int roffset = -1; roffset <= 1; roffset++) { 
       int nextRow = row + roffset; 
       if(nextRow >= 0 && nextRow < depth) { 
        for(int coffset = -1; coffset <= 1; coffset++) { 
         int nextCol = col + coffset; 
         // Exclude invalid locations and the original location. 
         if(nextCol >= 0 && nextCol < width && (roffset != 0 || coffset != 0)) { 
          locations.add(new Location(nextRow, nextCol)); 
         } 
        } 
       } 
      } 

      // Shuffle the list. Several other methods rely on the list 
      // being in a random order. 
      Collections.shuffle(locations, rand); 
     } 
     return locations; 
    } 

    /** 
    * Return the depth of the field. 
    * @return The depth of the field. 
    */ 
    public int getDepth() 
    { 
     return depth; 
    } 

    /** 
    * Return the width of the field. 
    * @return The width of the field. 
    */ 
    public int getWidth() 
    { 
     return width; 
    } 
} 
+0

首先,你必須隔離問題的所在來這裏傾倒,可能有沒有相關的問題在所有代碼之前。使用調試器或println語句來隔離它。或者,如果您確定此問題存在於此代碼中,請告訴我們您爲什麼這麼想以及上述代碼轉儲位於何處。 –

+0

爲什麼你的新課程不包括在內?我無法看到這段代碼中的任何循環都可能變得無窮無盡,所以問題可能就在於此。 –

+0

@Mark:我知道。現在我們不得不猜測代碼中發生了什麼,他沒有向我們展示這些有點令人沮喪。在原始的海報上:再次,你有責任做一些基本的調試步驟,以便嘗試隔離問題,然後在這裏發佈**代碼。 –

回答

0

您的問題不在字段類中,但在它下面。模擬器的構造函數調用reset(),它創建一個新的PopulationGenerator對象,然後調用該對象上的populate()。 populate()方法調用Simulator simulator = new Simulator();從而創建一個新的模擬器對象,繼續循環。解決方案:不要在PopulationGenerator中創建新的Simulator對象,而是將現有的模擬器通過構造函數或setSimulator(...)方法傳遞給PopulationGenerator。

例如,

class PopulationGenerator { 
    // ... etc... 
    private Simulator simulator; // null to begin with 

    // pass Simulator instance into constructor. 
    // Probably will need to do the same with SimulatorView 
    public PopulationGenerator(Simulator simulator, int depth, int width) { 
    this.simulator = simulator; // set the instance 

    // ... more code etc... 

    } 

    public void populate() { 
    // don't re-create Simulator here but rather use the instance passed in 
    } 

} 
+0

好吧我會給那一槍...還沒有機會嘗試它,但生病讓你知道它是怎麼回事...再次感謝男人 –