Jump to content

Tik-Tak-Toe


Recommended Posts

VERY simple.. lol i took the lazy way out.. see Unbeatable tick tack toe for a better one...

X=AI

O=USER

USER goes first

this has SOMEwhat of a strategy in it... and is MUCH harder to win has custom GUI's and messages... blah blah check it out.. post some comments on how i could do it better please... and i DON'T want to make it UNBEATABLE.. cause that wouldn't be fun.. maybe nearly unbeatable.. maybe later..

EDIT

its more difficult now but still has a few bugs X's replace O's spot in center some times and declares a AI WIN when it should have been a TIE

EDIT

fairly random scenarios based on a valued system.

3|2|3

2|4|2

3|2|3

if there isn't a spot to block\win it goes to find the most valuable, if there are multiple it randomizes it. not exactly predictable. or is it? :S

Opt ('GuiOnEVentMode',1)
Dim $GRID[3][3]
Dim $row[3], $column[3],$diagonal[2]
$nTieCount = 0
$nTurnCount = 0
$nLossCount = 0
$nWinCount = 0
$nAI = -1
$sAI = 'o'
$nPLAYER = 1
$sPLAYER = 'x'
$turn = $nPLAYER
$w_h = 75
$guiw = ($w_h*3)+40
$guih = ($w_h*5)
$font_s = ($w_h*2)/4
$window_hwnd = GUICreate ('tic tac toe',$guiw,$guih)
GUISetOnEvent (-3,'End')
$lWinCount = GUICtrlCreateLabel ('WINS:',10,40+($w_h*3),($guiw-20)/3,$w_h/2,0x0200)
$lLossCount = GUICtrlCreateLabel ('LOSSES:',10+($guiw-20)/3,40+($w_h*3),($guiw-20)/3,$w_h/2,0x0200)
$lTieCount = GUICtrlCreateLabel ('Ties:',$guiw-($guiw-20)/3,40+($w_h*3),($guiw-20)/3,$w_h/2,0x0200)
For $x = 0 To 2
    For $y = 0 To 2
        $GRID[$x][$y] = GUICtrlCreateButton ('',10+(10*$x)+($x*$w_h),10+(10*$y)+($y*$w_h),$w_h,$w_h)
            GUICtrlSetOnEvent ($GRID[$x][$y],'Clicked')
    Next
Next
Dim $GRIDval2[4]
    $GRIDval2[0] = $GRID[0][1]
    $GRIDval2[1] = $GRID[2][0]
    $GRIDval2[2] = $GRID[2][2]
    $GRIDval2[3] = $GRID[2][1]
Dim $GRIDval3[4]
    $GRIDval3[0] = $GRID[0][0]
    $GRIDval3[1] = $GRID[0][2]
    $GRIDval3[2] = $GRID[2][0]
    $GRIDval3[3] = $GRID[2][2]
$diagonal[0] = $GRID[0][0] & '|' & $GRID[1][1] & '|' & $GRID[2][2]
$diagonal[1] = $GRID[2][0] & '|' & $GRID[1][1] & '|' & $GRID[0][2]
For $n = 0 To 2
    $row[$n] = $GRID[$n][0] & '|' & $GRID[$n][1] & '|' & $GRID[$n][2]
    $column[$n] = $GRID[0][$n] & '|' & $GRID[1][$n] & '|' & $GRID[2][$n]
Next
GUICtrlCreateButton ('Reset',10,(3*$w_h)+$w_h+20,$guiw-20,$w_h/2)
GUICtrlSetOnEvent (-1,'Start')
GUISetState ()
Start ()
While 1
    CheckStats ()
    CheckWin ()
    Sleep (100)
WEnd
Func Start ()
    $turn = $nPLAYER
    $nTurnCount = 0
    WinSetState ($window_hwnd,'',@SW_ENABLE)
    For $n = 0 To 2
        For $u = 0 To 2
            GUICtrlSetData ($GRID[$n][$u],'')
            GUICtrlSetState ($GRID[$n][$u],64)
        Next
    Next
