Tic-tac-toe: Difference between revisions

46,166 bytes added ,  1 month ago
m
Fixed the name of the GitHub repo of the PostScript version
(Added a traditional Pascal solution)
m (Fixed the name of the GitHub repo of the PostScript version)
 
(33 intermediate revisions by 15 users not shown)
Line 10:
 
''Tic-tac-toe''   is also known as:
::*   ''naughtsnoughts and crosses''
::*   ''tic tac toe''
::*   ''tick tack toe''
Line 26:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">UInt32 seed = 0
F nonrandom_choice(lst)
:seed = 1664525 * :seed + 1013904223
Line 111:
L.break
L.was_no_break
print("\nA draw")</langsyntaxhighlight>
 
{{out}}
Line 158:
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO, Ada.Numerics.Discrete_Random;
-- can play human-human, human-computer, computer-human or computer-computer
-- the computer isn't very clever: it just chooses a legal random move
Line 281:
Ada.Text_IO.Put_Line("The winner is: " & Find_Winner(The_Board));
end if;
end Tic_Tac_Toe;</langsyntaxhighlight>
 
{{out}}
Line 396:
=={{header|ALGOL W}}==
The user can play O, X, both or neither. O goes first whether user or computer controlled.
<langsyntaxhighlight lang="algolw">begin
 
string(10) board;
Line 575:
do begin end
 
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 621:
 
=={{header|AppleScript}}==
<langsyntaxhighlight AppleScriptlang="applescript">property OMask : missing value
property XMask : missing value
property winningNumbers : {7, 56, 73, 84, 146, 273, 292, 448}
Line 733:
end repeat
return theResult as integer
end BWAND</langsyntaxhighlight>
 
=={{header|AutoHotkey}}==
This program uses a Gui with 9 buttons. Clicking on one will place an X there, disable the button, and cause the program to go somewhere.
It plays logically, trying to win, trying to block, or playing randomly in that order.
<langsyntaxhighlight AutoHotkeylang="autohotkey">Gui, Add, Button, x12 y12 w30 h30 vB1 gButtonHandler,
Gui, Add, Button, x52 y12 w30 h30 vB2 gButtonHandler,
Gui, Add, Button, x92 y12 w30 h30 vB3 gButtonHandler,
Line 844:
GuiClose:
ExitApp
</syntaxhighlight>
</lang>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f TIC-TAC-TOE.AWK
BEGIN {
Line 961:
}
function abs(x) { if (x >= 0) { return x } else { return -x } }
</syntaxhighlight>
</lang>
 
=={{header|Bash}}==
Line 983:
#encourage use of bash for more interesting tasks.
 
<langsyntaxhighlight lang="bash">
#!/bin/bash
declare -a B=( e e e e e e e e e ) # Board
Line 1,048:
show; [[ RANDOM%2 -eq 0 ]] && { turn O X; exit $?; } || turn X O
 
</syntaxhighlight>
</lang>
{{out}} (nice ANSI formatting is not shown)
<pre>
Line 1,091:
=={{header|BASIC}}==
==={{header|BASIC256}}===
<syntaxhighlight lang="basic256">
<lang BASIC256>
# basado en código de Antonio Rodrigo dos Santos Silva (gracias):
# http://statusgear.freeforums.net/thread/17/basic-256-tic-tac-toe
Line 1,363:
call gameMenu()
end
</syntaxhighlight>
</lang>
 
==={{header|FreeBASIC}}===
====graphics mode====
<syntaxhighlight lang="freebasic">
 
'About 400 lines of code, but it is a graphical (GUI ish) i.e. mouse driven.
===Microsoft Small Basic===
'I have made provision for the player to beat the computer now and then.
 
Type box
As long x,y
As long wide,high,index
Dim As ulong colour
As String caption
Declare Sub show
Declare Sub NewCaption(s As String)
Declare Constructor
Declare Constructor(x As long,y As long,wide As long,_
high As long,index As long,colour As ulong,caption As String)
End Type
Constructor box
End Constructor
Constructor box(x As long,y As long,wide As long,_
high As long,index As long,colour As ulong,caption As String)
this.x=x
this.y=y
this.wide=wide
this.high=high
this.index=index
this.colour=colour
this.caption=caption
End Constructor
'ALL PROCEDURES:
Declare Function inside(B As box,px As long,py As long) As long
Declare Sub make_frame_image(im As ulong Pointer)
Declare Sub setup_grid(boxes() As box,cellsacross As long,cellsdown As long,xp As long,yp As long,w As long,h As long)
Declare Function all_clicked(b() As box) As long
Declare Sub OnCLICK(a() As box,b As box)
Declare Sub refresh_screen(b() As box,f1 As long=0,f2 As long=0)
Declare Function Get_Mouse_Events(boxes() As box) As long
Declare Sub thickline(x1 As long,y1 As long,x2 As long,y2 As long,thickness As Single,colour As ulong,im As Any Pointer=0)
Declare Sub lineto(x1 As long,y1 As long,x2 As long,y2 As long,l As long,th As Single,col As ulong,im As Any Pointer=0)
Declare Sub thickcircle(x As long,y As long,rad As long,th As Single,col As ulong,im As Any Pointer=0)
Declare Sub startup(b() As box)
Declare Sub get_computer_events(b() As box)
 
