2010-12-04 16 views
0

私は完璧に動作するはずだと思うプログラムを書いた。何らかの理由でそれはしません。私はコードを提供し、誰かが間違っていることを理解できるように願っています。私は数時間それを座っていたが、私はそれ以上得ることはできません。奇妙なランダムエラー、java描画

import java.awt.*; 
import javax.swing.*; 

public class CrystalModel 
{ 
    private int radius; 
    private int index; 
    private boolean[][] crystal; 
    private Point concludingPoint; 
    private int escapeRadius; 

    /** 
    * Constructor. Initiates an electron bath of size 30x30. 
    */ 
    public CrystalModel() 
    { 
     radius = 30; 
     index = 30*2-1; 
     start(); 
    } 

    /** 
    * Constructor. Initiates an electron bath of size r. 
    * @param r bath radius 
    */ 
    public CrystalModel(int r) 
    { 
     radius = r; 
     index = r*2-1; 
     start(); 
    } 

    /** 
    * Initiates the experiment 
    */ 
    private void start() 
    { 
     crystal = new boolean[radius*2][radius*2]; 
     crystal[radius][radius] = true; //The width is always even (2*r), this is as close to the center as one gets 
     escapeRadius = (int)(1.1*radius); 
    } 

    /** 
    * Determines if a given xy-coordinate is within radius 
    * @param x x-coordinate 
    * @param y y-coordinate 
    * @return whether the active ion is out of range 
    */ 
    private boolean outsideCircle(int r, int x, int y) 
    { 
     return (Math.pow(x,2)+Math.pow(y,2) >= Math.pow(r, 2)); 
    } 

    /** 
    * Determines if the currently active ion has a neighbouring crystallized ion 
    * @param whether the is a neighbour 
    */ 
    private boolean anyNeighbours(int x, int y) 
    { 
      x = xBathToModel(x); 
      y = yBathToModel(y); 

      boolean left = (x-1 >= 0) && (x-1 <= index) && (y >= 0) && (y <= index) ? crystal[x-1][y] : false; 
      boolean right = (x+1 >= 0) && (x+1 <= index) && (y >= 0) && (y <= index) ? crystal[x+1][y] : false; 
      boolean up  = (y-1 >= 0) && (y-1 <= index) && (x >= 0) && (x <= index) ? crystal[x][y-1] : false; 
      boolean down = (y+1 >= 0) && (y+1 <= index) && (x >= 0) && (x <= index) ? crystal[x][y+1] : false; 

      return (left || right || up || down); 
    } 

    /** 
    * Determines an xy-coordinate at radius distance from the center 
    * @param radius radius of escape for ions 
    * @return Point object encapsulating x, y 
    */ 
    private Point dropNewIon() 
    { 
     double angle = (int)(Math.random()*2*Math.PI); 
     return new Point((int)(Math.cos(angle)*(index/2)), (int)(Math.sin(angle)*(index/2))); 
    } 

    /** 
    * Transform x-coordinate upon the moving of origo from center to top-left 
    * @ x x-coordinate 
    */ 
    public int xBathToModel(int x) 
    { 
     return radius+x; 
    } 

    /** 
    * Transform y-coordinate upon the moving of origo from center to top-left 
    * @param y y-coordinate 
    */ 
    public int yBathToModel(int y) 
    { 
     return radius+y; 
    } 

    /** 
    * Increments the number of ions in the crystal by one 
    * @return boolean indicating whether the experiment is done or not 
    */ 
    private Point crystallizeOneIon() 
    { 
     Point point = dropNewIon(); 
     for(; ;) 
     { 
      switch((int)(Math.random()*4+1)) 
      { 
       case 1: point.x+=1; 
        break; 
       case 2: point.x-=1; 
        break; 
       case 3: point.y+=1; 
        break; 
       case 4: point.y-=1; 
        break; 
      } 

      if(outsideCircle(escapeRadius, point.x, point.y)) point = dropNewIon(); 

      if(anyNeighbours(point.x, point.y)) break; 
     } 

     crystal[xBathToModel(point.x)][yBathToModel(point.y)] = true; 
     return point; 
    } 

