Microsoft Small Basic

Program Listing:
Embed this in your website
' TicTacToe MIX
' RANDOM vs
' RANDOMX only for O vs
' RUNANDSTOP vs
' MONTECARLO vs
' HUMAN
logicO = "MONTECARLO"
logicX = "HUMAN"
tiO = 0 ' times O win
tiX = 0 ' times X win
tiD = 0 ' times draw
tiG = 0 ' times games
tiGmax = 100
tiW = 10 ' times work out for MONTECARLO
GraphicsWindow.BrushColor = "SteelBlue"
seed = 0
debug = "False"

nextgame:
GraphicsWindow.Clear()
If tiG > 0 Then
  ShowResult()
EndIf
s = 0
ClearBoard() ' board <- 0
SaveBoard() ' current board <- board
ShowBoard()

loop:
  ' turn O
  GetPutList()
  s = s + 1
  If logicO = "RANDOM" Then
    Random()
  ElseIf logicO = "RANDOMX" Then
    RandomX()
  ElseIf logicO = "RUNANDSTOP" Then
    RunAndStop()
  ElseIf logicO = "MONTECARLO" Then
    WorkOut() 'determine a from put list by MONTECARLO method
  ElseIf logicO = "HUMAN" Then
    Human()
  EndIf
  c[x][y] = 1
  Record()
  RestoreBoard() ' board <- current board
  ShowBoard()
  CheckGameEnd()
  If game <> "continue" Then
    Goto exit
  EndIf

  'MONTECARLO X
  GetPutList()
  s = s + 1
  If logicX = "RANDOM" Then
    Random()
  ElseIf logicX = "RANDOMX" Then
    RandomX()
  ElseIf logicX = "RUNANDSTOP" Then
    RunAndStop()
  ElseIf logicX = "MONTECARLO" Then
    WorkOut() 'determine a from put list by MONTECARLO method
  ElseIf logicX = "HUMAN" Then
    Human()
  EndIf
  c[x][y] = 2
  Record()
  RestoreBoard() ' board <- current board
  ShowBoard()
  CheckGameEnd()
  If game <> "continue" Then
    Goto exit
  EndIf

Goto loop

exit:
GraphicsWindow.DrawText(10, 10, game)
If game = "O win" then
  tiO = tiO + 1
ElseIf game = "X win" then
  tiX = tiX + 1
Else
  tiD = tiD + 1
EndIf
tiG = tiG + 1
If game = "O win" then
  Program.Delay(500)
Else
  Program.Delay(500)
EndIf
If tiG < tiGmax Then
  Goto nextgame
EndIf
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FillRectangle(400, 20, 150, 150)
GraphicsWindow.BrushColor = "SteelBlue"
ShowResult()

Sub Human
  x = px[1]
  y = py[1]
  ShowPointer()
currentmouse:
  Program.Delay(100)
  mx = GraphicsWindow.MouseX
  my = GraphicsWindow.MouseY
  GetPosition()
  HidePointer()
  ShowPointer()
  If Mouse.isLeftButtonDown Then
    Goto checkput
  Else
    Goto currentmouse
  EndIf
checkput:
  For a = 1 To p
    If px[a] = x And py[a] = y Then
      Goto returnmouse
    EndIf
  EndFor
  Goto currentmouse
returnmouse:
  HidePointer()
  x = px[a]
  y = py[a]
EndSub

Sub ShowPointer
  cx = x
  cy = y
  GraphicsWindow.PenColor = "DeepSkyBlue"
  GraphicsWindow.DrawRectangle(60 + (3 - x) * 100, 60 + (3 - y) * 100, 80, 80)
  GraphicsWindow.PenColor = "Black"
EndSub

Sub HidePointer
  GraphicsWindow.PenColor = "White"
  GraphicsWindow.DrawRectangle(60 + (3 - cx) * 100, 60 + (3 - cy) * 100, 80, 80)
  GraphicsWindow.PenColor = "Black"