Declare Sub finish
'Macro used by more than one procedure
#macro incircle(cx,cy,radius,x,y)
(cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
#endmacro
'=============== RUN ============================
Screen 19,32',1,16
Color ,Rgb(233,236,216) 'background colour
windowtitle string(100," ")+"Noughts and crosses"
'Globals:
Dim Shared As ulong Pointer frame
Dim Shared As long computer,player
Dim Shared As String msg1,msg2,message
message="In Play"
msg1="Computer Start"
msg2="Player Start"
'Custom Frame
frame=Imagecreate(800,600)
 
Dim As box boxes(0 To 9)
 
setup_grid(boxes(),3,3,175,85,150,150)
make_frame_image(frame)
 
Do
If player=0 And computer=0 Then
startup(boxes())
End If
If player Then
Get_Mouse_Events(boxes())
End If
If computer Then
get_computer_events(boxes())
End If
If all_clicked(boxes()) Then get_computer_events(boxes())
Loop Until Inkey=Chr(27)
finish
 
Sub box.show
Line(this.x,this.y)-(this.x+this.wide,this.y+this.high),this.colour,bf
Line(this.x,this.y)-(this.x+this.wide,this.y+this.high),Rgb(200,200,200),b
''Draw String(this.x+.5*this.wide-4*Len(this.caption),this.y+(.5*this.high-4)),this.caption,Rgb(0,0,0)
If this.index=0 Then
Draw String(this.x+.5*this.wide-4*Len(this.caption),this.y+.5*this.high-6),this.caption,Rgb(0,0,0)
End If
End Sub
 
Sub box.NewCaption(s As String)
Var cx=(this.x+this.x+this.wide)/2
Var cy=(this.y+this.y+this.high)/2
If s="X" Then
For k As long=20 To 0 Step -1
lineto(cx,cy,this.x,this.y,50,k,Rgb(50+10*k,5*k,0),frame)
lineto(cx,cy,this.x+this.wide,this.y+this.high,50,k,Rgb(50+10*k,5*k,0),frame)
lineto(cx,cy,this.x,this.y+this.high,50,k,Rgb(50+10*k,5*k,0),frame)
lineto(cx,cy,this.x+this.wide,this.y,50,k,Rgb(50+10*k,5*k,0),frame)
Next k
Else
For k As long=20 To 0 Step -1
thickcircle(cx,cy,40,k,Rgb(50+10*k,5*k,0),frame)
Next k
End If
End Sub
 
Sub get_computer_events(b() As box)
#define other(n) b(n).caption<>"0" And b(n).caption<>"C"
#define another(n) b(n).caption="0"
#define rr(f,l) (Rnd*((l)-(f))+(f))
Dim As long flag,i,k,Cwin,Pwin,NoWin
Static As long firstclick
var chance="001100"
dim as long ch
'horiz player finish
For x As long=1 To 3
If b(1+k).caption="0" And b(2+k).caption="0" And another((3+k)) Then b(3+k).Caption="0":Pwin=1:Goto fin
If b(2+k).caption="0" And b(3+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1=1:Goto fin
If b(1+k).caption="0" And b(3+k).caption="0" And another((2+k))Then b(2+k).Caption="0":Pwin=1:Goto fin
k=k+3
Next x
k=0
'vert player finish
For x As long=1 To 3
If b(1+k).caption="0" And b(4+k).caption="0" And another((7+k)) Then b(7+k).Caption="0":Pwin=1:Goto fin
If b(4+k).caption="0" And b(7+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1:Goto fin
If b(1+k).caption="0" And b(7+k).caption="0" And another((4+k))Then b(4+k).Caption="0":Pwin=1:Goto fin
k=k+1
Next x
k=0
'player finish main diag
If b(1+k).caption="0" And b(5+k).caption="0" And another((9+k)) Then b(9+k).Caption="0":Pwin=1:Goto fin
If b(1+k).caption="0" And b(9+k).caption="0" And another((5+k))Then b(5+k).Caption="0":Pwin=1:Goto fin
If b(5+k).caption="0" And b(9+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1:Goto fin
'player finish other diag
If b(7+k).caption="0" And b(5+k).caption="0" And another((3+k)) Then b(3+k).Caption="0":Pwin=1:Goto fin
If b(5+k).caption="0" And b(3+k).caption="0" And another((7+k))Then b(7+k).Caption="0":Pwin=1:Goto fin
If b(7+k).caption="0" And b(3+k).caption="0" And another((5+k))Then b(5+k).Caption="0":Pwin=1:Goto fin
'horiz computer finish
For x As long=1 To 3
If b(1+k).caption="C" And b(2+k).caption="C" And other((3+k)) Then b(3+k).Caption="C":Cwin=1:Goto fin
If b(2+k).caption="C" And b(3+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
If b(1+k).caption="C" And b(3+k).caption="C" And other((2+k))Then b(2+k).Caption="C":Cwin=1:Goto fin
k=k+3
Next x
k=0
'vert computer finish
For x As long=1 To 3
If b(1+k).caption="C" And b(4+k).caption="C" And other((7+k)) Then b(7+k).Caption="C":Cwin=1:Goto fin
If b(4+k).caption="C" And b(7+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
If b(1+k).caption="C" And b(7+k).caption="C" And other((4+k))Then b(4+k).Caption="C":Cwin=1:Goto fin
k=k+1
Next x
k=0
'computer finish main diag
If b(1+k).caption="C" And b(5+k).caption="C" And other((9+k)) Then b(9+k).Caption="C":Cwin=1:Goto fin
If b(1+k).caption="C" And b(9+k).caption="C" And other((5+k))Then b(5+k).Caption="C":Cwin=1:Goto fin
If b(5+k).caption="C" And b(9+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
'computer finish other diag
If b(7+k).caption="C" And b(5+k).caption="C" And other((3+k)) Then b(3+k).Caption="C":Cwin=1:Goto fin
If b(5+k).caption="C" And b(3+k).caption="C" And other((7+k))Then b(7+k).Caption="C":Cwin=1:Goto fin
If b(7+k).caption="C" And b(3+k).caption="C" And other((5+k))Then b(5+k).Caption="C":Cwin=1:Goto fin
'block horizontals
For x As long=1 To 3
If b(1+k).caption="0" And b(2+k).caption="0" And other((3+k)) Then b(3+k).Caption="C":flag=1:Goto fin
If b(2+k).caption="0" And b(3+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
If b(1+k).caption="0" And b(3+k).caption="0" And other((2+k))Then b(2+k).Caption="C":flag=1:Goto fin
k=k+3
Next x
k=0
'block verticals
For x As long=1 To 3
If b(1+k).caption="0" And b(4+k).caption="0" And other((7+k)) Then b(7+k).Caption="C":flag=1:Goto fin
If b(4+k).caption="0" And b(7+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
If b(1+k).caption="0" And b(7+k).caption="0" And other((4+k))Then b(4+k).Caption="C":flag=1:Goto fin
k=k+1
Next x
k=0
'block main diag
If b(1+k).caption="0" And b(5+k).caption="0" And other((9+k)) Then b(9+k).Caption="C":flag=1:Goto fin
If b(1+k).caption="0" And b(9+k).caption="0" And other((5+k))Then b(5+k).Caption="C":flag=1:Goto fin
If b(5+k).caption="0" And b(9+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
'block other diag
If b(7+k).caption="0" And b(5+k).caption="0" And other((3+k)) Then b(3+k).Caption="C":flag=1:Goto fin
If b(5+k).caption="0" And b(3+k).caption="0" And other((7+k))Then b(7+k).Caption="C":flag=1:Goto fin
If b(7+k).caption="0" And b(3+k).caption="0" And other((5+k))Then b(5+k).Caption="C":flag=1:Goto fin
If firstclick=0 Then
firstclick=1
var st="1379"
dim as long i=rr(0,3)
If Valint(b(5).caption)=0 and b(5).caption <> "C" Then b(st[i]-48).caption="C":Goto fin
End If
ch=rr(0,5)
if chance[ch]-48=1 then
If Valint(b(5).caption)<>0 Then b(5).caption="C":Goto fin
end if
If all_clicked(b()) Then Nowin=1:Goto fin
If flag=0 Then
Randomize
Do
i=rr(1,9)
If Valint(b(i).caption) <> 0 Then b(i).caption="C":Exit Do
Loop
End If
fin:
If Cwin=1 Or Pwin=1 Or NoWin=1 Then
Dim As long mx,my,mb
dim as integer x,y
screencontrol 0,x,y
for z as single=0 to 8*atn(1) step .001
dim as integer xx=x+100*cos(z)
dim as integer yy=y+100*sin(z)
screencontrol 100,xx,yy
next z
screencontrol 100,x,y
If Cwin=1 Then Message="You Loose"
If Pwin=1 Then Message="You WIN"
If Nowin=1 Then Message="DRAW"
cwin=0:k=0:pWin=0:Nowin=0:firstclick=0'i
Do
Getmouse mx,my,,mb
If inside(b(0),mx,my) And mb=1 Then finish
Var ic=incircle(500,55,20,mx,my)
If incircle(500,55,20,mx,my) And mb=1 Then Exit Do
refresh_screen(b(),ic)
Loop Until Inkey=chr(27)
For z As long=1 To Ubound(b)
b(z).caption=Str(b(z).index)
Next z
Imagedestroy frame
frame=Imagecreate(800,600)
make_frame_image(frame)
computer=0:player=0
Exit Sub
End If
player=1:computer=0
End Sub
 
Sub startup(b() As box)
message="In Play"
Dim As long mx,my,mb
Getmouse mx,my,,mb
For n As long=0 To Ubound(b)
If inside(b(n),mx,my) And mb=1 Then
If b(n).index=0 Then
finish
End If
End If
b(0).colour=Rgb(200,0,0)
Next n
Dim As long f1,f2
If incircle(80,230,10,mx,my) Then
f1=1:f2=0
If mb=1 Then computer=1:player=0
End If
If incircle(670,230,10,mx,my) Then
f1=0:f2=1
If mb=1 Then player=1:computer=0
End If
refresh_screen(b(),f1,f2)
End Sub
 
Sub thickcircle(x As long,y As long,rad As long,th As Single,col As ulong,im As Any Pointer=0)
Circle(x,y),rad+th/2,col
Circle(x,y),rad-th/2,col
Paint(x,y+rad),col,col
End Sub
 
Sub thickline(x1 As long,_
y1 As long,_
x2 As long,_
y2 As long,_
thickness As Single,_
colour As ulong,_
im As Any Pointer=0)
Dim p As ulong=Rgb(255, 255, 255)
If thickness<2 Then
Line(x1,y1)-(x2,y2),colour
Else
Dim As Double s,h,c
h=Sqr((x2-x1)^2+(y2-y1)^2)
If h=0 Then h=1e-6
s=(y1-y2)/h
c=(x2-x1)/h
For x As long=1 To 2
Line im,(x1+s*thickness/2,y1+c*thickness/2)-(x2+s*thickness/2,y2+c*thickness/2),p
Line im,(x1-s*thickness/2,y1-c*thickness/2)-(x2-s*thickness/2,y2-c*thickness/2),p
Line im,(x1+s*thickness/2,y1+c*thickness/2)-(x1-s*thickness/2,y1-c*thickness/2),p
Line im,(x2+s*thickness/2,y2+c*thickness/2)-(x2-s*thickness/2,y2-c*thickness/2),p
Paint im,((x1+x2)/2, (y1+y2)/2), p, p
p=colour
Next x
End If
End Sub
 
Sub lineto(x1 As long,y1 As long,x2 As long,y2 As long,l As long,th As Single,col As ulong,im As Any Pointer=0)
Dim As long diffx=x2-x1,diffy=y2-y1,ln=Sqr(diffx*diffx+diffy*diffy)
Dim As Single nx=diffx/ln,ny=diffy/ln
thickline(x1,y1,(x1+l*nx),(y1+l*ny),th,col,im)
End Sub
 
Function inside(B As box,px As long,py As long) As long
Return (px>B.x)*(px<(B.x+B.wide))*(py>B.y)*(py<(B.y+B.high))
End Function
Sub make_frame_image(im As ulong Pointer)
#macro map(a,b,x,d,c)
((d)-(c))*((x)-(a))/((b)-(a))+(c)
#endmacro
#macro logo(sx,sy,rad)
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx,sy),rad+k,Rgb(15,118,155):Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+1.3*rad,sy+rad),rad+k,Rgb(230,193,78),2.,1.7:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+2*1.3*rad,sy),rad+k,Rgb(21,3,0),3.25,3.05:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+3*1.3*rad,sy+rad),rad+k,Rgb(26,143,76),2,1.8:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+4*1.3*rad,sy),rad+k,Rgb(200,63,87),3.25,3.05:Next
#endmacro
For k As long=0 To 50
Var r=map(0,50,k,233,193-20)
Var g=map(0,50,k,236,153-20)
Var b=map(0,50,k,216,19-19)
Line im,(0+k,20+k)-(800-k,600-k),Rgb(r,g,b),b
Next k
For k As long=0 To 20
Var r=map(0,20,k,250,0)
Var g=map(0,20,k,250,0)
Var b=map(0,20,k,250,255)
Line im,(0,k)-(780,k),Rgb(r,g,b)',bf
Next k
logo(60,8,5)
logo(380,8,5)
logo(720,8,5)
End Sub
Sub setup_grid(boxes() As box,cellsacross As long,cellsdown As long,xp As long,yp As long,w As long,h As long)
Dim As long index
For y As long=yp To yp+h*(cellsdown-1) Step h
For x As long=xp To xp+w*(cellsacross-1) Step w
index=index+1
boxes(index)=Type<box>(x,y,w,h,index,Rgb(133,136,116),Str(index))
Next x
Next y
boxes(0)=Type<box>(780,-2,20,24,0,Rgb(200,0,0),"X")
End Sub
 
Function all_clicked(b() As box) As long
Dim As long sum
For z As long=1 To Ubound(b)
sum=sum+Valint(b(z).caption)
Next z
If sum<=0 Then Return -1
End Function
 
Sub OnCLICK(a() As box,b As box)
If b.caption="0" Then Exit Sub
If b.caption="C" Then Exit Sub
If b.caption <> "C" Then b.caption="0"
If b.index=0 Then finish
player=0:computer=1
End Sub
 
Sub refresh_screen(b() As box,f1 As long=0,f2 As long=0)
Screenlock:Cls
For n As long=0 To Ubound(b)
b(n).show 'draw boxes
If b(n).caption="0" Then b(n).NewCaption("X")
If b(n).caption="C" Then b(n).NewCaption("O")
Next n
Put(0,0),frame,trans
Draw String (390,50),message,Rgb(0,0,0)
If message <>"In Play" Then
Circle(500,55),20,Rgb(255,20,255),,,,f
If f1=-1 Then Circle(500,55),20,Rgb(202,200,200),,,,f
Draw String(480,50),"Click",Rgb(0,0,0)
End If
If computer=0 And player=0 Then
Draw String (60,200),msg1,Rgb(0,0,0)
Circle(80,230),10,Rgb(0,0,0)
Circle(80,230),5,Rgb(100,100,100),,,,f
If f1=1 Then Circle(80,230),10,Rgb(200,0,0),,,,f
Draw String (650,200),msg2,Rgb(0,0,0)
Circle(670,230),10,Rgb(0,0,0)
Circle(670,230),5,Rgb(100,100,100),,,,f
If f2=1 Then Circle(670,230),10,Rgb(200,0,0),,,,f
End If
Screenunlock:Sleep 1,1
End Sub
 
Function Get_Mouse_Events(boxes() As box) As long
Static released As long
Static pressed As long
Dim As long mousex,mousey,mousebutton ,x,y
Getmouse mousex,mousey,,mousebutton
Dim As box bar=Type<box>(0,0,780,50,0,0,"")
refresh_screen(boxes())
For n As long=0 To Ubound(boxes)
If inside(boxes(n),mousex,mousey) Then
If released Then
boxes(n).colour=Rgb(120,123,103)
If n=0 Then boxes(0).colour=Rgb(255,0,0)
End If
If mousebutton=1 Then
If released Then OnCLICK(boxes(),boxes(n))
Exit For
End If
Else
boxes(n).colour=Rgb(133,136,116)
If n=0 Then boxes(0).colour=Rgb(200,0,0)
End If
Next n
If mousebutton=0 Then released=1 Else released=0 'clean clicks
Return 0
End Function
Sub finish
Screenunlock
Imagedestroy frame
End
End Sub
</syntaxhighlight>
 
====text mode====
<syntaxhighlight lang="freebasic">
Screenres 320,240,32
 
'global variables globales
Dim Shared As Integer b(3,3) 'tablero
Dim Shared As Integer mx, my, btns, ox, oy
 
'prueba para ganar posición
'3 victorias horizontales
Function TestWin(t As Integer) As Integer
Dim As Integer win = 0
If b(0,0)= t And b(1,0)= t And b(2,0)= t Then win = t
If b(0,1)= t And b(1,1)= t And b(2,1)= t Then win = t
If b(0,2)= t And b(1,2)= t And b(2,2)= t Then win = t
'3 en vertical gana
If b(0,0)= t And b(0,1)= t And b(0,2)= t Then win = t
If b(1,0)= t And b(1,1)= t And b(1,2)= t Then win = t
If b(2,0)= t And b(2,1)= t And b(2,2)= t Then win = t
'cruzada gana
If b(0,0)= t And b(1,1)= t And b(2,2)= t Then win = t
If b(2,0)= t And b(1,1)= t And b(0,2)= t Then win = t
Return win
End Function
 
Sub InicializarTablero()
For j As Integer = 0 To 2
For i As Integer = 0 To 2
b(i,j)=0
Next i
Next j
End Sub
 
Sub DibujaTablero()
Locate 1,1 : Print "+---+---+---+"
For j As Integer = 0 To 2
Print "|";
For i As Integer = 0 To 2
If b(i,j) = 0 Then Print " |";
If b(i,j) = 1 Then Print " x |";
If b(i,j) = 2 Then Print " o |";
Next i
Print !"\n+---+---+---+"
Next j
End Sub
 
Function MovimientoHumano() As Integer
DibujaTablero()
Print !"\n HAZ CLICK CON EL MOUSE"
Print "EN LA CASILLA QUE ELIJAS"
Dim As Integer opcion = -1
While opcion = -1
Getmouse mx,my,,btns
While btns <> 1 'esperar a pulsar botón
Getmouse mx,my,,btns
Wend
mx = (mx-4)\32
my = (my-4)\16
If mx >= 0 And mx < 3 And my >= 0 And my < 3 Then
If b(mx,my) = 0 Then opcion = mx+my*3 'Casilla vacía?
End If
While btns=1
Getmouse mx,my,,btns
Wend
Wend
Return opcion
End Function
 
Function MovimientoAleatorio() As Integer
Dim As Integer opcion, i, j
opcion = Int(Rnd(1)*9)
j = Int(opcion/3)
i = opcion - Int(opcion/3)*3
While b(i,j) <> 0 Or (opcion > 8 Or opcion < 0)
opcion = Int(Rnd(1)*9)
j = Int(opcion/3)
i = opcion - Int(opcion/3)*3
Wend
Return j*3+i
End Function
 
Function MovimientoInteligente(t As Integer) As Integer
Dim As Integer i, j, opcion, t2
opcion = -1 'opcion aún no seleccionada
'obtener la ficha t2 de los oponentes
If t = 1 Then t2 = 2 Else t2 = 1
'prueba para la casilla central
If b(1,1) = 0 Then opcion = 4
'prueba para ganar
If opcion = -1 Then
If b(0,0)= 0 And b(1,0)= t And b(2,0)= t Then opcion = 0
If b(0,0)= t And b(1,0)= 0 And b(2,0)= t Then opcion = 1
If b(0,0)= t And b(1,0)= t And b(2,0)= 0 Then opcion = 2
If b(0,1)= 0 And b(1,1)= t And b(2,1)= t Then opcion = 3
If b(0,1)= t And b(1,1)= 0 And b(2,1)= t Then opcion = 4
If b(0,1)= t And b(1,1)= t And b(2,1)= 0 Then opcion = 5
If b(0,2)= 0 And b(1,2)= t And b(2,2)= t Then opcion = 6
If b(0,2)= t And b(1,2)= 0 And b(2,2)= t Then opcion = 7
If b(0,2)= t And b(1,2)= t And b(2,2)= 0 Then opcion = 8
'3 bloques verticales
If b(0,0)= 0 And b(0,1)= t And b(0,2)= t Then opcion = 0
If b(0,0)= t And b(0,1)= 0 And b(0,2)= t Then opcion = 3
If b(0,0)= t And b(0,1)= t And b(0,2)= 0 Then opcion = 6
If b(1,0)= 0 And b(1,1)= t And b(1,2)= t Then opcion = 1
If b(1,0)= t And b(1,1)= 0 And b(1,2)= t Then opcion = 4
If b(1,0)= t And b(1,1)= t And b(1,2)= 0 Then opcion = 7
If b(2,0)= 0 And b(2,1)= t And b(2,2)= t Then opcion = 2
If b(2,0)= t And b(2,1)= 0 And b(2,2)= t Then opcion = 5
If b(2,0)= t And b(2,1)= t And b(2,2)= 0 Then opcion = 8
'bloques cruzados
If b(0,0)= 0 And b(1,1)= t And b(2,2)= t Then opcion = 0
If b(0,0)= t And b(1,1)= 0 And b(2,2)= t Then opcion = 4
If b(0,0)= t And b(1,1)= t And b(2,2)= 0 Then opcion = 8
If b(2,0)= 0 And b(1,1)= t And b(0,2)= t Then opcion = 2
If b(2,0)= t And b(1,1)= 0 And b(0,2)= t Then opcion = 4
If b(2,0)= t And b(1,1)= t And b(0,2)= 0 Then opcion = 6
End If
'prueba para bloques
If opcion = -1 Then
If b(0,0)= 0 And b(1,0)= t2 And b(2,0)= t2 Then opcion = 0
If b(0,0)= t2 And b(1,0)= 0 And b(2,0)= t2 Then opcion = 1
If b(0,0)= t2 And b(1,0)= t2 And b(2,0)= 0 Then opcion = 2
If b(0,1)= 0 And b(1,1)= t2 And b(2,1)= t2 Then opcion = 3
If b(0,1)= t2 And b(1,1)= 0 And b(2,1)= t2 Then opcion = 4
If b(0,1)= t2 And b(1,1)= t2 And b(2,1)= 0 Then opcion = 5
If b(0,2)= 0 And b(1,2)= t2 And b(2,2)= t2 Then opcion = 6
If b(0,2)= t2 And b(1,2)= 0 And b(2,2)= t2 Then opcion = 7
If b(0,2)= t2 And b(1,2)= t2 And b(2,2)= 0 Then opcion = 8
'3 bloques verticales
If b(0,0)= 0 And b(0,1)= t2 And b(0,2)= t2 Then opcion = 0
If b(0,0)= t2 And b(0,1)= 0 And b(0,2)= t2 Then opcion = 3
If b(0,0)= t2 And b(0,1)= t2 And b(0,2)= 0 Then opcion = 6
If b(1,0)= 0 And b(1,1)= t2 And b(1,2)= t2 Then opcion = 1
If b(1,0)= t2 And b(1,1)= 0 And b(1,2)= t2 Then opcion = 4
If b(1,0)= t2 And b(1,1)= t2 And b(1,2)= 0 Then opcion = 7
If b(2,0)= 0 And b(2,1)= t2 And b(2,2)= t2 Then opcion = 2
If b(2,0)= t2 And b(2,1)= 0 And b(2,2)= t2 Then opcion = 5
If b(2,0)= t2 And b(2,1)= t2 And b(2,2)= 0 Then opcion = 8
'bloques cruzados
If b(0,0)= 0 And b(1,1)= t2 And b(2,2)= t2 Then opcion = 0
If b(0,0)= t2 And b(1,1)= 0 And b(2,2)= t2 Then opcion = 4
If b(0,0)= t2 And b(1,1)= t2 And b(2,2)= 0 Then opcion = 8
If b(2,0)= 0 And b(1,1)= t2 And b(0,2)= t2 Then opcion = 2
If b(2,0)= t2 And b(1,1)= 0 And b(0,2)= t2 Then opcion = 4
If b(2,0)= t2 And b(1,1)= t2 And b(0,2)= 0 Then opcion = 6
End If
If opcion = -1 Then
If b(0,0) = 0 Then opcion = 0
If b(2,0) = 0 Then opcion = 2
If b(0,2) = 0 Then opcion = 6
If b(2,2) = 0 Then opcion = 8
End If
'no hay opción de hacer una elección al azar
If opcion = -1 Then
opcion = Int(Rnd(1)*9)
j = Int(opcion/3)
i = opcion - Int(opcion/3)*3
'encontrar una casilla vacía
While b(i,j) <> 0
opcion = Int(Rnd(1)*9)
j = Int(opcion/3)
i = opcion - Int(opcion/3)*3
Wend
End If
Return opcion
End Function
 
 
InicializarTablero()
DibujaTablero()
Dim As Integer resultado
Dim As Integer jugador = 1
Dim As Integer ContarMovimientos = 0
Dim As Integer ContarPartidas = 0
Dim As Integer movimiento = 0
Dim As Integer i, j
 
Do
'alternar jugadores
If jugador = 1 Then jugador = 2 Else jugador = 1
'selecciona tipo de movimiento para cada jugador
If jugador = 1 Then
movimiento = MovimientoHumano()
Else
movimiento = MovimientoInteligente(2)
End If
'print "movimiento ="; movimiento
'print "jugador ="; jugador
'convertir la elección a las coordenadas del tablero i,j
j = Int(movimiento/3)
i = movimiento - (j*3)
b(i,j) = jugador 'ingrese la ficha de jugador 1 o 2
resultado = TestWin(jugador) 'comprobar si el jugador ha ganado
DibujaTablero()
ContarMovimientos += 1
'=======================================================
'Comprobar final de partida y/o un resultado de victoria
'=======================================================
If ContarMovimientos = 9 Or resultado <> 0 Then
DibujaTablero()
If resultado = 0 Then Print !"\n EMPATE "
If resultado = 1 Then Print !"\n x GANA "
If resultado = 2 Then Print !"\n o GANA "
Print Space(28)
Print "PULSA BARRA ESPACIADORA PARA"
Print "OTRA PARTIDA, ESC PARA SALIR"
Sleep
Cls
InicializarTablero() 'reiniciar tablero
ContarMovimientos = 0
ContarPartidas += 1
End If
Loop Until Multikey(&H01)
End
</syntaxhighlight>
 
==={{header|Microsoft Small Basic}}===
This game has a simple AI.
<langsyntaxhighlight lang="smallbasic">place1 = 1
place2 = 2
place3 = 3
Line 1,511 ⟶ 2,186:
Else
Goto reset
EndIf</langsyntaxhighlight>
 
===ZX Spectrum Basic{{header|QuickBASIC}}===
{{works with|QuickBasic|4.5}}
<lang zxbasic>
<syntaxhighlight lang="qbasic">
</lang>
' Tic-tac-toe
 
DECLARE FUNCTION Win% (Piece AS STRING)
DECLARE FUNCTION SpacesFilled% ()
DECLARE SUB ClearBoard ()
DECLARE SUB DisplayNumberedBoard ()
DECLARE SUB DisplayPiecedBoard ()
DECLARE FUNCTION Evaluate% (Me AS STRING, Him AS STRING)
 
DIM SHARED Board(8) AS STRING * 1, BestMove AS INTEGER
DIM SHARED WinPos(7, 2) AS INTEGER
DIM SHARED MyPiece AS STRING, HisPiece AS STRING
 
FOR I = 0 TO 7
FOR J = 0 TO 2
READ WinPos(I, J)
NEXT J
NEXT I
' Winning positions
DATA 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 3, 6, 1, 4, 7, 2, 5, 8, 0, 4, 8, 2, 4, 6
MyWinsCnt = 0: HisWinsCnt = 0: DrawsCnt = 0
CompFirst = -1 ' It be reversed, so human goes first
CLS
PRINT
PRINT " TIC-TAC-TOE"
PRINT
PRINT "In this version, X always goes first."
PRINT "The board is numbered:"
DO
CompFirst = NOT CompFirst ' reverse who goes first
MovesCnt = 0
PRINT
DisplayNumberedBoard
PRINT
IF CompFirst THEN PRINT "I go first." ELSE PRINT "You go first. ";
ClearBoard
IF CompFirst THEN MyPiece = "X": HisPiece = "O" ELSE MyPiece = "O": HisPiece = "X"
' -1: human; 1: computer; 0: nobody
IF CompFirst THEN Mover = 1 ELSE Mover = -1
WHILE Mover <> 0
SELECT CASE Mover
CASE 1
IF MovesCnt = 0 THEN
BestMove = INT(RND * 9)
ELSEIF MovesCnt = 1 THEN
IF Board(4) <> " " THEN BestMove = INT(RND * 2) * 6 + INT(RND * 2) * 2 ELSE BestMove = 4
ELSE
T = Evaluate(MyPiece, HisPiece)
END IF
Board(BestMove) = MyPiece
MovesCnt = MovesCnt + 1
PRINT
CALL DisplayPiecedBoard
PRINT
IF Win(MyPiece) THEN
MyWinsCnt = MyWinsCnt + 1
PRINT "I win!"
Mover = 0
ELSEIF SpacesFilled THEN
DrawsCnt = DrawsCnt + 1
PRINT "It's a draw. Thank you."
Mover = 0
ELSE
Mover = -1
END IF
CASE -1
DO
INPUT "Where do you move? ", I
IF I < 1 OR I > 9 THEN
PRINT "Illegal! ";
ELSEIF Board(I - 1) <> " " THEN
PRINT "Place already occupied. ";
ELSE
EXIT DO
END IF
LOOP
Board(I - 1) = HisPiece
MovesCnt = MovesCnt + 1
PRINT
CALL DisplayPiecedBoard
PRINT
IF Win(HisPiece) THEN
HisWinsCnt = HisWinsCnt + 1
PRINT "You beat me! Good game."
Mover = 0
ELSEIF SpacesFilled THEN
DrawsCnt = DrawsCnt + 1
PRINT "It's a draw. Thank you."
Mover = 0
ELSE
Mover = 1
END IF
END SELECT
WEND
PRINT
INPUT "Another game (y/n)? ", Answ$
LOOP UNTIL UCASE$(Answ$) <> "Y"
PRINT
PRINT "Final score:"
PRINT "You won", HisWinsCnt; "game";
IF HisWinsCnt <> 1 THEN PRINT "s";
PRINT "."
PRINT "I won", MyWinsCnt; "game";
IF MyWinsCnt <> 1 THEN PRINT "s";
PRINT "."
PRINT "We tied", DrawsCnt; "game";
IF DrawsCnt <> 1 THEN PRINT "s";
PRINT "."
PRINT "See you later!"
END
 
SUB ClearBoard
FOR I = 0 TO 8: Board(I) = " ": NEXT I
END SUB
 
SUB DisplayNumberedBoard
FOR I = 0 TO 8 STEP 3
PRINT I + 1; "|"; I + 2; "|"; I + 3
IF I <> 6 THEN PRINT "---+---+---"
NEXT I
END SUB
 
SUB DisplayPiecedBoard
FOR I = 0 TO 8 STEP 3
PRINT " "; Board(I); " | "; Board(I + 1); " | "; Board(I + 2)
IF I <> 6 THEN PRINT "---+---+---"
NEXT I
END SUB
 
FUNCTION Evaluate% (Me AS STRING, Him AS STRING)
' Recursive algorithm
IF Win(Me) THEN Evaluate = 1: EXIT FUNCTION
IF Win(Him) THEN Evaluate = -1: EXIT FUNCTION
IF SpacesFilled THEN Evaluate = 0: EXIT FUNCTION
LoseFlag = 1
FOR I = 0 TO 8
IF Board(I) = " " THEN
Board(I) = Me ' Try the move.
V = Evaluate(Him, Me)
Board(I) = " " ' Restore the empty space.
IF V = -1 THEN BestMove = I: Evaluate = 1: EXIT FUNCTION
IF V = 0 THEN LoseFlag = 0: SafeMove = I
END IF
NEXT
BestMove = SafeMove
Evaluate = -LoseFlag
END FUNCTION
 
FUNCTION SpacesFilled%
FOR I = 0 TO 8
IF Board(I) = " " THEN SpacesFilled = 0: EXIT FUNCTION
NEXT I
SpacesFilled = -1
END FUNCTION
 
FUNCTION Win% (Piece AS STRING)
FOR I = 0 TO 7
IF Board(WinPos(I, 0)) = Piece AND Board(WinPos(I, 1)) = Piece AND Board(WinPos(I, 2)) = Piece THEN Win = -1: EXIT FUNCTION
NEXT I
Win = 0
END FUNCTION
</syntaxhighlight>
 
==={{header|RapidQ}}===
{{trans|QuickBASIC}}
<syntaxhighlight lang="basic">
' Tic-tac-toe
' Console application
 
DECLARE FUNCTION Win (Piece AS STRING) AS INTEGER
DECLARE FUNCTION SpacesFilled () AS INTEGER
DECLARE SUB ClearBoard ()
DECLARE SUB DisplayNumberedBoard ()
DECLARE SUB DisplayPiecedBoard ()
DECLARE FUNCTION Evaluate (Me AS STRING, Him AS STRING) AS INTEGER
 
DIM Board(8) AS STRING * 1, BestMove AS INTEGER
DIM WinPos(7, 2) AS INTEGER
DIM MyPiece AS STRING, HisPiece AS STRING
 
FOR I = 0 TO 7
FOR J = 0 TO 2
READ WinPos(I, J)
NEXT J
NEXT I
' Winning positions
DATA 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 3, 6, 1, 4, 7, 2, 5, 8, 0, 4, 8, 2, 4, 6
MyWinsCnt = 0: HisWinsCnt = 0: DrawsCnt = 0
CompFirst = -1 ' It be reversed, so human goes first
CLS
PRINT
PRINT " TIC-TAC-TOE"
PRINT
PRINT "In this version, X always goes first."
PRINT "The board is numbered:"
DO
CompFirst = NOT CompFirst ' reverse who goes first
MovesCnt = 0
PRINT
DisplayNumberedBoard
PRINT
PRINT IIF(CompFirst, "I go first.", "You go first.")
ClearBoard
IF CompFirst THEN MyPiece = "X": HisPiece = "O" ELSE MyPiece = "O": HisPiece = "X"
' -1: human; 1: computer; 0: nobody
Mover = IIF(CompFirst, 1, -1)
WHILE Mover <> 0
SELECT CASE Mover
CASE 1
IF MovesCnt = 0 THEN
BestMove = INT(RND * 9)
ELSEIF MovesCnt = 1 THEN
BestMove = IIF(Board(4) <> " ", INT(RND * 2) * 6 + INT(RND * 2) * 2, 4)
ELSE
T = Evaluate(MyPiece, HisPiece)
END IF
Board(BestMove) = MyPiece
INC(MovesCnt)
PRINT
CALL DisplayPiecedBoard
PRINT
IF Win(MyPiece) THEN
INC(MyWinsCnt)
PRINT "I win!"
Mover = 0
ELSEIF SpacesFilled THEN
INC(DrawsCnt)
PRINT "It's a draw. Thank you."
Mover = 0
ELSE
Mover = -1
END IF
CASE -1
DO
INPUT "Where do you move? ",I
IF I < 1 OR I > 9 THEN
PRINT "Illegal! ";
ELSEIF Board(I - 1) <> " " THEN
PRINT "Place already occupied. ";
ELSE
EXIT DO
END IF
LOOP
Board(I - 1) = HisPiece
INC(MovesCnt)
PRINT
CALL DisplayPiecedBoard
PRINT
IF Win(HisPiece) THEN
INC(HisWinsCnt)
PRINT "You beat me! Good game."
Mover = 0
ELSEIF SpacesFilled THEN
INC(DrawsCnt)
PRINT "It's a draw. Thank you."
Mover = 0
ELSE
Mover = 1
END IF
END SELECT
WEND
PRINT
INPUT "Another game (y/n)? ", Answ$
LOOP UNTIL UCASE$(Answ$) <> "Y"
PRINT
PRINT "Final score:"
PRINT "You won "; HisWinsCnt; " game"; IIF(HisWinsCnt <> 1, "s.", ".")
PRINT "I won "; MyWinsCnt; " game"; IIF(MyWinsCnt <> 1, "s.", ".")
PRINT "We tied "; DrawsCnt; " game"; IIF(DrawsCnt <> 1, "s.", ".")
PRINT "See you later!"
END
 
SUB ClearBoard
FOR I = 0 TO 8: Board(I) = " ": NEXT I
END SUB
 
SUB DisplayNumberedBoard
FOR I = 0 TO 8 STEP 3
PRINT " "; I + 1; " | "; I + 2; " | "; I + 3
IF I <> 6 THEN PRINT "---+---+---"
NEXT I
END SUB
 
SUB DisplayPiecedBoard
FOR I = 0 TO 8 STEP 3
PRINT " "; Board(I); " | "; Board(I + 1); " | "; Board(I + 2)
IF I <> 6 THEN PRINT "---+---+---"
NEXT I
END SUB
 
FUNCTION Evaluate (Me AS STRING, Him AS STRING)
' Recursive algorithm
DIM I AS INTEGER, SafeMove AS INTEGER, V AS INTEGER, LoseFlag AS INTEGER
IF Win(Me) THEN Evaluate = 1: EXIT FUNCTION
IF Win(Him) THEN Evaluate = -1: EXIT FUNCTION
IF SpacesFilled THEN Evaluate = 0: EXIT FUNCTION
LoseFlag = 1
I = 0
WHILE I <= 8
IF Board(I) = " " THEN
Board(I) = Me ' Try the move.
V = Evaluate(Him, Me)
Board(I) = " " ' Restore the empty space.
IF V = -1 THEN BestMove = I: Evaluate = 1: EXIT FUNCTION
IF V = 0 THEN LoseFlag = 0: SafeMove = I
END IF
INC(I)
WEND
BestMove = SafeMove
Evaluate = -LoseFlag
END FUNCTION
 
FUNCTION SpacesFilled
FOR I = 0 TO 8
IF Board(I) = " " THEN SpacesFilled = 0: EXIT FUNCTION
NEXT I
SpacesFilled = -1
END FUNCTION
 
FUNCTION Win (Piece AS STRING)
FOR I = 0 TO 7
IF Board(WinPos(I, 0)) = Piece AND Board(WinPos(I, 1)) = Piece AND Board(WinPos(I, 2)) = Piece THEN Win = -1: EXIT FUNCTION
NEXT I
Win = 0
END FUNCTION
</syntaxhighlight>
 
==={{header|Run BASIC}}===
<syntaxhighlight lang="runbasic">' ---------------------------
' TIC TAC TOE
' ---------------------------
winBox$ = "123 456 789 159 147 258 369 357"
boxPos$ = "123 231 456 564 789 897 159 591 357 753 132 465 798 174 285 396 159 471 582 693 147 258 369 195 375"
ai$ = "519628374"
ox$ = "OX"
[newGame]
for i = 1 to 9
box$(i) = ""
next i
goto [shoTic]
 
[loop]
for j = 1 to 2
tic$ = mid$(ox$,j,1)
for i = 1 to 25
b$ = word$(boxPos$,i," ")
b1 = val(mid$(b$,1,1))
b2 = val(mid$(b$,2,1))
b3 = val(mid$(b$,3,1))
if box$(b1) = tic$ AND box$(b2) = tic$ AND box$(b3) = "" then
box$(b3) = "O"
goto [shoTic]
end if
next i
next j
if box$(1) = "O" AND box$(5) = "X" and box$(9) = "X" then
if box$(3) = "" then
box$(3) = "O"
goto [shoTic]
end if
if box$(7) = "" then
box$(7) = "O"
goto [shoTic]
end if
end if
for i = 1 to 9
b1 = val(mid$(ai$,i,1))
if box$(b1) = "" then
box$(b1) = "O"
exit for
end if
next i
 
[shoTic]
cls
' ----------------------------------------
' show tic tac toe screen
' ----------------------------------------
html "<table border=1 width=300px height=225px><TR>"
for i = 1 to 9
html "<td align=center width=33%><h1>"
if box$(i) <> "" then
html box$(i)
else
button #box, " ";box$(i);" ", [doTic]
#box setkey(str$(i))
end if
if i mod 3 = 0 then html "</tr><tr>"
next i
html "</table>"
gosub [checkWin]
wait
 
[doTic]
box$(val(EventKey$)) = "X"
turn = 1
gosub [checkWin]
goto [loop]
 
' --- check for a winner ----------
[checkWin]
for i = 1 to 8
b$ = word$(winBox$,i," ")
b1 = val(mid$(b$,1,1))
b2 = val(mid$(b$,2,1))
b3 = val(mid$(b$,3,1))
if box$(b1) = "O" and box$(b2) = "O" and box$(b3) = "O" then
print "You Lose!"
goto [playAgain]
end if
if box$(b1) = "X" and box$(b2) = "X" and box$(b3) = "X" then
print "You Win!"
goto [playAgain]
end if
next i
 
moveCount = 0
for i = 1 to 9
if box$(i) <> "" then moveCount = moveCount + 1
next i
if moveCount = 9 then
print "Draw!"
goto [playAgain]
end if
RETURN
 
[playAgain]
input "Play again (y/n)";p$
if upper$(p$) = "Y" then goto [newGame]
end</syntaxhighlight>
 
==={{Header|Tiny BASIC}}===
<syntaxhighlight lang="basic"> REM Tic-tac-toe for Tiny BASIC
REM
REM Released as public domain by Damian Gareth Walker, 2019
REM Created: 21-Sep-2019
REM --- Variables
REM A - first square in line examined
REM B - second square in line examined
REM C - third square in line examined
REM D - player whose pieces to count
REM E - number of DREM s pieces on a line
REM F - first square of line to examine
REM G - game winner
REM H - which side the human takes
REM I - increment for line to examine
REM L - line to examine
REM M - where to move (various uses)
REM N - piece found in a square
REM P - player currently playing
REM Q - square to examine
REM R-Z - contents of the board
 
REM --- Main Program
GOSUB 40
GOSUB 60
GOSUB 80
END
 
REM --- Subroutine to initialise the game
REM Outputs: H - Human play order
REM P - Whose turn it is
40 PRINT "Tic tac toe. Board positions are:"
PRINT " 1 2 3"
PRINT " 4 5 6"
PRINT " 7 8 9"
PRINT "Play first or second (1/2)?"
INPUT H
IF H<1 THEN GOTO 40
IF H>2 THEN GOTO 40
LET P=1
RETURN
 
REM --- Subroutine to take turns
REM Inputs: H - who is the human
REM P - whose turn it is
REM Outputs: G - who won the game
60 IF P=H THEN GOSUB 100
IF P<>H THEN GOSUB 120
GOSUB 200
IF G>0 THEN RETURN
LET P=3-P
IF R=0 THEN GOTO 60
IF S=0 THEN GOTO 60
IF T=0 THEN GOTO 60
IF U=0 THEN GOTO 60
IF V=0 THEN GOTO 60
IF W=0 THEN GOTO 60
IF X=0 THEN GOTO 60
IF Y=0 THEN GOTO 60
IF Z=0 THEN GOTO 60
RETURN
 
REM --- Victory
REM Inputs: H - which side was the human
REM P - player who won
80 IF G=H THEN PRINT "You win!"
IF G<>0 THEN IF G<>H THEN PRINT "Computer wins"
IF G=0 THEN PRINT "A draw"
RETURN
 
REM --- Subroutine to allow the player to move
REM Inputs: P - player number
REM Outputs: M - where the player wishes to move
100 PRINT "Move? "
INPUT Q
IF Q<1 THEN GOTO 100
IF Q>9 THEN GOTO 100
GOSUB 220
IF N<>0 THEN GOTO 100
LET M=Q
GOSUB 240
RETURN
 
REM --- Subroutine to make the computerREM s move
REM Inputs: P - player number
REM Outputs: M - the move chosen
120 LET M=0
LET D=3-H
GOSUB 145
IF M>0 THEN GOTO 135
LET D=H
GOSUB 145
IF M=0 THEN IF V=0 THEN LET M=5
IF M=0 THEN IF R=0 THEN LET M=1
IF M=0 THEN IF T=0 THEN LET M=3
IF M=0 THEN IF X=0 THEN LET M=7
IF M=0 THEN IF Z=0 THEN LET M=9
IF M=0 THEN IF S=0 THEN LET M=2
IF M=0 THEN IF U=0 THEN LET M=4
IF M=0 THEN IF Y=0 THEN LET M=8
IF M=0 THEN IF W=0 THEN LET M=6
135 GOSUB 240
PRINT "Computer move ",M
RETURN
 
REM --- Identify moves to win or avoid a loss
REM Inputs: D - player whose pieces weREM re counting
REM Changes: E - number of pieces on line being scanned
REM F - first square in winning line
REM I - increment of winning line
REM L - line being scanned (counter)
145 LET L=1
146 GOSUB 170
IF E<2 THEN GOTO 152
IF A=0 THEN LET M=F
IF B=0 THEN LET M=F+I
IF C=0 THEN LET M=F+I+I
IF M>0 THEN RETURN
152 LET L=L+1
IF L<9 THEN GOTO 146
RETURN
 
REM --- Count a playerREM s pieces on a line
REM Inputs: D - player whose pieces weREM re counting
REM L - line number
REM Changes: F - first square on the line
REM I - increment of the line
REM Q - individual squares to examine
REM Outputs: A - contents of first square
REM B - contents of second square
REM C - contents of third square
REM E - number of the playerREM s pieces
170 IF L>3 THEN GOTO 174
LET F=3*L-2
LET I=1
GOTO 180
174 IF L>6 THEN GOTO 178
LET F=L-3
LET I=3
GOTO 180
178 LET F=1+2*(L-7)
LET I=4-2*(L-7)
180 LET E=0
LET Q=F
GOSUB 220
LET A=N
IF N=D THEN LET E=E+1
LET Q=Q+I
GOSUB 220
LET B=N
IF N=D THEN LET E=E+1
LET Q=Q+I
GOSUB 220
LET C=N
IF N=D THEN LET E=E+1
RETURN
 
REM --- Subroutine to check for a win
REM Inputs: R-Z - board squares
REM Outputs: G - the winning player (0 for neither)
200 LET G=0
IF R>0 THEN IF R=S THEN IF S=T THEN LET G=R
IF U>0 THEN IF U=V THEN IF V=W THEN LET G=U
IF X>0 THEN IF X=Y THEN IF Y=Z THEN LET G=X
IF R>0 THEN IF R=U THEN IF U=X THEN LET G=R
IF S>0 THEN IF S=V THEN IF V=Y THEN LET G=S
IF T>0 THEN IF T=W THEN IF W=Z THEN LET G=T
IF R>0 THEN IF R=V THEN IF V=Z THEN LET G=R
IF T>0 THEN IF T=V THEN IF V=X THEN LET G=T
RETURN
 
REM --- Subroutine to see what piece is in a square
REM Inputs: Q - the square to check
REM R-Z - the contents of the squares
REM Outputs: N - the piece in that square
220 LET N=0
IF Q=1 THEN LET N=R
IF Q=2 THEN LET N=S
IF Q=3 THEN LET N=T
IF Q=4 THEN LET N=U
IF Q=5 THEN LET N=V
IF Q=6 THEN LET N=W
IF Q=7 THEN LET N=X
IF Q=8 THEN LET N=Y
IF Q=9 THEN LET N=Z
RETURN
 
REM --- Subroutine to put a piece in a square
REM Inputs: P - the player whose piece should be placed
REM M - the square to put the piece in
REM Changes: R-Z - the contents of the squares
240 IF M=1 THEN LET R=P
IF M=2 THEN LET S=P
IF M=3 THEN LET T=P
IF M=4 THEN LET U=P
IF M=5 THEN LET V=P
IF M=6 THEN LET W=P
IF M=7 THEN LET X=P
IF M=8 THEN LET Y=P
IF M=9 THEN LET Z=P
RETURN </syntaxhighlight>
 
==={{header|VBA}}===
Human play first with the "X". You must choose the row and the column you want to play...
<syntaxhighlight lang="vb">
Option Explicit
 
Private Lines(1 To 3, 1 To 3) As String
Private Nb As Byte, player As Byte
Private GameWin As Boolean, GameOver As Boolean
 
Sub Main_TicTacToe()
Dim p As String
 
InitLines
printLines Nb
Do
p = WhoPlay
Debug.Print p & " play"
If p = "Human" Then
Call HumanPlay
GameWin = IsWinner("X")
Else
Call ComputerPlay
GameWin = IsWinner("O")
End If
If Not GameWin Then GameOver = IsEnd
Loop Until GameWin Or GameOver
If Not GameOver Then
Debug.Print p & " Win !"
Else
Debug.Print "Game Over!"
End If
End Sub
 
Sub InitLines(Optional S As String)
Dim i As Byte, j As Byte
Nb = 0: player = 0
For i = LBound(Lines, 1) To UBound(Lines, 1)
For j = LBound(Lines, 2) To UBound(Lines, 2)
Lines(i, j) = "#"
Next j
Next i
End Sub
 
Sub printLines(Nb As Byte)
Dim i As Byte, j As Byte, strT As String
Debug.Print "Loop " & Nb
For i = LBound(Lines, 1) To UBound(Lines, 1)
For j = LBound(Lines, 2) To UBound(Lines, 2)
strT = strT & Lines(i, j)
Next j
Debug.Print strT
strT = vbNullString
Next i
End Sub
 
Function WhoPlay(Optional S As String) As String
If player = 0 Then
player = 1
WhoPlay = "Human"
Else
player = 0
WhoPlay = "Computer"
End If
End Function
 
Sub HumanPlay(Optional S As String)
Dim L As Byte, C As Byte, GoodPlay As Boolean
 
Do
L = Application.InputBox("Choose the row", "Numeric only", Type:=1)
If L > 0 And L < 4 Then
C = Application.InputBox("Choose the column", "Numeric only", Type:=1)
If C > 0 And C < 4 Then
If Lines(L, C) = "#" And Not Lines(L, C) = "X" And Not Lines(L, C) = "O" Then
Lines(L, C) = "X"
Nb = Nb + 1
printLines Nb
GoodPlay = True
End If
End If
End If
Loop Until GoodPlay
End Sub
 
Sub ComputerPlay(Optional S As String)
Dim L As Byte, C As Byte, GoodPlay As Boolean
 
Randomize Timer
Do
L = Int((Rnd * 3) + 1)
C = Int((Rnd * 3) + 1)
If Lines(L, C) = "#" And Not Lines(L, C) = "X" And Not Lines(L, C) = "O" Then
Lines(L, C) = "O"
Nb = Nb + 1
printLines Nb
GoodPlay = True
End If
Loop Until GoodPlay
End Sub
 
Function IsWinner(S As String) As Boolean
Dim i As Byte, j As Byte, Ch As String, strTL As String, strTC As String
 
Ch = String(UBound(Lines, 1), S)
'check lines & columns
For i = LBound(Lines, 1) To UBound(Lines, 1)
For j = LBound(Lines, 2) To UBound(Lines, 2)
strTL = strTL & Lines(i, j)
strTC = strTC & Lines(j, i)
Next j
If strTL = Ch Or strTC = Ch Then IsWinner = True: Exit For
strTL = vbNullString: strTC = vbNullString
Next i
'check diagonales
strTL = Lines(1, 1) & Lines(2, 2) & Lines(3, 3)
strTC = Lines(1, 3) & Lines(2, 2) & Lines(3, 1)
If strTL = Ch Or strTC = Ch Then IsWinner = True
End Function
 
Function IsEnd() As Boolean
Dim i As Byte, j As Byte
 
For i = LBound(Lines, 1) To UBound(Lines, 1)
For j = LBound(Lines, 2) To UBound(Lines, 2)
If Lines(i, j) = "#" Then Exit Function
Next j
Next i
IsEnd = True
End Function
</syntaxhighlight>
{{out}}
<pre>Loop 0
###
###
###
Human Play
Loop 1
X##
###
###
Computer Play
Loop 2
X#O
###
###
Human Play
Loop 3
X#O
#X#
###
Computer Play
Loop 4
XOO
#X#
###
Human Play
Loop 5
XOO
#X#
##X
Human Win !</pre>
 
==={{header|Yabasic}}===
In the classic style.
<syntaxhighlight lang="yabasic">5 REM Adaptation to Yabasic of the program published in Tim Hartnell's book "Artificial Intelligence: Concepts and Programs", with some minor modifications. 6/2018.
10 REM TICTAC
15 INPUT "English (0), Spanish (other key): " IDIOMA : IF NOT IDIOMA THEN RESTORE 2020 ELSE RESTORE 2010 END IF
20 GOSUB 1180: REM INICIALIZACION
30 REM *** REQUISITOS PREVIOS AL JUEGO ***
40 FOR J = 1 TO 9
50 A(J) = 32
60 NEXT J
70 FOR J = 1 TO 5
80 D(J) = 0
90 NEXT J
100 CCONTADOR = 0
110 R$ = ""
120 GOSUB 1070: REM IMPRESION DEL TABLERO
130 REM ** CICLO PRINCIPAL **
140 GOSUB 540: REM MOVIMIENTO DEL ORDENADOR
150 GOSUB 1070: REM IMPRESION DEL TABLERO
160 GOSUB 870: REM COMPRUEBA LA VICTORIA
170 IF R$ <> "" GOTO 240
180 GOSUB 980: REM SE ACEPTA EL MOVIMIENTO DE LA PERSONA
190 GOSUB 1070: REM IMPRESION DEL TABLERO
200 GOSUB 870: REM COMPRUEBA LA VICTORIA
210 IF R$ = "" GOTO 140
220 REM ** FIN DEL CICLO PRINCIPAL **
230 REM *****************************
240 REM FIN DEL JUEGO
250 GOSUB 1070: REM IMPRESION DEL TABLERO
260 PRINT: PRINT
270 IF R$ = "G" PRINT MENSAJE$(1): BANDERA = -1
280 IF R$ = "P" PRINT MENSAJE$(2): BANDERA = 1
290 IF R$ = "D" PRINT MENSAJE$(3): GOTO 430
300 REM ACTUALIZACION DE LA BASE DE DATOS
310 FOR B = 1 TO 5
320 FOR J = 2 TO 9
330 IF M(J) = D(B) GOSUB 370
340 NEXT J
350 NEXT B
360 GOTO 430
370 REM ** REORDENACION DE LOS ELEMENTOS DE LA MATRIZ M **
380 TEMP = M(J + BANDERA)
390 M(J + BANDERA) = M(J)
400 M(J) = TEMP
410 J = 9
420 RETURN
430 PRINT: PRINT
440 PRINT MENSAJE$(4)
450 PRINT: PRINT
460 FOR J = 1 TO 9
470 PRINT M(J), " ";
480 NEXT J
490 PRINT: PRINT
500 PRINT MENSAJE$(5)
510 INPUT A$
520 GOTO 30
530 REM ************************
540 REM MOVIMIENTO DEL ORDENADOR
550 P = ASC("O")
560 X = 0
570 J = 1
580 IF A(W(J)) = A(W(J + 1)) AND A(W(J + 2)) = 32 AND A(W(J)) = P X = W(J + 2): GOTO 750
590 IF A(W(J)) = A(W(J + 2)) AND A(W(J + 1)) = 32 AND A(W(J)) = P X = W(J + 1): GOTO 750
600 IF A(W(J + 1)) = A(W(J + 2)) AND A(W(J)) = 32 AND A(W(J + 1)) = P X = W(J): GOTO 750
610 IF J < 21 J = J + 3: GOTO 580
620 IF P = ASC("O") P = ASC("X"): GOTO 570
630 REM ** SI NO SE GANA SE BUSCA UN MOVIMIENTO DE BLOQUEO **
640 REM * ENTONCES SE USA LA SIGUIENTE SECCION *
650 J = 1
660 IF A(M(J)) = 32 X = M(J): GOTO 750
670 IF J < 10 J = J + 1: GOTO 660
680 H = 0
690 H = H + 1
700 X = INT(RAN(1) * 9): IF A(X) = 32 GOTO 750
710 IF H < 100 GOTO 690
720 R$ = "D": REM ES SIMPLEMENTE UN DIBUJO
730 RETURN
740 REM *********************
750 REM REALIZA EL MOVIMIENTO
760 A(X) = ASC("O")
770 CCONTADOR = CCONTADOR + 1
780 D(CCONTADOR) = X
790 BANDERA = 0
800 FOR J = 1 TO 9
810 IF A(J) = 32 BANDERA = 1
820 NEXT J
830 IF BANDERA = 0 AND R$ = "" R$ = "D"
840 REM SI TODAS LAS CASILLAS ESTAN LLENAS Y R$ ESTA VACIO, ENTONCES ES SIMPLEMENTE UN DIBUJO
850 RETURN
860 REM *********************
870 REM COMPRUEBA LA VICTORIA
880 J = 1
890 IF A(W(J)) = 32 J = J + 3
900 IF J > 23 RETURN
910 IF A(W(J)) = A(W(J + 1)) AND A(W(J)) = A(W(J + 2)) GOTO 940
920 IF J < 22 J = J + 3: GOTO 890
930 RETURN
940 IF A(W(J)) = ASC("O") R$ = "G": REM EL ORDENADOR GANA
950 IF A(W(J)) = ASC("X") R$ = "P": REM EL ORDENADOR PIERDE
960 RETURN
970 REM ************************
980 REM MOVIMIENTO DE LA PERSONA
990 PRINT: PRINT
1000 PRINT MENSAJE$(6)
1010 PRINT MENSAJE$(7); : INPUT MOVIMIENTO
1020 IF MOVIMIENTO < 1 OR MOVIMIENTO > 9 GOTO 1010
1030 IF A(MOVIMIENTO) <> 32 GOTO 1010
1040 A(MOVIMIENTO) = ASC("X")
1050 RETURN
1060 REM *********************
1070 REM IMPRESION DEL TABLERO
1080 CLEAR SCREEN
1090 PRINT: PRINT: PRINT
1100 PRINT " 1 : 2 : 3 ", CHR$(A(1)), " : ", CHR$(A(2)), " : ", CHR$(A(3))
1110 PRINT "----------- ------------"
1120 PRINT " 4 : 5 : 6 ", CHR$(A(4)), " : ", CHR$(A(5)), " : ", CHR$(A(6))
1130 PRINT "----------- ------------"
1140 PRINT " 7 : 8 : 9 ", CHR$(A(7)), " : ", CHR$(A(8)), " : ", CHR$(A(9))
1150 PRINT
1160 RETURN
1170 REM **************
1180 REM INICIALIZACION
1190 CLEAR SCREEN
1200 DIM A(9) : REM TABLERO
1210 DIM M(10) : REM ACCESO A LA BASE DE DATOS
1220 DIM W(24) : REM DATOS DE VICTORIA O BLOQUEO
1230 DIM D(5) : REM ACCESO AL MOVIMIENTO EN EL JUEGO ACTUAL
1235 DIM MENSAJE$(1) : READ M$ : N = TOKEN(M$,MENSAJE$(),",") : RESTORE
1240 REM DATOS DE VICTORIA O BLOQUEO
1250 FOR J = 1 TO 24
1260 READ W(J)
1270 NEXT J
1280 DATA 1, 2, 3, 4, 5, 6, 7, 8, 9
1290 DATA 1, 4, 7, 2, 5, 8, 3, 6, 9
1300 DATA 1, 5, 9, 3, 5, 7
1310 REM BASE INICIAL DE DATOS
1320 FOR J = 1 TO 10
1330 READ M(J)
1340 NEXT J
1350 DATA 2, 6, 8, 4, 7, 3, 1, 9, 5, 2
1360 RETURN
2000 REM MENSAJES EN ESPAÑOL
2010 DATA "YO GANO,TU GANAS,ES SIMPLEMENTE UN DIBUJO,ESTA ES MI PRIORIDAD ACTUALIZADA,PULSE LA TECLA <RETURN> PARA CONTINUAR,REALICE SU MOVIMIENTO,MOVIMIENTO: "
2020 DATA "I WIN,YOU WIN,IT'S JUST A DRAWING,THIS IS MY PRIORITY UPDATE,PRESS <RETURN> TO CONTINUE,TO MAKE YOUR MOVE,MOVEMENT: "
</syntaxhighlight>
 
=={{header|Batch File}}==
This is just a game between two human players.
<langsyntaxhighlight lang="dos">@echo off
setlocal enabledelayedexpansion
:newgame
Line 1,567 ⟶ 3,183:
pause
goto newgame
</syntaxhighlight>
</lang>
===Advanced===
This code makes a version of Tic Tac Toe with more features:
<langsyntaxhighlight lang="dos">@ECHO OFF
:BEGIN
REM Skill level
Line 1,890 ⟶ 3,506:
set t7=
set t8=
set t9=</langsyntaxhighlight>
 
=={{header|Befunge}}==
Line 1,897 ⟶ 3,513:
Plays reasonably well, but not perfectly, so can be beaten.
 
<langsyntaxhighlight Befungelang="befunge">v123456789 --- >9 >48*,:55+\-0g,1v
>9>066+0p076+0p^ ^,," |"_v#%3:- <
:,,0537051v>:#,_$#^5#,5#+<>:#v_55+
Line 1,911 ⟶ 3,527:
>"yM">:#,_$ :. 1234+++, 789*+ \0^<
"a s't"98:*+>:#,_$@>365*+"ward"48*
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,957 ⟶ 3,573:
=={{header|C}}==
Opening alternates between human and computer. Computer never loses.
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <stdlib.h>
 
Line 2,059 ⟶ 3,675:
while (1) printf("%s", game(first = !first));
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp}}==
Line 2,065 ⟶ 3,681:
It tries to show a number of C# code features while still keeping each function small and understandable.
 
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 2,310 ⟶ 3,926:
}
 
}</langsyntaxhighlight>
 
{{out}}
Line 2,356 ⟶ 3,972:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">
#include <windows.h>
#include <iostream>
Line 2,536 ⟶ 4,152:
}
//--------------------------------------------------------------------------------------------------
</syntaxhighlight>
</lang>
{{out}} Computer plays 'X' and human plays 'O'
<pre>
Line 2,549 ⟶ 4,165:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">
(defun generate-board ()
(loop repeat 9 collect nil))
Line 2,642 ⟶ 4,258:
(format t "The winner is ~a!" (find-winner board))
(format t "It's a tie.")))))
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,671 ⟶ 4,287:
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.stdio, std.string, std.algorithm, std.conv, std.random,
std.ascii, std.array, std.range, std.math;
 
