Avatar billede martin421 Nybegynder
19. oktober 2009 - 12:05 Der er 8 kommentarer og
1 løsning

Værdier i obj ændres sig? Hvorfor!?

Hej Eksperter. Jeg har brug for hjælp til et mærkeligt problem, jeg ikke helt kan løse/forstå..?!

Jeg er i gang med en lille "kryds-og-bolle(TicTacToe)" app i Java, hvor man kan spille mod PC'en(AI). Her har jeg en CurrentPosition, som er et nutid billede af positionen, denne må ikke ændres, før jeg selv vælge det.

Jeg køre en recursive alphaBeta methode, når AI skal regne det bedste træk ud, her opretter den en 'new' position for hver træk mulighed... I det jeg ændre denne position, ændres også CuurenPosition(Den MÅ den IKKE) Men nu ændre de også CurrentPosition samtidigt(Det store spørgsmål???) Position indeholder en int[][] som er 3x3

Fra main køre jeg en test på alphaBeta metoden, hvor jeg checker træk muligheder(bestMoves) samt udskriver positionen.

Når jeg starter alphBeta metoden, bliver jeg nød til at hente position fra currentPosition, for at have et sted at starte fra.


Her main:
------------------------------
public static void main(String[] args) {
   
    TicToe game = new TicToe(true);   

    game.currentPosition.print();
   
    //udskriver alphaBeta sidste return value
    System.out.println("Last output: "+game.alphaBeta(new Position(game.currentPosition)));
   
    // uskriver træk som AI har gemt(som der skal vælges fra, senere...)
    for (BestMove move : game.moves){

            System.out.println("ValueScore: "+move.value+" Pos: X"+move.y+", Y"+move.x);

        }
    //Udskriv currentPosition
    game.currentPosition.print();
   

    }

------------------------------
her alphaBeta metoden:
------------------------------
public int alphaBeta(Position gameposition){
       
       
        int depth = 0;
        System.out.println(alpha);
        System.out.println(beta);
       
        if(gameposition.isEndOfPosition()){
           
            return gameposition.calcEndOfPosition();
           
        }
       
        // if Leaf node
        if(false){
           
            int staticValue = gameposition.calcStaticValue();
           
            return staticValue;
        }
       
        // hvis det er AI i trækket   
        if(gameposition.isMax()){
   
                while(alpha < beta){
           
                // for every child note possibel eller træk mulighed ud fra positionen
                for (int y = 0; y < 3; y++) for (int x = 0; x < 3; x++)
                {
                    // Is there a free spot to set a piece
                    if(gameposition.checkFreePlace(y, x)){
                       
    // ved træk, opret en ny position hvor trækket er med                    Position p = new Position(gameposition);
    //opdatere positionen me depth samt set til min(modstander træk)                    p.addDepth();
                        p.setPiece(1, y, x);
                        p.setToMin();
                        // kalder sig selv med den NYE position
                        int V = alphaBeta(p);
                        //System.out.println(V);
Når vi modtager en return value, set træk hvis vi er i depth 0                        if(depth == 0) moves.addFirst(new BestMove(V, y, x));
       
hvis value er større end alph, udskift alpha(public int alpha)                    if(V > alpha) alpha = V;
                       
                       
                      }
                   
                    }
                    return alpha;
                }
                return alpha;
        }
   
        if(gameposition.isMin()){
           
           
            while(alpha < beta){
           
            // for every child note possibel
            for (int y = 0; y < 3; y++) for (int x = 0; x < 3; x++)
            {

                if(gameposition.checkFreePlace(y, x)){
                   
                    Position p = new Position(gameposition);
                    p.addDepth();
                    p.setPiece(-1, y, x);
                    p.setToMax();
                   
                    int V = alphaBeta(p);
                   
                    if(V < beta) beta = V;
                   
                  }
               
                }
                return beta;
            }
            return beta;
           

        }
       
        System.out.println("ERROR in alphaBeta method");
        return 0;
       
    }
---------------------------------

Her en udskrift fra consolen:
Her ses hvordan position har ændret sig!
---------------------------------
----------
|0|0|0|
|0|0|0|
|0|0|0|
----------

