Les détails sur l'évaluation du jeu sont commentés dans le code
► Afficher le texte
Code : Tout sélectionner
#include <GUIConstantsEx.au3>
Global $jeu[3][3], $case[3][3][1], $cnt
;====================================================
$gui = GUICreate("L'ordi joue en 2ème", 360, 240, -1, 200)
GUISetBkColor(0x000000)
For $i = 0 To 2
For $j = 0 To 2
$case[$i][$j][0] = GUICtrlCreateButton("", $i*68+5, $j*68+5, 64, 64)
GUICtrlSetBkColor(-1, 0xffffff)
GUICtrlSetFont(-1, 32)
Next
Next
$list = GUICtrlCreateEdit("", 230, 5, 120, 200)
$r1 = GUICtrlCreateRadio("facile", 40, 210, 60, 20)
GUICtrlSetColor(-1, 0xffffff)
$r2 = GUICtrlCreateRadio("difficile", 110, 210, 60, 20)
GUICtrlSetColor(-1, 0xffffff)
GUICtrlCreateLabel("évaluations :", 230, 214, 60, 20)
GUICtrlSetColor(-1, 0xffffff)
GUICtrlSetBkColor(-1, 0x000000)
$label = GUICtrlCreateLabel("", 300, 212, 40, 17)
GUICtrlSetBkColor(-1, 0xffffff)
GUISetState()
While 1
If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
If GUICtrlRead($r1) = 1 Then
$profondeur = 3
Exitloop
EndIf
If GUICtrlRead($r2) = 1 Then
$profondeur = 5
Exitloop
EndIf
Wend
While 1
$msg = GUIGetMsg()
If $msg = $GUI_EVENT_CLOSE Then Exit
For $i = 0 To 2
For $j = 0 To 2
;joueur
If $msg = $case[$i][$j][0] Then
GUICtrlSetData($case[$i][$j][0], "X")
GUICtrlSetState($case[$i][$j][0], $GUI_DISABLE)
$jeu[$i][$j] = 2
_check()
;ordi
$c = _jeu_IA($jeu, $profondeur)
GUICtrlSetData($label, $cnt)
$jeu[$c[0]][$c[1]] = 1
GUICtrlSetData($case[$c[0]][$c[1]][0], "O")
GUICtrlSetState($case[$c[0]][$c[1]][0], $GUI_DISABLE)
_check()
EndIf
Next
Next
Wend
;=============================================================
Func _jeu_IA($jeu, $profondeur)
Local $max = -10000, $tmp, $maxi, $maxj, $coords[2], $t
If $profondeur <> 0 or _gagnant($jeu) = 0 Then
$cnt = 0
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] = 0 Then
$jeu[$i][$j] = 1
$tmp = _Min($jeu, $profondeur-1)
If $tmp > $max Then
$max = $tmp
$maxi = $i
$maxj = $j
EndIf
$jeu[$i][$j] = 0
;debug
$t &= "(" & $i & "," & $j & ") > " & $tmp &" , "& $max &@crlf
GUICtrlSetData($list, $t)
EndIf
Next
Next
EndIf
;debug
$t &= @crlf& "choix (" & $maxi &","& $maxj &")"&@crlf
GUICtrlSetData($list, $t)
$coords[0] = $maxi
$coords[1] = $maxj
Return $coords
EndFunc
Func _Min($jeu, $profondeur)
If $profondeur = 0 or _gagnant($jeu) <> 0 Then Return _eval($jeu)
Local $min = 10000, $tmp
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] = 0 Then
$jeu[$i][$j] = 2
$tmp = _Max($jeu, $profondeur-1)
If $tmp < $min Then $min = $tmp
$jeu[$i][$j] = 0
EndIf
Next
Next
Return $min
EndFunc
Func _Max($jeu, $profondeur)
If $profondeur = 0 or _gagnant($jeu) <> 0 Then Return _eval($jeu)
Local $max = -10000, $tmp
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] = 0 Then
$jeu[$i][$j] = 1
$tmp = _Min($jeu, $profondeur-1)
If $tmp > $max Then $max = $tmp
$jeu[$i][$j] = 0
EndIf
Next
Next
Return $max
EndFunc
Func _eval($jeu)
$cnt += 1
Local $nb_de_pions = 0, $vainqueur = _gagnant($jeu)
;on compte le nombre de pions présents
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] <> 0 Then $nb_de_pions += 1
Next
Next
;s'il y a un gagnant :
If $vainqueur <> 0 Then
If $vainqueur = 1 Then
Return 1000 - $nb_de_pions
ElseIf $vainqueur = 2 Then
Return -1000 + $nb_de_pions
Else
Return 0
EndIf
EndIf
;sinon, on compte le nombre de séries de 2 pions alignés de chacun des joueurs
Local $series = _nb_series($jeu, 2)
Return $series[0] - $series[1]
EndFunc
Func _gagnant($jeu)
Local $series = _nb_series($jeu, 3)
If $series[0] > 0 Then
Return 1
ElseIf $series[1] > 0 Then
Return 2
Else ; si personne n'a gagné
;si le jeu n'est pas fini
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] = 0 Then Return 0
Next
Next
;si le jeu est fini
Return 3
EndIf
EndFunc
Func _check()
Local $win = _gagnant($jeu)
Switch $win
Case 1
Exit Msgbox(0,"" , "L'ordi a gagné")
Case 2
Exit Msgbox(0,"" , "Tu as gagné")
Case 3
Exit Msgbox(0,"" , "Match nul")
EndSwitch
EndFunc
Func _nb_series($jeu, $n)
;compte le nombre de séries de $n pions alignés de chacun des joueurs
Local $compteur1 = 0, $compteur2 = 0, $s_j1 = 0, $s_j2 = 0, $series[2]
;diagonale descendante
For $i = 0 to 2
If $jeu[$i][$i] = 1 Then
$compteur1 += 1
$compteur2 = 0
if $compteur1 = $n Then $s_j1 += 1
ElseIf $jeu[$i][$i] = 2 Then
$compteur2 += 1
$compteur1 = 0
if $compteur2 = $n Then $s_j2 += 1
EndIf
Next
;diagonale montante
$compteur1 = 0
$compteur2 = 0
For $i = 0 to 2
If $jeu[$i][2-$i] = 1 Then
$compteur1 += 1
$compteur2 = 0
if $compteur1 = $n Then $s_j1 += 1
ElseIf $jeu[$i][2-$i] = 2 Then
$compteur2 += 1
$compteur1 = 0
if $compteur2 = $n Then $s_j2 += 1
EndIf
Next
;lignes
For $i = 0 to 2
$compteur1 = 0
$compteur2 = 0
;horizontalement
For $j = 0 to 2
If $jeu[$i][$j] = 1 Then
$compteur1 += 1
$compteur2 = 0
if $compteur1 = $n Then $s_j1 += 1
ElseIf $jeu[$i][$j] = 2 Then
$compteur2 += 1
$compteur1 = 0
if $compteur2 = $n Then $s_j2 += 1
EndIf
Next
$compteur1 = 0
$compteur2 = 0
;verticalement
For $j = 0 to 2
If $jeu[$j][$i] = 1 Then
$compteur1 += 1
$compteur2 = 0
if $compteur1 = $n Then $s_j1 += 1
ElseIf $jeu[$j][$i] = 2 Then
$compteur2 += 1
$compteur1 = 0
if $compteur2 = $n Then $s_j2 += 1
EndIf
Next
Next
$series[0] = $s_j1
$series[1] = $s_j2
Return $series
EndFunc
Cette variante de l'algorithme MinMax permet de limiter le nombre d'évaluations et donc d'accélérer le calcul
► Afficher le texte
Code : Tout sélectionner
#include <GUIConstantsEx.au3>
Global $jeu[3][3], $case[3][3][1], $cnt
;====================================================
$gui = GUICreate("L'ordi joue en 2ème", 360, 240, -1, 200)
GUISetBkColor(0x000000)
For $i = 0 To 2
For $j = 0 To 2
$case[$i][$j][0] = GUICtrlCreateButton("", $i*68+5, $j*68+5, 64, 64)
GUICtrlSetBkColor(-1, 0xffffff)
GUICtrlSetFont(-1, 32)
Next
Next
$list = GUICtrlCreateEdit("", 230, 5, 120, 200)
$r1 = GUICtrlCreateRadio("facile", 40, 210, 60, 20)
GUICtrlSetColor(-1, 0xffffff)
$r2 = GUICtrlCreateRadio("difficile", 110, 210, 60, 20)
GUICtrlSetColor(-1, 0xffffff)
GUICtrlCreateLabel("évaluations :", 230, 214, 60, 20)
GUICtrlSetColor(-1, 0xffffff)
GUICtrlSetBkColor(-1, 0x000000)
$label = GUICtrlCreateLabel("", 300, 212, 40, 17)
GUICtrlSetBkColor(-1, 0xffffff)
GUISetState()
While 1
If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
If GUICtrlRead($r1) = 1 Then
$profondeur = 3
Exitloop
EndIf
If GUICtrlRead($r2) = 1 Then
$profondeur = 5
Exitloop
EndIf
Wend
While 1
$msg = GUIGetMsg()
If $msg = $GUI_EVENT_CLOSE Then Exit
For $i = 0 To 2
For $j = 0 To 2
;joueur
If $msg = $case[$i][$j][0] Then
GUICtrlSetData($case[$i][$j][0], "X")
GUICtrlSetState($case[$i][$j][0], $GUI_DISABLE)
$jeu[$i][$j] = 2
_check()
;ordi
$c = _jeu_IA($jeu, $profondeur)
GUICtrlSetData($label, $cnt)
$jeu[$c[0]][$c[1]] = 1
GUICtrlSetData($case[$c[0]][$c[1]][0], "O")
GUICtrlSetState($case[$c[0]][$c[1]][0], $GUI_DISABLE)
_check()
EndIf
Next
Next
Wend
;=============================================================
Func _jeu_IA($jeu, $profondeur)
Local $alpha = -10000, $beta = 10000, $tmp, $maxi, $maxj, $coords[2], $t
If $profondeur <> 0 or _gagnant($jeu) = 0 Then
$cnt = 0
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] = 0 Then
$jeu[$i][$j] = 1
$tmp = _Min($jeu, $profondeur-1, $alpha, $beta)
If $alpha < $tmp Then
$alpha = $tmp
$maxi = $i
$maxj = $j
EndIf
$jeu[$i][$j] = 0
;debug
$t &= "(" & $i & "," & $j & ") > " & $beta &" , "& $alpha &@crlf
GUICtrlSetData($list, $t)
EndIf
Next
Next
EndIf
;debug
$t &= @crlf& "choix (" & $maxi &","& $maxj &")"&@crlf
GUICtrlSetData($list, $t)
$coords[0] = $maxi
$coords[1] = $maxj
Return $coords
EndFunc
Func _Min($jeu, $profondeur, $alpha, $beta)
If $profondeur = 0 or _gagnant($jeu) <> 0 Then Return _eval($jeu)
Local $tmp
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] = 0 Then
$jeu[$i][$j] = 2
$tmp = _Max($jeu, $profondeur-1, $alpha, $beta)
$jeu[$i][$j] = 0
If $beta > $tmp Then $beta = $tmp
If $beta <= $alpha Then Return $beta
EndIf
Next
Next
Return $beta
EndFunc
Func _Max($jeu, $profondeur, $alpha, $beta)
If $profondeur = 0 or _gagnant($jeu) <> 0 Then Return _eval($jeu)
Local $tmp
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] = 0 Then
$jeu[$i][$j] = 1
$tmp = _Min($jeu, $profondeur-1, $alpha, $beta)
$jeu[$i][$j] = 0
If $alpha < $tmp Then $alpha = $tmp
If $beta <= $alpha Then Return $alpha
EndIf
Next
Next
Return $alpha
EndFunc
Func _eval($jeu)
$cnt += 1
Local $nb_de_pions = 0, $vainqueur = _gagnant($jeu)
;on compte le nombre de pions présents
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] <> 0 Then $nb_de_pions += 1
Next
Next
;s'il y a un gagnant :
If $vainqueur <> 0 Then
If $vainqueur = 1 Then
Return 1000 - $nb_de_pions
ElseIf $vainqueur = 2 Then
Return -1000 + $nb_de_pions
Else
Return 0
EndIf
EndIf
;sinon, on compte le nombre de séries de 2 pions alignés de chacun des joueurs
Local $series = _nb_series($jeu, 2)
Return $series[0] - $series[1]
EndFunc
Func _gagnant($jeu)
Local $series = _nb_series($jeu, 3)
If $series[0] > 0 Then
Return 1
ElseIf $series[1] > 0 Then
Return 2
Else ; si personne n'a gagné
;si le jeu n'est pas fini
For $i = 0 to 2
For $j = 0 to 2
If $jeu[$i][$j] = 0 Then Return 0
Next
Next
;si le jeu est fini
Return 3
EndIf
EndFunc
Func _check()
Local $win = _gagnant($jeu)
Switch $win
Case 1
Exit Msgbox(0,"" , "L'ordi a gagné")
Case 2
Exit Msgbox(0,"" , "Tu as gagné")
Case 3
Exit Msgbox(0,"" , "Match nul")
EndSwitch
EndFunc
Func _nb_series($jeu, $n)
;compte le nombre de séries de $n pions alignés de chacun des joueurs
Local $compteur1 = 0, $compteur2 = 0, $s_j1 = 0, $s_j2 = 0, $series[2]
;diagonale descendante
For $i = 0 to 2
If $jeu[$i][$i] = 1 Then
$compteur1 += 1
$compteur2 = 0
if $compteur1 = $n Then $s_j1 += 1
ElseIf $jeu[$i][$i] = 2 Then
$compteur2 += 1
$compteur1 = 0
if $compteur2 = $n Then $s_j2 += 1
EndIf
Next
;diagonale montante
$compteur1 = 0
$compteur2 = 0
For $i = 0 to 2
If $jeu[$i][2-$i] = 1 Then
$compteur1 += 1
$compteur2 = 0
if $compteur1 = $n Then $s_j1 += 1
ElseIf $jeu[$i][2-$i] = 2 Then
$compteur2 += 1
$compteur1 = 0
if $compteur2 = $n Then $s_j2 += 1
EndIf
Next
;lignes
For $i = 0 to 2
$compteur1 = 0
$compteur2 = 0
;horizontalement
For $j = 0 to 2
If $jeu[$i][$j] = 1 Then
$compteur1 += 1
$compteur2 = 0
if $compteur1 = $n Then $s_j1 += 1
ElseIf $jeu[$i][$j] = 2 Then
$compteur2 += 1
$compteur1 = 0
if $compteur2 = $n Then $s_j2 += 1
EndIf
Next
$compteur1 = 0
$compteur2 = 0
;verticalement
For $j = 0 to 2
If $jeu[$j][$i] = 1 Then
$compteur1 += 1
$compteur2 = 0
if $compteur1 = $n Then $s_j1 += 1
ElseIf $jeu[$j][$i] = 2 Then
$compteur2 += 1
$compteur1 = 0
if $compteur2 = $n Then $s_j2 += 1
EndIf
Next
Next
$series[0] = $s_j1
$series[1] = $s_j2
Return $series
EndFunc