Line 2,785 ⟶ 4,401:
break;
}
}</langsyntaxhighlight>
{{out}}
<pre>Tic-tac-toe game player.
Line 2,829 ⟶ 4,445:
 
You win!</pre>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
This is a GUI, event driven version of the game. The game board is a "TStringGrid" component, which has a grid that can hold and display characters. In this case, the grid displays Xs and Ox using a large font.
 
When the user clicks on the grid, this generates an event that is handled by the program. The mouse click coordinates are converted to a cell coordinates and a large X is placed in the box. At this point program tests if this resulted in a win. Next it calculate the computer's response and it checks to see if the computer won. The process is repeated until there is a winner or a draw.
 
[[File:DelphiTicTacToe.png|frame|none]]
 
<syntaxhighlight lang="Delphi">
{Array contain possiple winning lines}
 
type TWinLine = array [0..3-1] of TPoint;
 
var WinLines: array [0..8-1] of TWinLine = (
((X:0; Y:0), (X:1; Y:0), (X:2; Y:0)),
((X:0; Y:1), (X:1; Y:1), (X:2; Y:1)),
((X:0; Y:2), (X:1; Y:2), (X:2; Y:2)),
((X:0; Y:0), (X:0; Y:1), (X:0; Y:2)),
((X:1; Y:0), (X:1; Y:1), (X:1; Y:2)),
((X:2; Y:0), (X:2; Y:1), (X:2; Y:2)),
((X:0; Y:0), (X:1; Y:1), (X:2; Y:2)),
((X:2; Y:0), (X:1; Y:1), (X:0; Y:2))
);
 
 
{Array containing all characters in a line}
 
