mboost-dp1

Java Hjælp..


Gå til bund
Gravatar #1 - tazimn
5. feb. 2009 19:50
Hej derude... jeg har set mig blind på min kode efterhånden.

Jeg er ved at lave spillet "Game of life" hvis det siger Jer noget.

Hvor om alting er så skal jeg have fundet ud af hvor mange celler der er i live, i et område af 3x3 felter.

Hvis den pågældende celle har 2 naboer, og selv er i live, så overlever han. Hvis han ikke er i live så forbliver han død.

Hvis han derimod har 3 naboer, og han er død, liver han op. Hvis han er levende forbliver han levende. Alle andre muligheder vil dræbe den pågældende celle.

koden er som følger:

public void findNeighbors(Cell[][] cell, int x, int y) {
int nrAlive = 0;

for (int col = x - 1; col < x + 2; col++) {
for (int row = y - 1; row < y + 2; row++) {
if (col >= 0 && col < cell.length && row >= 0 && row < cell[col].length) {
if (cell[col][row].isAlive()==true) {
nrAlive++;
}
}
}
}
if (cell[x][y].isAlive()==true) {
nrAlive--;

}
if (nrAlive==2 && cell[x][y].isAlive()==true){
cell[x][y].setAlive(true);
}
if (nrAlive==3){
cell[x][y].setAlive(true);
}else{
cell[x][y].setAlive(false);
}
}


Håber der er nogen som kan tyde min kode og som har nogle friske øjne på den..

Kenn Stadager
Gravatar #2 - Emil Melgaard
5. feb. 2009 23:24
Denne kode har ikke nogen effekt:

if (nrAlive==2 && cell[x][y].isAlive()==true) {
cell[x][y].setAlive(true);
}


Da den kun vil sætte cellen til "levende" hvis den er levende i forvejen.

Derfor vil denne kode:

if (nrAlive==3) {
cell[x][y].setAlive(true);
} else {
cell[x][y].setAlive(false);
}


Altid dræbe cellen hvis den har to naboer.

Det du mangler er en "else" mellem de to kodeblokke, så der kommer til at stå:

if (nrAlive==2 && cell[x][y].isAlive()==true) {
cell[x][y].setAlive(true);
} else if (nrAlive==3) {
cell[x][y].setAlive(true);
} else {
cell[x][y].setAlive(false);
}


Men da det som sagt er lidt meningsløst at oplive cellen hvis den allerede er levende, burde du også bare kunne skrive følgende:

if (nrAlive==3) {
cell[x][y].setAlive(true);
} else if (nrAlive != 2) {
cell[x][y].setAlive(false);
}


Så vil cellen bare beholde sin status hvis den har to naboer.
Gravatar #3 - tazimn
6. feb. 2009 07:10
Jeg prøver det efter jeg kommer hjem fra Arbejde... Tak indtil videre..
Gravatar #4 - myplacedk
6. feb. 2009 07:50
Nu siger du jo ikke noget om hvad problemet er, men jeg kan da kommentere din kode. Jo mere læsevenlig koden er, jo nemmere er det at finde fejl. (Det er sværere at skrive kode som både computer og menneske kan forstå, end kode som kun computeren kan forstå.)

Jeg har ikke ændret noget i koden, kun indsat kommentarer.

public void findNeighbors(Cell[][] cell, int x, int y) {
int nrAlive = 0;

// Her forvirrer det mig at du kigger på "-1" og "+2". Jeg ville tælle til "<= x+1" i stedet for "< x+2".
for (int col = x - 1; col < x + 2; col++) {
// For at forkorte den lange betingelse i if-sætningen længere nede, kunne du allerede her tjekke om "col" er inden for din matrix. Det vil også performe ubetydeligt bedre. Fx:
// if (col < 0 || col >= cell.length) {
// continue;
// }
for (int row = y - 1; row < y + 2; row++) {
if (col >= 0 && col < cell.length && row >= 0 && row < cell[col].length) {
// Du skulle nok også tjekke om du er midt i din 3x3-matrix, da det jo kun er naboer du tæller. Du kan evt. gøre det i en selvstændig "if": if (col==x && row==y) continue;
if (cell[col][row].isAlive()==true) {
nrAlive++;
}
}
}
}
// Hvis du følger mit ovenstående råd, slipper du for at kompensere her, og kan slette de tre næste linjer.
if (cell[x][y].isAlive()==true) {
nrAlive--;

}
// De næste 3 linjer gør intet ud over at bruge CPU-tid.
if (nrAlive==2 && cell[x][y].isAlive()==true){
cell[x][y].setAlive(true);
}
// Her går der lidt ged i din indrykning. Især hos begyndere er det næsten garanti for at lave fejl senere.
if (nrAlive==3){
cell[x][y].setAlive(true);
}else{
cell[x][y].setAlive(false);
}

// Logikken for om om cellen er levende eller ej ville jeg nok lave som en switch:
// switch(nrAlive) {
// case 0:
// case 1:
// cell[x][y].setAlive(false);
// break;
// case 2:
// // No change
// break;
// case 3:
// cell[x][y].setAlive(true);
// break;
// default:
// cell[x][y].setAlive(false);
// }

}
Gravatar #5 - myplacedk
6. feb. 2009 09:13
...så fik jeg lige tid til at skrive lidt mere. :)

Tænk at når du beregner hvordan din matrix ser ud i trin 2, så skal du kigge på hvordan den så ud i trin 1.

Først beregner du felt 1,1. Alt OK. Så beregner du felt 1,2. For at beregner felt 1,2 skal du vide hvordan felt 1,1 så ud. Men det kan du ikke se længere, fordi du måske allerede har modificeret den.

Du er faktisk nødt til at lave en ny matrix. Når du beregner kigger du i den gamle, og gemmer resultaterne i den nye. Til sidst kan du så overføre fra den nye matrix til den gamle, eller returnere den nye matrix.
Gravatar #6 - Windcape
6. feb. 2009 14:29
Jeg ville nok strukturer koden lidt op.

Lav en metode som retunerer en liste/matrix af naboer, ud fra en given celle, uden at redigerer på værdien af cellen.

Lidt ligesom man ville gøre i graph-theroy.
Gravatar #7 - tazimn
6. feb. 2009 16:55
Hej alle sammen.. og tak for kommentarene..

Emil: Tak for forsøget... det virkede desværre ikke..

MyPlace.dk: Har også prøvet med en switch, dog uden held..
btw.. så godt at indrykningen var elendig. Dog blev den være efter jeg satte code tags om den..

ifølge reglerne for Game of life, så vil 3 celler på stribe være en stabil struktur idet, den skifter mellem følgende:

*
*
*
------------
* * *
------------
*
*
*

Lige nu opfører det sig således:

*
*
*
------------
*
*
* *
------------
* *
* *

Firkanten bliver der selvfølgelig..

Og jeg aner virkelig ikke hvor det er at det går galt..
Gravatar #8 - myplacedk
6. feb. 2009 16:59
Jeg kan ikke debugge uden kode. ;-)
Gravatar #9 - tazimn
6. feb. 2009 17:15
hmmm... det kan der være noget om..

int nrAlive = 0;

for (int col = x - 1; col < x + 2; col++) {
for (int row = y - 1; row < y + 2; row++) {
if (col >= 0 && col < cell.length && row >= 0 && row < cell[col].length) {
if (cell[col][row].isAlive() == true) {
nrAlive++;
}
}
}
}
//Trækker sig selv fra naboer.
if (cell[x][y].isAlive() == true) {
nrAlive--;

}
//hvis der er 3 naboer, så skal den lives op.
if (nrAlive == 3) {
cell[x][y].setAlive(true);
//Hvis der ikke er 2 naboer skal den dø.
} else if (nrAlive != 2) {
cell[x][y].setAlive(false);
}
Gravatar #10 - arne_v
6. feb. 2009 17:22
Jeg tror at han fisker efter en SSCCE !

(http://pscode.org/sscce.html)

Gravatar #11 - myplacedk
6. feb. 2009 17:44
#10
Det gør de alle. Men de får det ikke af mig, for typisk bliver det hverken læst eller forstået. :-/
Gravatar #12 - tazimn
6. feb. 2009 17:49
Det jeg leder efter er mere en forklaring på hvad det er jeg gør forkert.. for som jeg kan se er det dækket ind, angående spillereglerne.. Men det er det jo så ikke alligevel..
Gravatar #13 - myplacedk
6. feb. 2009 17:49
#9
Du mangler at løse problemet beskrevet i #5. Indtil da, kan jeg ikke se nogen grund til at debugge yderligere.
Gravatar #14 - arne_v
6. feb. 2009 18:05
#11

Nu var det spørger som skulle lave en SSCCE til dig ...
Gravatar #15 - myplacedk
6. feb. 2009 18:09
#14
Oh. Ja, jeg elsker "SSCCE" der viser problemet. Især fordi fremstillingen af det meget ofte viser fejlen.

Men den kode jeg ser er nok i dette tilfælde. Jeg kan tydeligt se problemet blot ved at læse koden. ;-)
Gravatar #16 - Emil Melgaard
6. feb. 2009 23:11
#7:

Jeg tror ikke længere problemet skal findes i den kode du har vist her, så du bliver nødt til vise os noget mere af din kode, eller ihf. beskrive hvordan du har løst det problem myplacedk beskriver i #5.
Gravatar #17 - Windcape
7. feb. 2009 23:54
Simplified, skrevet som hjælp til en ven i Finland.


package game;

