Xs and Os (or Tic-Tac-Toe)

General FreeBASIC programming questions.
Post Reply
NorbyDroid
Posts: 70
Joined: May 21, 2016 22:55

Xs and Os (or Tic-Tac-Toe)

Post by NorbyDroid »

Here is a REALLY simple game where the computer plays itself at Xs and Os. Nothin special.

Computer is dumb and just randomly chooses a position to play without thinkin of the "best" move.

Code: Select all

CLS
Randomize Timer

Dim as String Text="Simple Xs and Os by Norby Droid"

Color 9 : Locate 2, 40-Len(Text)\2, 0 : Print Text;

Function GetMove(Board as String) as Integer
  Dim as Integer tPos, tVal

  While tVal=0
    tPos=Int(9*Rnd)+1
    If Mid(Board, tPos, 1)=" " then tVal=1
  Wend

  Return tPos
End Function

Function WinTest(Board as String) as Integer
  Dim as String tStr

  For t as Integer=0 to 7
    tStr=Mid("123456789147258369159357", 3*t+1, 3)

    tStr=Mid(Board, Val(Left(tStr, 1)), 1)+   _
         Mid(Board, Val(Mid(tStr, 2, 1)), 1)+ _
         Mid(Board, Val(Right(tStr,1)), 1)

    If tStr="XXX" then WinTest=1
    If tStr="OOO" then WinTest=2
  Next
End Function

Sub UpdateBoard(Board as String)
  Color 13
  Locate 11, 34, 0 : Print "   |   |   ";
  Locate 12, 34, 0 : Print "---+---+---";
  Locate 13, 34, 0 : Print "   |   |   ";
  Locate 14, 34, 0 : Print "---+---+---";
  Locate 15, 34, 0 : Print "   |   |   ";

  For t as Integer=0 to 2
    Locate 11, 4*t+35, 0 : Print Mid(Board, t+1, 1);
    Locate 13, 4*t+35, 0 : Print Mid(Board, t+4, 1);
    Locate 15, 4*t+35, 0 : Print Mid(Board, t+7, 1);
  Next
End Sub

Sub Main(Board as String)
  Dim as Integer Moves=0
  Dim as Integer Winner=0
  
  While Winner=0
    DIm as String Player=Mid("XO", (Moves Mod 2)+1, 1)

    Dim as Integer tPos=GetMove(Board)
    Mid(Board, tPos, 1)=Player
    UpdateBoard Board

    Winner=WinTest(Board)>0
    If Instr(Board, " ")=0 then Winner=3

    Moves+=1
    Sleep 50 : If Inkey=Chr(27) then End
  Wend
End Sub

Dim as String Board=Space(9)
UpdateBoard Board

Dim as Integer x, o, t

Do
  Board=Space(9)

  Main Board
  Dim as Integer Winner=WinTest(Board)

  ' Display Winner ot non winner
  Locate 17, 35, 0
  If Winner=0 then Print "No Winner" : t+=1
  If Winner=1 then Print " X  Wins " : x+=1
  If Winner=2 then Print " O  Wins " : o+=1

  Locate 20, 2, 0 : Print "X:"; Str(x)
  Locate 20, 32, 0 : Print "O:"; Str(o)
  Locate 20, 62, 0 : Print "Tie:"; Str(t)

  Sleep 500
  Locate 17, 35, 0: Print Space(10);
Loop
Updated: There were a few gremlins in the code and they have been fixed and tested in WinFBE. Thanks to PaulDoe on Discord.
Last edited by NorbyDroid on May 03, 2023 12:34, edited 1 time in total.
integer
Posts: 408
Joined: Feb 01, 2007 16:54
Location: usa

Re: Xs and Os (or Tic-Tac-Toe)

Post by integer »

in main:
player is defined twice
winner is not defined

however,
the subroutine/macro "incr" is not defined
believe it should be: moves += 1

The player with the first move has the advantage.
NorbyDroid
Posts: 70
Joined: May 21, 2016 22:55

Re: Xs and Os (or Tic-Tac-Toe)

Post by NorbyDroid »

integer wrote: May 03, 2023 8:25 in main:
player is defined twice
winner is not defined

however,
the subroutine/macro "incr" is not defined
believe it should be: moves += 1

The player with the first move has the advantage.
You are correct:

Code: Select all

"Incr Moves, 1" -> "Moves+=1"
Player has been fixed along with other issues. Thanks for your reply.
NorbyDroid
Posts: 70
Joined: May 21, 2016 22:55

Re: Xs and Os (or Tic-Tac-Toe)

Post by NorbyDroid »

Here is a small update to the Xs and Os game.