type TCellArray = array [0..3-1] of char;
 
var WinLineInx: integer;
var GameOver: boolean;
 
procedure ClearGrid;
{Clear TTT Grid by setting all cells to a space}
var X,Y: integer;
begin
with TicTacToeDlg do
begin
for Y:=0 to GameGrid.RowCount-1 do
for X:=0 to GameGrid.ColCount-1 do GameGrid.Cells[X,Y]:=' ';
WinLineInx:=-1;
Status1Dis.Caption:='';
GameOver:=False;
end;
 
end;
 
 
function FirstEmptyCell(var P: TPoint): boolean;
{Find first empty grid i.e. the one containing a space}
{Returns false if there are no empty cells (a tie game)}
var X,Y: integer;
begin
Result:=True;
with TicTacToeDlg do
begin
{Iterate through all cells in array}
for Y:=0 to GameGrid.RowCount-1 do
for X:=0 to GameGrid.ColCount-1 do
if GameGrid.Cells[X,Y]=' ' then
begin
P.X:=X; P.Y:=Y;
Exit;
end;
end;
Result:=False;
end;
 
 
 
procedure GetLineChars(Inx: integer; var CA: TCellArray);
{Get all the characters in a specific win line}
var P1,P2,P3: TPoint;
begin
with TicTacToeDlg do
begin
{Get cell position of specific win line}
P1:=WinLines[Inx,0];
P2:=WinLines[Inx,1];
P3:=WinLines[Inx,2];
{Get the characters from each and put in array}
CA[0]:=GameGrid.Cells[P1.X,P1.Y][1];
CA[1]:=GameGrid.Cells[P2.X,P2.Y][1];
CA[2]:=GameGrid.Cells[P3.X,P3.Y][1];
end;
end;
 
 
 
function IsWinner(var Inx: integer; var C: char): boolean;
{Test if the specified line is a winner}
{Return index of line and the char of winner}
var I,J: integer;
var CA: TCellArray;
begin
with TicTacToeDlg do
begin
Result:=False;
{Go through all winning patterns}
for J:=0 to High(WinLines) do
begin
{Get one winning pattern}
GetLineChars(J,CA);
{Look for line that has the same char in all three places}
if (CA[0]<>' ') and (CA[0]=CA[1]) and (CA[0]=CA[2]) then
begin
Result:=True;
Inx:=J;
C:=CA[0];
end;
end;
 
end;
end;
 
 
procedure DrawWinLine(Inx: integer);
{Draw line through winning squares}
var Line: TWinLine;
var C1,C2: TPoint;
var P1,P2: TPoint;
var W2,H2: integer;
begin
with TicTacToeDlg do
begin
{Offset to center of cell}
W2:=GameGrid.ColWidths[0] div 2;
H2:=GameGrid.RowHeights[0] div 2;
{Get winning pattern of lines}
Line:=WinLines[Inx];
{Get beginning and ending cell of win}
C1:=Line[0]; C2:=Line[2];
{Convert to screen coordinates}
P1.X:=C1.X * GameGrid.ColWidths[0] + W2;
P1.Y:=C1.Y * GameGrid.RowHeights[0] + H2;
P2.X:=C2.X * GameGrid.ColWidths[0] + W2;
P2.Y:=C2.Y * GameGrid.RowHeights[0] + H2;
{Set line attributes}
GameGrid.Canvas.Pen.Color:=clRed;
GameGrid.Canvas.Pen.Width:=5;
{Draw line}
GameGrid.Canvas.MoveTo(P1.X,P1.Y);
GameGrid.Canvas.LineTo(P2.X,P2.Y);
end;
end;
 
 
 