EndSub

Sub GetPosition
  If mx < 150 Then
    x = 3
  ElseIf mx < 250 Then
    x = 2
  Else
    x = 1
  EndIf
  If my < 150 Then
    y = 3
  ElseIf my < 250 Then
    y = 2
  Else
    y = 1
  EndIf
EndSub

Sub Record
  rx[s] = x
  ry[s] = y
EndSub

Sub ShowRecord
  For i = 1 to s
    TextWindow.Write("[" + rx[i] + "][" + ry[i] + "],")
  EndFor
  TextWindow.WriteLine("")
EndSub

Sub ShowPutList
  For i = 1 To p
    TextWindow.Write("px[" + i + "]=" + px[i])
    TextWindow.WriteLine(",py[" + i + "]=" + py[i])
  EndFor
EndSub

Sub SavePutList
  n = p
  For i = 1 To n
    sx[i] = px[i]
    sy[i] = py[i]
  EndFor
EndSub

Sub RestorePutList
  p = n
  For i = 1 To p
    px[i] = sx[i]
    py[i] = sy[i]
  EndFor
EndSub

Sub SaveBoard
  For y = 3 To 1 Step -1
    For x = 3 To 1 Step -1
      c[x][y] = b[x][y]
    EndFor
  EndFor
EndSub

Sub RestoreBoard
  For y = 3 To 1 Step -1
    For x = 3 To 1 Step -1
      b[x][y] = c[x][y]
    EndFor
  EndFor
EndSub

Sub WorkOut
  SavePutList()
  ss = s ' save stage

  For i = 1 To n ' instead of p
    win[i] = 0 ' result clear
  EndFor
  For g = 1 To tiW * n
    s = ss - 1 ' temporaly stage
    RestoreBoard() ' board <- current board
    turn = "O"
    If Math.Remainder(s, 2) = 0 Then
      turn = "X"
      Goto nextX
    EndIf

nextO:
    ' RANDOM O
    GetPutList()
    s = s + 1
    RunAndStop()
    If s = ss Then
      f = a ' first put
    EndIf
    b[x][y] = 1
    CheckGameEnd()
    If game <> "continue" Then
      Goto endgame
    EndIf

nextX:
    ' RANDOM X
    GetPutList()
    s = s + 1
    RunAndStop()
    If s = ss Then
      f = a ' first put
    EndIf
    b[x][y] = 2
    CheckGameEnd()
    If game <> "continue" Then
      Goto endgame
    EndIf

    Goto nextO

endgame:
    If game = turn + " win" then
      win[f] = win[f] + 3 * (10 - s)
    ElseIf game = "draw" then
      win[f] = win[f] + (10 - s)
    Else
      win[f] = win[f] + 2 * (10 - s)
    EndIf
  EndFor

  max = 0
  For i = 1 to n ' instead of p
    If win[i] >= max Then
      max = win[i]
      a = i
    EndIf
  EndFor
  RestorePutList()
  s = ss ' restore stage
  x = px[a]
  y = py[a]
EndSub

Sub Random
  a = Math.GetRandomNumber(p)
  If debug Then
    seed = seed + 1
    If seed > p Then
      seed = 1
    EndIf
    a = seed
  EndIf
  x = px[a]
  y = py[a]
EndSub

Sub RandomX
  If s = 1 Then
    x = 2
    y = 2
  Else
    Random()
  EndIf
EndSub

