133 lines
3.5 KiB
Text
133 lines
3.5 KiB
Text
\( Simple (not perfect) solver for tic-tac-toe
|
|
The state is a 9-element vector, with
|
|
0 for free, 1 for user; 4 for machine
|
|
Lanes are used to check if there is a win or near-win:
|
|
1 2 3
|
|
4 5 6
|
|
7 8 9
|
|
1 4 7
|
|
2 5 8
|
|
3 6 9
|
|
1 5 9
|
|
3 5 7
|
|
For each lane, the sum of the values is calculated
|
|
and the number of free ones determined.
|
|
After the player's move and the machine action,
|
|
the lane sums are checked for wins:
|
|
- if = 3, the player has won, stop.
|
|
- if = 12, the machine has won, stop.
|
|
- if none are free, the game ends with a draw
|
|
The machine action is:
|
|
- if = 2, the player could win; set the free place
|
|
- if = 8, the machine will win, set the free place
|
|
- if field 5 is free, set
|
|
- if any of the fields 1, 3, 7 or 9 are free, set at random
|
|
- if any of the fields 2, 4, 6 or 8 are free, set at random
|
|
\)
|
|
main (parms):+
|
|
random set seed ()
|
|
print "enter field number, or 'x' to quit:"
|
|
state =: new row size 9 init 0
|
|
state.lanes =: ((1, 2, 3), (4, 5, 6), (7, 8, 9), (1, 4, 7), (2, 5, 8), (3, 6, 9), (1, 5, 9), (3, 5, 7))
|
|
state.free =: 9
|
|
?* state.free > 0
|
|
show state
|
|
set user state
|
|
show state
|
|
check end state
|
|
? state.free > 0
|
|
step move state
|
|
check end state
|
|
show state
|
|
|
|
check end (state):
|
|
?# t =: tuple state.lanes give values
|
|
c =: sum of places state lane t
|
|
\ print c, t
|
|
? c = 3:
|
|
print "You win:", t
|
|
?# i =: tuple t give values
|
|
state[i] =: '+'
|
|
state.free =: 0
|
|
:>
|
|
? c = 12:
|
|
print "I win:", t
|
|
?# i =: tuple t give values
|
|
state[i] =: '*'
|
|
state.free =: 0
|
|
:>
|
|
? state.free = 0
|
|
print "This is a draw."
|
|
|
|
step move (state):
|
|
?# t =: tuple state.lanes give values
|
|
c =: sum of places state lane t
|
|
? c = 2
|
|
set state at t
|
|
:>
|
|
? c = 8
|
|
set state at t
|
|
:>
|
|
? set state at 5
|
|
:>
|
|
? set state at shuffle 1, 3, 7, 9
|
|
:>
|
|
? set state at shuffle 2, 4, 6, 8
|
|
:>
|
|
|
|
set (state) at (points):
|
|
? ~ is points tuple
|
|
points =: points, () \ make it a tuple
|
|
?# i =: tuple points give values
|
|
? state[i] = 0
|
|
state[i] =: 4
|
|
print "my move:", i
|
|
:> ?+
|
|
:> ?-
|
|
|
|
shuffle (points):
|
|
n =: points.Count
|
|
r =: random tuple n
|
|
points =: tuple points select r
|
|
:> points
|
|
|
|
sum of places (state) lane (tpl):
|
|
s =: 0
|
|
?# i =: tuple tpl give values
|
|
v =: state[i]
|
|
? v ~= 0
|
|
s =+ state[i]
|
|
:> s
|
|
|
|
set user (state):
|
|
?*
|
|
print "your move: " nonl
|
|
c =: file stream () get
|
|
? c = 'q' || c = 'x' || c = ()
|
|
system exit 0
|
|
n =: string c as integer else ()
|
|
? n = () || n < 1 || n > state.Count
|
|
print "Invalid input, " nonl
|
|
?^
|
|
? state[n] = 0
|
|
state[n] =: 1
|
|
:>
|
|
print "not free; retry " nonl
|
|
|
|
show (state):
|
|
state.free =:0
|
|
?# i =: from 1 upto 9
|
|
v =: state[i]
|
|
w =: v
|
|
? v = 0
|
|
w =: i
|
|
state.free =+ 1
|
|
? v = 1
|
|
w =: 'X'
|
|
? v = 4
|
|
w =: 'O'
|
|
print ' ' _ w nonl
|
|
? i = 3 || i = 6
|
|
print ''
|
|
print ''
|
|
\ state.free=0 is used to terminate the central loop
|