0

私はコンウェイのライブゲームをJavaで作成しようとしていました。コードには問題はありませんが、ゲームの出力には問題があります。静物画のパターンは期待どおりに機能しますが、すべての動く構造物は別の何かになってしまいます。

例:1は生細胞です。0は死んだ細胞です

wikiページにはオシレーター、ブリンカーがあります。私の場合、次のように動作します。

ライフゲーム

私はアプレットですべてのことをやっていて、それをjframeに追加します。アプレットコードは次のとおりです(ドイツ語でない限り、ドイツ語のコメントは無視してください:P):

import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Canvas extends Applet implements MouseListener{
    private static final long serialVersionUID = -9195952699213522986L;

    private boolean[][] cells; //True lebt; false ist tod
    private int cellWidth;
    private int margin = 2;
    private int step = 0;
    private boolean isRunning = false;

    public Canvas(int size, int cv){ //size = 50; cv = 10;
        addMouseListener(this);
        cells = new boolean[size][size];
        cellWidth = cv;
        //Zellen Füllen
        for(int i = 0; i < cells.length; i++){
            for(int j = 0; j < cells[0].length; j++){
                cells[i][j] = false;
            }
        }
    }

    @Override
    public void paint(Graphics g){
        //Updaten
        if(isRunning)
            update();
        //Hintergrund
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, getWidth(), getHeight());

        //Punkte zeichnen
        for(int i = 0; i < cells.length; i++){
            for(int j = 0; j < cells[0].length; j++){
                if(cells[i][j]){
                    g.setColor(Color.GREEN);
                    g.fillRect(i * cellWidth + margin, j * cellWidth + margin, cellWidth - margin, cellWidth - margin);
                }
                else if(!cells[i][j]){
                    g.setColor(new Color(0x222222));
                    g.fillRect(i * cellWidth + margin, j * cellWidth + margin, cellWidth - margin, cellWidth - margin);
                }
            }
        }
        repaint();
    }

    private void update(){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Für jede Zelle Spielregeln anwenden ( siehe Wikipedia: http://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens )
        //Wichtig:
        //Die Matrix muss komplett bearbeitet und neu gespeichert werden, deswegen newCells
        boolean[][] newCells = cells.clone();
        for(int i = 0; i < cells.length; i++){
            for(int j = 0; j < cells[0].length; j++){

                //Nachbarn
                int neighbors = countNeighbors(i, j);
                //Lebende Zelle
                if(cells[i][j]){
                    //Einsamkeit
                    if(neighbors < 2){
                        newCells[i][j] = false;
                    }
                    //Überbevölkerung
                    else if(neighbors > 3){
                        newCells[i][j] = false;
                    }
                    //alles ok
                    else if(neighbors == 2 || neighbors == 3){
                        newCells[i][j] = true;
                    }
                }
                //Tote Zelle
                else if(!cells[i][j]){
                    //Neue Zellen wird geboren
                    if(neighbors == 3){
                        newCells[i][j] = true;
                    }
                }
            }
        }
        cells = newCells;
        System.out.println("Step #" + (++step));
    }

    private int countNeighbors(int x, int y){
        int neighbors = 0;
        for(int i = x-1; i <= x+1; i++){
            for(int j = y-1; j <= y+1; j++){
                if(x == i && y == j) //Dieselbe Zelle
                    continue;
                try{
                    if(cells[i][j])
                        neighbors++;

                } catch(java.lang.ArrayIndexOutOfBoundsException e){
                }
            }
        }
        return neighbors;
    }

    //Double Buffering
        @Override
        public void update(Graphics g){
                Graphics offgc;
                Image offscreen = null;
                Dimension d = getSize();

                // create the offscreen buffer and associated Graphics
                offscreen = createImage(d.width, d.height);
                offgc = offscreen.getGraphics();
                // clear the exposed area
                offgc.setColor(getBackground());
                offgc.fillRect(0, 0, d.width, d.height);
                offgc.setColor(getForeground());
                // do normal redraw
                paint(offgc);
                // transfer offscreen to window
                g.drawImage(offscreen, 0, 0, this);
        }

        @Override
        public void mouseClicked(MouseEvent e) {

        }

        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mousePressed(MouseEvent e) {
            if(e.isMetaDown()){
                isRunning = !isRunning;
            }
            else if(!isRunning){
                int x = e.getX() / cellWidth;
                int y = e.getY() / cellWidth;
                cells[x][y] = !cells[x][y];
            }   
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub

        }
}
4

1 に答える 1

3

これは複雑なアルゴリズムであるため、この後も機能するかどうかは保証できませんが、残りのコードは問題ないように見えます。

boolean[][] newCells = cells.clone();

わかりました。clone()は、プリミティブに対して適切に機能するシャドウコピーを実行します。ただし、2次元配列(1次元配列の1次元配列として機能します)では機能しません。だから、あなたはまだ浅いコピーを持っています。

それを行った後、すべての計算が終了する前に、実際に古い配列を上書きしています。静的な状況(新しいピクセルが死ぬ/生きていない)の場合、新しい配列と古い配列は同じであると予想されるため、問題ありません。他の場合は、エラーが見つかります。

于 2012-08-21T19:09:02.090 に答える