procedure DoBestComputerMove;
{Analyze game board and execute the best computer move}
var I,J,Inx: integer;
var CA: TCellArray;
var P: TPoint;
 
 
function UrgentMove(CA: TCellArray; var EmptyInx: integer): boolean;
{Test row, column or diagonal for an urgent move}
{This would be either an immediate win or immediate loss}
{Returns True if there is an urgent move and the index of location to respond}
var I: integer;
var OCnt,XCnt,EmptyCnt: integer;
begin
Result:=False;
OCnt:=0; XCnt:=0;
EmptyCnt:=0; EmptyInx:=-1;
{Count number of Xs, Os or Spaces in line}
for I:=0 to High(CA) do
begin
case CA[I] of
'O': Inc(OCnt);
'X': Inc(XCnt);
' ':
begin
Inc(EmptyCnt);
if EmptyCnt=1 then EmptyInx:=I;
end;
end;
end;
{Look for pattern of one empty and two Xs or two Os}
{Which means it's one move away from a win}
Result:=(EmptyCnt=1) and ((OCnt=2) or (XCnt=2));
end;
 
 
begin
with TicTacToeDlg do
begin
{Look for urgent moves in all patterns of wins}
for J:=0 to High(WinLines) do
begin
{Get a winning pattern of chars}
GetLineChars(J,CA);
if UrgentMove(CA,Inx) then
begin
{Urgent move found - take it}
P:=WinLines[J,Inx];
GameGrid.Cells[P.X,P.Y]:='O';
exit;
end;
end;
{No urgent moves, so use first empty}
{If there is no empty, the game is stalemated}
if FirstEmptyCell(P) then GameGrid.Cells[P.X,P.Y]:='O';
end;
end;
 
 
function TestWin: boolean;
{Test if last move resulted in win/draw}
var Inx: integer; var C: char;
var P: TPoint;
var S: string;
begin
Result:=True;
{Test if somebody won}
if IsWinner(Inx,C) then
begin
WinLineInx:=Inx;
TicTacToeDlg.GameGrid.Invalidate;
if C='O' then S:=' Computer Won!!' else S:=' You Won!!';
TicTacToeDlg.Status1Dis.Caption:=S;
GameOver:=True;
exit;
end;
{Test if game is a draw}
if not FirstEmptyCell(P) then
begin
TicTacToeDlg.Status1Dis.Caption:=' Game is Draw.';
GameOver:=True;
exit;
end;
Result:=False;
end;
 
 
procedure PlayTicTacToe;
{Show TicTacToe dialog box}
begin
ClearGrid;
TicTacToeDlg.ShowModal
end;
 
 
 
procedure TTicTacToeDlg.GameGridMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
{Handle user click on TicTacToe grid}
var Row,Col: integer;
begin
with TicTacToeDlg do
begin
if GameOver then exit;;
{Convert Mouse X,Y to Grid row and column}
GameGrid.MouseToCell(X,Y,Col,Row);
{Mark user's selection by placing X in the cell}
if GameGrid.Cells[Col,Row]=' 'then
GameGrid.Cells[Col,Row]:='X';
{Did this result in a win? }
if TestWin then exit;
{Get computer's response}
DoBestComputerMove;
{Did computer win}
TestWin;
end;
end;
 
procedure TTicTacToeDlg.ReplayBtnClick(Sender: TObject);
begin
ClearGrid;
end;
 
 
 
procedure TTicTacToeDlg.GameGridDrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
{Draw winner line on top of Xs and Os}
begin
if WinLineInx>=0 then DrawWinLine(WinLineInx);
end;
 
 
 
</syntaxhighlight>
{{out}}
<pre>
 
Elapsed Time: 19.126 Sec.
 
</pre>
 
=={{header|EasyLang}}==
Line 2,834 ⟶ 4,741:
It uses minimax with alpha-beta pruning. Therefore, the computer never loses.
 
[https://easylang.onlinedev/apps/tictactoe.html Run it]
 
<syntaxhighlight>
<lang>len f[] 9
len f[] 9
state = 0
textsize 14
#
funcproc init . .
linewidth 2
clear
color 666
move 34 496
line 34 8020
move 62 496
line 62 8020
move 10 2872
line 86 2872
move 10 5644
line 86 5644
linewidth 2.5
for i range= 1 to 9
f[i] = 0
.
if state = 1
timer 0.2
.
.
funcproc draw ind . .
c = (ind - 1) mod 3
r = (ind - 1) div 3
x = c * 28 + 20
y = r * 28 + 1430
if f[ind] = 4
color 900
move x - 7 y - 7
line x + 7 y + 7
move x + 7 y - 7
line x - 7 y + 7
elif f[ind] = 1
color 009
move x y
circle 10
color -2
circle 7.5
.
.
funcproc sum3 a d . st .
for i range= 1 to 3
s += f[a]
a += d
.
if s = 3
st = -1
elif s = 12
st = 1
.
.
funcproc rate . res done .
res = 0
for i range= 1 step 3 to 7
call sum3 i * 3 1 res
.
for i range= 1 to 3
call sum3 i 3 res
.
call sum3 01 4 res
call sum3 23 2 res
cnt = 1
for i range= 1 to 9
if f[i] = 0
cnt += 1
.
.
res *= cnt
done = 1
if res = 0 and cnt > 1
done = 0
.
.
funcproc minmax player alpha beta . rval rmov .
call rate rval done
if done = 1
if player = 1
rval = -rval
.
else
rval = alpha
start = randomrandint 9
mov = start
repeat
if f[mov] = 0
f[mov] = player
call minmax (5 - player) (-beta) (-rval) val h
val = -val
f[mov] = 0
if val > rval
rval = val
rmov = mov
.
.
mov = mov mod 9 + 1
until mov = start or rval >= beta
.
.
mov = (mov + 1) mod 9
until mov = start or rval >= beta
.
.
.
funcproc show_result val . .
color 555
move 16 844
if val < 0
# this never happens
text "You won"
elif val > 0
text "You lost"
else
text "Tie"
.
state += 2
.
funcproc computer . .
call minmax 4 -11 11 val mov
f[mov] = 4
call draw mov
call rate val done
state = 0
if done = 1
call show_result val
.
.
funcproc human . .
mov = floor ((mouse_x - 6) / 28) + 3 * floor ((mouse_y - 16) / 28) + 1
if f[mov] = 0
f[mov] = 1
call draw mov
state = 1
timer 0.5
.
.
on timer
call rate val done
if done = 1
call show_result val
else
call computer
.
.
on mouse_down
if state = 0
if mouse_x > 6 and mouse_x < 90 and mouse_y <> 8416
call human
.
elif state >= 2
state -= 2
call init
.
.
call init</lang>
</syntaxhighlight>
 
=={{header|Erlang}}==
The program will randomly chose if the computer ("X") or the user ("O") starts. The computer look ahead is only one level. Perhaps the computer might lose?
<syntaxhighlight lang="erlang">
<lang Erlang>
-module(tic_tac_toe).
 
Line 3,098 ⟶ 5,007:
turn_next_move_ok( true, _Prompt, _Ns, N ) -> N;
turn_next_move_ok( false, Prompt, Ns, _N ) -> turn_next_move( Prompt, Ns ).
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,384 ⟶ 5,293:
{{works with|OpenEuphoria}}
No computer AI
<langsyntaxhighlight lang="euphoria">
include std/console.e
include std/text.e
Line 3,485 ⟶ 5,394:
 
end while
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,583 ⟶ 5,492:
A purely-functional solution with a naive (but perfect) computer player implementation. The first move is played randomly by the computer.
 
<langsyntaxhighlight lang="fsharp">type Brick =
| Empty
| Computer
Line 3,715 ⟶ 5,624:
let b = set Computer emptyBoard (choose (freeSpace emptyBoard))
printBoard b
gameLoop b User</langsyntaxhighlight>
 
Example game:
Line 3,787 ⟶ 5,696:
Game over. I have won.
</pre>
 
 
 
=={{header|Forth}}==
{{works with|gforth|0.7.3}}
Game between two humans.
 
<syntaxhighlight lang="forth">create board 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
 
\ board: 0=empty, 1=player X, 2=player O
: player. ( player -- ) C" XO" 1+ + @ emit ;
: spot ( n -- addr ) cells board + ;
: clean-board ( -- ) 9 0 do 0 i spot ! loop ;
: show-board
CR ." +---+---+---+ +---+---+---+" CR
3 0 do
." | "
3 0 do
i j 3 * + spot @ player. ." | "
loop
." | "
3 0 do
i j 3 * + . ." | "
loop
CR ." +---+---+---+ +---+---+---+" CR
loop ;
 
: spots-equal ( n1 n2 n3 -- f )
over spot @ swap spot @ = >r spot @ swap spot @ = r> and ;
: spots-win ( n1 n2 n3 -- f )
dup >r spots-equal r> spot @ 0<> and ;
 
: winner-check ( -- player )
0 1 2 spots-win if 0 spot @ exit then
3 4 5 spots-win if 3 spot @ exit then
6 7 8 spots-win if 6 spot @ exit then
0 3 6 spots-win if 0 spot @ exit then
1 4 7 spots-win if 1 spot @ exit then
2 5 8 spots-win if 2 spot @ exit then
0 4 8 spots-win if 0 spot @ exit then
2 4 6 spots-win if 2 spot @ exit then
0 ;
 
: player-move ( player -- )
begin
key dup emit [char] 0 - dup
spot @ 0= if spot ! exit else drop then
again ;
 
: game
clean-board show-board
9 0 do
i 2 mod 1+ dup ." Player " player. ." : "
player-move show-board
winner-check dup 0<> if player. ." wins !" unloop exit else drop then
loop
." Draw!" ;
 
game
</syntaxhighlight>
 
{{out}}
<pre>
+---+---+---+ +---+---+---+
| | | | | 0 | 1 | 2 |
+---+---+---+ +---+---+---+
| | | | | 3 | 4 | 5 |
+---+---+---+ +---+---+---+
| | | | | 6 | 7 | 8 |
+---+---+---+ +---+---+---+
Player X: 0
+---+---+---+ +---+---+---+
| X | | | | 0 | 1 | 2 |
+---+---+---+ +---+---+---+
| | | | | 3 | 4 | 5 |
+---+---+---+ +---+---+---+
| | | | | 6 | 7 | 8 |
+---+---+---+ +---+---+---+
Player O: 3
+---+---+---+ +---+---+---+
| X | | | | 0 | 1 | 2 |
+---+---+---+ +---+---+---+
| O | | | | 3 | 4 | 5 |
+---+---+---+ +---+---+---+
| | | | | 6 | 7 | 8 |
+---+---+---+ +---+---+---+
Player X: 1
+---+---+---+ +---+---+---+
| X | X | | | 0 | 1 | 2 |
+---+---+---+ +---+---+---+
| O | | | | 3 | 4 | 5 |
+---+---+---+ +---+---+---+
| | | | | 6 | 7 | 8 |
+---+---+---+ +---+---+---+
Player O: 4
+---+---+---+ +---+---+---+
| X | X | | | 0 | 1 | 2 |
+---+---+---+ +---+---+---+
| O | O | | | 3 | 4 | 5 |
+---+---+---+ +---+---+---+
| | | | | 6 | 7 | 8 |
+---+---+---+ +---+---+---+
Player X: 2
+---+---+---+ +---+---+---+
| X | X | X | | 0 | 1 | 2 |
+---+---+---+ +---+---+---+
| O | O | | | 3 | 4 | 5 |
+---+---+---+ +---+---+---+
| | | | | 6 | 7 | 8 |
+---+---+---+ +---+---+---+
X wins ! ok
</pre>
 
 
 
 
=={{header|Fortran}}==
Objective: write program in less than 100 lines, not using semicolons. Computer never loses, but plays as random as possible. Player gets first move of first game. Afterwards, first move alternates between computer and player.
<langsyntaxhighlight lang="fortran">
! This is a fortran95 implementation of the game of tic-tac-toe.
! - Objective was to use less than 100 lines.
Line 3,890 ⟶ 5,915:
enddo mainloop
end program
</syntaxhighlight>
</lang>
=={{header|FreeBASIC}}==
===graphics mode===
<lang freebasic>
 
'About 400 lines of code, but it is a graphical (GUI ish) i.e. mouse driven.
'I have made provision for the player to beat the computer now and then.
 
 
Type box
As long x,y
As long wide,high,index
Dim As ulong colour
As String caption
Declare Sub show
Declare Sub NewCaption(s As String)
Declare Constructor
Declare Constructor(x As long,y As long,wide As long,_
high As long,index As long,colour As ulong,caption As String)
End Type
Constructor box
End Constructor
Constructor box(x As long,y As long,wide As long,_
high As long,index As long,colour As ulong,caption As String)
this.x=x
this.y=y
this.wide=wide
this.high=high
this.index=index
this.colour=colour
this.caption=caption
End Constructor
'ALL PROCEDURES:
Declare Function inside(B As box,px As long,py As long) As long
Declare Sub make_frame_image(im As ulong Pointer)
Declare Sub setup_grid(boxes() As box,cellsacross As long,cellsdown As long,xp As long,yp As long,w As long,h As long)
Declare Function all_clicked(b() As box) As long
Declare Sub OnCLICK(a() As box,b As box)
Declare Sub refresh_screen(b() As box,f1 As long=0,f2 As long=0)
Declare Function Get_Mouse_Events(boxes() As box) As long
Declare Sub thickline(x1 As long,y1 As long,x2 As long,y2 As long,thickness As Single,colour As ulong,im As Any Pointer=0)
Declare Sub lineto(x1 As long,y1 As long,x2 As long,y2 As long,l As long,th As Single,col As ulong,im As Any Pointer=0)
Declare Sub thickcircle(x As long,y As long,rad As long,th As Single,col As ulong,im As Any Pointer=0)
Declare Sub startup(b() As box)
Declare Sub get_computer_events(b() As box)
 
Declare Sub finish
'Macro used by more than one procedure
#macro incircle(cx,cy,radius,x,y)
(cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
#endmacro
'=============== RUN ============================
Screen 19,32',1,16
Color ,Rgb(233,236,216) 'background colour
windowtitle string(100," ")+"Noughts and crosses"
'Globals:
Dim Shared As ulong Pointer frame
Dim Shared As long computer,player
Dim Shared As String msg1,msg2,message
message="In Play"
msg1="Computer Start"
msg2="Player Start"
'Custom Frame
frame=Imagecreate(800,600)
 
Dim As box boxes(0 To 9)
 
setup_grid(boxes(),3,3,175,85,150,150)
make_frame_image(frame)
 
Do
If player=0 And computer=0 Then
startup(boxes())
End If
If player Then
Get_Mouse_Events(boxes())
End If
If computer Then
get_computer_events(boxes())
End If
If all_clicked(boxes()) Then get_computer_events(boxes())
Loop Until Inkey=Chr(27)
finish
 
Sub box.show
Line(this.x,this.y)-(this.x+this.wide,this.y+this.high),this.colour,bf
Line(this.x,this.y)-(this.x+this.wide,this.y+this.high),Rgb(200,200,200),b
''Draw String(this.x+.5*this.wide-4*Len(this.caption),this.y+(.5*this.high-4)),this.caption,Rgb(0,0,0)
If this.index=0 Then
Draw String(this.x+.5*this.wide-4*Len(this.caption),this.y+.5*this.high-6),this.caption,Rgb(0,0,0)
End If
End Sub
Sub box.NewCaption(s As String)
Var cx=(this.x+this.x+this.wide)/2
Var cy=(this.y+this.y+this.high)/2
If s="X" Then
For k As long=20 To 0 Step -1
lineto(cx,cy,this.x,this.y,50,k,Rgb(50+10*k,5*k,0),frame)
lineto(cx,cy,this.x+this.wide,this.y+this.high,50,k,Rgb(50+10*k,5*k,0),frame)
lineto(cx,cy,this.x,this.y+this.high,50,k,Rgb(50+10*k,5*k,0),frame)
lineto(cx,cy,this.x+this.wide,this.y,50,k,Rgb(50+10*k,5*k,0),frame)
Next k
Else
For k As long=20 To 0 Step -1
thickcircle(cx,cy,40,k,Rgb(50+10*k,5*k,0),frame)
Next k
End If
End Sub
Sub get_computer_events(b() As box)
#define other(n) b(n).caption<>"0" And b(n).caption<>"C"
#define another(n) b(n).caption="0"
#define rr(f,l) (Rnd*((l)-(f))+(f))
Dim As long flag,i,k,Cwin,Pwin,NoWin
Static As long firstclick
var chance="001100"
dim as long ch
'horiz player finish
For x As long=1 To 3
If b(1+k).caption="0" And b(2+k).caption="0" And another((3+k)) Then b(3+k).Caption="0":Pwin=1:Goto fin
If b(2+k).caption="0" And b(3+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1=1:Goto fin
If b(1+k).caption="0" And b(3+k).caption="0" And another((2+k))Then b(2+k).Caption="0":Pwin=1:Goto fin
k=k+3
Next x
k=0
'vert player finish
For x As long=1 To 3
If b(1+k).caption="0" And b(4+k).caption="0" And another((7+k)) Then b(7+k).Caption="0":Pwin=1:Goto fin
If b(4+k).caption="0" And b(7+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1:Goto fin
If b(1+k).caption="0" And b(7+k).caption="0" And another((4+k))Then b(4+k).Caption="0":Pwin=1:Goto fin
k=k+1
Next x
k=0
'player finish main diag
If b(1+k).caption="0" And b(5+k).caption="0" And another((9+k)) Then b(9+k).Caption="0":Pwin=1:Goto fin
If b(1+k).caption="0" And b(9+k).caption="0" And another((5+k))Then b(5+k).Caption="0":Pwin=1:Goto fin
If b(5+k).caption="0" And b(9+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1:Goto fin
'player finish other diag
If b(7+k).caption="0" And b(5+k).caption="0" And another((3+k)) Then b(3+k).Caption="0":Pwin=1:Goto fin
If b(5+k).caption="0" And b(3+k).caption="0" And another((7+k))Then b(7+k).Caption="0":Pwin=1:Goto fin
If b(7+k).caption="0" And b(3+k).caption="0" And another((5+k))Then b(5+k).Caption="0":Pwin=1:Goto fin
'horiz computer finish
For x As long=1 To 3
If b(1+k).caption="C" And b(2+k).caption="C" And other((3+k)) Then b(3+k).Caption="C":Cwin=1:Goto fin
If b(2+k).caption="C" And b(3+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
If b(1+k).caption="C" And b(3+k).caption="C" And other((2+k))Then b(2+k).Caption="C":Cwin=1:Goto fin
k=k+3
Next x
k=0
'vert computer finish
For x As long=1 To 3
If b(1+k).caption="C" And b(4+k).caption="C" And other((7+k)) Then b(7+k).Caption="C":Cwin=1:Goto fin
If b(4+k).caption="C" And b(7+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
If b(1+k).caption="C" And b(7+k).caption="C" And other((4+k))Then b(4+k).Caption="C":Cwin=1:Goto fin
k=k+1
Next x
k=0
'computer finish main diag
If b(1+k).caption="C" And b(5+k).caption="C" And other((9+k)) Then b(9+k).Caption="C":Cwin=1:Goto fin
If b(1+k).caption="C" And b(9+k).caption="C" And other((5+k))Then b(5+k).Caption="C":Cwin=1:Goto fin
If b(5+k).caption="C" And b(9+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
'computer finish other diag
If b(7+k).caption="C" And b(5+k).caption="C" And other((3+k)) Then b(3+k).Caption="C":Cwin=1:Goto fin
If b(5+k).caption="C" And b(3+k).caption="C" And other((7+k))Then b(7+k).Caption="C":Cwin=1:Goto fin
If b(7+k).caption="C" And b(3+k).caption="C" And other((5+k))Then b(5+k).Caption="C":Cwin=1:Goto fin
'block horizontals
For x As long=1 To 3
If b(1+k).caption="0" And b(2+k).caption="0" And other((3+k)) Then b(3+k).Caption="C":flag=1:Goto fin
If b(2+k).caption="0" And b(3+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
If b(1+k).caption="0" And b(3+k).caption="0" And other((2+k))Then b(2+k).Caption="C":flag=1:Goto fin
k=k+3
Next x
k=0
'block verticals
For x As long=1 To 3
If b(1+k).caption="0" And b(4+k).caption="0" And other((7+k)) Then b(7+k).Caption="C":flag=1:Goto fin
If b(4+k).caption="0" And b(7+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
If b(1+k).caption="0" And b(7+k).caption="0" And other((4+k))Then b(4+k).Caption="C":flag=1:Goto fin
k=k+1
Next x
k=0
'block main diag
If b(1+k).caption="0" And b(5+k).caption="0" And other((9+k)) Then b(9+k).Caption="C":flag=1:Goto fin
If b(1+k).caption="0" And b(9+k).caption="0" And other((5+k))Then b(5+k).Caption="C":flag=1:Goto fin
If b(5+k).caption="0" And b(9+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
'block other diag
If b(7+k).caption="0" And b(5+k).caption="0" And other((3+k)) Then b(3+k).Caption="C":flag=1:Goto fin
If b(5+k).caption="0" And b(3+k).caption="0" And other((7+k))Then b(7+k).Caption="C":flag=1:Goto fin
If b(7+k).caption="0" And b(3+k).caption="0" And other((5+k))Then b(5+k).Caption="C":flag=1:Goto fin
If firstclick=0 Then
firstclick=1
var st="1379"
dim as long i=rr(0,3)
If Valint(b(5).caption)=0 and b(5).caption <> "C" Then b(st[i]-48).caption="C":Goto fin
End If
ch=rr(0,5)
if chance[ch]-48=1 then
If Valint(b(5).caption)<>0 Then b(5).caption="C":Goto fin
end if
If all_clicked(b()) Then Nowin=1:Goto fin
If flag=0 Then
Randomize
Do
i=rr(1,9)
If Valint(b(i).caption) <> 0 Then b(i).caption="C":Exit Do
Loop
End If
fin:
If Cwin=1 Or Pwin=1 Or NoWin=1 Then
Dim As long mx,my,mb
dim as integer x,y
screencontrol 0,x,y
for z as single=0 to 8*atn(1) step .001
dim as integer xx=x+100*cos(z)
dim as integer yy=y+100*sin(z)
screencontrol 100,xx,yy
next z
screencontrol 100,x,y
If Cwin=1 Then Message="You Loose"
If Pwin=1 Then Message="You WIN"
If Nowin=1 Then Message="DRAW"
cwin=0:k=0:pWin=0:Nowin=0:firstclick=0'i
Do
Getmouse mx,my,,mb
If inside(b(0),mx,my) And mb=1 Then finish
Var ic=incircle(500,55,20,mx,my)
If incircle(500,55,20,mx,my) And mb=1 Then Exit Do
refresh_screen(b(),ic)
Loop Until Inkey=chr(27)
For z As long=1 To Ubound(b)
b(z).caption=Str(b(z).index)
Next z
Imagedestroy frame
frame=Imagecreate(800,600)
make_frame_image(frame)
computer=0:player=0
Exit Sub
End If
player=1:computer=0
End Sub
 
Sub startup(b() As box)
message="In Play"
Dim As long mx,my,mb
Getmouse mx,my,,mb
For n As long=0 To Ubound(b)
If inside(b(n),mx,my) And mb=1 Then
If b(n).index=0 Then
finish
End If
End If
b(0).colour=Rgb(200,0,0)
Next n
Dim As long f1,f2
If incircle(80,230,10,mx,my) Then
f1=1:f2=0
If mb=1 Then computer=1:player=0
End If
If incircle(670,230,10,mx,my) Then
f1=0:f2=1
If mb=1 Then player=1:computer=0
End If
refresh_screen(b(),f1,f2)
End Sub
Sub thickcircle(x As long,y As long,rad As long,th As Single,col As ulong,im As Any Pointer=0)
Circle(x,y),rad+th/2,col
Circle(x,y),rad-th/2,col
Paint(x,y+rad),col,col
End Sub
 
Sub thickline(x1 As long,_
y1 As long,_
x2 As long,_
y2 As long,_
thickness As Single,_
colour As ulong,_
im As Any Pointer=0)
Dim p As ulong=Rgb(255, 255, 255)
If thickness<2 Then
Line(x1,y1)-(x2,y2),colour
Else
Dim As Double s,h,c
h=Sqr((x2-x1)^2+(y2-y1)^2)
If h=0 Then h=1e-6
s=(y1-y2)/h
c=(x2-x1)/h
For x As long=1 To 2
Line im,(x1+s*thickness/2,y1+c*thickness/2)-(x2+s*thickness/2,y2+c*thickness/2),p
Line im,(x1-s*thickness/2,y1-c*thickness/2)-(x2-s*thickness/2,y2-c*thickness/2),p
Line im,(x1+s*thickness/2,y1+c*thickness/2)-(x1-s*thickness/2,y1-c*thickness/2),p
Line im,(x2+s*thickness/2,y2+c*thickness/2)-(x2-s*thickness/2,y2-c*thickness/2),p
Paint im,((x1+x2)/2, (y1+y2)/2), p, p
p=colour
Next x
End If
End Sub
Sub lineto(x1 As long,y1 As long,x2 As long,y2 As long,l As long,th As Single,col As ulong,im As Any Pointer=0)
Dim As long diffx=x2-x1,diffy=y2-y1,ln=Sqr(diffx*diffx+diffy*diffy)
Dim As Single nx=diffx/ln,ny=diffy/ln
thickline(x1,y1,(x1+l*nx),(y1+l*ny),th,col,im)
End Sub
 
 
Function inside(B As box,px As long,py As long) As long
Return (px>B.x)*(px<(B.x+B.wide))*(py>B.y)*(py<(B.y+B.high))
End Function
Sub make_frame_image(im As ulong Pointer)
#macro map(a,b,x,d,c)
((d)-(c))*((x)-(a))/((b)-(a))+(c)
#endmacro
#macro logo(sx,sy,rad)
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx,sy),rad+k,Rgb(15,118,155):Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+1.3*rad,sy+rad),rad+k,Rgb(230,193,78),2.,1.7:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+2*1.3*rad,sy),rad+k,Rgb(21,3,0),3.25,3.05:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+3*1.3*rad,sy+rad),rad+k,Rgb(26,143,76),2,1.8:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+4*1.3*rad,sy),rad+k,Rgb(200,63,87),3.25,3.05:Next
#endmacro
For k As long=0 To 50
Var r=map(0,50,k,233,193-20)
Var g=map(0,50,k,236,153-20)
Var b=map(0,50,k,216,19-19)
Line im,(0+k,20+k)-(800-k,600-k),Rgb(r,g,b),b
Next k
For k As long=0 To 20
Var r=map(0,20,k,250,0)
Var g=map(0,20,k,250,0)
Var b=map(0,20,k,250,255)
Line im,(0,k)-(780,k),Rgb(r,g,b)',bf
Next k
logo(60,8,5)
logo(380,8,5)
logo(720,8,5)
End Sub
Sub setup_grid(boxes() As box,cellsacross As long,cellsdown As long,xp As long,yp As long,w As long,h As long)
Dim As long index
For y As long=yp To yp+h*(cellsdown-1) Step h
For x As long=xp To xp+w*(cellsacross-1) Step w
index=index+1
boxes(index)=Type<box>(x,y,w,h,index,Rgb(133,136,116),Str(index))
Next x
Next y
boxes(0)=Type<box>(780,-2,20,24,0,Rgb(200,0,0),"X")
End Sub
 
Function all_clicked(b() As box) As long
Dim As long sum
For z As long=1 To Ubound(b)
sum=sum+Valint(b(z).caption)
Next z
If sum<=0 Then Return -1
End Function
 
Sub OnCLICK(a() As box,b As box)
If b.caption="0" Then Exit Sub
If b.caption="C" Then Exit Sub
If b.caption <> "C" Then b.caption="0"
If b.index=0 Then finish
player=0:computer=1
End Sub
 
Sub refresh_screen(b() As box,f1 As long=0,f2 As long=0)
Screenlock:Cls
For n As long=0 To Ubound(b)
b(n).show 'draw boxes
If b(n).caption="0" Then b(n).NewCaption("X")
If b(n).caption="C" Then b(n).NewCaption("O")
Next n
Put(0,0),frame,trans
Draw String (390,50),message,Rgb(0,0,0)
If message <>"In Play" Then
Circle(500,55),20,Rgb(255,20,255),,,,f
If f1=-1 Then Circle(500,55),20,Rgb(202,200,200),,,,f
Draw String(480,50),"Click",Rgb(0,0,0)
End If
If computer=0 And player=0 Then
Draw String (60,200),msg1,Rgb(0,0,0)
Circle(80,230),10,Rgb(0,0,0)
Circle(80,230),5,Rgb(100,100,100),,,,f
If f1=1 Then Circle(80,230),10,Rgb(200,0,0),,,,f
Draw String (650,200),msg2,Rgb(0,0,0)
Circle(670,230),10,Rgb(0,0,0)
Circle(670,230),5,Rgb(100,100,100),,,,f
If f2=1 Then Circle(670,230),10,Rgb(200,0,0),,,,f
End If
Screenunlock:Sleep 1,1
End Sub
 
Function Get_Mouse_Events(boxes() As box) As long
Static released As long
Static pressed As long
Dim As long mousex,mousey,mousebutton ,x,y
Getmouse mousex,mousey,,mousebutton
Dim As box bar=Type<box>(0,0,780,50,0,0,"")
refresh_screen(boxes())
For n As long=0 To Ubound(boxes)
If inside(boxes(n),mousex,mousey) Then
If released Then
boxes(n).colour=Rgb(120,123,103)
If n=0 Then boxes(0).colour=Rgb(255,0,0)
End If
If mousebutton=1 Then
If released Then OnCLICK(boxes(),boxes(n))
Exit For
End If
Else
boxes(n).colour=Rgb(133,136,116)
If n=0 Then boxes(0).colour=Rgb(200,0,0)
End If
Next n
If mousebutton=0 Then released=1 Else released=0 'clean clicks
Return 0
End Function
Sub finish
Screenunlock
Imagedestroy frame
End
End Sub
</lang>
 
 
===text mode===
<lang freebasic>
Screenres 320,240,32
 
'global variables globales
Dim Shared As Integer b(3,3) 'tablero
Dim Shared As Integer mx, my, btns, ox, oy
 
'prueba para ganar posición
'3 victorias horizontales
Function TestWin(t As Integer) As Integer
Dim As Integer win = 0
If b(0,0)= t And b(1,0)= t And b(2,0)= t Then win = t
If b(0,1)= t And b(1,1)= t And b(2,1)= t Then win = t
If b(0,2)= t And b(1,2)= t And b(2,2)= t Then win = t
'3 en vertical gana
If b(0,0)= t And b(0,1)= t And b(0,2)= t Then win = t
If b(1,0)= t And b(1,1)= t And b(1,2)= t Then win = t
If b(2,0)= t And b(2,1)= t And b(2,2)= t Then win = t
'cruzada gana
If b(0,0)= t And b(1,1)= t And b(2,2)= t Then win = t
If b(2,0)= t And b(1,1)= t And b(0,2)= t Then win = t
Return win
End Function
 
Sub InicializarTablero()
For j As Integer = 0 To 2
For i As Integer = 0 To 2
b(i,j)=0
Next i
Next j
End Sub
 
Sub DibujaTablero()
Locate 1,1 : Print "+---+---+---+"
For j As Integer = 0 To 2
Print "|";
For i As Integer = 0 To 2
If b(i,j) = 0 Then Print " |";
If b(i,j) = 1 Then Print " x |";
If b(i,j) = 2 Then Print " o |";
Next i
Print !"\n+---+---+---+"
Next j
End Sub
 
Function MovimientoHumano() As Integer
DibujaTablero()
Print !"\n HAZ CLICK CON EL MOUSE"
Print "EN LA CASILLA QUE ELIJAS"
Dim As Integer opcion = -1
While opcion = -1
Getmouse mx,my,,btns
While btns <> 1 'esperar a pulsar botón
Getmouse mx,my,,btns
Wend
mx = (mx-4)\32
my = (my-4)\16
If mx >= 0 And mx < 3 And my >= 0 And my < 3 Then
If b(mx,my) = 0 Then opcion = mx+my*3 'Casilla vacía?
End If
While btns=1
Getmouse mx,my,,btns
Wend
Wend
Return opcion
End Function
 
Function MovimientoAleatorio() As Integer
Dim As Integer opcion, i, j
opcion = Int(Rnd(1)*9)
j = Int(opcion/3)
i = opcion - Int(opcion/3)*3
While b(i,j) <> 0 Or (opcion > 8 Or opcion < 0)
opcion = Int(Rnd(1)*9)
j = Int(opcion/3)
i = opcion - Int(opcion/3)*3
Wend
Return j*3+i
End Function
 
Function MovimientoInteligente(t As Integer) As Integer
Dim As Integer i, j, opcion, t2
opcion = -1 'opcion aún no seleccionada
'obtener la ficha t2 de los oponentes
If t = 1 Then t2 = 2 Else t2 = 1
'prueba para la casilla central
If b(1,1) = 0 Then opcion = 4
'prueba para ganar
If opcion = -1 Then
If b(0,0)= 0 And b(1,0)= t And b(2,0)= t Then opcion = 0
If b(0,0)= t And b(1,0)= 0 And b(2,0)= t Then opcion = 1
If b(0,0)= t And b(1,0)= t And b(2,0)= 0 Then opcion = 2
If b(0,1)= 0 And b(1,1)= t And b(2,1)= t Then opcion = 3
If b(0,1)= t And b(1,1)= 0 And b(2,1)= t Then opcion = 4
If b(0,1)= t And b(1,1)= t And b(2,1)= 0 Then opcion = 5
If b(0,2)= 0 And b(1,2)= t And b(2,2)= t Then opcion = 6
If b(0,2)= t And b(1,2)= 0 And b(2,2)= t Then opcion = 7
If b(0,2)= t And b(1,2)= t And b(2,2)= 0 Then opcion = 8
'3 bloques verticales
If b(0,0)= 0 And b(0,1)= t And b(0,2)= t Then opcion = 0
If b(0,0)= t And b(0,1)= 0 And b(0,2)= t Then opcion = 3
If b(0,0)= t And b(0,1)= t And b(0,2)= 0 Then opcion = 6
If b(1,0)= 0 And b(1,1)= t And b(1,2)= t Then opcion = 1
If b(1,0)= t And b(1,1)= 0 And b(1,2)= t Then opcion = 4
If b(1,0)= t And b(1,1)= t And b(1,2)= 0 Then opcion = 7
If b(2,0)= 0 And b(2,1)= t And b(2,2)= t Then opcion = 2
If b(2,0)= t And b(2,1)= 0 And b(2,2)= t Then opcion = 5
If b(2,0)= t And b(2,1)= t And b(2,2)= 0 Then opcion = 8
'bloques cruzados
If b(0,0)= 0 And b(1,1)= t And b(2,2)= t Then opcion = 0
If b(0,0)= t And b(1,1)= 0 And b(2,2)= t Then opcion = 4
If b(0,0)= t And b(1,1)= t And b(2,2)= 0 Then opcion = 8
If b(2,0)= 0 And b(1,1)= t And b(0,2)= t Then opcion = 2
If b(2,0)= t And b(1,1)= 0 And b(0,2)= t Then opcion = 4
If b(2,0)= t And b(1,1)= t And b(0,2)= 0 Then opcion = 6
End If
'prueba para bloques
If opcion = -1 Then
If b(0,0)= 0 And b(1,0)= t2 And b(2,0)= t2 Then opcion = 0
If b(0,0)= t2 And b(1,0)= 0 And b(2,0)= t2 Then opcion = 1
If b(0,0)= t2 And b(1,0)= t2 And b(2,0)= 0 Then opcion = 2
If b(0,1)= 0 And b(1,1)= t2 And b(2,1)= t2 Then opcion = 3
If b(0,1)= t2 And b(1,1)= 0 And b(2,1)= t2 Then opcion = 4
If b(0,1)= t2 And b(1,1)= t2 And b(2,1)= 0 Then opcion = 5
If b(0,2)= 0 And b(1,2)= t2 And b(2,2)= t2 Then opcion = 6
If b(0,2)= t2 And b(1,2)= 0 And b(2,2)= t2 Then opcion = 7
If b(0,2)= t2 And b(1,2)= t2 And b(2,2)= 0 Then opcion = 8
'3 bloques verticales
If b(0,0)= 0 And b(0,1)= t2 And b(0,2)= t2 Then opcion = 0
If b(0,0)= t2 And b(0,1)= 0 And b(0,2)= t2 Then opcion = 3
If b(0,0)= t2 And b(0,1)= t2 And b(0,2)= 0 Then opcion = 6
If b(1,0)= 0 And b(1,1)= t2 And b(1,2)= t2 Then opcion = 1
If b(1,0)= t2 And b(1,1)= 0 And b(1,2)= t2 Then opcion = 4
If b(1,0)= t2 And b(1,1)= t2 And b(1,2)= 0 Then opcion = 7
If b(2,0)= 0 And b(2,1)= t2 And b(2,2)= t2 Then opcion = 2
If b(2,0)= t2 And b(2,1)= 0 And b(2,2)= t2 Then opcion = 5
If b(2,0)= t2 And b(2,1)= t2 And b(2,2)= 0 Then opcion = 8
'bloques cruzados
If b(0,0)= 0 And b(1,1)= t2 And b(2,2)= t2 Then opcion = 0
If b(0,0)= t2 And b(1,1)= 0 And b(2,2)= t2 Then opcion = 4
If b(0,0)= t2 And b(1,1)= t2 And b(2,2)= 0 Then opcion = 8
If b(2,0)= 0 And b(1,1)= t2 And b(0,2)= t2 Then opcion = 2
If b(2,0)= t2 And b(1,1)= 0 And b(0,2)= t2 Then opcion = 4
If b(2,0)= t2 And b(1,1)= t2 And b(0,2)= 0 Then opcion = 6
End If
If opcion = -1 Then
If b(0,0) = 0 Then opcion = 0
If b(2,0) = 0 Then opcion = 2
If b(0,2) = 0 Then opcion = 6
If b(2,2) = 0 Then opcion = 8
End If
'no hay opción de hacer una elección al azar
If opcion = -1 Then
opcion = Int(Rnd(1)*9)
j = Int(opcion/3)
i = opcion - Int(opcion/3)*3
'encontrar una casilla vacía
While b(i,j) <> 0
opcion = Int(Rnd(1)*9)
j = Int(opcion/3)
i = opcion - Int(opcion/3)*3
Wend
End If
Return opcion
End Function
 
 
InicializarTablero()
DibujaTablero()
Dim As Integer resultado
Dim As Integer jugador = 1
Dim As Integer ContarMovimientos = 0
Dim As Integer ContarPartidas = 0
Dim As Integer movimiento = 0
Dim As Integer i, j
 
Do
'alternar jugadores
If jugador = 1 Then jugador = 2 Else jugador = 1
'selecciona tipo de movimiento para cada jugador
If jugador = 1 Then
movimiento = MovimientoHumano()
Else
movimiento = MovimientoInteligente(2)
End If
'print "movimiento ="; movimiento
'print "jugador ="; jugador
'convertir la elección a las coordenadas del tablero i,j
j = Int(movimiento/3)
i = movimiento - (j*3)
b(i,j) = jugador 'ingrese la ficha de jugador 1 o 2
resultado = TestWin(jugador) 'comprobar si el jugador ha ganado
DibujaTablero()
ContarMovimientos += 1
'=======================================================
'Comprobar final de partida y/o un resultado de victoria
'=======================================================
If ContarMovimientos = 9 Or resultado <> 0 Then
DibujaTablero()
If resultado = 0 Then Print !"\n EMPATE "
If resultado = 1 Then Print !"\n x GANA "
If resultado = 2 Then Print !"\n o GANA "
Print Space(28)
Print "PULSA BARRA ESPACIADORA PARA"
Print "OTRA PARTIDA, ESC PARA SALIR"
Sleep
Cls
InicializarTablero() 'reiniciar tablero
ContarMovimientos = 0
ContarPartidas += 1
End If
Loop Until Multikey(&H01)
End
</lang>
 
 
=={{header|Go}}==
Intermediate, like Python's "Better skilled player." Computer wins and blocks where it can, but otherwise plays randomly. Plays multiple games and keeps score. Player gets first move of first game. Afterwards, loser gets to go first, or after cat games, first move alternates.
<langsyntaxhighlight lang="go">package main
 
import (
Line 4,728 ⟶ 6,078:
{0, 4, 8}, // diagonals
{2, 4, 6},
}</langsyntaxhighlight>
 
=={{header|Groovy}}==
Simplified version of Tic Tac Toe for player vs. player (no AI computer-controlled option).
<langsyntaxhighlight Groovylang="groovy">class Main {
 
def input = new Scanner(System.in)
Line 4,865 ⟶ 6,215:
return builder.toString();
}
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
Computer player has three strategies: 1. Try to block the opponent first, 2. Try to guess a good position for the next move, 3. Place a piece randomly.
There are lots of comments throughout the code.
<syntaxhighlight lang="haskell">
<lang Haskell>
module Main where
 
Line 5,091 ⟶ 6,441:
putStrLn "3 : player X is human and player O is computer"
putStrLn "Player X always begins."
</syntaxhighlight>
</lang>
{{out}}
Player X is computer, O is human.
Line 5,220 ⟶ 6,570:
The following works in both Icon and Unicon. The computer plays randomly against a human player, with legal moves enforced and wins/draws notified.
 
<syntaxhighlight lang="icon">
<lang Icon>
# Play TicTacToe
 
Line 5,333 ⟶ 6,683:
play_game ()
end
</syntaxhighlight>
</lang>
 
=={{header|J}}==
To subsequent j poster: replacing this entry is fine by me.
<syntaxhighlight lang="j">
<lang J>
Note 'ttt adjudicates or plays'
 
Line 5,432 ⟶ 6,782:
nor=: 8 b.
infix_pairs_agree=: 2&(=/\)
</syntaxhighlight>
</lang>
 
=={{header|Java}}==
This version works in the terminal itself, and uses the numpad for data entry. The computer is unbeatable, but some lines can be removed to avoid that. There's also an override that thrown in, just for fun.
<langsyntaxhighlight lang="java">
import java.io.BufferedReader;
import java.io.InputStreamReader;
Line 5,761 ⟶ 7,111:
}
}
</syntaxhighlight>
</lang>
 
<pre>
Line 5,811 ⟶ 7,161:
 
This version uses javax.swing.
<langsyntaxhighlight lang="java">import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
Line 5,974 ⟶ 7,324:
}
}
</syntaxhighlight>
</lang>
 
Graphical Java Example
<langsyntaxhighlight lang="java">
import javax.swing.*;
import java.awt.event.*;
Line 6,452 ⟶ 7,802:
}
}
</syntaxhighlight>
</lang>
The following program may be executed for a player-against-player game.
<langsyntaxhighlight lang="java">
import javax.swing.*;
import javax.swing.border.Border;
Line 6,735 ⟶ 8,085:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Javascript}}==
HTML5 Canvas implementation. Should play perfectly or near-perfectly.
<syntaxhighlight lang="javascript">
<lang Javascript>
<!DOCTYPE html>
 
Line 7,176 ⟶ 8,526:
 
</html>
</syntaxhighlight>
</lang>
 
 
Line 7,184 ⟶ 8,534:
Human is X and goes first.
 
<syntaxhighlight lang="javascript">
<lang Javascript>
// Board
const topLeft = 1;
Line 7,369 ⟶ 8,719:
}
});
</syntaxhighlight>
</lang>
 
