Data update
This commit is contained in:
parent
29a5eea0d4
commit
5c1bb7bfa9
2011 changed files with 35081 additions and 3229 deletions
|
|
@ -1,94 +1,9 @@
|
|||
Note 'ttt adjudicates or plays'
|
||||
|
||||
use: markers ttt characters
|
||||
|
||||
characters represent the cell names.
|
||||
|
||||
markers is a length 3 character vector of the
|
||||
characters to use for first and second player
|
||||
followed by the opponent's mark.
|
||||
'XOX' means X plays 1st, O is the other mark,
|
||||
and the first strategy plays 1st.
|
||||
'XOO' means X plays 1st, O is the other mark,
|
||||
and the second strategy moves first.
|
||||
|
||||
The game is set up for the computer as the
|
||||
first strategy (random), and human as second.
|
||||
|
||||
A standard use:
|
||||
'XOX'ttt'abcdefghijkl'
|
||||
|
||||
Example game reformatted w/ emacs artist-mode
|
||||
to fit your display:
|
||||
|
||||
'#-#'ttt'wersdfxcv'
|
||||
w│e│r w│e│r .... -│e│r . -│e│#
|
||||
─┼─┼─ . ─┼─┼─ .. ─┼─┼─ .. ─┼─┼─
|
||||
s│d│f . s│#│f .. s│#│f .. -│#│f
|
||||
─┼─┼─ .. ─┼─┼─ . ─┼─┼─ ... ─┼─┼─
|
||||
x│c│v .. -│c│v . -│c│# .. -│c│#
|
||||
d .. v .. r . VICTORY
|
||||
w│e│r .. w│e│r .. -│e│# .
|
||||
─┼─┼─ ... ─┼─┼─ .. ─┼─┼─ .
|
||||
s│#│f ... s│#│f .. s│#│f .
|
||||
─┼─┼─ .. ─┼─┼─ ... ─┼─┼─ ...
|
||||
x│c│v -│c│# -│c│#
|
||||
-->cell for -? -->cell for -? -->cell for -?
|
||||
x w s
|
||||
)
|
||||
|
||||
while=: conjunction def 'u ^: v ^:_' NB. j assumes while is a verb and needs to know while is a conjunction.
|
||||
|
||||
ttt=: outcome@:((display@:move) while undecided)@:display@:prepare
|
||||
|
||||
blindfolded_variant=: outcome@:display@:(move while undecided)@:display@:prepare
|
||||
|
||||
outcome=: {&(>;:'kitty VICTORY')@:won NB. (outcome does not pass along the state)
|
||||
move=: post locate
|
||||
undecided=: won nor full
|
||||
prepare=: , board@:] NB. form the state vector
|
||||
|
||||
Note 'locate'
|
||||
is a monadic verb. y is the state vector.
|
||||
returns the character of the chosen cell.
|
||||
Generally:
|
||||
locate=: second_strategy`first_strategy@.(first = mark)
|
||||
Simplified:
|
||||
locate=: human_locate NB. human versus human
|
||||
)
|
||||
locate=: human_locate`computer_locate@.(first = mark)
|
||||
|
||||
display=: show [: (1 1,:5 5)&(];.0)@:": [: <"0 fold
|
||||
|
||||
computer_locate=: [: show@{. board -. marks NB. strategy: first available
|
||||
computer_locate=: [: show@({~ ?@:#) board -. marks NB. strategy: random
|
||||
|
||||
human_locate=: monad define
|
||||
state=. y
|
||||
m=. mark state
|
||||
b=. board state
|
||||
cells=. b -. marks state
|
||||
show '-->cell for ' , m , '?'
|
||||
whilst. cell -.@:e. cells do. cell =. {. (1!:1]1) , m end.
|
||||
)
|
||||
|
||||
post=: 2&A.@:(3&{.)@:[ prepare mark@:[`((i.~ board)~)`(board@:[)}
|
||||
|
||||
mark=: {. NB. mark of the current player from state
|
||||
marks=: 2&{. NB. extract both markers from state
|
||||
board=: _9&{. NB. extract board from state
|
||||
first=: 2&{ NB. extract first player from state
|
||||
|
||||
show=: [ smoutput
|
||||
|
||||
full=: 2 = #@:~.
|
||||
won=: test@:fold
|
||||
fold=: 3 3 $ board
|
||||
test=: [: any [: all [: infix_pairs_agree |:@:lines
|
||||
|
||||
lines=: , diagonal , diagonal@:|. , |:
|
||||
diagonal=: (<0 1)&|:
|
||||
all=: *./
|
||||
any=: +./
|
||||
nor=: 8 b.
|
||||
infix_pairs_agree=: 2&(=/\)
|
||||
'`turn board open full'=: {.`}.`(0=[{board@])`(0-.@e.board)
|
||||
'`cpu_move position'=: (?@#{])@([:I.0=board)`(cpu_move`you_move@.(_1 1 i.turn))
|
||||
you_move=: $:@echo@'invalid'^:(-.@e.i.@9)@:<:@".@{.@;:@(1!:1@1)
|
||||
move=: position (][echo@'already taken!')`(-@turn@] , turn@]`[`(board@])})@.open ]
|
||||
show=: [ [: echo@''@echo (,' '&,)/"1@({&'.XO')@(3 3$board) [ echo@''
|
||||
won=: [: +./ (3=[:|+/)"1@(], |:, (<@i.@#|:]),: <@i.@#|:|.)@(3 3$board)
|
||||
prompt=: echo@:>:@i.@3 3@echo@'enter a move (1–9) each turn; you''re X''s'
|
||||
outcome=: (echo@'tie')`(' wins'echo@,~{&'.XO'@-@turn)@.won
|
||||
ttt=: outcome@([F.(show@move[_2:Z:won+.full))@(10{._1)@prompt
|
||||
|
|
|
|||
151
Task/Tic-tac-toe/Jq/tic-tac-toe.jq
Normal file
151
Task/Tic-tac-toe/Jq/tic-tac-toe.jq
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
include "MRG32k3a" {search: "."}; # see comment above
|
||||
|
||||
### Generic functions
|
||||
|
||||
def inform(msg):
|
||||
. as $in
|
||||
| msg + "\n" | stderr
|
||||
| $in;
|
||||
|
||||
def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .;
|
||||
|
||||
# Create an m x n matrix with initial values specified by .
|
||||
def matrix($m; $n):
|
||||
if $m == 0 then []
|
||||
else . as $init
|
||||
| if $m == 1 then [range(0;$n) | $init]
|
||||
elif $m > 0 then
|
||||
matrix(1; $n) as $row
|
||||
| [range(0; $m) | $row ]
|
||||
else error("matrix\($m);\($n)) invalid")
|
||||
end
|
||||
end;
|
||||
|
||||
|
||||
### Tic-Tac-Toe
|
||||
|
||||
# The board is represented by a matrix in which:
|
||||
# 0 : blank; -1: computer; 1: user
|
||||
def init:
|
||||
{b: (0 | matrix(3;3)),
|
||||
bestI: 0,
|
||||
bestJ: 0,
|
||||
prng: seed(now | tostring | sub("^.*[.]";"") | tonumber)};
|
||||
|
||||
# Output: 0 if undecided, null if game over, otherwise the player id
|
||||
def checkWinner:
|
||||
first(range(0; 3) as $i
|
||||
| if .b[$i][0] != 0 and .b[$i][1] == .b[$i][0] and .b[$i][2] == .b[$i][0] then .b[$i][0]
|
||||
elif .b[0][$i] != 0 and .b[1][$i] == .b[0][$i] and .b[2][$i] == .b[0][$i] then .b[0][$i]
|
||||
else empty
|
||||
end)
|
||||
// if (.b[1][1] == 0) then 0
|
||||
elif (.b[1][1] == .b[0][0] and .b[2][2] == .b[0][0]) then .b[0][0]
|
||||
elif (.b[1][1] == .b[2][0] and .b[0][2] == .b[1][1]) then .b[1][1]
|
||||
elif all(.b[][]; . != 0) then null
|
||||
else 0
|
||||
end ;
|
||||
|
||||
def showBoard:
|
||||
["X", " ", "O"] as $t
|
||||
| .b as $b
|
||||
| range(0;3) as $i
|
||||
| reduce range(0;3) as $j ("";
|
||||
. + "\($t[$b[$i][$j] + 1]) " ), # b == -1 => "X"; b == 1 => "O"
|
||||
"-----";
|
||||
|
||||
# Examine possible moves of the player identified by $value, avoiding embarrassment
|
||||
# Set .result, .bestI, .bestJ, etc
|
||||
def testMove($value; $depth):
|
||||
checkWinner as $score
|
||||
| if $score == null then .result = 0
|
||||
elif $score != 0
|
||||
then .result = (if $score == $value then 1 else -1 end)
|
||||
else .best = -1
|
||||
| .changed = 0
|
||||
| reduce range(0;3) as $i (.;
|
||||
reduce range(0;3) as $j (.;
|
||||
if .b[$i][$j] == 0
|
||||
then .b[$i][$j] = $value
|
||||
| .changed = $value
|
||||
| testMove(-$value; $depth + 1) as $test
|
||||
| (-$test.result) as $score
|
||||
| .b[$i][$j] = 0
|
||||
| if $score > .best
|
||||
then if $depth == 0
|
||||
then .bestI = $i
|
||||
| .bestJ = $j
|
||||
end
|
||||
| .best = $score
|
||||
end
|
||||
end ) )
|
||||
| .result = if .changed != 0 then .best else 0 end
|
||||
end;
|
||||
|
||||
# Issue prompts on stderr;
|
||||
# always allow q for quit
|
||||
def read($prompt; $regex):
|
||||
def r:
|
||||
($prompt | stderr | empty),
|
||||
(try ((input
|
||||
| if . == "q" then halt
|
||||
else select(test($regex))
|
||||
end) // r)
|
||||
catch if . == "break" then halt else r end );
|
||||
r;
|
||||
|
||||
# Input: irrelevant
|
||||
# $user should be boolean; specify `true` if the user plays first
|
||||
def game($user):
|
||||
"Board positions are numbered so:\n1 2 3\n4 5 6\n7 8 9",
|
||||
"You have O, I have X.\n",
|
||||
(init + {$user}
|
||||
| label $out
|
||||
| foreach range(0;9) as $k (.;
|
||||
if .user
|
||||
then .move = null
|
||||
| until(.move;
|
||||
(read("Your move: "; "^ *[1-9]") | tonumber - 1) as $move
|
||||
| ($move/3|floor) as $i
|
||||
| ($move % 3) as $j
|
||||
| if .b[$i][$j] == 0
|
||||
then .b[$i][$j] = 1
|
||||
| .move = $move
|
||||
end )
|
||||
end
|
||||
| if (.user|not)
|
||||
then # in the interests of entertainment, randomize if computer opens
|
||||
if $k == 0
|
||||
then .prng |= nextFloat
|
||||
| .bestI = (.prng.nextFloat * 100 | trunc) % 3
|
||||
| .prng |= nextFloat
|
||||
| .bestJ = (.prng.nextFloat * 100 | trunc) % 3
|
||||
else testMove(-1; 0)
|
||||
end
|
||||
| .b[.bestI][.bestJ] = -1
|
||||
| inform("My move: \(.bestI * 3 + .bestJ + 1)")
|
||||
end
|
||||
| .user |= not
|
||||
;
|
||||
# Output:
|
||||
showBoard,
|
||||
(checkWinner
|
||||
| if . == 0 then empty
|
||||
else (if . == 1 then "You win"
|
||||
elif . == -1 then "I win"
|
||||
else "A draw.\n\n"
|
||||
end),
|
||||
break $out
|
||||
end ) )) ;
|
||||
|
||||
# Alternate players
|
||||
def controller:
|
||||
def c($user):
|
||||
game($user),
|
||||
(read("Play again? [yn]: "; "^[yYnN]") as $in
|
||||
| if $in|.[0:1]|ascii_downcase == "n" then halt
|
||||
else c($user|not)
|
||||
end);
|
||||
c(true);
|
||||
|
||||
controller
|
||||
Loading…
Add table
Add a link
Reference in a new issue