-->

vrijdag 21 april 2017

4 op een rij (met zeer eenvoudige agent)

In een voorgaande blog heb ik al aangegeven dat een AI-agent een combinatie van algoritmen is dat er voor zorgt dat de best mogelijk beslissing wordt genomen gegeven bepaalde onzekerheid in de omgeving waarin de agent acteert.

Vervolgens wou ik in vier stappen een AI agent maken die een waardig tegenstander van een menselijke speler zou worden.

Stap 1. 4 op een rij met twee menselijke spelers.

Stap 2. 4 op een rij waarbij de gebruiker tegen een (zeer simpele) AI-agent speelt. De AI-agent weet enkel wat geldige zetten zijn (kies een kolom tussen 0 en 7 en die niet vol is). Als keuze voor de kolom gebruikt ie een randomize-functie.

Stap 3. Deze agent kent de geldige zetten, maar kijkt ook naar de stand van het bord om zijn keuze te maken.

Stap 4. De agent kijkt niet alleen naar geldige stappen en maakt een inschatting wat de beste volgende stap. Deze agent houdt bij zijn inschatting ook rekening met 2 of meer toekomstige stappen van hem en zijn tegenstander.



In deze versie van 4 op een rij speel je als gebruiker tegen een zeer eenvoudige agent. Eigenlijk kiest de agent alleen maar een willekeurige kolom voor zijn zet. Hij is nog net wel zo intelligent dat ie weet dat alleen geldige zetten zijn toegestaan. M.a.w. zetten tussen 0 en 7 (aantal kolommen in het bord) en dat de kolom niet vol mag zijn.

Bord.java beschrijft het bord en de belangrijkste spelregels.


  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
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package javaapplication10;
import java.util.Scanner;
/**
 *
 * @author gerard
 */


class Board{
    byte[][] board = new byte[6][7];
    
    public Board(){
        board = new byte[][]{
            {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,},    
        };
        
     
        
    } 
    
    
    
    public void undoMove(int column){
        for(int i=0;i<=5;++i){
            if(board[i][column] != 0) {
                board[i][column] = 0;
                break;
            }
        }        
    }

}
public class Bord {

    private Board b;
    private Scanner scan;
    private int nextMoveLocation=-1;
    private int maxDepth = 9;
    
          
    private static final char[] symbolen = new char[] { 'X', 'O','.' };
    private final char[][] velden;
    private int breedte;
    private int hoogte;
    
    private int gekozenKolom = -1; // laatst gekozen kolom
    private int grensRij = -1;// hoogste rij (grensrij)bij deze kolom
    
    

    public Bord(int pbreedte, int phoogte) {
        this.velden = new char[phoogte][pbreedte];
        
        for (int rij = 0; rij < this.velden.length; rij++)
          {
        for (int kolom = 0; kolom < this.velden[rij].length; kolom++)
        {
            this.velden[rij][kolom] = symbolen[2];
        }
    } 
    breedte = this.velden[0].length;
    hoogte = this.velden.length;
        
        
    }       
    public String toString() {
        String BordBeeld = "";
        for (int rij = 0; rij < this.hoogte; rij++)
           {
           for (int kolom = 0; kolom < this.breedte; kolom++)
           {
            BordBeeld = BordBeeld + this.velden[rij][kolom];
           }
           BordBeeld = BordBeeld + "\n";
           }
       return BordBeeld; 
    }
    
   
     public boolean isLegaleZet(int pkolom){
            boolean result = true;
                        
            if ( !(0 <= pkolom && pkolom < breedte)) {
                System.out.println("Kolom moeten tussen 0 and " +
                                   (this.hoogte - 1) + " zijn");
                result = false;
            }
           
         return result;
    }
     
     public boolean KolomIsVol(int pkolom) {
          boolean result = true;
          int hoogte = 0;// this.velden.length - 1;
          
          if (this.velden[hoogte][pkolom] != symbolen[2]) {
             System.out.println("Deze Kolom is vol.");
             result = false; 
          }
       
           return result;
         
     }
    
     public boolean BordIsVol() {
         boolean result = true;
         int aantalVolleKol = 0;
         
          for (int kol = 0;kol <= this.breedte -1; kol++) {
              if (KolomIsVol(kol)) { 
                  aantalVolleKol++;
              }
          }   
         if (aantalVolleKol < this.breedte) {
             result = false;
         }
       return result;  
     }
         
           
     