    /** 
    * Let the algorithm (CrystalExperiment) simulate a number of steps 
    * @param steps how many steps 
    * @return boolean indiciating whether the experiment is concluded 
    */ 
    public boolean runExperiment(int steps) 
    { 
     for(int i=0; i<steps; i++) 
     { 
      concludingPoint = crystallizeOneIon(); 

      if(outsideCircle((int)index/2, concludingPoint.x, concludingPoint.y)) 
      { 
       concludingPoint.x = xBathToModel(concludingPoint.x); 
       concludingPoint.y = yBathToModel(concludingPoint.y); 
       return true; 
      } 
      else 
      { 
       concludingPoint.x = xBathToModel(concludingPoint.x); 
       concludingPoint.y = yBathToModel(concludingPoint.y); 
      } 
     } 

     return false; 
    } 

    /** 
    * Return a textual representation of the crystal 
    * @return String representing the crystal 
    */ 
    public String toString() 
    { 
     String output = ""; 
     for(int y=-1; y<=index+1; y++) 
     { 
      for(int x=-1; x<=index+1; x++) 
      { 
       if(y == -1) output+="--"; 
       else if(y == index+1) output+="--"; 
       else 
       { 
        if(x == -1) output+="|"; 
        else if(x == index+1) output+="|"; 
        else 
        { 
         if(concludingPoint.equals(new Point(x,y))) output+="# "; 
         else if(crystal[x][y] == true) output+="* "; 
         else output+=" "; 
        } 
       } 
      } 
      output+="\n"; 
     } 

     return output; 
    } 

    public int getIndexSize() 
    { 
     return index; 
    } 

    public boolean getMatrixValue(int x, int y) 
    { 
     return crystal[x][y]; 
    } 

    private void drawCrystal() 
    { 
     JFrame frame = new JFrame(""); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     frame.setBounds(0, 0, 200, 200); 

     CrystalView drawing = new CrystalView(this); 
     frame.add(drawing); 
    } 

    public static void main(String[] args) 
    { 
     (new CrystalModel(200)).drawCrystal(); 
    } 

} 

これが私の見解である、(toStringメソッドは動作しますが、これは似ている)、それは動作しませんが:

import javax.swing.*; 
import java.awt.*; 

public class CrystalView extends JPanel 
{ 
    CrystalModel model; 
    public CrystalView(CrystalModel m) 
    { 
     model = m; 
    } 

    public void paintComponent(Graphics g) 
    { 
     while(!model.runExperiment(1)) 
     { 
      for(int y=0; y<model.getIndexSize(); y++) 
      { 
       for(int x=0; x<model.getIndexSize(); x++) 
       { 
        if(model.getMatrixValue(x,y)) 
        g.drawOval(x, y, 1, 1); 
       } 
      } 
      this.repaint(); 
     } 
    } 
} 

誤差は、図にあります。 (1)端末にエラーを生成し、(2)フルサイズを描画しない。プログラムを実行すると、私の言いたいことが分かります。

+1

* "プログラムを実行して、あなたは私が何を意味するかが表示されますしてください。" *。いいえ、私はしません。助けが必要な場合は、問題の内容を教えてください。 –

+0

問題は非常に簡単です。 for-loopを見ると、ループは1-200までループし、この領域(200x200)内のピクセルで塗りつぶします。しかし、それを描くと、図は非常に小さくなります。それがまったく描かれれば、そうです。ちょうど200pxのサイズで完全にフリーズするので、私はそれを遅くする何かをやっていると思います。 –

+0

また、モデルが機能していることを既に確認しているので、描画部分に注目してください。 toStringは、グラフィックがどのように表示されるべきかの正しいイメージを返します。 –

答えて

1
public void paintComponent(Graphics g) 
{ 
    while(!model.runExperiment(1)) 
    { 
     for(int y=0; y<model.getIndexSize(); y++) 
     { 
      for(int x=0; x<model.getIndexSize(); x++) 
      { 
       if(model.getMatrixValue(x,y)) 
       g.drawOval(x, y, 1, 1); 
      } 
     } 
     this.repaint(); 
    } 
} 

コードで何をすべきかわかりませんが、そのようなrepaint()を呼び出すループは決してありません。これは、無限ループを引き起こす1つの方法です。

アニメーションを作成する場合は、スレッドまたはスイングタイマーを使用してアニメーションを行う必要があります。

+0

基本的には、私が描いている画像が徐々に増えていきます。私が "runExperiment"を実行するたびに、行列は新しい値を取得します。だから私はすべてを引き出すためにループをやり直さなければならない。その結果、画像が大きくなるのを見ることができるアニメーションが少なくなるはずですが、タイマーなどの必要はありません。私はこれが何らかの形で意図された解決であることをほぼ100%確信しています。 –