Sub RunAndStop
  ' clear run and stop candidate
  For i = 1 To p
    run[i] = 0
    stop[i] = 0
  EndFor
  ' set next of candidate
  For i = 1 To p
    x0 = px[i]
    If x0 = 1 Then
      x1 = 2
      x2 = 3
    ElseIf x0 = 2 Then
      x1 = 1
      x2 = 3
    Else
      x1 = 1
      x2 = 2
    EndIf
    y0 = py[i]
    If y0 = 1 Then
      y1 = 2
      y2 = 3
    ElseIf y0 = 2 Then
      y1 = 1
      y2 = 3
    Else
      y1 = 1
      y2 = 2
    EndIf
    '
    If b[x1][y0] = b[x2][y0] Then
      ' horizontal run or stop found
      If b[x1][y0] = 1 Then
        ' O O
        If Math.Remainder(s, 2) = 1 Then
          ' turn O
          run[i] = run[i] + 1
        Else
          ' turn X
          stop[i] = stop[i] + 1
        EndIf
      EndIf
      If b[x1][y0] = 2 Then
        ' X X
        If Math.Remainder(s, 2) = 1 Then
          ' turn O
          stop[i] = stop[i] + 1
        Else
          ' turn X
          run[i] = run[i] +1
        EndIf
      EndIf
    EndIf
    If b[x0][y1] = b[x0][y2] Then
      ' vartical run found
      If b[x0][y1] = 1 Then
        ' O O
        If Math.Remainder(s, 2) = 1 Then
          ' turn O
          run[i] = run[i] +1
        Else
          ' turn X
          stop[i] = stop[i] + 1
        EndIf
      EndIf
      If b[x0][y1] = 2 Then
        ' X X
        If Math.Remainder(s, 2) = 1 Then
          ' turn O
          stop[i] = stop[i] + 1
        Else
          ' turn X
          run[i] = run[i] +1
        EndIf
      EndIf
    EndIf
    If x0 = y0 And b[x1][y1] = b[x2][y2] Then
      ' down run or stop found
      If b[x1][y1] = 1 Then
        ' O O
        If Math.Remainder(s, 2) = 1 Then
          ' turn O
          run[i] = run[i] + 1
        Else
          ' turn X
          stop[i] = stop[i] + 1
        EndIf
      EndIf
      If b[x1][y1] = 2 Then
        ' X X
        If Math.Remainder(s, 2) = 1 Then
          ' turn O
          stop[i] = stop[i] + 1
        Else
          ' turn X
          run[i] = run[i] + 1
        EndIf
      EndIf
    EndIf
    If x0 + y0 = 4 And b[x1][y2] = b[x2][y1] Then
      ' up run or stop found
      If b[x1][y2] = 1 Then
        ' O O
        If Math.Remainder(s, 2) = 1 Then
          ' turn O
          run[i] = run[i] + 1
        Else
          ' turn X
          stop[i] = stop[i] + 1
        EndIf
      EndIf
      If b[x1][y2] = 2 Then
        ' X X
        If Math.Remainder(s, 2) = 1 Then
          ' turn O
          stop[i] = stop[i] + 1
        Else
          ' turn X
          run[i] = run[i] + 1
        EndIf
      EndIf
    EndIf
  EndFor
  max = 0
  For i = 1 To p
    If run[i] > max Then
      max = run[i]
      a = i
    EndIf
  EndFor
  If max > 0 Then
    Goto returna
  EndIf
  For i = 1 To p
    If stop[i] > max Then
      max = stop[i]
      a = i
    EndIf
  EndFor
  If max > 0 Then
    Goto returna
  EndIf
  Random()
returna:
  x = px[a]
  y = py[a]
EndSub

Sub ShowResult
  GraphicsWindow.DrawText(400, 20, "O win: " + tiO + " (" + Math.Floor(tiO / tiG * 100) + "%)")
  GraphicsWindow.DrawText(400, 40, "X win: " + tiX + " (" + Math.Floor(tiX / tiG * 100) + "%)")
  GraphicsWindow.DrawText(400, 60, "draw : " + tiD + " (" + Math.Floor(tiD / tiG * 100) + "%)")
  GraphicsWindow.DrawText(400, 80, "games: " + tiG)
  GraphicsWindow.DrawText(400, 120, "O: " + logicO)
  GraphicsWindow.DrawText(400, 140, "X: " + logicX)
EndSub