It adds Players:
0) Computer vs Computer
1) Player vs Computer
2) Player vs Player
When choosin Players 1 or 2 a random player is chosen to start.

Simple brain to play intelligently.

Changes here and there.

Code: Select all

CLS
Randomize Timer

Dim as String Text="Simple Xs and Os by Norby Droid"

Color 9 : Locate 2, 40-Len(Text)\2, 0 : Print Text;

Sub Message(Text as String)
  Color 12 : Locate 24, 40-Len(Text)\2, 0 : Print Text;
  Sleep 1000 : Locate 24, 1 : Print Space(80);
End Sub

Function GetMove(Board as String) as Integer
  Dim as Integer tPos, tVal

  While tVal=0
    tPos=Int(9*Rnd)+1
    If Mid(Board, tPos, 1)=" " then tVal=1
  Wend

  Return tPos
End Function

Function Brain(Board as String, Think as Integer) as Integer
  Dim tPos as Integer

  If Trim(Board)="" then
    If Think=1 then Message "Pick a Corner Position"
    
    Return Val(Mid("1379", Int(4*Rnd)+1, 1)) : Exit Function
  EndIf
  
  If Len(Trim(Board))=1 and _
     (Mid(Board, 1, 1)<>" " or Mid(Board, 3, 1)<>" " or _
      Mid(Board, 1, 1)<>" " or Mid(Board, 3, 1)<>" ") then
      
      If Think=1 then Message "Pick the Center Position"
      
      Return 5
      Exit Function
  EndIf

  Dim as String tMoves="123456789147258369159357"
  
  If Think=1 then Message "Check for a possible Block"
  
  For t as Integer=0 to 7
    Dim as String Block=Mid(tMoves, 3*t+1, 3)
   
    Dim as Integer p1=Val(Left(Block, 1))
    Dim as Integer p2=Val(Mid(Block, 2, 1))
    Dim as Integer p3=Val(Right(Block, 1))
    
    Block=Mid(Board, p1, 1)+Mid(Board, p2, 1)+Mid(Board, p3, 1)
    If Think=1 then Message "["+Str(p1)+Str(p2)+Str(p3)+" }"+Block+"{"
    
    If Block=" XX" or Block=" OO" then
        If Think=1 then Message "Left Block"
        
        Return p1 : Exit Function
    EndIf

    If Block="X X" or Block="O O" then 
        If Think=1 then Message "Middle Block"
        
        Return p2 : Exit Function
    EndIf
    
    If Block="XX " or Block="OO " then
        If Think=1 then Message "Right Block"
        
        Return p3 : Exit Function
    EndIf
  Next
     
  If tPos=0 then
    If Think=1 then Message "Pick a Random Position"
    
    Return GetMove(Board) : Exit Function
  EndIf
End FUnction

Function WinTest(Board as String) as Integer
  Dim as String tStr

  For t as Integer=0 to 7
    tStr=Mid("123456789147258369159357", 3*t+1, 3)

    tStr=Mid(Board, Val(Left(tStr, 1)), 1)+   _
         Mid(Board, Val(Mid(tStr, 2, 1)), 1)+ _
         Mid(Board, Val(Right(tStr,1)), 1)

    If tStr="XXX" then WinTest=1
    If tStr="OOO" then WinTest=2
  Next
End Function

Sub UpdateBoard(Board as String)
  Color 13
  Locate 11, 34, 0 : Print "   |   |   ";
  Locate 12, 34, 0 : Print "---+---+---";
  Locate 13, 34, 0 : Print "   |   |   ";
  Locate 14, 34, 0 : Print "---+---+---";
  Locate 15, 34, 0 : Print "   |   |   ";

  For t as Integer=0 to 2
    Locate 11, 4*t+35, 0 : Print Mid(Board, t+1, 1);
    Locate 13, 4*t+35, 0 : Print Mid(Board, t+4, 1);
    Locate 15, 4*t+35, 0 : Print Mid(Board, t+7, 1);
  Next
End Sub

Sub Player0(Board as String)
  Dim as Integer Moves=Int(2*Rnd)
  Dim as Integer Winner=0
  
  Dim as String Player

  While Winner=0
    Mid(Board, Brain(Board, 0), 1)=Mid("XO", (Moves Mod 2)+1, 1)
    UpdateBoard Board

    Moves+=1 : Winner=WinTest(Board)
    If Instr(Board, " ")=0 then Winner=3

    Sleep 50 : If Inkey=Chr(27) then End
  Wend
End Sub