+1

そのループは確かにそこに属していません。再描画すると、paintComponentが再度呼び出されます。必要なのは、そのループの内容と、 'model.runExperiment(1)'と 'repaint()'を繰り返し呼び出すタイマーです。 – configurator

+0

paintComponent()メソッドは、コンポーネントの現在の状態を描画するために使用されます。コンポーネントの状態を変更するには、他の方法があります。つまり、コンポーネントの状態を変更するメソッドを呼び出すTimerなどがあり、そのメソッドはrepaint()を呼び出します。 – camickr

1

あなたのコードを修正しようとしました(下記参照)。問題の場所はTODOでマークされています。どのように動作することが意図されているのかわからないが、今はいくつかの点を描いている。

前述のように、このようなアニメーションを取得することはできません。 paintComponent()メソッドは、コンポーネントを描画するために1回だけ呼び出されます。これは、たとえばフォームのサイズが変更されたときに発生します。だから静的な画像しか得ることはできません。

CrystalModel.java

import java.awt.Point; 
import javax.swing.JFrame; 

public class CrystalModel 
{ 
    private int radius; 
    private int index; 
    private boolean[][] crystal; 
    private Point concludingPoint; 
    private int escapeRadius; 

    /** 
    * Constructor. Initiates an electron bath of size 30x30. 
    */ 
    public CrystalModel() 
    { 
     radius = 30; 
     index = 30*2-1; 
     start(); 
    } 

    /** 
    * Constructor. Initiates an electron bath of size r. 
    * @param r bath radius 
    */ 
    public CrystalModel(int r) 
    { 
     radius = r; 
     index = r*2-1; 
     start(); 
    } 

    /** 
    * Initiates the experiment 
    */ 
    private void start() 
    { 
     crystal = new boolean[radius*2][radius*2]; 
     crystal[radius][radius] = true; //The width is always even (2*r), this is as close to the center as one gets 
     escapeRadius = (int)(1.1*radius); 
    } 

    /** 
    * Determines if a given xy-coordinate is within radius 
    * @param x x-coordinate 
    * @param y y-coordinate 
    * @return whether the active ion is out of range 
    */ 
    private boolean outsideCircle(int r, int x, int y) 
    { 
     return (Math.pow(x,2)+Math.pow(y,2) >= Math.pow(r, 2)); 
    } 

    /** 
    * Determines if the currently active ion has a neighbouring crystallized ion 
    * @param whether the is a neighbour 
    */ 
    private boolean anyNeighbours(int x, int y) 
    { 
      x = xBathToModel(x); 
      y = yBathToModel(y); 

      boolean left = (x-1 >= 0) && (x-1 <= index) && (y >= 0) && (y <= index) ? crystal[x-1][y] : false; 
      boolean right = (x+1 >= 0) && (x+1 <= index) && (y >= 0) && (y <= index) ? crystal[x+1][y] : false; 
      boolean up  = (y-1 >= 0) && (y-1 <= index) && (x >= 0) && (x <= index) ? crystal[x][y-1] : false; 
      boolean down = (y+1 >= 0) && (y+1 <= index) && (x >= 0) && (x <= index) ? crystal[x][y+1] : false; 

      return (left || right || up || down); 
    } 

    /** 
    * Determines an xy-coordinate at radius distance from the center 
    * @param radius radius of escape for ions 
    * @return Point object encapsulating x, y 
    */ 
    private Point dropNewIon() 
    { 
     double angle = (int)(Math.random()*2*Math.PI); 
     return new Point((int)(Math.cos(angle)*(index/2)), (int)(Math.sin(angle)*(index/2))); 
    } 

    /** 
    * Transform x-coordinate upon the moving of origo from center to top-left 
    * @ x x-coordinate 
    */ 
    public int xBathToModel(int x) 
    { 
     return radius+x; 
    } 

    /** 
    * Transform y-coordinate upon the moving of origo from center to top-left 
    * @param y y-coordinate 
    */ 
    public int yBathToModel(int y) 
    { 
     return radius+y; 
    } 