{{out}}
Line 7,396 ⟶ 8,746:
=={{header|Julia}}==
One move look-ahead algorithm. Computer plays to win or at least draw.
<langsyntaxhighlight lang="julia">const winningpositions = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7],
[2, 5, 8], [3, 6, 9],[1, 5, 9], [7, 5, 3]]
 
Line 7,498 ⟶ 8,848:
 
tictactoe()
</langsyntaxhighlight> {{output}} <pre>
Board move grid:
1 2 3
Line 7,542 ⟶ 8,892:
Game over. Computer wins!
</pre>
 
=={{header|Koka}}==
Effectful Version
<syntaxhighlight lang="koka">
import std/os/readline
 
fun member(x: a, xs: list<a>, compare: (a, a) -> bool) : bool
match xs
Nil -> False
Cons(y, ys) -> x.compare(y) || member(x, ys,compare)
 
fun member(xs: list<a>, x: a, compare: (a, a) -> bool) : bool
x.member(xs, compare)
 
 
struct coord
x: int
y: int
 
fun show(c: coord) : string {
"(" ++ c.x.show() ++ ", " ++ c.y.show() ++ ")"
}
 
 
fun (==)(c1: coord, c2: coord) : bool
c1.x == c2.x && c1.y == c2.y
 
 
effect ctl eject(): a
 
 
fun parse(str : string, moves : list<coord>) : <console, exn|_e>coord
match str.list()
Cons('0', Cons(' ', Cons('0', Nil))) -> Coord(0,0)
Cons('0', Cons(' ', Cons('1', Nil))) -> Coord(0,1)
Cons('0', Cons(' ', Cons('2', Nil))) -> Coord(0,2)
Cons('1', Cons(' ', Cons('0', Nil))) -> Coord(1,0)
Cons('1', Cons(' ', Cons('1', Nil))) -> Coord(1,1)
Cons('1', Cons(' ', Cons('2', Nil))) -> Coord(1,2)
Cons('2', Cons(' ', Cons('0', Nil))) -> Coord(2,0)
Cons('2', Cons(' ', Cons('1', Nil))) -> Coord(2,1)
Cons('2', Cons(' ', Cons('2', Nil))) -> Coord(2,2)
Cons('0', Cons(',', Cons('0', Nil))) -> Coord(0,0)
Cons('0', Cons(',', Cons('1', Nil))) -> Coord(0,1)
Cons('0', Cons(',', Cons('2', Nil))) -> Coord(0,2)
Cons('1', Cons(',', Cons('0', Nil))) -> Coord(1,0)
Cons('1', Cons(',', Cons('1', Nil))) -> Coord(1,1)
Cons('1', Cons(',', Cons('2', Nil))) -> Coord(1,2)
Cons('2', Cons(',', Cons('0', Nil))) -> Coord(2,0)
Cons('2', Cons(',', Cons('1', Nil))) -> Coord(2,1)
Cons('2', Cons(',', Cons('2', Nil))) -> Coord(2,2)
Cons('q', Nil) -> eject()
_ ->
println("Invalid move, please try again")
gen_move(moves)
 
fun gen_move(moves : list<coord>) : <console, exn|_e> coord
val move : coord = parse(readline(), moves)
 
if moves.any() fn (c : coord) { c == move } then {
println("Invalid move, please try again")
gen_move(moves)
} else {
move
}
 
fun create-board() : list<list<char>> {
[['.','.','.'],['.','.','.'],['.','.','.']]
}
 
fun show(grid: list<list<char>>) : string
var line := 0
grid.foldl(" 0 1 2\n") fn(acc, row: list<char>)
val out = row.foldl(acc ++ line.show() ++ " ") fn(acc, col: char)
acc ++ col.string() ++ " "
++ "\n"
line := line + 1
out
 
fun get_board_position(board : list<list<char>>, coord : coord) : maybe<char> {
match board[coord.y] {
Nothing -> Nothing
Just(row) -> row[coord.x]
}
}
fun mark_board(board: list<list<char>>,coord: coord, mark: char): maybe<list<list<char>>>
val new_row: maybe<list<char>> = match board[coord.y]
Nothing -> Nothing
Just(row) -> Just(row.take(coord.x) ++ mark.Cons(row.drop(coord.x + 1)))
match new_row
Nothing -> Nothing
Just(row) -> Just(board.take(coord.y) ++ row.Cons(board.drop(coord.y + 1)))
 
 
effect ctl not_full() : ()
 
fun check_full(board: list<list<char>>) : bool
fun helper()
var full := True
board.foreach() fn(row)
if '.'.member(row) fn (a, b) a == b then {
not_full()
}
full
with ctl not_full() False
helper()
 
fun check_win(board: list<list<char>>, mark: char) : <div, exn|_e>bool
var win := False
var i := 0
while {i < 3} {
if board.get_board_position(Coord(i,0)).unwrap() == mark && board.get_board_position(Coord(i,1)).unwrap() == mark && board.get_board_position(Coord(i,2)).unwrap() == mark then {
win := True
}
if board.get_board_position(Coord(0,i)).unwrap() == mark && board.get_board_position(Coord(1,i)).unwrap() == mark && board.get_board_position(Coord(2,i)).unwrap() == mark then {
win := True
}
i := i + 1
}
if board.get_board_position(Coord(0,0)).unwrap() == mark && board.get_board_position(Coord(1,1)).unwrap() == mark && board.get_board_position(Coord(2,2)).unwrap() == mark then {
win := True
}
if board.get_board_position(Coord(0,2)).unwrap() == mark && board.get_board_position(Coord(1,1)).unwrap() == mark && board.get_board_position(Coord(2,0)).unwrap() == mark then {
win := True
}
win
 
 
 
fun human_logic(board: list<list<char>>, moves: list<coord>, mark: char, other_mark: char) : <console,div,exn|_e> coord
gen_move(moves)
 
fun ai_logic(board: list<list<char>>, moves: list<coord>, mark: char, other_mark: char)
board.gen_ai_move(moves,mark, other_mark)
 
 
struct move
move : coord
score: int
 
fun (==)(m1 : move, m2 : move) : bool {
m1.move == m2.move && m1.score == m2.score
}
 
fun eval_board(board : list<list<char>>, mark: char, other-mark : char) {
if board.check_win(mark) then {
10
}
elif board.check_win(other-mark) then {
-10
}
else {
0
}
}
 
fun maximum-move(a : move, b : move) : move {
if a.score > b.score then {
a
}
else {
b
}
}
 
 
fun gen_ai_move(board : list<list<char>>, moves : list<coord>, mark : char, other-mark : char) {
val best_move : move = Move(Coord(-1,-1), -1000)
[0,1,2].foldl(best_move) fn (bstMove : move, i : int) {
[0,1,2].foldl(bstMove) fn (bstMve : move, j : int) {
if Coord(i,j).member(moves) fn (a,b) {a == b} then {
bstMve
}
else {
val new_board : list<list<char>> = board.mark_board(Coord(i,j), mark).unwrap()
val new-max = maximum-move(bstMve, Move(Coord(i,j), new_board.minimax(moves ++ [Coord(i,j)], 0, False, mark, other-mark)))
new-max
}
}
}.move
}
 
fun unwrap(x: maybe<a>): <exn> a
match x
Just(a) -> a
Nothing -> throw("value was Nothing")
 
// A basic implementation of Minimax
// This uses brace style to show that it is possible
fun minimax(board : list<list<char>>, moves: list<coord>, depth : int, isMaximizingPlayer : bool, mark : char, other-mark : char) : <div,exn|_e> int {
val score : int = board.eval_board(mark, other-mark)
if score == 10 then {
score
}
elif score == -10 then {
score
}
elif board.check_full() then {
0
}
else {
if isMaximizingPlayer then {
val bestVal: int = -1000
[0,1,2].foldl(bestVal) fn (bstVal : int, i : int) {
[0,1,2].foldl(bstVal) fn (bstVl : int, j : int) {
if Coord(i,j).member(moves) fn(a, b) {a == b} then {
bstVl
}
else {
val new_board : list<list<char>> = board.mark_board(Coord(i,j), mark).unwrap()
val value : int = new_board.minimax(moves ++ [Coord(i,j)], depth + 1, !isMaximizingPlayer, mark, other-mark)
max(bstVl, value)
}
}
}
}
else {
val bestVal: int = 1000
[0,1,2].foldl(bestVal) fn (bstVal : int, i : int) {
[0,1,2].foldl(bstVal) fn (bstVl : int, j : int) {
if Coord(i,j).member(moves) fn(a,b) {a == b} then {
bstVl
}
else {
val new_board : list<list<char>> = board.mark_board(Coord(i,j), other-mark).unwrap()
val value : int = new_board.minimax(moves ++ [Coord(i,j)], depth + 1, !isMaximizingPlayer, mark, other-mark)
min(bstVl, value)
}
}
}
}
}
}
 
// The main business logic of the entire game
// This function checks if there is a draw or a win
fun play_game()
val board = get_board()
if board.check_full() then
println("Draw!")
println("Final board:")
board.show().println
else
"Next Turn:".println
board.show().println
val current_mark = get_current_mark()
val other_mark = get_other_mark()
play_turn(current_mark, other_mark)
val new_board = get_board()
if new_board.check_win(current_mark) then
println("Player " ++ current_mark.show() ++ " wins!")
println("Final board:")
new_board.show().println
else
flip()
play_game()
 
 
effect human_turn
fun play_human_turn(pair: (list<list<char>>, list<coord>), marks: (char, char)) : coord
effect ai_turn
fun play_ai_turn(pair: (list<list<char>>, list<coord>), marks: (char, char)) : coord
 
effect player1
fun player1_turn(pair: (list<list<char>>, list<coord>), marks: (char, char)) : coord
fun get_player1_mark() : char
effect player2
fun player2_turn(pair: (list<list<char>>, list<coord>), marks: (char, char)) : coord
fun get_player2_mark() : char
 
 
effect turn
// Changes the current player to a different one
fun flip() : ()
// Calls the appropriate code for the current player
fun play_turn(mark: char, other_mark: char) : ()
// Gets the symbol of the active player
fun get_current_mark(): char
// Gets the symbol of the inactive player
fun get_other_mark(): char
// This allows us to access the board
fun get_board() : list<list<char>>
// This allows us to access the moves that have been made
fun get_moves(): list<coord>
 
 
 
type player
Human
AI
 
type players
One
Two
 
// This function encapsulates the state of the entire game
// Think of it as calling a method on an object but with pure functions
fun initialize_and_start_game(game_type: int)
var current_player := One
var current_board := create-board()
var all_moves := []
 
var player1 := Human
var player2 := AI
 
match game_type
1 -> {
player1 := Human
player2 := Human
}
2 -> {
player1 := Human
player2 := AI
}
3 -> {
player1 := AI
player2 := AI
}
_ -> throw("invalid game type")
 
with handler
ctl eject()
println("Have a nice day.")
with fun play_human_turn(pair: (list<list<char>>, list<coord>), marks: (char, char))
human_logic(pair.fst,pair.snd,marks.fst,marks.snd)
with fun play_ai_turn(pair: (list<list<char>>, list<coord>), marks: (char, char))
ai_logic(pair.fst,pair.snd,marks.fst,marks.snd)
with handler
fun player1_turn(pair: (list<list<char>>, list<coord>), marks: (char, char))
match player1
Human -> play_human_turn(pair, marks)
AI -> play_ai_turn(pair, marks)
fun get_player1_mark()
'X'
with handler
fun player2_turn(pair: (list<list<char>>, list<coord>), marks: (char, char))
match player2
Human -> play_human_turn(pair, marks)
AI -> play_ai_turn(pair, marks)
fun get_player2_mark()
'O'
with handler
return(x) ()
fun flip()
match current_player
One -> current_player := Two
Two -> current_player := One
fun play_turn(mark: char, other_mark: char)
match current_player
One -> {
val coord = player1_turn((current_board, all_moves), (mark, other_mark))
current_board := mark_board(current_board,coord,get_player1_mark()).unwrap
all_moves := Cons(coord, all_moves)
()
}
Two -> {
val coord = player2_turn((current_board, all_moves), (mark, other_mark))
 
current_board := mark_board(current_board,coord,get_player2_mark()).unwrap
all_moves := Cons(coord, all_moves)
()
}
fun get_current_mark() match current_player
One -> get_player1_mark()
Two -> get_player2_mark()
fun get_other_mark() match current_player
Two -> get_player1_mark()
One -> get_player2_mark()
fun get_board() current_board
fun get_moves() all_moves
play_game()
 
 
fun prompt_game_type()
match readline().list()
Cons('1', Nil) -> 1
Cons('2', Nil) -> 2
Cons('3', Nil) -> 3
_ ->
println("Invalid game mode, please try again")
prompt_game_type()
 
 
fun main ()
println("Welcome to Tic Tac Toe!")
println("Please select a game mode:")
println("1. Two player")
println("2. One player")
println("3. Zero player")
println("Enter the number of the game mode you want to play")
 
val game_type = prompt_game_type()
 
"Enter your input as 'x y' or 'x,y' when selecting a spot".println
 
initialize_and_start_game(game_type)
</syntaxhighlight>
 
=={{header|Kotlin}}==
{{trans|C}}
<langsyntaxhighlight lang="scala">// version 1.1.51
 
import java.util.Random
Line 7,651 ⟶ 9,413:
println()
}
}</langsyntaxhighlight>
 
Sample game:
Line 7,711 ⟶ 9,473:
 
As image uploads has been disabled, a live version can be viewed at: [http://jono.guthrie.net.nz/rosetta/Tic-tac-toe.lasso http://jono.guthrie.net.nz/rosetta/Tic-tac-toe.lasso]
<syntaxhighlight lang="lasso">[
<lang Lasso>[
session_start('user')
session_addvar('user', 'matrix')
Line 7,805 ⟶ 9,567:
$matrix = array('-','-','-','-','-','-','-','-','-')
$turn = 'x'
}]</langsyntaxhighlight>
 
=={{header|Lingo}}==
Line 7,811 ⟶ 9,573:
Screenshot of application window: http://valentin.dasdeck.com/lingo/tic-tac-toe/tic-tac-toe-lingo.png<br />
"Human" cannot win this game.
<langsyntaxhighlight Lingolang="lingo">global $ -- object representing simple framework
global gBoard -- current board image
global gBoardTemplate -- empty board image
Line 8,047 ⟶ 9,809:
on sum (aLine)
return aLine[1]+aLine[2]+aLine[3]
end</langsyntaxhighlight>
 
=={{header|Lua}}==
Version for LuaJIT with or without ffi, negamax algorithm with alpha-beta pruning and caching of results. Human can't win.
<langsyntaxhighlight Lualang="lua">#!/usr/bin/env luajit
ffi=require"ffi"
local function printf(fmt,...) io.write(string.format(fmt, ...)) end
Line 8,240 ⟶ 10,002:
draw(board)
until endgame()
end</langsyntaxhighlight>
 
{{out}}
Line 8,305 ⟶ 10,067:
=={{header|M2000 Interpreter}}==
Computer May loose;
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Tic.Tac.Toe {
Dim Board$(1 to 3, 1 to 3)=" "
Line 8,417 ⟶ 10,179:
}
Tic.Tac.Toe
</syntaxhighlight>
</lang>
{{out}}
<pre style="height:30ex;overflow:scroll">
Line 8,491 ⟶ 10,253:
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="text">DynamicModule[{board = ConstantArray[0, {3, 3}], text = "Playing...",
first, rows =
Join[#, Transpose@#, {Diagonal@#, Diagonal@Reverse@#}] &},
Line 8,526 ⟶ 10,288:
text = "Draw."]]]]], {i, 1, 3}, {j, 1, 3}], Thickness[.01],
Line[{{{1, 0}, {1, 3}}, {{2, 0}, {2, 3}}, {{0, 1}, {3, 1}}, {{0,
2}, {3, 2}}}]}], Dynamic@text}]</langsyntaxhighlight>
 
=={{header|MATLAB}}==
Allows for choice between any combination of human or computer players. Computer players are intelligent, but not perfect. It implements the "rules" used by the Newell and Simon's 1972 tic-tac-toe program (as explained by Wikipedia), but this implementation does not factor in the move before the move causing the fork (either for creation or prevention).
<langsyntaxhighlight MATLABlang="matlab">function TicTacToe
% Set up the board (one for each player)
Line 8,753 ⟶ 10,515:
% boards - 3x3x2 logical representation of all players' pieces
draw = all(all(boards(:, :, 1) | boards(:, :, 2)));
end</langsyntaxhighlight>
{{out}}
Computer goes first and plays perfectly:
Line 8,875 ⟶ 10,637:
 
=={{header|mIRC Scripting Language}}==
<langsyntaxhighlight lang="mirc">alias ttt {
if ($2 isin %ttt) || (!%ttt) {
var %ttt~ = $remove($iif(%ttt,%ttt,1 2 3 4 5 6 7 8 9),$2,X,O)
Line 8,905 ⟶ 10,667:
echo -ag � $+ $iif($7 isnum,$chr(32),$7) $+ $chr(124) $+ $iif($8 isnum,$chr(32),$8) $+ $chr(124) $+ $iif($9 isnum, ,$9)
}
}</langsyntaxhighlight>
 
=={{header|МК-61/52}}==
<langsyntaxhighlight lang="mk-61">9 С/П ПП 28 пи * cos x<0 16 ИП2
ПП 28 1 - БП 51 ИП7 ПП 28 ИП7
ПП 28 КИП2 ИП2 ВП 4 4 С/П 1 -
x=0 33 8 П2 С/П П7 ИП2 4 - x#0
43 x<0 45 8 + П8 ИП7 - x#0 55
ИП8 ВП 6 6 С/П ИП2 В/О</langsyntaxhighlight>
 
Cell numbering 1 to 9; starts from the upper left cell, then clockwise in a spiral. The first move is a calculator. Result: 44 - draw, 66 - victory of the calculator.
Line 8,921 ⟶ 10,683:
This is a translation of the second version with the better AI, but with some differences. For instance, we have chosen to display the board in the same way as the first version. All procedures have a parameter "board" rather accessing a global variable. We use also base 1-indexing for the board. Etc.
 
<langsyntaxhighlight Nimlang="nim">import options, random, sequtils, strutils
 
type
Line 9,024 ⟶ 10,786:
echo "Input the index of where you wish to place your mark at your turn."
randomize()
play()</langsyntaxhighlight>
 
{{out}}
Line 9,087 ⟶ 10,849:
=={{header|Objeck}}==
Tic-tac-toe game using Minimax algorithm.
<langsyntaxhighlight lang="objeck">class TicTacToe {
@board : Char[,];
@cpu_opening : Bool;
Line 9,458 ⟶ 11,220:
"===========\n"->PrintLine();
}
}</langsyntaxhighlight>
 
=={{header|Pascal}}==
Line 9,464 ⟶ 11,226:
In some ways easier to read, but because Pascal lack return/break/continue
functions a little long and different style. Tested with FreePascal on macOS.
I thinkwould expect this version should compilercompile onwith most Pascal variants including Delphi, but YMMR.
 
<langsyntaxhighlight Pascallang="pascal">program ticTic(Input, Output);
 
type
Contents = (Unassigned, Human, Computer);
var
best_iBestI, best_jBestJ: Integerinteger; { best solution a depth of zero in the search }
bB: array[0..2, 0..2] of Contents; {zero based so modulus works later}
playerPlayer: Contents;
 
