简体   繁体   English

康威的生活游戏无法按预期进行

[英]conway's game of life doesn't work as expected

I was trying to create conway's game of live in java. 我试图在Java中创建conway的现场游戏。 I've no trouble with my code, but with the output of the game. 我的代码没有问题,但游戏的输出却没有问题。 The still lifes pattern work as expected, but all the moving sructures are ending up in something different. 静物模式按预期工作,但是所有移动的结构都以不同的方式结束。

For example: 1 is a living cell; 例如:1是活细胞; 0 is a dead cell 0是一个死单元

On the wiki page there is an oscillator, the blinker. 在Wiki页面上,有一个振荡器,即闪烁器。 in my case it behaves like this: 就我而言,它的行为如下:

生活游戏问题

I'm doing all the stuff in an applet, which i add to a jframe. 我正在将小程序中的所有内容都添加到jframe中。 Here's the applet code (ignore the german comments, unless you're german :P): 这是小程序代码(忽略德语注释,除非您是德语: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

        }
}

It is a complex algorithm so I can't ensure you that it will work after this, but the rest of the code looks ok. 这是一个复杂的算法,所以我不能保证在此之后它会起作用,但是其余的代码看起来还可以。

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

Ok, clone() performs a shadow copy which works well for primitives. 好的,clone()执行一个卷影副本,该卷影副本非常适合基元。 But it does not work for a bidimensional array (which acts as a onedimensional array of onedimensional arrays). 但是它不适用于二维数组 (充当一维数组的一维数组)。 So, you have still a shallow copy. 因此,您的副本仍然很浅。

After doing that, you are really overwritting the old array before all the calculations are over. 之后,您真的要在所有计算结束之前覆盖旧数组。 For static situations (no new pixels die/live), it is ok because new and old array are expected to be the same, for the others cases you find the error. 对于静态情况(没有新像素消亡/存活),这是可以的,因为新旧阵列应该是相同的,对于其他情况,您会发现错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM