Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

Java wijzigt ongevraagd objecten

Pagina: 1
Acties:

  • Waster
  • Registratie: September 2006
  • Laatst online: 14-04 17:49
Ik heb een probleem met de objecten in java. Ik ben een AI proberen te maken voor reversi. Ik zit met het probleem dat een deel van mijn object steeds ongevraagd gewijzigd wordt. Mijn code:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.util.*;

public class Spel
{
    byte[][] velden; //Hier worden de schijfjes opgeslagen
    int width_x, width_y;
    byte aanzet;
    boolean help;
    
    //Ik heb ook nog een constructor die alleen de breedte als argument nodig heeft.
    public Spel(int width, byte[][] i_velden, byte i_aanzet)
    {
        this.width_x = width;
        this.width_y = width;
        
        this.velden = i_velden;
        this.aanzet = i_aanzet;
        this.help = false;
    }
    
    //Heel veel functies en hulpfuncties die het prima doen, zoals eindeSpel(), doeZet(), aantalStukken(), tegenstanderAanzet(), zetMogelijk() enz.
    //...
    //...
    //...
    //Verder nog een tekenBord() functie die een reversi bord kan tekenen in de console
    //En als laatste heb ik een simpele bordEvaluatie() functie toegevoegd die een waarde toekent aan een bordpositie
    
    //Bij deze functie gaat het fout
    public Move bestNextMove(byte[][] startPositie, byte aanzet)
    {
        Spel stelling = new Spel(8, startPositie, aanzet);
        TreeSet<Move> moves = new TreeSet<Move>();
        
        for(byte i=0; i<width_x; i++)
            for(byte j=0; j<width_y; j++)
                if(stelling.velden[i][j] == 0 || stelling.velden[i][j] == 3)
                    if(stelling.isLegaleZet(i, j))
                    {
                        Spel evaluatie = new Spel(8, stelling.velden, aanzet);
                        
                        //Hier verandert hij dus ook alle andere objecten ??
                        evaluatie.doeZet(i, j);
                        byte value = evaluatie.bordEvaluatie();
                        
                        moves.add(new Move(i, j, value));
                    }
        
        return moves.first();
    }
}


De klasse Move is niet meer dan drie variabelen die de x- en y-waarde van de zet opslaat en de totale waarde van de bordpositie. Ik heb deze klasse nodig, omdat ik een comparable implementatie nodig had die de Move-objecten ordent zodat ik een treeset kan gebruiken.

Als ik in een andere klasse de bestNextMove() functie wil aanroepen veranderd deze ook de velden-array in mijn oorspronkelijke klasse:

Java:
1
2
3
4
5
6
7
8
public class ShowGame   extends Frame {
    Spel s;
    
    void paint(Graphics g){
        s = new Spel(6);
        s.bestNextMove(s.showVelden(), s.aanzet());
    }
}


Dan wordt de velden array aangepast terwijl dit niet mag gebeuren. Ik heb twee keer een nieuw lokaal Spel-object gemaakt, stelling en evaluatie. Dus zou hij de velden array van het lokale object moeten wijzigen en niet ook nog eens van het spel-object in de andere klasse. Ik heb verder gecontroleerd in de console. Alle spel-objecten hebben een apart id, dus het zijn ook werkelijk verschillende objecten. Verder heb ik geprobeerd om de functie bestNextMove() in een andere klasse te zetten, ik heb hem static gemaakt en ik heb geprobeerd de velden-array private te maken. Het maakt niks uit. De functie rommelt altijd aan mijn velden-array en ik wil dat deze hetzelfde blijft en ik wil alleen de beste zet uitrekenen met hulp van mijn bordevaluatie functie.

Hier is de console wat hij met de beginstelling doet als ik de functie aanroep:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Lokaal Spel-object stelling: Spel@1d85f79
1 . . . . . . 
2 . . . . . . 
3 . . 0 x . . 
4 . . x 0 . . 
5 . . . . . . 
6 . . . . . . 
  a b c d e f g h

Lokaal Spel-object evaluatie: Spel@641e9a
1 . . . . . . 
2 . . x . . . 
3 . . x x . . 
4 . . x 0 . . 
5 . . . . . . 
6 . . . . . . 
  a b c d e f g h

Ander lokaal Spel-object evaluatie: Spel@1c282a1
1 . . . . . . 
2 . . x . . . 
3 . . x x . . 
4 . . x x x . 
5 . . . . . . 
6 . . . . . . 
  a b c d e f g h