procedure displayBoardDisplayBoard;
var
iI, jJ: Integerinteger;
tT: array [Contents] of char;
begin
tT[Unassigned] := ' ';
tT[Human] := 'O';
tT[Computer] := 'X';
for iI := 0 to 2 do begin
for j := 0 to 2 do begin
for J := 0 to 2 write(t[b[i][j]]);do
begin
if j <> 2 then write(' | ');
endWrite(T[B[I, J]]);
writeln();if J <> 2 then
if i < 2 then writeln Write('--------- | ');
end;
WriteLn;
if I < 2 then
WriteLn('---------');
end;
writeln()WriteLn;
writeln()WriteLn;
end;
 
function swapPlayer function SwapPlayer(Player: Contents): Contents;
begin
if Player = Computer then swapPlayer := Human else swapPlayer := Computer;
SwapPlayer := Human
end;
else
SwapPlayer := Computer;
end;
 
function checkWinnerCheckWinner: Contents;
var
iI: Integerinteger;
begin
checkWinnerCheckWinner := Unassigned; (*{ no winner yet *)}
for iI := 0 to 2 do begin
begin
(* first horizontal solution *)
{ first horizontal solution }
if ((checkWinner = Unassigned) and (b[i][0] <> Unassigned)) and ((b[i][1] = b[i][0]) and (b[i][2] = b[i][0])) then
if (CheckWinner = Unassigned) and (B[I, 0] <> Unassigned) and
checkWinner := b[i][0]
(B[I, 1] = B[I, 0]) and (B[I, 2] = B[I, 0]) then
else
(*CheckWinner now:= verticalB[I, solution *)0]
else
if ((checkWinner = Unassigned) and (b[0][i] <> Unassigned)) and ((b[1][i] = b[0][i]) and (b[2][i] = b[0][i])) then
{ now vertical solution }
checkWinner := b[0][i];
if (CheckWinner = Unassigned) and (B[0, I] <> Unassigned) and
end; (* now check the paths of the two cross line slants that share the middle position *)
if (checkWinnerB[1, I] = UnassignedB[0, I]) and (bB[1][12, I] <>= UnassignedB[0, I]) then begin
CheckWinner := B[0, I];
if ((b[1][1] = b[0][0]) and (b[2][2] = b[0][0])) then checkWinner := b[0][0]
else if ((b[1][1] = b[2][0]) and (b[0][2] = b[1][1])) then checkWinner := b[1][1];
end;
{ now check the paths of the two cross line slants that share the middle position }
end;
if (CheckWinner = Unassigned) and (B[1, 1] <> Unassigned) then
begin
if (B[1, 1] = B[0, 0]) and (B[2, 2] = B[0, 0]) then
CheckWinner := B[0, 0]
else if (B[1, 1] = B[2, 0]) and (B[0, 2] = B[1, 1]) then
CheckWinner := B[1, 1];
end;
end;
 
{ Basic strategy test - is this te best solution we have seen }
function saveBestSaveBest(CurScore, CurBest: Contents) : boolean;
begin
if CurScore = CurBest then saveBest := false
SaveBest := False
else if (Curscore = Unassigned) and (CurBest = Human) then saveBest := false
else if (CurscoreCurScore = ComputerUnassigned) and ((CurBest = Unassigned) or (CurBest = Human)) then saveBest := false
else saveBest SaveBest := true;False
else if (CurScore = Computer) and ((CurBest = Unassigned) or
end;
(CurBest = Human)) then
SaveBest := False
else
SaveBest := True;
end;
 
 
{ Basic strategy - recursive depth first serachsearch of possible moves
if computer can win save it, otherwise block if need be, else do deeper.
At each level modify the board for the next call, but clean up as go back up,
by remembering the modified position on the call stack. }
function test_move function TestMove(valVal: Contents; depthDepth: Integerinteger): Contents;
var
iI, jJ: Integerinteger;
scoreScore, bestBest, changedChanged: Contents;
begin
bestBest := Computer;
changedChanged := Unassigned;
scoreScore := checkWinner()CheckWinner;
if scoreScore <> Unassigned then begin
begin
if score = val then test_move := Human else test_move := Computer;
if Score = Val then
end else begin
for i := 0 to 2 do for jTestMove := 0 to 2 do beginHuman
else
if b[i][j] = Unassigned then begin
changedTestMove := valComputer;
end
b[i][j] := val; (* the value for now and try wioth the other player *)
else
score := test_move(swapPlayer(val), depth + 1);
begin
if (score <> Unassigned) then score := swapPlayer(score);
for I := 0 b[i][j]to :=2 Unassigned;do
for J if:= saveBest(score,0 best)to then2 begindo
begin
if depth = 0 then begin { top level, so remember actual position }
if B[I, J] = best_i :=Unassigned i;then
best_j := j;begin
Changed := Val;
B[I, J] := Val;
{ the value for now and try wioth the other player }
Score := TestMove(SwapPlayer(Val), Depth + 1);
if Score <> Unassigned then
Score := SwapPlayer(Score);
B[I, J] := Unassigned;
if SaveBest(Score, Best) then
begin
if Depth = 0 then
begin { top level, so remember actual position }
BestI := I;
BestJ := J;
end;
Best := Score;
end;
best := score;
end;
end;
if Changed <> Unassigned then
end;
TestMove := Best
if (changed <> Unassigned) then test_move := best else test_move := Unassigned;
else
TestMove := Unassigned;
end;
end;
 
function playGamePlayGame(whomWhom: Contents): string;
var
iI, jJ, kK, moveMove: Integerinteger;
winWin: Contents;
begin
winWin := Unassigned;
for iI := 0 to 2 do for j := 0 to 2 do b[i][j] := Unassigned;
for J := 0 to 2 do
 
B[I, J] := Unassigned;
writeln('The board positions are numbered as follows:');
writelnWriteLn('1The |board 2positions |are 3numbered as follows:');
writelnWriteLn('---------1 | 2 | 3');
writelnWriteLn('4 | 5 | 6---------');
writelnWriteLn('---------4 | 5 | 6');
writelnWriteLn('7 | 8 | 9---------');
writelnWriteLn('You7 have| O,8 I| have X.9');
WriteLn('You have O, I have X.');
writeln();
WriteLn;
 
kK := 1;
repeat {rather a for loop but can not have two actions or early termination in Pascal}
if Whom = Human then
begin
repeat
Write('Your move: ');
ReadLn(Move);
if (Move < 1) or (Move > 9) then
WriteLn('Opps: enter a number between 1 - 9.');
Dec(Move);
{humans do 1 -9, but the computer wants 0-8 for modulus to work}
I := Move div 3; { convert from range to corridinated of the array }
J := Move mod 3;
if B[I, J] <> Unassigned then
WriteLn('Opps: move ', Move + 1, ' was already done.')
until (Move >= 0) and (Move <= 8) and (B[I, J] = Unassigned);
B[I, J] := Human;
end;
if Whom = Computer then
begin
{ randomize if computer opens, so its not always the same game }
if K = 1 then
begin
if whomBestI := Human then beginRandom(3);
BestJ := repeat beginRandom(3);
write('Your move: ');end
readln(move);else
Win := TestMove(Computer, 0);
if (move < 1) or (move > 9) then writeln('Opps: enter a number between 1 - 9')
B[BestI, BestJ] := Computer;
else move := pred(move); {humans do 1 -9, but the computer wants 0-8 for modulus to work}
WriteLn('My move: ', BestI end* until3 ((move+ >= 0) and (moveBestJ <=+ 8)1);
end;
i := move div 3; { convert from range to corridinated of the array }
j := move mod 3DisplayBoard;
Win := CheckWinner;
if b[i][j] = Unassigned then b[i][j] := Human;
if Win <> Unassigned end;then
if whom = Computer then begin
if Win = Human then
(* randomize if computer opens, so its not always the same game *)
PlayGame if k := 1 then'You beginwin.'
else
best_i := random(3); {Pascal random returns poisitive integers from 0 to func arg}
best_jPlayGame := random(3)'I win.';
end else
else
win := test_move(Computer, 0);
begin
b[best_i][best_j] := Computer;
writelnInc('MyK); move:{ ',"for" best_iloop *counter 3actions + best_j + 1);}
Whom := endSwapPlayer(Whom);
end;
 
until (Win <> Unassigned) or displayBoard(K > 9);
if Win = Unassigned then
win := checkWinner();
PlayGame := 'A draw.';
if win <> Unassigned then begin
end;
if win = Human then playGame := 'You win.' else playGame := 'I win.';
end else begin
k := succ(k); { "for" loop counter actions }
whom := swapPlayer(whom);
end;
end;
until (win <> Unassigned) or (k > 9);
if win = Unassigned then playGame := 'A draw.';
end;
 
begin
Randomize;
randomize();
playerPlayer := Human;
while (true)True do
begin
writelnWriteLn(playGamePlayGame(playerPlayer));
writeln()WriteLn;
playerPlayer := swapPlayerSwapPlayer(playerPlayer);
end
end.</langsyntaxhighlight>
 
=={{header|Perl}}==
Line 9,640 ⟶ 11,449:
the computer. Anyone who can identify the mistake, is welcome to fix it.
 
<langsyntaxhighlight Perllang="perl">use warnings;
use strict;
 
Line 9,739 ⟶ 11,548:
$whose_turn = !$whose_turn;
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 9,797 ⟶ 11,606:
</pre>
===Alternate with GUI===
<langsyntaxhighlight Perllang="perl">#!/usr/bin/perl
 
use strict;
Line 9,868 ⟶ 11,677:
(sort {$a->[0] <=> $b->[0]} shuffle @moves)[ -($who eq 'X') ]
};
}</langsyntaxhighlight>
 
=={{header|Phix}}==
Line 9,875 ⟶ 11,684:
{{libheader|Phix/online}}
You can run this online [http://phix.x10.mx/p2js/Tic_tac_toe.htm here].
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Tic_tac_toe.exw
Line 10,113 ⟶ 11,922:
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</langsyntaxhighlight>-->
 
=={{header|PHP}}==
Line 10,119 ⟶ 11,928:
NOTE: While PHP can considered a super-set of HTML/JS, usage has been kept to a minimum to focus on the more specific PHP parts.
 
<syntaxhighlight lang="php">
<lang PHP>
<?php
const BOARD_NUM = 9;
Line 10,177 ⟶ 11,986:
echo '<a href="?b=', $EMPTY_BOARD_STR, '">Reset</a>';
if ($gameOver) echo '<h1>Game Over!</h1>';
</syntaxhighlight>
</lang>
 
=={{header|PicoLisp}}==
This solution doesn't bother about the game logic, but simply uses the alpha-beta-pruning 'game' function in the "simul" library.
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/simul.l") # for 'game' function
 
(de display ()
Line 10,247 ⟶ 12,056:
((find3 T) "Congratulation, you won!")
((not (myMove)) "No moves")
((find3 0) "Sorry, you lost!") ) )</langsyntaxhighlight>
{{out}}
<pre>: (main)
Line 10,276 ⟶ 12,085:
+---+---+---+
a b c</pre>
 
=={{header|PostScript}}==
<syntaxhighlight lang="postscript">
%!PS
%
% Play Tic-Tac-Toe against your printer
% 2024-04 Nicolas Seriot https://github.com/nst/PSTicTacToe
%
% On GhostScript:
% gs -DNOSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile="%d.pdf" ttt.ps
%
% On a real PostScript printer:
% cat ttt.ps - | nc 192.168.2.10 9100
 
<</PageSize[595 842]>>setpagedevice/Courier findfont 48 scalefont setfont/b
(.........)def/f{/n 0 def b{46 eq{/n n 1 add def}if}forall n}def/w{/c exch def
[(O)(X)]{/p exch def[[0 1 2][3 4 5][6 7 8][0 3 6][1 4 7][2 5 8][0 4 8][2 4 6]]{
/t exch def/o true def t{/pos exch def/o c pos 1 getinterval p eq o and def}
forall o{exit}if}forall o{exit}if}forall o}def/g{/s exch def/m null def f 0 eq{
/m(TIE)def}if b w{/m(XXXXXXX WINS)def m 0 s putinterval}if()= 0 3 6{b exch 3
getinterval =}for()= m null ne{m =}if 4 setlinewidth 200 700 moveto 200 400
lineto 300 700 moveto 300 400 lineto 100 600 moveto 400 600 lineto 100 500
moveto 400 500 lineto stroke 0 1 b length 1 sub{/i exch def b i 1 getinterval
(.)ne{gsave 0 0 moveto 100 i 3 mod 100 mul add 35 add 700 i 3 idiv 100 mul sub
65 sub moveto b i 1 getinterval show grestore}if}for m null ne{100 300 moveto m
show}if showpage m null ne{quit}if}def{/d false def 0 1 8{/i exch def/e b dup
length string cvs def e i 1 getinterval(.)eq{[(X)(O)]{/p exch def e i p
putinterval e w{b i(X)putinterval/d true def exit}if}forall}if d{exit}if}for d
not{/x rand f mod def/c 0 def 0 1 b length 1 sub{/i exch def b i 1 getinterval
(.)eq{c x eq{b i(X)putinterval exit}if/c c 1 add def}if}for}if(PRINTER)g b{
(human turn (1-9) >)print flush(%lineedit)(r)file( )readline pop dup length
0 gt{0 1 getinterval}{pop( )}ifelse/o exch def(123456789)o search{pop pop pop b
o cvi 1 sub 1 getinterval(.)eq{o cvi 1 sub exit}if}{pop}ifelse(bad input) ==}
loop(O)putinterval(HUMAN )g}loop
</syntaxhighlight>
 
=={{header|Prolog}}==
Line 10,281 ⟶ 12,125:
Uses a minimax algorithm with no Alpha-beta pruning, as the max depth of the recursion is 8. Computer never loses.<br>
A GUI interface written in XPCE is given.
<langsyntaxhighlight Prologlang="prolog">:- use_module('min-max.pl').
 
:-dynamic box/2.
Line 10,490 ⟶ 12,334:
computer(o).
 
</syntaxhighlight>
</lang>
Module min-max.pl defines minimax algorithm.
<langsyntaxhighlight lang="prolog">:- module('min-max.pl', [minimax/5]).
 
% minimax(Player, Deep, MaxDeep, B, V-B)
Line 10,519 ⟶ 12,363:
lie(TTT, V-_, V-TTT).
 
</syntaxhighlight>
</lang>
 
=={{header|Python}}==
The computer enforces the rules but plays a random game.
<langsyntaxhighlight lang="python">
'''
Tic-tac-toe game player.
Line 10,598 ⟶ 12,442:
else:
print('\nA draw')
</syntaxhighlight>
</lang>
 
'''Sample Game'''
Line 10,641 ⟶ 12,485:
In this version, The computer player will first complete a winning line of its own if it can, otherwise block a winning line of its opponent if they have two in a row, or then choose a random move.
 
<langsyntaxhighlight lang="python">
'''
Tic-tac-toe game player.
Line 10,732 ⟶ 12,576:
break
else:
print('\nA draw')</langsyntaxhighlight>
 
{{out}}
Line 10,817 ⟶ 12,661:
This program simulates a game of Tic-Tac-Toe inside of an interactive window. It includes three player modes, which are a two-player game, a human versus random AI, or human versus maximized AI. This implementation belongs to "X", and can also be found here.
 
<syntaxhighlight lang="r">
<lang R>
rm(list=ls())
library(RColorBrewer)
Line 10,880 ⟶ 12,724:
place.na[!is.na(place.na)] <<- NA
if(total.1==0 | total.2==0 | total.3==0 | total.4==0){
title(sub=list(""You Won ?! That's a first!", col="red", font=2, cex=2.5), line=2)
}else{
title(sub=list("You Don't Get Tired of Losing ?!", col="darkblue", font=2, cex=2.5), line=2)
Line 11,231 ⟶ 13,075:
#start("name", "mode" = 0 - 2, type = 0,1)
 
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
Line 11,252 ⟶ 13,096:
 
The <tt>minimax.rkt</tt> module:
<langsyntaxhighlight lang="racket">
#lang lazy
(provide minimax)
Line 11,273 ⟶ 13,117:
(next (cdr x)
(min β (minimax (car x) α β (not max-player))))))]))))
</langsyntaxhighlight>
 
The <tt>game.rkt</tt> module:
 
<langsyntaxhighlight lang="racket">
#lang lazy
(require racket/class
Line 11,387 ⟶ 13,231:
(set-field! opponent p2 p1)
(send p1 your-turn initial-state))
</syntaxhighlight>
</lang>
 
The <tt>tick-tack.rkt</tt> module:
<langsyntaxhighlight lang="racket">#lang racket
 
(require "game.rkt"
Line 11,481 ⟶ 13,325:
(new (interactive-player o%) [name "Dummy"] [look-ahead 0]))
 
</syntaxhighlight>
</lang>
 
Sample games:
Line 11,608 ⟶ 13,452:
As an example of another zero-sum game consider the classical [http://en.wikipedia.org/wiki/Nim Nim] game:
 
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 11,648 ⟶ 13,492:
(define player-B
(new (interactive-player second%) [name "B"] [look-ahead 4]))
</syntaxhighlight>
</lang>
 
Computer plays with the computer:
Line 11,684 ⟶ 13,528:
The computer plays a random game.
 
<syntaxhighlight lang="raku" perl6line>my @board = 1..9;
my @winning-positions = [0..2], [3..5], [6..8], [0,3,6], [1,4,7], [2,5,8],
[0,4,8], [6,4,2];
Line 11,730 ⟶ 13,574:
} else {
say "How boring, a draw!";
}</langsyntaxhighlight>
 
=={{header|REXX}}==
Line 11,749 ⟶ 13,593:
<br>A fair amount of code was dedicated to error detection &nbsp; and &nbsp; the displaying of error messages, &nbsp; and
<br>also the presentation of the tic─tac─toe game boards (grids).
<langsyntaxhighlight lang="rexx">/*REXX program plays (with a human) the tic─tac─toe game on an NxN grid. */
$= copies('─', 9) /*eyecatcher for error messages, prompt*/
oops = $ '***error*** ' /*literal for when an error happens. */
Line 11,890 ⟶ 13,734:
 
if _==N | (_>=w & ec\=='') then return 1==1 /*a winner has been determined.*/
return 0==1 /*no winner " " " */</langsyntaxhighlight>
This REXX program makes use of &nbsp; '''LINESIZE''' &nbsp; REXX program (or BIF) which is used to determine the screen width (or linesize) of the terminal (console); &nbsp; this is used to determine the amount of padding for a centered display of the two grids.
 
Line 12,094 ⟶ 13,938:
 
The tecTacToe.ring is provided [https://github.com/AbdelrahmanGIT/RingSamples/blob/master/src/TecTacToe.ring here]
<langsyntaxhighlight lang="ring">
Load "guilib.ring"
 
Line 12,224 ⟶ 14,068:
next
if tie=true return 3 ok return 0
</syntaxhighlight>
</lang>
 
{{out}}
Line 12,236 ⟶ 14,080:
This implementation stores the board as a one-dimensional array and hardcodes all possible straight lines in <code>LINES</code>, rather than storing the board as a two-dimensional matrix and identifying straight lines dynamically.
 
<langsyntaxhighlight lang="ruby">module TicTacToe
LINES = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]]
Line 12,421 ⟶ 14,265:
puts
players_with_human = [HumanPlayer, ComputerPlayer].shuffle
Game.new(*players_with_human).play</langsyntaxhighlight>
 
{{out}}
Line 12,488 ⟶ 14,332:
--+---+--
X | O | X</pre>
 
=={{header|Run BASIC}}==
<lang runbasic>' ---------------------------
' TIC TAC TOE
' ---------------------------
winBox$ = "123 456 789 159 147 258 369 357"
boxPos$ = "123 231 456 564 789 897 159 591 357 753 132 465 798 174 285 396 159 471 582 693 147 258 369 195 375"
ai$ = "519628374"
ox$ = "OX"
[newGame]
for i = 1 to 9
box$(i) = ""
next i
goto [shoTic]
 
[loop]
for j = 1 to 2
tic$ = mid$(ox$,j,1)
for i = 1 to 25
b$ = word$(boxPos$,i," ")
b1 = val(mid$(b$,1,1))
b2 = val(mid$(b$,2,1))
b3 = val(mid$(b$,3,1))
if box$(b1) = tic$ AND box$(b2) = tic$ AND box$(b3) = "" then
box$(b3) = "O"
goto [shoTic]
end if
next i
next j
if box$(1) = "O" AND box$(5) = "X" and box$(9) = "X" then
if box$(3) = "" then
box$(3) = "O"
goto [shoTic]
end if
if box$(7) = "" then
box$(7) = "O"
goto [shoTic]
end if
end if
for i = 1 to 9
b1 = val(mid$(ai$,i,1))
if box$(b1) = "" then
box$(b1) = "O"
exit for
end if
next i
 
[shoTic]
cls
' ----------------------------------------
' show tic tac toe screen
' ----------------------------------------
html "<table border=1 width=300px height=225px><TR>"
for i = 1 to 9
html "<td align=center width=33%><h1>"
if box$(i) <> "" then
html box$(i)
else
button #box, " ";box$(i);" ", [doTic]
#box setkey(str$(i))
end if
if i mod 3 = 0 then html "</tr><tr>"
next i
html "</table>"
gosub [checkWin]
wait
 
[doTic]
box$(val(EventKey$)) = "X"
turn = 1
gosub [checkWin]
goto [loop]
 
' --- check for a winner ----------
[checkWin]
for i = 1 to 8
b$ = word$(winBox$,i," ")
b1 = val(mid$(b$,1,1))
b2 = val(mid$(b$,2,1))
b3 = val(mid$(b$,3,1))
if box$(b1) = "O" and box$(b2) = "O" and box$(b3) = "O" then
print "You Lose!"
goto [playAgain]
end if
if box$(b1) = "X" and box$(b2) = "X" and box$(b3) = "X" then
print "You Win!"
goto [playAgain]
end if
next i
 
moveCount = 0
for i = 1 to 9
if box$(i) <> "" then moveCount = moveCount + 1
next i
if moveCount = 9 then
print "Draw!"
goto [playAgain]
end if
RETURN
 
[playAgain]
input "Play again (y/n)";p$
if upper$(p$) = "Y" then goto [newGame]
end</lang>
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">
use GameState::{ComputerWin, Draw, PlayerWin, Playing};
 
Line 12,715 ⟶ 14,455:
}
 
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 12,747 ⟶ 14,487:
Computer vs. human. Human starts. Computer plays 'O' and human plays 'X'.
Computer moves are legal, but random.
<langsyntaxhighlight lang="scala">package object tictactoe {
val Human = 'X'
val Computer = 'O'
Line 12,828 ⟶ 14,568:
}
 
}</langsyntaxhighlight>
 
{{out}}(human is always first)
Line 12,863 ⟶ 14,603:
Can be a game of human v. human, human v. machine, or machine v. machine. Machine moves have a hierarchy: firstly, it looks for a winning move; secondly, it looks for a way to block the opponent's victory; lastly, it makes a random move.
 