public class Game
{
/**
* Starts the Game of Life.
*
* @param args
*/
public static void main(String[] args)
{
int generations = 3;

char[][] start_data = {
new char[] { '.','.','.','.','.' },
new char[] { '.','o','.','o','.' },
new char[] { '.','.','o','.','.' },
new char[] { '.','.','.','.','.' },
new char[] { '.','.','.','.','.' },
};

for(int i = 0; i < generations; i++)
{
System.out.println("Evoloution #" + (i+1));
printData(start_data);
start_data = evolve(start_data);
System.out.print("\n");
}
}

/**
* Utility: Prints a evolution.
*
* @param data
*/
private static void printData(char[][] data)
{
for(int o=0;o<data.length;o++)
{
for(int i=0;i<data[0].length;i++)
{
System.out.print(data[o][i] + " ");
}
System.out.print("\n");
}
}

/**
* Utility: Copies a nested array.
*
* @param input
* @return
*/
private static char[][] deepArrayCopy(char[][] input)
{
char[][] tmp = new char[input.length][];

for(int i=0; i<tmp.length; i++)
{
tmp[i] = new char[input[i].length];
for(int t=0;t<input[i].length;t++)
{
tmp[i][t] = input[i][t];
}
}

return tmp;
}

/**
* Evolve a set of spicies.
*
* @param data
* @return
*/
private static char[][] evolve(char[][] data)
{
char[][] result = deepArrayCopy(data);

int neighbors = 0;

// Outer Iteration (Rows)
for(int o=0;o<data.length;o++)
{
// Inner Iteration (Columns)
for(int i=0;i<data[0].length;i++)
{
neighbors = countNeighbors(data, o, i);

// 1. Any live cell with fewer than two live neighbours dies,
// as if by needs caused by underpopulation
if(neighbors < 2)
{
result[o][i] = '.';
}
// 2. Any live cell with more than three live neighbours dies,
// as if by overcrowding.
else if(neighbors > 3)
{
result[o][i] = '.';
}
// 3. Any live cell with two or three live neighbours lives,
// unchanged, to the next generation.
else if((neighbors == 2 || neighbors == 3) && (data[o][i] == 'o'))
{
result[o][i] = 'o';
}
/// 4. Any dead cell with exactly three live neighbours becomes a live cell.
else if((neighbors == 3) && (data[o][i] == '.'))
{
result[o][i] = 'o';
}
}
}

return result;
}

/**
* Checks all 8 surrounding cells for life,
* and return the amount of neighbors.
*
* @param rowIndex
* @param columnIndex
*/
private static int countNeighbors(char[][] data, int rowIndex, int columnIndex)
{
int neighbors = 0;

// Horisontal (Left)
if((columnIndex > 0)
&& (data[rowIndex][columnIndex-1] == 'o'))
{
neighbors++;
}

// Horisontal (Right)
if((columnIndex < data[rowIndex].length-1)
&& (data[rowIndex][columnIndex+1] == 'o'))
{
neighbors++;
}

// Vertical (Top)
if((rowIndex > 0)
&& (data[rowIndex-1][columnIndex] == 'o'))
{
neighbors++;
}

// Vertical (Below)
if((rowIndex < data.length-1)
&& (data[rowIndex+1][columnIndex] == 'o'))
{
neighbors++;
}

// Dimensional
if(rowIndex > 0)
{
// Below-Left
if((columnIndex > 0)
&& (data[rowIndex-1][columnIndex-1] == 'o')) {
neighbors++;
}

// Below-Right
if((columnIndex < data[rowIndex].length-1)
&& (data[rowIndex-1][columnIndex+1] == 'o')) {
neighbors++;
}
}

// Dimensional
if(rowIndex < data.length-1)
{
// Top-Left
if((columnIndex > 0)
&& (data[rowIndex+1][columnIndex-1] == 'o')) {
neighbors++;
}

// Top-Right
if((columnIndex < data[rowIndex].length-1)
&& (data[rowIndex+1][columnIndex+1] == 'o')) {
neighbors++;
}
}

return neighbors;
}
}

Gravatar #18 - Windcape
7. feb. 2009 23:55
Og et kørt eksemple resultat:


Evoloution #1
. . . . .
. o . o .
. . o . .
. . . . .
. . . . .

Evoloution #2
. . . . .
. . o . .
. . o . .
. . . . .
. . . . .

Evoloution #3
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Gravatar #19 - Windcape
8. feb. 2009 00:26
Og for lidt nemmere at læse kode: http://www.twilight-wizard.net/game-of-life.aspx

:p

Gravatar #20 - KarstenP
8. feb. 2009 16:01
http://pastebin.com/f690d393d

Jeg lavede lige en hurtig implementation, som bruger et to-dimentionelt array af booleans. Bemærk at jeg i min evolve()-metode, kun skal bekymre mig om en celle skal leve, da alle celler i tmp som default er false.
Gravatar #21 - tazimn
8. feb. 2009 16:52
Tak for svarende..

jeg vender tilbage når jeg har fået det til at virke, og poster min løsning.. Dog er det et fritidssyfleri så jeg har ikke så meget tid til det.
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login