    /** 
    * Increments the number of ions in the crystal by one 
    * @return boolean indicating whether the experiment is done or not 
    */ 
    private Point crystallizeOneIon() 
    { 
     Point point = dropNewIon(); 
     for(; ;) 
     { 
      switch((int)(Math.random()*4+1)) 
      { 
       case 1: point.x+=1; 
        break; 
       case 2: point.x-=1; 
        break; 
       case 3: point.y+=1; 
        break; 
       case 4: point.y-=1; 
        break; 
      } 

      if(outsideCircle(escapeRadius, point.x, point.y)) point = dropNewIon(); 

      if(anyNeighbours(point.x, point.y)) break; 
      break; 
     } 

     try { 
      // TODO The logic is wrong here - calculated points sometimes are out of array. See console output 
      crystal[xBathToModel(point.x)][yBathToModel(point.y)] = true; 
     } catch (ArrayIndexOutOfBoundsException e) { 
      System.out.println("Oops, point (" + point.x + ", " + point.y + ") is out of array"); 
     } 
     return point; 
    } 

    /** 
    * Let the algorithm (CrystalExperiment) simulate a number of steps 
    * @param steps how many steps 
    * @return boolean indiciating whether the experiment is concluded 
    */ 
    public synchronized boolean runExperiment(int steps) 
    { 
     for(int i=0; i<steps; i++) 
     { 
      concludingPoint = crystallizeOneIon(); 

      if(outsideCircle((int)index/2, concludingPoint.x, concludingPoint.y)) 
      { 
       concludingPoint.x = xBathToModel(concludingPoint.x); 
       concludingPoint.y = yBathToModel(concludingPoint.y); 
       return true; 
      } 
      else 
      { 
       concludingPoint.x = xBathToModel(concludingPoint.x); 
       concludingPoint.y = yBathToModel(concludingPoint.y); 
      } 
     } 

     return false; 
    } 

    /** 
    * Return a textual representation of the crystal 
    * @return String representing the crystal 
    */ 
    public String toString() 
    { 
     String output = ""; 
     for(int y=-1; y<=index+1; y++) 
     { 
      for(int x=-1; x<=index+1; x++) 
      { 
       if(y == -1) output+="--"; 
       else if(y == index+1) output+="--"; 
       else 
       { 
        if(x == -1) output+="|"; 
        else if(x == index+1) output+="|"; 
        else 
        { 
         if(concludingPoint.equals(new Point(x,y))) output+="# "; 
         else if(crystal[x][y] == true) output+="* "; 
         else output+=" "; 
        } 
       } 
      } 
      output+="\n"; 
     } 

     return output; 
    } 

    public int getIndexSize() 
    { 
     return index; 
    } 

    public boolean getMatrixValue(int x, int y) 
    { 
     return crystal[x][y]; 
    } 

    private void drawCrystal() 
    { 
     JFrame frame = new JFrame(""); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     frame.setBounds(0, 0, 600, 600); 

     CrystalView drawing = new CrystalView(this); 
     frame.add(drawing); 
     frame.validate(); 
    } 

    public static void main(String[] args) 
    { 
     (new CrystalModel(200)).drawCrystal(); 
    } 

} 

CrystalView.java

import java.awt.Graphics; 

import javax.swing.JPanel; 

public class CrystalView extends JPanel { 
    private static final long serialVersionUID = 1L; 

    CrystalModel model; 

    public CrystalView(CrystalModel m) { 
     model = m; 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     while (!model.runExperiment(1)) { 
      for (int y = 0; y < model.getIndexSize(); y++) { 
       for (int x = 0; x < model.getIndexSize(); x++) { 
        if (model.getMatrixValue(x, y)) { 
         g.drawOval(x, y, 2, 2); 
        } 
       } 
      } 
     } 
    } 
} 
+0

ありがとう、本当にありがとうございます。ただし、drawCrystalのコードをwhile(this.runExperiment(1)){System.out.println(this。toString()); }これをメインプログラムで次のように呼び出します:(new CrystalModel())。drawCrystal();端末には、正確に正しい画像が表示されます。それのテキスト表現。ロジックにエラーはなく、完全に機能します。そして、私がしたいのは、完全にtoStringによって描画されたイメージを描画することですが、JPanelでは...エラーはロジックではなく、描画コードで行うべきです:/ –

+0

私はうれしいです助け、あなたが何を意味するのか分からなかった:)「描画コード」はJPanelにいくつかの点を置くだけです。ポイントはそこにありますので、今すぐ動作します。問題はそれがどれ点を描くのかということです。 –

+0

ちょうど助言 - すべての計算を無効にして、ハードコーディングされた値を描画メソッドに入れてみてください(目的の画像を取得する)。これは論理のない純粋な図面になるので、問題が実際に描画にあれば誰かがあなたを助けることができます。 –

関連する問題