EndFunc
Func CheckStats ()
    If GUICtrlRead ($lWinCount) <> 'WINS:'&$nWinCount Then GUICtrlSetData ($lWinCount,'WINS:'&$nWinCount)
    If GUICtrlRead ($lLossCount) <> 'LOSSES:'&$nLossCount Then GUICtrlSetData ($lLossCount,'LOSSES:'&$nLossCount)
    If GUICtrlRead ($lTieCount) <> 'TIES:'&$nTieCount Then GUICtrlSetData ($lTieCount,'TIES:'&$nTieCount)
EndFunc
Func CheckWin ()
    Local $eval, $n
    $eval = StringEval($diagonal[0])
    If $eval = -3 Or $eval = 3 Then Win ($eval)
    $eval = StringEval($diagonal[1])
    If $eval = -3 Or $eval = 3 Then Win ($eval)
    For $n = 0 To 2
        $eval = StringEval($row[$n])
        If $eval = -3 Or $eval = 3 Then Win ($eval)
        $eval = StringEval($column[$n])
        If $eval = -3 Or $eval = 3 Then Win ($eval)
    Next
EndFunc
Func Win ($value)
    If $value/$nPLAYER = 3 Then
        MsgBox (0,'WIN','Player Has Won!',25,$window_hwnd)
        $nWinCount += 1
    EndIf
    If $value/$nAI = 3 Then
        MsgBox (0,'WIN','Computer Has Won!',25,$window_hwnd)
        $nLossCount += 1
    EndIf
    Start ()
EndFunc
Func Check ()
    Local $n
    If $nTurnCount >= 8 Then
        MsgBox (0,'TIE','Tie Game',25,$window_hwnd)
        $nTieCount += 1
        Start ()
    Else
        CheckMove(StringEval($diagonal[0]),$diagonal[0])
        CheckMove(StringEval($diagonal[1]),$diagonal[1])
        For $n = 0 To 2
            CheckMove(StringEval($row[$n]),$row[$n])
            CheckMove(StringEval($column[$n]),$column[$n])
        Next
        If $turn = $nAI Then
            If GUICtrlRead ($GRID[1][1]) == '' Then
                Move($GRID[1][1])
            Else
                If MiniMaxValuing ($GRIDval3) = -1 Then
                    If MiniMaxValuing ($GRIDval2) = -1 Then
                        Do
                            $r = Random (0,2,1)
                            $c = Random (0,2,1)
                        Until GUICtrlRead ($GRID[$r][$c]) == ''
                        Move ($GRID[$r][$c])
                    EndIf
                EndIf
            EndIf
        EndIf
    EndIf
EndFunc
Func Move ($ID)
    GUICtrlSetData ($ID,$sAI)
    GUICtrlSetState ($ID,128)
    $turn = $nPLAYER
    $nTurnCount += 1
    WinSetState ($window_hwnd,'',@SW_ENABLE)
EndFunc
Func Clicked ()
    $turn = $nAI
    $nTurnCount += 1
    GUICtrlSetData (@GUI_CtrlId,$sPLAYER)
    GUICtrlSetState (@GUI_CtrlId,128)
    WinSetState ($window_hwnd,'',@SW_DISABLE)
    Check ()
EndFunc
Func CheckMove ($value,$IDarray)
    If $value = 3 Or $value = -3 Then
        Win ($value)
        If $turn = $nAI Then
            If GUICtrlRead ($GRID[1][1]) == '' Then
                Move ($GRID[1][1])
                Return
            EndIf
            If $value = 2 Or $value = -2 Then
                Local $guiIDarray = StringSplit ($IDarray,'|',2)
                Local $n = 0
                For $n = 0 To UBound ($guiIDarray)-1
                    $guiIDarray[$n] = Number ($guiIDarray[$n])
                    If GUICtrlRead ($guiIDarray[$n]) == '' Then
                        Move ($guiIDarray[$n])
                        Return
                    EndIf
                Next
            EndIf
            Return
        EndIf
    EndIf
EndFunc
Func StringEval ($IDarray)
    Dim $guiIDarray = StringSplit ($IDarray,'|',2)
    Dim $valuearray[UBound ($guiIDarray)]
    Local $value = 0, $n = 0
    For $n = 0 To UBound ($guiIDarray)-1
        $guiIDarray[$n] = $guiIDarray[$n]
        If GUICtrlRead ($guiIDarray[$n]) == '' Then $valuearray[$n] = 0
        If GUICtrlRead ($guiIDarray[$n]) == $sPLAYER Then $valuearray[$n] = $nPLAYER
        If GUICtrlRead ($guiIDarray[$n]) == $sAI Then $valuearray[$n] = $nAI
        $value += $valuearray[$n]
    Next
    Return $value