Spel-object in de hoofdapplicatie s: Spel@157aa53
1 . . . . . . 
2 . . x . . . 
3 . . x x . . 
4 . . x x x . 
5 . . . . . . 
6 . . . . . . 
  a b c d e f g h


Je ziet de id's van de objecten en de posities geprint met tekenBord() functie. Voor de duidelijkheid zou ik dus willen dat er de volgende borden uitkwamen:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Lokaal Spel-object stelling: Spel@1d85f79
1 . . . . . . 
2 . . . . . . 
3 . . 0 x . . 
4 . . x 0 . . 
5 . . . . . . 
6 . . . . . . 
  a b c d e f g h

Lokaal Spel-object evaluatie: Spel@641e9a
1 . . . . . . 
2 . . x . . . 
3 . . x x . . 
4 . . x 0 . . 
5 . . . . . . 
6 . . . . . . 
  a b c d e f g h

Ander lokaal Spel-object evaluatie: Spel@1c282a1
1 . . . . . . 
2 . . . . . . 
3 . . 0 x . . 
4 . . x x x . 
5 . . . . . . 
6 . . . . . . 
  a b c d e f g h

//En er moet dus niets veranderen aan het oorspronkelijke object:
Spel-object in de hoofdapplicatie s: Spel@157aa53
1 . . . . . . 
2 . . . . . . 
3 . . 0 x . . 
4 . . x 0 . . 
5 . . . . . . 
6 . . . . . . 
  a b c d e f g h

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-11 23:43

.oisyn

Moderator Devschuur®

Demotivational Speaker

Tja, typisch gevalletje documentatie lezen :). Arrays zijn objecten, en worden derhalve niet gekopieerd als je ze doorgeeft aan een functie (of in dit geval de Spel constructor). Elk Spel werkt derhalve met dezelfde array, zoals je zelf al ziet. Je zult de array in de Spel constructor moeten dupliceren.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Waster
  • Registratie: September 2006
  • Laatst online: 14-04 17:49
Thanks. Ik heb het uitgeprobeerd en dat is inderdaad het probleem. Ik heb imperatief programmeren gevolgd, maar daar kwam dit niet ter sprake. Ik kopieer positie dus naar de array startPositie. Maar is er een snellere manier dan zoals ik nu doe?

Java:
1
2
3
4
5
public Move bestNextMove(byte[][] positie, byte aanzet){
        byte[][] startPositie = new byte[8][8];
        for(int i=0; i<8; i++)
            for(int j=0; j<8; j++)
                startPositie[i][j] = positie[i][j];

  • DutchCommando
  • Registratie: November 2000
  • Laatst online: 20:20

  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 18:44
Waarom rommelen met reflection? System.arraycopy() ;)

[ Voor 9% gewijzigd door Jaap-Jan op 19-03-2008 18:17 ]

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


  • Waster
  • Registratie: September 2006
  • Laatst online: 14-04 17:49
En die heb ik geprobeerd, als ook newInstance en clone(). Ze werken bij niet omdat ik meerdere dimensionale array heb. Of bij arraycopy maakt hij er alleen een copy van en ik moet nou juist een nieuw object hebben. Arraycopy kopieerd ook gewoon de oorspronkelijke array en wat je in de copy veranderd, veranderd in het origineel mee. Zie de startpost.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-11 23:43

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat komt omdat je in feite een array van arrays hebt. Je kunt wel een clone() doen, maar dat is een shallow copy van je array - positie[0] t/m positie[7] wijzen elk weer naar de originele rij, dus in feite moet je elke rij clonen.

Je zou evt. kunnen overwegen om een eendimensionale array te gebruiken, en dan ipv positie[x][y] te doen doe je positie[x + y * 8]

Maar feit blijft dat er eigenlijk niets mis is met je huidige for-loopje om je kopie te maken ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 18:44
Hmm, ik wilde net zeggen wat .oisyn ook zegt: ombouwen naar een ééndimensionale array is ook een mogelijkheid.

En met een for- loop is niets mis, inderdaad. En qua performance kun je natuurlijk testen hoe snel je for- loop werkt ten opzichte van System.arraycopy() op een één dimensionale array. Tot slot kun je, in plaats van alle elementen afzondelijk te kopiëren, ook per rij System.arraycopy() doen. :)

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


  • Waster
  • Registratie: September 2006
  • Laatst online: 14-04 17:49
Ok bedankt voor de info. De posite omzetten naar [x + y * 8] zal niet gaan, want dan zal ik dit voor twintig andere functies ook moeten veranderen, die er vanuit gaan dat er velden[x][y] array is. Ik denk dat mijn eerste oplossing dus in ieder geval de meest praktische oplossing is. :)
Pagina: 1