Sub CheckGameEnd
  game = "continue"
  If p <= 6 Then
    If Math.Remainder(s, 2) = 1 Then
      If b[3][3] = 1 And b[2][3] = 1 And b[1][3] = 1 Then
        game = "O win"
      EndIf
      If b[3][2] = 1 And b[2][2] = 1 And b[1][2] = 1 Then
        game = "O win"
      EndIf
      If b[3][1] = 1 And b[2][1] = 1 And b[1][1] = 1 Then
        game = "O win"
      EndIf
      If b[3][3] = 1 And b[3][2] = 1 And b[3][1] = 1 Then
        game = "O win"
      EndIf
      If b[2][3] = 1 And b[2][2] = 1 And b[2][1] = 1 Then
        game = "O win"
      EndIf
      If b[1][3] = 1 And b[1][2] = 1 And b[1][1] = 1 Then
        game = "O win"
      EndIf
      If b[3][3] = 1 And b[2][2] = 1 And b[1][1] = 1 Then
        game = "O win"
      EndIf
      If b[3][1] = 1 And b[2][2] = 1 And b[1][3] = 1 Then
        game = "O win"
      EndIf
    Else
      If b[3][3] = 2 And b[2][3] = 2 And b[1][3] = 2 Then
        game = "X win"
      EndIf
      If b[3][2] = 2 And b[2][2] = 2 And b[1][2] = 2 Then
        game = "X win"
      EndIf
      If b[3][1] = 2 And b[2][1] = 2 And b[1][1] = 2 Then
        game = "X win"
      EndIf
      If b[3][3] = 2 And b[3][2] = 2 And b[3][1] = 2 Then
        game = "X win"
      EndIf
      If b[2][3] = 2 And b[2][2] = 2 And b[2][1] = 2 Then
        game = "X win"
      EndIf
      If b[1][3] = 2 And b[1][2] = 2 And b[1][1] = 2 Then
        game = "X win"
      EndIf
      If b[3][3] = 2 And b[2][2] = 2 And b[1][1] = 2 Then
        game = "X win"
      EndIf
      If b[3][1] = 2 And b[2][2] = 2 And b[1][3] = 2 Then
        game = "X win"
      EndIf
    EndIF
    If p = 1 And game = "continue" Then
      game = "draw"
    EndIf
  EndIf
EndSub

Sub GetPutList
  p = 0
  For a = 0 to 8
    If b[Math.Remainder(a, 3) + 1][Math.Floor(a / 3) + 1] = 0 Then
      p = p + 1
      px[p] = Math.Remainder(a, 3) + 1
      py[p] = Math.Floor(a / 3) + 1
    EndIf
  EndFor
EndSub

Sub ShowBoard
  GraphicsWindow.DrawLine(50, 150, 350, 150)
  GraphicsWindow.DrawLine(50, 250, 350, 250)
  GraphicsWindow.DrawLine(150, 50, 150, 350)
  GraphicsWindow.DrawLine(250, 50, 250, 350)
  For y = 3 To 1 Step -1
    For x = 3 To 1 Step -1
      If b[x][y] = 1 Then
        GraphicsWindow.DrawEllipse(65 + (3 - x) * 100, 65 + (3 - y) * 100, 70, 70)
      ElseIf b[x][y] = 2 Then
        GraphicsWindow.DrawLine(65 + (3 - x) * 100, 65 + (3 - y) * 100, 135 + (3 - x) * 100, 135 + (3 - y) * 100)
        GraphicsWindow.DrawLine(135 + (3 - x) * 100, 65 + (3 - y) * 100, 65 + (3 - x) * 100, 135 + (3 - y) * 100)
      EndIf
    EndFor
  EndFor
EndSub

Sub ClearBoard
  b[3][3] = 0
  b[2][3] = 0
  b[1][3] = 0
  b[3][2] = 0
  b[2][2] = 0
  b[1][2] = 0
  b[3][1] = 0
  b[2][1] = 0
  b[1][1] = 0
EndSub
Copyright (c) Microsoft Corporation. All rights reserved.