Last output: 10000
ValueScore: 1000 Pos: X0, Y0
ValueScore: 1000 Pos: X0, Y2
ValueScore: 1000 Pos: X1, Y1
ValueScore: 1000 Pos: X2, Y0
ValueScore: 10000 Pos: X2, Y2
----------
|1|-1|1|
|-1|1|-1|
|1|-1|1|
----------
---------------------------------------

Håber der sidder en java haj eller to, eller bare én med et godt bud på denne opførelse...?
Avatar billede martin421 Nybegynder
19. oktober 2009 - 12:09 #1
P.s. Her sker fejlen i følge debug:

p.setPiece(-1, y, x);

Jeg sætter en brik i min tempPositon(man man kalde det), men Current ændres sig også som kan ses i debuggen.
Avatar billede ksoren Nybegynder
20. oktober 2009 - 17:40 #2
Fejlen opstår altså i en funktion, som du ikke har taget med i spørgsmålet?
Avatar billede erikjacobsen Ekspert
20. oktober 2009 - 22:10 #3
Klassen Position kunne også være interessant.
Avatar billede arne_v Ekspert
21. oktober 2009 - 02:50 #4
Noget komplet kode der:
- builder
- viser fejlen ved kørsel
ville gøre det meget nemt at finde fejlen.
Avatar billede martin421 Nybegynder
22. oktober 2009 - 15:40 #5
DEr er en pointe dér, da der alligvel sker en del i Position class:


public class Position {
   
   
    public int alpha;
    public int beta;
    public int depth;
    private boolean max = true;
    private int[][] board= {{0,0,0},
            {0, 0, 0},
            {0, 0, 0}};
   
    // 1. constructor
    public Position(int alpha, int beta, int depth) {
       
        this.alpha = alpha;
        this.beta = beta;
        this.depth = depth;
       
    }
    // 2. constructor
    public Position(Position p){
       
        this.alpha = p.alpha;
        this.beta = p.beta;
        this.depth = p.depth;
        this.max = p.max;
        this.board = p.board;
    }
    // 3. constructor
    public Position(Board b){
        this.alpha = -1000;
        this.beta = 1000;
        this.depth = 0;
        this.board = b.getBoardPosition();
    }
   
    // 4. constructor
    public Position(int[][] temp){
       
        this.alpha = -1000;
        this.beta = 1000;
        this.depth = 0;
        board = temp;
    }
   
    public void setPiece(int p, int y, int x)
    {
       
    this.board[y][x]= p;
   
    }
   
    public boolean checkFreePlace(int y, int x){
       
        if(board[y][x] == 0) return true;
       
        return false;
       
    }
   
    public int calcStaticValue(){
       
        int computerValue = 0;
        int humanValue = 0;
       
        if(board[0][0] == 1) computerValue = computerValue + 3;
        if(board[0][0] == -1) humanValue = humanValue + 3;
        if(board[2][0] == 1) computerValue = computerValue + 3;
        if(board[2][0] == -1) humanValue = humanValue + 3;
        if(board[2][2] == 1) computerValue = computerValue + 3;
        if(board[2][2] == -1) humanValue = humanValue + 3;
        if(board[0][2] == 1) computerValue = computerValue + 3;
        if(board[0][2] == -1) humanValue = humanValue + 3;
        if(board[0][1] == 1) computerValue = computerValue + 2;
        if(board[0][1] == -1) humanValue = humanValue + 2;
        if(board[1][0] == 1) computerValue = computerValue + 2;
        if(board[1][0] == -1) humanValue = humanValue + 2;
        if(board[1][2] == 1) computerValue = computerValue + 2;
        if(board[1][2] == -1) humanValue = humanValue + 2;
        if(board[2][1] == 1) computerValue = computerValue + 2;
        if(board[2][1] == -1) humanValue = humanValue + 2;
        if(board[1][1] == 1) computerValue = computerValue + 4;
        if(board[1][1] == -1) humanValue = humanValue + 4;
       
        return computerValue - humanValue;
    }
   