EndFunc
Func MiniMaxValuing ($array)
    Local $n, $Count = ''
    For $n = 0 To UBound ($array,1)-1
        If GUICtrlRead ($array[$n]) == '' Then $Count &= $n & '|'
    Next
    If $Count == '' Then Return -1
    $Count = StringSplit (StringTrimRight ($Count,1),'|',2)
    Move ($array[$Count[Random (0,UBound ($Count,1)-1,1)]])
    Return 1
EndFunc
Func End ()
    Exit
EndFunc
Edited by CodyBarrett
Link to comment
Share on other sites

  • Replies 43
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

.. post some comments on how i could do it better please...

of course ^_^

1) make the x's and o's bigger, so they fill the button.

2) don't show the 2nd gui when ai is working. it looks so much better like this:

Func _PC_Move ()
    Do
        $i = Random (0, 9)
    Until GUICtrlRead ($Array[$i]) <> 'X' And GUICtrlRead ($Array[$i]) <> 'O'
    GUICtrlSetData ($Array[$i], 'X')
    GUICtrlSetState ($Array[$i], $GUI_DISABLE)
    $Turn += 1
    _MouseTrap ()
EndFunc

3) For other messages, try splashtexton...

Func _Tie_ ()
    SplashTextOn ("Result!!", "You tied the game!! <>_<>", 300, 50, -1, -1)
    Sleep (1000)
    _Random_ ()
    Sleep (1000)
    SplashOff ()
EndFunc

generally, just make it better!! I had a bit of fun though.

MDiesel

Link to comment
Share on other sites

well thanks.... i put the "Please wait..." to make it SEEM like the copmuter is making its decision haha ^_^ ill try a few more things out

Link to comment
Share on other sites

lol i made it in like.. 10 mins at school haha 7 of those minutes were googling how tic tac toe works... and i might still add a few strategies to the AI

if you didn't notice it has NO strategy.. just randomly pics out a black spot lmao

Link to comment
Share on other sites

well... sorry haha but in the new version up at the top... i havent won once.. and your still O but you get to go first

EDIT

just tested 10 times.. all 10 i started in the center.. it was a 40% WIN.. 30% TIE and 20% LOSE haha and well.. 10% glitch (would have been a win but it said TIE and restarted)

Edited by CodyBarrett
Link to comment
Share on other sites

lol sometimes it does that.. xD.. but then again.. i wanna keep the player interested and not frustrated... not like

"OMFG!! YOU DOU***BAG!! LEMME WIN ONCE!!! F***!!!"

but more like

"^_^ sweet i won!, lets play again!"

hahaha... but yeah anyone know how to fix the few bugs in there?

bugs i found:

#1 soemtimes if you go middle.. it replaces your O with an X and freezes... SOLUTION hit TAB then ENTER to restart

#2 sometimes when the AI is about to lose it calls a TIE...

#3 like the post above this.. sometimes it isn't very smart...SOLUTION make it smarter LMAO but nah...this isn't a real problem

Link to comment
Share on other sites

thats my problem #1... just hit TAB ENTER and it will restart it.. because it freezes when it happens... im not sure why this is happening

EDIT

fixed it alittle... UPDATED AT TOP lol

FIXED:

*reduced the glitches now it only does it a few times..

*smarter AI

*harder to win

*i find it more fun ^_^

Edited by CodyBarrett
Link to comment
Share on other sites

Very nice interface.

You will need to work on the code because the game is still bugged. Here is what I've noticed so far:

- sometimes the script replaces the upper corner with its own entry overwriting my own entry (work on _Find_Blank_Spot )

- sometimes the script decides it's a tie after only 2 moves

- the script freeze quite often during the game and it needs to be shut down

Other than that: keep up the good work ^_^

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Link to comment
Share on other sites

thanks enaiman..

#1 ill look into..

i realized #2 when i went Middle.. bottom left... and it said tie...

#3 haven't had this happen yet in the new one but if it does hit [TAB] [Enter] to reset game...

EDIT

