0

私はコンウェイの人生ゲームのクローンに取り組んでいましたが、それは良い習慣だったのですが、問題が発生しました。ピクセルの削除と再生がありますが、すべてのピクセルが画面の最後に広がり、他のピクセルが再生されますが、その時点ではアイドル状態になっています。

ここにいくつかのスクリーンショットがあります: ここに画像の説明を入力

このロジックのコードの一部を紹介します。それはすべてchangeメソッドで処理されます。

package main;

import java.awt.Color;
import java.awt.Graphics;

public class Functions {

  public static int pixelsize=6,gridwidth=800/6,gridheight=600/6;
  static int[][] pixels = new int[gridwidth][gridheight];
  static boolean first = true;

  public static void change(){

    for(int i = 0; i < gridwidth; i++){
      for(int j = 0; j < gridheight; j++){
        int neighbors = 0;
        //check each cell

        try{

          if(pixels[i+1][j] == 1){neighbors++;}
          if(pixels[i-1][j] == 1){neighbors++;}
          if(pixels[i+1][j-1] == 1){neighbors++;}
          if(pixels[i][j+1] == 1){neighbors++;}
          if(pixels[i][j-1] == 1){neighbors++;}
          if(pixels[i+1][j+1] == 1){neighbors++;}
          if(pixels[i-1][j-1] == 1){neighbors++;}
          if(pixels[i-1][j+1] == 1){neighbors++;}

        }catch(ArrayIndexOutOfBoundsException e){

        }

        if(neighbors == 3 || neighbors == 2 ){
          pixels[i][j] = 1;
        }else if(neighbors < 2 || neighbors >= 4){
          pixels[i][j] = 0;
        }
      }
    }
  }

  public static void render(Graphics g){

    for(int i = 0; i < gridwidth;i++){
      for(int j = 0; j < gridheight; j++){
        if(pixels[i][j] == 1){

          g.setColor(Color.red);
          g.fillRect(i*6, j*6, 6, 6);
        }
      }
    }
  }
}


すべての助けに感謝します。残念ながら、まだ正しく動作していません。
今は同じことをしていますが、ダイヤモンド形成では次のようになっています:
ここに画像の説明を入力

4

2 に答える 2

6

ここで私が目にする主な問題は、値を発見しながら値を更新しているという事実です。

更新する前にグリッド全体 (または少なくとも隣接カウント) をキャッシュする必要があります。そうしないと、 で要素を更新するときに、現在の反復の結果をカウントすることによって、、(x, y)として連続する要素の隣接カウントを変更します。(x+1,y)(x+1,y+1)(x,y+1)

たとえば、次のように cachedPixels という別の配列を更新できます。

for(int i = 0; i < gridwidth; i++){
    for(int j = 0; j < gridheight; j++){
        int neighbors = 0;
        // find the proper boundaries
        int minI = Math.max(0, i - 1);
        int maxI = Math.min(gridwidth, i + 2)
        int minJ = Math.max(0, j - 1);
        int maxJ = Math.min(gridheight, j + 2)

        for (int i2 = minI; i2 < maxI; i2++) {
           for (int j2 = minJ; j2 < maxJ; j2++) {
              if (i2 != i || j2 != j) {
                 if (pixels[i2][j2] == 1) {
                    neighbors++;
                 }
              }
           }
        }

        if (neighbors == 2 || neighbors == 3) {
           cachedPixels[i][j] = 1;
        } else {
           cachedPixels[i][j] = 0; // probably not even necessary as 0 is default value
        }
    }   
}

次に、arraycopy 関数を使用して配列セット全体に対してこのプロセスを完了した後、次のようにします。

for (int i = 0; i < length; i++) {
    System.arraycopy(cachedPixels[i], 0, pixels[i], 0, cachedPixels[i].length);
}

単純に pixel = cachedPixels を設定すると、「ピクセル」が「cachedPixels」配列を指すことになり、一方を変更すると他方が変更され、システムが崩壊します。

PS GoL に使用しているルールは、John H. Conway のルールと同じではありません。セルは、隣接するセルが 3 つある場合は常に次のタイム ステップで生存し、このタイム ステップで生きている場合にのみ次のタイム ステップで隣接するセルが 2 つ存在する場合に存続し、それ以外の場合は死亡します。

cachedPixels[i][j] = 0; // Default value - death.
if (neighbors == 3) {
   cachedPixels[i][j] = 1;
} else if (thisCell == 1 && neighbors == 2) {
   cachedPixels[i][j] = 1;
}
于 2013-02-08T17:39:45.823 に答える
2

生まれたばかりのピクセルは、この動きの隣人としてカウントされるべきではなく、死にかけているピクセルはカウントされるべきです。これは、生まれたばかりのピクセルと死にかけているピクセルに対して、 と2などの別の値を設定することで実現できます。3フィールドを処理した後、新生児の値を に置き換え、死期の値を に置き換えて、その状態をコミット10ます。

于 2013-02-08T17:41:49.533 に答える