Sub Computer
  Dim x as Integer, o as Integer, t as Integer

  Locate 13, 2, 0 : Print Space(40);

  Do
    Dim as String Board=Space(9)

    Player0 Board
    Dim as Integer Winner=WinTest(Board)

    ' Display Winner ot non winner
    Locate 17, 35, 0
    If Winner=0 then Print "No Winner" : t+=1
    If Winner=1 then Print " X  Wins " : x+=1
    If Winner=2 then Print " O  Wins " : o+=1

    Locate 20, 2, 0 : Print "X: "; Str(x)
    Locate 20, 32, 0 : Print "O: "; Str(o)
    Locate 20, 62, 0 : Print "Tie: "; Str(t)

    Sleep 500
    Locate 17, 35, 0: Print Space(10);
  Loop
end sub

Sub Players1
  Dim as String Touch

  Dim as String Board=Space(9)
  UpdateBoard Board
  
  DIm as Integer Winner=0
  
  Dim as Integer CurPlayer=Int(2*Rnd)+1
  If CurPlayer=1 then Message "Computer Starts" else Message "Player Starts"

  While Winner=0
    If CurPlayer=1 then 
      Mid(Board, Brain(Board, 0), 1)="O"
    Else
      Dim as Integer tPos=0

      Locate 17, 28 : Print "Choose a Position (1-9)"
      
      While tPos=0
        Touch=Inkey

        If Touch="" then
          tPos=0
        Else
          tPos=Asc(Touch)-48
          If tPos<1 or tPos>9 then tPos=0
        end if

        If Mid(Board, tPos, 1)<>" " then tPos=0
      Wend
      
      Mid(Board, Asc(Touch)-48, 1)="X"

      Locate 17, 28 : Print Space(24);
    EndIf

    UpdateBoard Board

    Winner=WinTest(Board)
    If Instr(Board, " ")=0 then Winner=3

    CurPlayer=(CurPlayer+1) Mod 2
    Sleep 500
  wend

  Print : Print
  If Winner=1 then Message "Player Wins"
  If Winner=2 then Message "Computer Wins"
  If Winner=3 then Message "Tie Game"
end sub

Sub Players2
  Dim Touch as String

  Dim as String Board=Space(9)
  UpdateBoard Board

  Dim as Integer CurPlayer=Int(2*Rnd)+1
  If CurPlayer=1 then Message "Player "+Mid("XO", CurPlayer, 1)+" Starts"

  Dim as Integer Winner=0

  While Winner=0
    Dim as Integer tPos=0

    Locate 17, 28 : Print "Player "; Str(CurPlayer); " Choose a Position (1-9)"
      
    While tPos=0
      Touch=Inkey

      If Touch="" then
        tPos=0
      Else
        tPos=Asc(Touch)-48
        If tPos<1 or tPos>9 then tPos=0
      end if

      If Mid(Board, tPos, 1)<>" " then tPos=0
    Wend
      
    Locate 17, 28 : Print Space(32);

    Mid(Board, Asc(Touch)-48, 1)=Mid("XO", CurPlayer+1, 1)
    UpdateBoard Board

    Winner=WinTest(Board)
    If Instr(Board, " ")=0 then Winner=3

    CurPlayer=(CurPlayer+1) Mod 2
    Sleep 500
  wend
end sub

Dim as Integer Quit=0
Dim as Integer Players

Locate 13, 2, 0 : Input "Number of Players (0, 1, 2)"; Players
Locate 13, 2, 0 : Print Space(40);

If Players=0 then Computer
If Players=1 then Players1
If Players=2 then Players2

While Quit=0
  Locate 13, 2, 0 : Input "Play again (0=Yes | 1=No)"; Quit
  
  If Quit=0 then
    If Players=0 then Computer
    If Players=1 then Players1
    If Players=2 then Players2
  EndIf
Wend
Created in DOS and tested and transfered to Windows and Tested in WinFBE.
anjexosdefrgos
Posts: 3
Joined: Jan 31, 2022 17:59

Re: Xs and Os (or Tic-Tac-Toe)

Post by anjexosdefrgos »

I like the idea of randomly selecting a player to start when choosing Players 1 or 2. It adds an element of surprise and fairness to the gameplay. Introducing a simple brain to play intelligently is also intriguing. It would be interesting to see how the computer makes strategic moves and provides a challenging experience for players. Overall, these updates seem like they would enhance the Xs and Os game and make it more engaging for players of different preferences and skill levels.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Xs and Os (or Tic-Tac-Toe)

Post by dodicat »

I did this a few years ago (around the time of the Olympic games).
viewtopic.php?p=177178&hilit=setup_grid#p177178
The first several lines compensated for a bug in version 1.08.0, but they could be removed now as time has moved on.
Post Reply