java - 奇怪的随机错误,java绘图

标签 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) 不绘制完整尺寸。请运行该程序,您就会明白我的意思。

最佳答案

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() 的循环。这是导致无限循环的一种方法。

如果您尝试制作动画,那么您需要使用线程或 Swing 计时器来制作动画。

关于java - 奇怪的随机错误,java绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4356322/

相关文章:

java - 如何为 Bukkit 插件从 10 开始倒计时?

java - NoClassDefFoundError : javax/xml/stream/XMLStreamException

java - log4j.xml 加载不记录消息

java - Redis如何将值存储为json

java - ListView 和适配器过滤器未更新

java - 连接管理器 : pool of connection

java - Maven 尝试再次下载 ojdbc14.jar - jar 已经存在于本地存储库中

java - Java套接字连接: receiving completely arbitrary integers from the Input Stream

java - 将生成的类打包到 jar 中并将其添加到构建类路径中

java - 我有机会运行用户定义的程序来生成资源吗?