<syntaxhighlight lang="text">function [] = startGame()
//Board size and marks
N = 3;
Line 13,241 ⟶ 14,981:
endfunction
 
startGame()</langsyntaxhighlight>
 
=={{header|SQL}}==
Basic playable TicTacToe in SQLite using only the sqlite3 CLI.
The CLI wasn't really designed for this, making the interactivity a little bit clunky. However, some of the higher-level constructs in SQL allow for some intriguingly elegant game logic.
<syntaxhighlight lang="sql">
<lang SQL>
--Setup
drop table if exists board;
Line 13,333 ⟶ 15,073:
.print "->update board set p = 'X' where rowid = ?; select * from ui; select * from msg;"'
 
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 13,365 ⟶ 15,105:
=={{header|Swift}}==
Some Basic AI for obvious losing and winning conditions
<syntaxhighlight lang="swift">
<lang Swift>
import Darwin
 
Line 13,572 ⟶ 15,312:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 13,676 ⟶ 15,416:
 
=={{header|Tailspin}}==
<langsyntaxhighlight lang="tailspin">
processor Tic-Tac-Toe
@: [position´1..9 -> (position:$) -> $::value´9];
 
source isWonOrDone
Line 13,685 ⟶ 15,425:
$@Tic-Tac-Toe([1,5,9]) -> #, $@Tic-Tac-Toe([3,5,7]) -> #
] -> \(
when <=[]?($@Tic-Tac-Toe <~[<1..9position>]>)> do 'draw' !
when <~=[]> do $(1) !
\) !
when <[<mark>+ VOID]?($ <[<=$(first)::raw>+ VOID]>)> do '$(first); wins!'!
end isWonOrDone
 
source validMoves
$@Tic-Tac-Toe -> \[i](<1..9position> $ !\) !
end validMoves
 
templates move
when <?($@Tic-Tac-Toe($.position::raw) <position>)> do @Tic-Tac-Toe($.position::raw): $.mark;
$ !
otherwise
Line 13,713 ⟶ 15,453:
source play
def board: $Tic-Tac-Toe;
@: mark´'X';
templates getMove
[] -> #
Line 13,721 ⟶ 15,461:
[{mark: $@play, position: $IN::readline -> toInt} -> board::move] -> #
otherwise
$(1) !
end getMove
 
Line 13,727 ⟶ 15,467:
when <{}> do
'$.mark; played $.position;$#10;' -> !OUT::write
@: $@ -> \(<=mark´'X'> mark´'O'! <=mark´'O'> mark´'X' !\);
[$board::isWonOrDone] -> \(
when <=[]> do $getMove!
Line 13,734 ⟶ 15,474:
end play
 
$play -> !VOID</langsyntaxhighlight>
{{out}}
<pre>
Line 13,791 ⟶ 15,531:
=={{header|Tcl}}==
{{trans|Python}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
 
# This code splits the players from the core game engine
Line 13,911 ⟶ 15,651:
# Assemble the pieces
set ttt [TicTacToe new HumanPlayer RandomRoboPlayer]
$ttt game</langsyntaxhighlight>
Sample game:
<pre>
Line 13,962 ⟶ 15,702:
</pre>
 
=={{header|VBAUNIX Shell}}==
{{works with|Bourne Again SHell}}
Human play first with the "X". You must choose the row and the column you want to play...
The computer plays randomly.
<lang vb>
Option Explicit
 
<syntaxhighlight lang="sh">#!/usr/bin/env bash
Private Lines(1 To 3, 1 To 3) As String
# play tic-tac-toe
Private Nb As Byte, player As Byte
main() {
Private GameWin As Boolean, GameOver As Boolean
local play_again=1
while (( play_again )); do
local board=(1 2 3 4 5 6 7 8 9) tokens=(X O)
show_board "${board[@]}"
# player colors: computer is red, human is green
local computer=31 human=32
if (( RANDOM % 2 )); then
players=(computer human)
colors=($computer $human)
printf 'I go first!\n'
else
players=(human computer)
colors=($human $computer)
printf 'You go first!\n'
fi
local token winner
local -i turn=0
while ! winner=$(winner "${board[@]}"); do
token=${tokens[turn%2]}
case "${players[turn%2]}" in
human) board=($(human_turn "$token" "${board[@]}"));;
computer) board=($(computer_turn "$token" "${board[@]}"));;
*) printf 'Unknown player "%s"\n' "${players[turn%2]}"; exit 1;;
esac
show_board "${board[@]}" | sed -e "s/${tokens[0]}/"$'\e['"${colors[0]}"$'m&\e[0m/g' \
-e "s/${tokens[1]}/"$'\e['"${colors[1]}"$'m&\e[0m/g'
 
(( turn=turn+1 ))
Sub Main_TicTacToe()
done
Dim p As String
case "$winner${players[0]}" in
Ohuman|Xcomputer) printf 'I win!\n';;
Xhuman|Ocomputer) printf 'You win!\n';;
cat*) printf 'The cat wins!\n';;
esac
yorn 'Play again'
play_again=$(( ! $? ))
done
}
 
show_board() {
InitLines
printf '\n'
printLines Nb
printf '%s %s %s\n' "$@"
Do
printf '\n'
p = WhoPlay
}
Debug.Print p & " play"
If p = "Human" Then
Call HumanPlay
GameWin = IsWinner("X")
Else
Call ComputerPlay
GameWin = IsWinner("O")
End If
If Not GameWin Then GameOver = IsEnd
Loop Until GameWin Or GameOver
If Not GameOver Then
Debug.Print p & " Win !"
Else
Debug.Print "Game Over!"
End If
End Sub
 
winner() {
Sub InitLines(Optional S As String)
local board=("$@") i j k
Dim i As Byte, j As Byte
local lines=("0 Nb1 =2" "0: player3 =6" "0 4 8" "1 4 7"
"2 4 6" "2 5 8" "3 4 5" "6 7 8")
For i = LBound(Lines, 1) To UBound(Lines, 1)
local line i j k
For j = LBound(Lines, 2) To UBound(Lines, 2)
for line in "${lines[@]}"; do
Lines(i, j) = "#"
read i j k Next j<<<"$line"
Nextlocal token=${board[i]}
if [[ "${board[j]}" == $token && "${board[k]}" == $token ]]; then
End Sub
printf '%s\n' "$token"
return 0
fi
done
case "${board[*]}" in
*[1-9]*) return 1;;
*) printf 'cat\n'; return 0;;
esac
}
 
human_turn() {
Sub printLines(Nb As Byte)
local token=$1
Dim i As Byte, j As Byte, strT As String
shift
Debug.Print "Loop " & Nb
local board=("$@")
For i = LBound(Lines, 1) To UBound(Lines, 1)
local n=0
For j = LBound(Lines, 2) To UBound(Lines, 2)
while (( n < 1 || n > 9 )) strT|| =[[ strT"${board[n-1]}" &!= Lines(i,$n j)]]; do
printf 'Enter space number: ' "$n" "${board[n-1]}" >/dev/tty
Next j
read n </dev/tty >/dev/tty 2>&1
Debug.Print strT
done
strT = vbNullString
board[n-1]=$token
Next i
printf '%s\n' "${board[@]}"
End Sub
}
 
computer_turn() {
Function WhoPlay(Optional S As String) As String
local token=$1
If player = 0 Then
shift
player = 1
local board=("$@")
WhoPlay = "Human"
local i=0 blanks=() choice
Else
for (( i=0; i<9; ++i )); player = 0do
if [[ "${board[i]}" == WhoPlay[1-9] =]]; "Computer"then
End If blanks+=("$i")
fi
End Function
done
choice=${blanks[RANDOM % ${#blanks[@]}]}
board[choice]=$token
printf '%s\n' "${board[@]}"
}
 
yorn() {
Sub HumanPlay(Optional S As String)
local yorn=
Dim L As Byte, C As Byte, GoodPlay As Boolean
while [[ $yorn != [Yy]* && $yorn != [Nn]* ]]; do
printf '%s? ' "$*"
read yorn
done
[[ $yorn == [Yy]* ]]
}
 
main "$@"</syntaxhighlight>
Do
L = Application.InputBox("Choose the row", "Numeric only", Type:=1)
If L > 0 And L < 4 Then
C = Application.InputBox("Choose the column", "Numeric only", Type:=1)
If C > 0 And C < 4 Then
If Lines(L, C) = "#" And Not Lines(L, C) = "X" And Not Lines(L, C) = "O" Then
Lines(L, C) = "X"
Nb = Nb + 1
printLines Nb
GoodPlay = True
End If
End If
End If
Loop Until GoodPlay
End Sub
 
{{Out}}
Sub ComputerPlay(Optional S As String)
<pre>
Dim L As Byte, C As Byte, GoodPlay As Boolean
1 2 3
4 5 6
7 8 9
 
I go first!
Randomize Timer
I go in space Do5.
L = Int((Rnd * 3) + 1)
C = Int((Rnd * 3) + 1)
If Lines(L, C) = "#" And Not Lines(L, C) = "X" And Not Lines(L, C) = "O" Then
Lines(L, C) = "O"
Nb = Nb + 1
printLines Nb
GoodPlay = True
End If
Loop Until GoodPlay
End Sub
 
1 2 3
Function IsWinner(S As String) As Boolean
4 X 6
Dim i As Byte, j As Byte, Ch As String, strTL As String, strTC As String
7 8 9
 
Enter space number: 1
Ch = String(UBound(Lines, 1), S)
'check lines & columns
For i = LBound(Lines, 1) To UBound(Lines, 1)
For j = LBound(Lines, 2) To UBound(Lines, 2)
strTL = strTL & Lines(i, j)
strTC = strTC & Lines(j, i)
Next j
If strTL = Ch Or strTC = Ch Then IsWinner = True: Exit For
strTL = vbNullString: strTC = vbNullString
Next i
'check diagonales
strTL = Lines(1, 1) & Lines(2, 2) & Lines(3, 3)
strTC = Lines(1, 3) & Lines(2, 2) & Lines(3, 1)
If strTL = Ch Or strTC = Ch Then IsWinner = True
End Function
 
O 2 3
Function IsEnd() As Boolean
4 X 6
Dim i As Byte, j As Byte
7 8 9
 
I go in space 8.
For i = LBound(Lines, 1) To UBound(Lines, 1)
 
For j = LBound(Lines, 2) To UBound(Lines, 2)
O 2 3
If Lines(i, j) = "#" Then Exit Function
4 X 6
Next j
7 X 9
Next i
 
IsEnd = True
Enter space number: 2
End Function
 
</lang>
O O 3
{{out}}
4 X 6
<pre>Loop 0
7 X 9
###
 
###
I go in space 7.
###
 
Human Play
O O 3
Loop 1
4 X 6
X##
X X 9
###
 
###
Enter space number: 3
Computer Play
 
Loop 2
O O O
X#O
4 X 6
###
X X 9
###
 
Human Play
You win!
Loop 3
Play again? n
X#O
</pre>
#X#
 
###
=={{header|V (Vlang)}}==
Computer Play
{{trans|Kotlin}}
Loop 4
<syntaxhighlight lang="v (vlang)">
XOO
import rand
#X#
import os
###
 
Human Play
__global (
Loop 5
b = [3][3]int{}
XOO
best_i = 0
#X#
best_j = 0
##X
)
Human Win !</pre>
 
fn main() {
mut user := false
mut yn :=''
for {
user = !user
print(game(user))
for (yn != "y" ) && (yn != "n") {
yn = os.input('Play again y/n: ').str().to_lower()
}
if yn != "y" {exit(0)} else {yn =''}
println('')
}
}
 
fn game(user bool) string {
mut u := user
mut move, mut my_move, mut i, mut j, mut win := 0, 0, 0, 0, 0
for k in 0..3 {
for l in 0..3 {
if b[k][l] != 0 {b[k][l] = 0}
}
}
print("Board postions are numbered so:\n1 2 3\n4 5 6\n7 8 9\n")
print("You have O, I have X.\n\n")
for k in 1..9 {
if u {
for move !in [1,2,3,4,5,6,7,8,9] {
move = os.input('your move: ').int()
}
move--
i = move / 3
j = move % 3
if b[i][j] != 0 {continue}
b[i][j] = 1
move = 0
}
if !u {
if k == 1 {
best_i = (rand.int_in_range(1, 9) or {exit(1)}) % 3
best_j = (rand.int_in_range(1, 9) or {exit(1)}) % 3
}
else {test_move(-1, 0)}
b[best_i][best_j] = -1
my_move = best_i * 3 + best_j + 1
println("My move: $my_move")
}
show_board()
win = check_winner()
println("win res: $win")
if win != 0 {
if win == 1 {return "You win" + ".\n\n"}
else {return "I win" + ".\n\n"}
}
u = !u
}
return "A draw.\n\n"
}
 
fn check_winner() int {
for i in 0..3 {
if b[i][0] != 0 && b[i][1] == b[i][0] && b[i][2] == b[i][0] {return b[i][0]}
if b[0][i] != 0 && b[1][i] == b[0][i] && b[2][i] == b[0][i] {return b[0][i]}
}
if b[1][1] == 0 {return 0}
if b[1][1] == b[0][0] && b[2][2] == b[0][0] {return b[0][0]}
if b[1][1] == b[2][0] && b[0][2] == b[1][1] {return b[1][1]}
return 0
}
 
fn show_board() {
mut t := "X O"
for i in 0..3 {
for j in 0..3 {
print("${t[b[i][j] + 1].ascii_str()} ")
}
println('')
}
println("-----")
}
 
fn test_move(value int, depth int) int {
mut best := -1
mut changed := 0
mut score := check_winner()
if score != 0 {
if score == value {return 1} else {return -1}
}
for i in 0..3 {
for j in 0..3 {
if b[i][j] != 0 {continue}
b[i][j] = value
changed = value
score = -test_move(-value, depth + 1)
b[i][j] = 0
if score <= best {continue}
if depth == 0 {
best_i = i
best_j = j
}
best = score
}
}
if changed != 0 {return best}
return 0
}
</syntaxhighlight>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-ioutil}}
<langsyntaxhighlight ecmascriptlang="wren">import "random" for Random
import "./ioutil" for Input
 
var r = Random.new()
Line 14,226 ⟶ 16,080:
if (yn == "n" || yn == "N") return
System.print()
}</langsyntaxhighlight>
 
{{out}}
Line 14,289 ⟶ 16,143:
=={{header|XPL0}}==
[[File:TTTXPL0.GIF|right]]
<langsyntaxhighlight XPL0lang="xpl0">\The computer marks its moves with an "O" and the player uses an "X". The
\ numeric keypad is used to make the player's move.
\
Line 14,433 ⟶ 16,287:
[SetVid(3); exit]; \clear screen & restore normal text mode
];
]</langsyntaxhighlight>
 
=={{header|Yabasic}}==
In the classic style.
<lang Yabasic>5 REM Adaptation to Yabasic of the program published in Tim Hartnell's book "Artificial Intelligence: Concepts and Programs", with some minor modifications. 6/2018.
10 REM TICTAC
15 INPUT "English (0), Spanish (other key): " IDIOMA : IF NOT IDIOMA THEN RESTORE 2020 ELSE RESTORE 2010 END IF
20 GOSUB 1180: REM INICIALIZACION
30 REM *** REQUISITOS PREVIOS AL JUEGO ***
40 FOR J = 1 TO 9
50 A(J) = 32
60 NEXT J
70 FOR J = 1 TO 5
80 D(J) = 0
90 NEXT J
100 CCONTADOR = 0
110 R$ = ""
120 GOSUB 1070: REM IMPRESION DEL TABLERO
130 REM ** CICLO PRINCIPAL **
140 GOSUB 540: REM MOVIMIENTO DEL ORDENADOR
150 GOSUB 1070: REM IMPRESION DEL TABLERO
160 GOSUB 870: REM COMPRUEBA LA VICTORIA
170 IF R$ <> "" GOTO 240
180 GOSUB 980: REM SE ACEPTA EL MOVIMIENTO DE LA PERSONA
190 GOSUB 1070: REM IMPRESION DEL TABLERO
200 GOSUB 870: REM COMPRUEBA LA VICTORIA
210 IF R$ = "" GOTO 140
220 REM ** FIN DEL CICLO PRINCIPAL **
230 REM *****************************
240 REM FIN DEL JUEGO
250 GOSUB 1070: REM IMPRESION DEL TABLERO
260 PRINT: PRINT
270 IF R$ = "G" PRINT MENSAJE$(1): BANDERA = -1
280 IF R$ = "P" PRINT MENSAJE$(2): BANDERA = 1
290 IF R$ = "D" PRINT MENSAJE$(3): GOTO 430
300 REM ACTUALIZACION DE LA BASE DE DATOS
310 FOR B = 1 TO 5
320 FOR J = 2 TO 9
330 IF M(J) = D(B) GOSUB 370
340 NEXT J
350 NEXT B
360 GOTO 430
370 REM ** REORDENACION DE LOS ELEMENTOS DE LA MATRIZ M **
380 TEMP = M(J + BANDERA)
390 M(J + BANDERA) = M(J)
400 M(J) = TEMP
410 J = 9
420 RETURN
430 PRINT: PRINT
440 PRINT MENSAJE$(4)
450 PRINT: PRINT
460 FOR J = 1 TO 9
470 PRINT M(J), " ";
480 NEXT J
490 PRINT: PRINT
500 PRINT MENSAJE$(5)
510 INPUT A$
520 GOTO 30
530 REM ************************
540 REM MOVIMIENTO DEL ORDENADOR
550 P = ASC("O")
560 X = 0
570 J = 1
580 IF A(W(J)) = A(W(J + 1)) AND A(W(J + 2)) = 32 AND A(W(J)) = P X = W(J + 2): GOTO 750
590 IF A(W(J)) = A(W(J + 2)) AND A(W(J + 1)) = 32 AND A(W(J)) = P X = W(J + 1): GOTO 750
600 IF A(W(J + 1)) = A(W(J + 2)) AND A(W(J)) = 32 AND A(W(J + 1)) = P X = W(J): GOTO 750
610 IF J < 21 J = J + 3: GOTO 580
620 IF P = ASC("O") P = ASC("X"): GOTO 570
630 REM ** SI NO SE GANA SE BUSCA UN MOVIMIENTO DE BLOQUEO **
640 REM * ENTONCES SE USA LA SIGUIENTE SECCION *
650 J = 1
660 IF A(M(J)) = 32 X = M(J): GOTO 750
670 IF J < 10 J = J + 1: GOTO 660
680 H = 0
690 H = H + 1
700 X = INT(RAN(1) * 9): IF A(X) = 32 GOTO 750
710 IF H < 100 GOTO 690
720 R$ = "D": REM ES SIMPLEMENTE UN DIBUJO
730 RETURN
740 REM *********************
750 REM REALIZA EL MOVIMIENTO
760 A(X) = ASC("O")
770 CCONTADOR = CCONTADOR + 1
780 D(CCONTADOR) = X
790 BANDERA = 0
800 FOR J = 1 TO 9
810 IF A(J) = 32 BANDERA = 1
820 NEXT J
830 IF BANDERA = 0 AND R$ = "" R$ = "D"
840 REM SI TODAS LAS CASILLAS ESTAN LLENAS Y R$ ESTA VACIO, ENTONCES ES SIMPLEMENTE UN DIBUJO
850 RETURN
860 REM *********************
870 REM COMPRUEBA LA VICTORIA
880 J = 1
890 IF A(W(J)) = 32 J = J + 3
900 IF J > 23 RETURN
910 IF A(W(J)) = A(W(J + 1)) AND A(W(J)) = A(W(J + 2)) GOTO 940
920 IF J < 22 J = J + 3: GOTO 890
930 RETURN
940 IF A(W(J)) = ASC("O") R$ = "G": REM EL ORDENADOR GANA
950 IF A(W(J)) = ASC("X") R$ = "P": REM EL ORDENADOR PIERDE
960 RETURN
970 REM ************************
980 REM MOVIMIENTO DE LA PERSONA
990 PRINT: PRINT
1000 PRINT MENSAJE$(6)
1010 PRINT MENSAJE$(7); : INPUT MOVIMIENTO
1020 IF MOVIMIENTO < 1 OR MOVIMIENTO > 9 GOTO 1010
1030 IF A(MOVIMIENTO) <> 32 GOTO 1010
1040 A(MOVIMIENTO) = ASC("X")
1050 RETURN
1060 REM *********************
1070 REM IMPRESION DEL TABLERO
1080 CLEAR SCREEN
1090 PRINT: PRINT: PRINT
1100 PRINT " 1 : 2 : 3 ", CHR$(A(1)), " : ", CHR$(A(2)), " : ", CHR$(A(3))
1110 PRINT "----------- ------------"
1120 PRINT " 4 : 5 : 6 ", CHR$(A(4)), " : ", CHR$(A(5)), " : ", CHR$(A(6))
1130 PRINT "----------- ------------"
1140 PRINT " 7 : 8 : 9 ", CHR$(A(7)), " : ", CHR$(A(8)), " : ", CHR$(A(9))
1150 PRINT
1160 RETURN
1170 REM **************
1180 REM INICIALIZACION
1190 CLEAR SCREEN
1200 DIM A(9) : REM TABLERO
1210 DIM M(10) : REM ACCESO A LA BASE DE DATOS
1220 DIM W(24) : REM DATOS DE VICTORIA O BLOQUEO
1230 DIM D(5) : REM ACCESO AL MOVIMIENTO EN EL JUEGO ACTUAL
1235 DIM MENSAJE$(1) : READ M$ : N = TOKEN(M$,MENSAJE$(),",") : RESTORE
1240 REM DATOS DE VICTORIA O BLOQUEO
1250 FOR J = 1 TO 24
1260 READ W(J)
1270 NEXT J
1280 DATA 1, 2, 3, 4, 5, 6, 7, 8, 9
1290 DATA 1, 4, 7, 2, 5, 8, 3, 6, 9
1300 DATA 1, 5, 9, 3, 5, 7
1310 REM BASE INICIAL DE DATOS
1320 FOR J = 1 TO 10
1330 READ M(J)
1340 NEXT J
1350 DATA 2, 6, 8, 4, 7, 3, 1, 9, 5, 2
1360 RETURN
2000 REM MENSAJES EN ESPAÑOL
2010 DATA "YO GANO,TU GANAS,ES SIMPLEMENTE UN DIBUJO,ESTA ES MI PRIORIDAD ACTUALIZADA,PULSE LA TECLA <RETURN> PARA CONTINUAR,REALICE SU MOVIMIENTO,MOVIMIENTO: "
2020 DATA "I WIN,YOU WIN,IT'S JUST A DRAWING,THIS IS MY PRIORITY UPDATE,PRESS <RETURN> TO CONTINUE,TO MAKE YOUR MOVE,MOVEMENT: "
</lang>
 
{{omit from|GUISS}}
2

edits