Kopiera 2D array med objekt i Java
Jag håller på att bli galen på det här nu. Jag försöker skriva ett enkelt Game of Life (https://en.wikipedia.org/wiki/Conway's_Game_of_Life) i Java och har börjat med en textbaserad version. För att representera själva spelbrädet har jag en 2D array. För varje ny generation går jag igenom hela arrayen och kollar vilka närliggande element som lever eller är döda och det är här det skiter sig. Tanken är att jag tittar på en array och sedan skriver alla ändringar till en ny kopia. När jag vandrat igenom hela arrayen så vill jag ersätta den gamla kopian med den nya och sedan kan man börja om med en ny generation.
Problemet är att hur jag än gör så får jag inte en deep copy utan den skriver över även den gamla arrayen vilket göra att programmet inte fungerar alls. Jag har fetmarkerat koden jag använder för att göra en kopia. Har testat både .clone() och Arrays.copyOf() med samma resultat. När jag ändrar något i den nya arrayen newCells så ändras även den gamla arrayen cells. Därför utgår jag från att jag inte får en riktig kopia utan att Java bara kopierar referenserna så att båda arrayerna fortfarande pekar på samma objekt.
Så här ser koden ut nu:
Seed.java ser ut så här och är bara en enum.
package lifetext;
public enum Seed {
ALIVE, DEAD
}
Cell.java sköter en enskild cell
package lifetext;
public class Cell {
Seed cellState;
int row, col;
public Cell(int row, int col) {
row = this.row;
col = this.col;
}
public void kill(){
cellState = Seed.DEAD;
}
public void birth(){
cellState = Seed.ALIVE;
}
public Seed getState() {
return cellState;
}
public void paint() {
switch(cellState) {
case DEAD:
System.out.print(" - ");
break;
case ALIVE:
System.out.print(" O ");
break;
}
}
}
Sedan har vi Board.java där felet ligger.
package lifetext;
import java.util.Arrays;
public class Board {
public static final int ROWS = 10;
public static final int COLS = 10;
Cell cells[][];
int currentRow, currentCol;
//Constructor
public Board() {
cells = new Cell[ROWS][COLS];
for (int row=0; row<ROWS; ++row) {
for (int col=0; col<COLS; ++col) {
cells[row][col] = new Cell(row, col);
}
}
}//End of constructor
//Rensa hela bordet genom att döda alla celler
public void init() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
cells[row][col].kill(); // clear the cell content
}
}
}//End of init
public void setStartState(int[][] startState) {
for (int row=0; row<ROWS; ++row) {
for (int col=0; col<COLS; ++col) {
if (startState[row][col] == 1) {
cells[row][col].birth();
}
}
}
}//End of setStartState
public void nextGen() {
int numberAlive = 0;
Cell[][] newCells = new Cell[cells.length][];
newCells = arrayClone(cells);
for (int row=1; row<(ROWS-1); ++row){
for (int col=1; col<(COLS-1); ++col) {
for (int irow=(row-1); irow<=(row+1); irow++) {
for (int icol=(col-1); icol<=(col+1); icol++) {
if (cells[irow][icol].getState() == Seed.ALIVE) {
numberAlive++;
}
}
}
//Ta kolla aktuell cell så den inte räknas
if (cells[row][col].getState() == Seed.ALIVE) {
numberAlive--;
}
//kill and give birth to new cells
if (numberAlive < 2) {
newCells[row][col].kill();
}
else if (numberAlive > 3) {
newCells[row][col].kill();
}
else if (cells[row][col].getState() == Seed.ALIVE && (numberAlive == 2 || numberAlive == 3)) {
newCells[row][col].birth();
}
else if (cells[row][col].getState() == Seed.DEAD && numberAlive == 3) {
newCells[row][col].birth();
}
numberAlive = 0;
}
}
cells = arrayClone(cells);
}//End of nextGen()
public static Cell[][] arrayClone(Cell[][] cells) {
Cell[][] newCells = new Cell[cells.length][];
for (int i=0; i<cells.length; i++) {
//newCells[i] = cells[i].clone();
newCells[i] = Arrays.copyOf(cells[i], cells.length);
}
return newCells;
}
public void paint() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
cells[row][col].paint(); // each cell paints itself
}
System.out.println();
}
System.out.println();
}
}//End of class
Här har vi main.
package lifetext;
public class LifeText {
private Board board;
private Seed currentPlayer;
//private int[][] startState = new int[10][10];
private static Scanner in = new Scanner(System.in);
public LifeText() {
board = new Board();
int[][] startState =
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
board.init();
board.setStartState(startState);
for (int gen=0; gen<2; gen++) {
board.paint();
board.nextGen();
try {
Thread.sleep(500);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
//Kör igång spelet
new LifeText();
}
}
Q9450, HD4850, 8 GB DDR2 800 MHz, 3x750 GB, Antec 300, Dell 2408WFP, U2410, Qnap TS-419p+ 4x2 TB Samsung F4, Asus UL30A-QX056V, Logitech Z-680, Sennheiser HD380pro, M-Audio FastTrack Pro, Ibanez sa160qm, Ibanez TB 15R, Zoom 505II, Ibanez GSR 200, Ibanez SW 35, Cort AC-15, Squier SD-3 BBL, Yamaha PSR 270, Røde NT1-A, Nikon D200, Nikkor 18-70/3,5-4,5, 70-300VR, 50/1,8, 28/2,8, Tamron 17-50/2,8, 90/2,8, Sigma 30/1,4, SB-800, SB-25, SB-24