enaiman yours is VIRTUALY unbeatable(i haven't beaten it yet).. but i want mine to have some mercy on the user haha... ^_^

Edited by CodyBarrett
Link to comment
Share on other sites

I dug out my implementation of a zero-sum game where I implemented tic-tac-toe. I've posted here for reference should anyone find that they wanted to go down the route of using a minimax algorithm for a turn-based game. Apologies to CodyBarrett in advance to a little bit of thread hijacking. Sorry to say that mine doesn't let you win ^_^

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <Array.au3>
#include <Misc.au3>

Global $aTree[10], $iSTM = Random(1, 2, 1)
$aTree[0] = "000000000"
Global $hBoard = GUICreate("Tic-Tac-Toe", 234, 234)
GUISetBkColor(0x000000)
Global $cBoard = GUICtrlCreateGraphic(8, 8, 218, 218)
GUISetState(@SW_SHOW)

_DrawBoard($aTree[0])

; Make the first move if necessary
If $iSTM = 2 Then
    _FindBestMove(0, $iSTM)
    $aTree[0] = $aTree[1]
    $iSTM = 3 - $iSTM
EndIf

Local $iMsg, $aCI, $x, $y, $iMove
Do
    $iMsg = GUIGetMsg()
    If $iMsg = $cBoard Then
        $aCI = GUIGetCursorInfo($hBoard)
        $aCI[0] -= 8
        $aCI[1] -= 8
        $x = Int($aCI[0] / 73)
        $y = Int($aCI[1] / 73)
        $iMove = $x + ($y * 3) + 1
        If StringMid($aTree[0], $iMove, 1) = "0" Then
            _MakeMove(0, $iMove, $iSTM)
            _DrawBoard(1)
            $aTree[0] = $aTree[1]
            $iSTM = 3 - $iSTM
            _FindBestMove(0, $iSTM)
            $aTree[0] = $aTree[1]
            $iSTM = 3 - $iSTM
        EndIf
    EndIf
    Sleep(10)
Until $iMsg = $GUI_EVENT_CLOSE

Exit

Func _RandomBoard()
    Local $i
    $aTree[1] = ""
    For $i = 1 To 9
        $aTree[1] &= String(Random(0, 2, 1))
    Next
    _DrawBoard(1)
EndFunc

Func _DrawBoard($iDepth)
    Local $i, $x, $y
    GUICtrlDelete($cBoard)
    $cBoard = GUICtrlCreateGraphic(8, 8, 218, 218)
    GUICtrlSetGraphic($cBoard, $GUI_GR_PENSIZE, 3)
    GUICtrlSetGraphic($cBoard, $GUI_GR_COLOR, 0xffffff, 0x000000)
    GUICtrlSetGraphic($cBoard, $GUI_GR_MOVE, 72, 0)
    GUICtrlSetGraphic($cBoard, $GUI_GR_LINE, 72, 217)
    GUICtrlSetGraphic($cBoard, $GUI_GR_MOVE, 145, 0)
    GUICtrlSetGraphic($cBoard, $GUI_GR_LINE, 145, 217)
    GUICtrlSetGraphic($cBoard, $GUI_GR_MOVE, 0, 72)
    GUICtrlSetGraphic($cBoard, $GUI_GR_LINE, 217, 72)
    GUICtrlSetGraphic($cBoard, $GUI_GR_MOVE, 0, 145)
    GUICtrlSetGraphic($cBoard, $GUI_GR_LINE, 217, 145)
    For $i = 1 To 9
        $x = Mod(($i - 1), 3) * 73 + 4
        $y = Int(($i - 1) / 3) * 73 + 4
        Switch StringMid($aTree[$iDepth], $i, 1)
            Case "1"
                GUICtrlSetGraphic($cBoard, $GUI_GR_ELLIPSE, $x, $y, 64, 64)
            Case "2"
                GUICtrlSetGraphic($cBoard, $GUI_GR_MOVE, $x, $y)
                GUICtrlSetGraphic($cBoard, $GUI_GR_LINE, $x + 63, $y + 63)
                GUICtrlSetGraphic($cBoard, $GUI_GR_MOVE, $x + 63, $y)
                GUICtrlSetGraphic($cBoard, $GUI_GR_LINE, $x, $y + 63)
        EndSwitch
    Next
    GUICtrlSetGraphic($cBoard, $GUI_GR_REFRESH)
EndFunc

Func _StaticEvaluator($iDepth)
    Local $s = 0
    $s += _ScoreLine($aTree[$iDepth], 1, 1)
    $s += _ScoreLine($aTree[$iDepth], 4, 1)
    $s += _ScoreLine($aTree[$iDepth], 7, 1)
    $s += _ScoreLine($aTree[$iDepth], 1, 3)
    $s += _ScoreLine($aTree[$iDepth], 2, 3)
    $s += _ScoreLine($aTree[$iDepth], 3, 3)
    $s += _ScoreLine($aTree[$iDepth], 1, 4)
    $s += _ScoreLine($aTree[$iDepth], 3, 2)
    Return $s
EndFunc

Func _ScoreLine(ByRef $sBoard, $a, $B)
    Local $s = StringMid($sBoard, $a, 1) & StringMid($sBoard, $a + $b, 1) & StringMid($sBoard, $a + $b + $b, 1)
    Switch $s
        Case "001", "010", "100"
            Return 1
        Case "011", "101", "110"
            Return 10
        Case "111"
            Return 1000
        Case "002", "020", "200"
            Return -1
        Case "022", "202", "220"
            Return -10
        Case "222"
            Return -1000
        Case Else
            Return 0
    EndSwitch
EndFunc

Func _GetLegalMoves(ByRef $iDepth, ByRef $iSideToMove)
    Local $s = "", $i = Random(0, 8, 1), $j
    For $j = 1 To 9
        If (StringMid($aTree[$iDepth], $i + 1, 1) = "0") Then
            $s &= String($i + 1)
        EndIf
        $i = Mod($i + 1, 9)
    Next
    Return StringSplit($s, "")
EndFunc

Func _MakeMove($iDepth, ByRef $iMove, ByRef $iSideToMove)
    $aTree[$iDepth + 1] = StringLeft($aTree[$iDepth], $iMove - 1) & String($iSideToMove) & StringMid($aTree[$iDepth], $iMove + 1)
EndFunc

Func _FindBestMove($iDepth, $iSideToMove)
    Local $iScore = _StaticEvaluator($iDepth)
    If $iDepth > 3 Then Return $iScore
    If StringInStr($aTree[$iDepth], "0") = 0 Then Return $iScore ; No valid moves available
    If ($iScore < -100) Or ($iScore > 100) Then Return $iScore ; Game is already won ... can't move any more
    Local $aMoves = _GetLegalMoves($iDepth, $iSideToMove), $i
    Local $iBestScore = _IIf(($iSideToMove = 1), -9999, 9999), $iNewScore, $iBestMove = 0
    For $i = 1 To $aMoves[0]
        _MakeMove($iDepth, $aMoves[$i], $iSideToMove)
        $iNewScore = _FindBestMove($iDepth + 1, 3 - $iSideToMove)
        If $iSideToMove = 1 Then
            If $iNewScore > $iBestScore Then
                $iBestScore = $iNewScore
                $iBestMove = $i
            EndIf
        Else
            If $iNewScore < $iBestScore Then
                $iBestScore = $iNewScore
                $iBestMove = $i
            EndIf
        EndIf
    Next
    If $iDepth = 0 Then
        _MakeMove($iDepth, $aMoves[$iBestMove], $iSideToMove)
        _DrawBoard($iDepth + 1)
    EndIf
    Return $iBestScore
EndFunc

WBD

Link to comment
Share on other sites

no problem WideBoyDixon... the more unbeatable examples the better... ill eventualy fix it.. got other stuff to do though

Link to comment
Share on other sites

@WideBoyDixon

Very nice approach - I really like it. Your example is exactly what I would expect from a good game algorythm.

It's a good algorythm and it finds always the best move. I like the way you keep the table info in a string ;)

Mine doesn't allow wins either but comparing to yours it looks like a "poor relative"

Very good job ^_^

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Link to comment
Share on other sites

ima look into each of your guys code anyway.. see if i can learn something about the algo

Link to comment
Share on other sites

Link to comment
Share on other sites

lol its beyond me... can some one post a simplified version?..... ^_^ i wish i was a genius

Link to comment
Share on other sites

  • 1 year later...

I was frustrated so i put this project aside. Now im trying it again... its still possible to win, can someone help me by showing me what i'm doin wrong? i think it doesnt have any bugs so far can you guys voice your oppinions?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...