    //Placing a Move on the board
    public void DoeZet(int column, int player){ 
                   
            for (int h = this.hoogte -1; h>=0; h--) {
                  if (this.velden[h][column] == '.') {// er is nog ruimte
                   
                    
                    this.gekozenKolom = column;
                    this.grensRij = h;
                    this.velden[this.grensRij][this.gekozenKolom] = symbolen[player]; 
                    break;
                    }    
        
            }
      }
    
    public boolean WinnendeZet() {
     
        char sym = this.velden[this.grensRij][this.gekozenKolom];
        String reeks = String.format("%c%c%c%c", sym, sym, sym, sym);
        return bevat(this.horizontaal(), reeks) ||
               bevat(this.vertikaal(), reeks) ||
               bevat(this.slashDiagonaal(), reeks) ||
               bevat(this.backslashDiagonaal(), reeks);
    }

    /**
     * zit er een winnende reeks in de horizontale rij
     */
    private String horizontaal() {
        return new String(this.velden[this.grensRij]);
    }

    /**
     * zit er een winende reeks en ide verticale rij
     */
    private String vertikaal() {
        StringBuilder sb = new StringBuilder(this.hoogte);
        for (int h = 0; h < this.hoogte; h++) {
            sb.append(this.velden[h][this.gekozenKolom]);
        }
        return sb.toString();
    }

    /**
     *  
     * 
     */
    private String slashDiagonaal() {
        StringBuilder sb = new StringBuilder(this.hoogte);
        for (int h = 0; h < this.hoogte; h++) {
            int w = this.gekozenKolom + this.grensRij - h;
            if (0 <= w && w < this.breedte) {
                sb.append(this.velden[h][w]);
            }
        }
        return sb.toString();
    }

    /**
     *
     */
    private String backslashDiagonaal() {
        StringBuilder sb = new StringBuilder(this.hoogte);
        for (int h = 0; h < this.hoogte; h++) {
            int w = this.gekozenKolom - this.grensRij + h;
            if (0 <= w && w < this.breedte) {
                sb.append(this.velden[h][w]);
            }
        }
        return sb.toString();
    }

    private boolean bevat(String hooiberg, String naald) {
        return hooiberg.contains(naald);
    }
    
              
    }    
    

spel.java handelt de interactie tussen speler (gebruiker) en agent af.

 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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package javaapplication10;

import java.util.Random;
import java.util.Scanner;

/**
 *
 * @author gerard
 */
public class Spel {
    Bord b = new Bord(7,8);
    int zet;
     
    public int GebruikerKiestZet(){
        System.out.println("Your move (0-6): ");
         Scanner scan = new Scanner(System.in);
        int g_zet = scan.nextInt();
        while (!b.isLegaleZet(g_zet) || !b.KolomIsVol(g_zet)){
             g_zet = scan.nextInt();
        }
        return g_zet;
    }
    
    public int AgentKiestZet() {
        
        int max = 7; // dit moet nog geparametiseerd worden
        int min =0;
        Random random = new Random();
        int l_zet = random.nextInt(max - min + 1) + min;
        
         while (!b.isLegaleZet(l_zet) || !b.KolomIsVol(l_zet)){
             l_zet = random.nextInt(max - min + 1) + min;
        }
        
       return l_zet; 
    }
    
    public int speel() {
          System.out.println(b);
          
          // remise moet nog worden ingebouwd. 
        while(true){ 
            zet = GebruikerKiestZet();
            b.DoeZet(zet, 0);
            System.out.println(b);
            if (b.WinnendeZet()) {System.out.println("You Win!");break;}
                
                      
            zet = AgentKiestZet();
            b.DoeZet(zet, 1);
            System.out.println(b);
            if (b.WinnendeZet()) {System.out.println("Agent wins!");break;}
            
    
        }
        return 1;
        
    }     
        
     
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
               
        Spel spel = new Spel();
        spel.speel();
        
        // ingebouwd moe tworden wie begint agent of gebruiker
       // Scanner scan = new Scanner(System.in);
       // System.out.println("Would you like to play first? (yes/no) ");
        //String answer = scan.next().trim();
        
      // if(answer.equalsIgnoreCase("yes")) GebruikerKiestZet();
      //  b.displayBoard();
      //  b.placeMove(3, 1);
       // b.displayBoard(); 
        
}
}

Geen opmerkingen:

Een reactie posten