    public int calcEndOfPosition(){
       
        // is Won
        if(board[0][0] ==1 && board[0][1] ==1 && board[0][2] == 1) return 10000;
        if(board[1][0] ==1 && board[1][1] ==1 && board[1][2] == 1) return 10000;
        if(board[2][0] ==1 && board[2][1] ==1 && board[2][2] == 1) return 10000;
        if(board[0][0] ==1 && board[1][0] ==1 && board[2][0] == 1) return 10000;
        if(board[0][1] ==1 && board[1][1] ==1 && board[2][1] == 1) return 10000;
        if(board[0][2] ==1 && board[1][2] ==1 && board[2][2] == 1) return 10000;
        if(board[0][1] ==1 && board[1][1] ==1 && board[2][1] == 1) return 10000;
        if(board[0][0] ==1 && board[1][1] ==1 && board[2][2] == 1) return 10000;
        if(board[0][1] ==1 && board[1][1] ==1 && board[2][1] == 1) return 10000;
        if(board[0][2] ==1 && board[1][1] ==1 && board[2][0] == 1) return 10000;
       
        // is Lost
        if(board[0][0] ==-1 && board[0][1] ==-1 && board[0][2] == -1) return -10000;
        if(board[1][0] ==-1 && board[1][1] ==-1 && board[1][2] == -1) return -10000;
        if(board[2][0] ==-1 && board[2][1] ==-1 && board[2][2] == -1) return -10000;
        if(board[0][0] ==-1 && board[1][0] ==-1 && board[2][0] == -1) return -10000;
        if(board[0][1] ==-1 && board[1][1] ==-1 && board[2][1] == -1) return -10000;
        if(board[0][2] ==-1 && board[1][2] ==-1 && board[2][2] == -1) return -10000;
        if(board[0][1] ==-1 && board[1][1] ==-1 && board[2][1] == -1) return -10000;
        if(board[0][0] ==-1 && board[1][1] ==-1 && board[2][2] == -1) return -10000;
        if(board[0][1] ==-1 && board[1][1] ==-1 && board[2][1] == -1) return -10000;
        if(board[0][2] ==-1 && board[1][1] ==-1 && board[2][0] == -1) return -10000;
        // is draw
        else return 0;
    }
   
    public boolean isEndOfPosition(){
       
        int temp = 0;
        for (int y = 0; y < 3; y++) for (int x = 0; x < 3; x++)
        {
            if(board[y][x] == 0) temp++;
        }
       
        if(temp == 0) return true;
        return false;
    }
   
    public boolean isMax() {
       
        return max;
    }
   
    public boolean isMin() {
       
        if(max == false) return true;
        else return false;
    }

    public void setToMax() {
        this.max = true;
    }
   
    public void setToMin() {
        this.max = false;
    }
   
    public void addDepth(){
       
        this.depth++;
    }
   
    public void print(){
       
          System.out.println("----------");
          System.out.println("|" + board[0][0] + "|" + board[0][1] + "|" + board[0][2]+ "|");
          System.out.println("|" + board[1][0] + "|" + board[1][1] + "|" + board[1][2]+ "|");
          System.out.println("|" + board[2][0] + "|" + board[2][1] + "|" + board[2][2]+ "|");
          System.out.println("----------");
       
    }
   
    public int calcMoves(){
       
        int temp = 0;
       
        for (int y = 0; y < 3; y++) for (int x = 0; x < 3; x++)
        {
            if(board[y][x] == 0) temp++;
        }
   
        return temp;
    }
   
}


Håber dette kaster lidt mere lys over tingene?
Avatar billede ksoren Nybegynder
22. oktober 2009 - 20:02 #6
public Position(int[][] temp){
  ...
  board = temp;
}

du kan heller ikke kopiere indholdet af et array over i et andet på den måde. Du ændrer blot en reference.

this.board vil efter ovenstående blot pege på det array, som temp peger på.
Avatar billede martin421 Nybegynder
26. oktober 2009 - 13:34 #7
Okay, det er et reference problem jeg har med at gøre... måske har jeg sovet i timen, men hvordan undgår jeg så dette problem? Jeg vil ike hente en reference men skabe et 'nyt' object med samme datastruktur...
Avatar billede martin421 Nybegynder
26. oktober 2009 - 15:22 #8
public Object clone()      {          try      {              return super.clone();          }      catch( CloneNotSupportedException e )      {              return null;          }      }

Dette er måske et bud på at clone et object!?
Avatar billede martin421 Nybegynder
19. august 2010 - 13:51 #9
Når man har med værdier at gøre er der 2 type, man skal være opmærksom på.

Value types: Såsom int, char og andre. Struct er en value type.
reference types: en reference til et obj. Class er en reference type.

I mit tilfælde var der tale om en reference type, derfor ændrede værdierne sig i min klasser.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester