Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
|
|
@ -1,7 +1,7 @@
|
|||
⎕IO←0 ⋄ t←1∘↑ ⋄ b←1∘↓ ⋄ c←{Z[?≢Z←⍸0=⍵]} ⍝ extract turn/board; cpu's move
|
||||
y←{3::∇⍵⊣⎕←'no' ⋄ ⍞←'move (1-9): ' ⋄ 0=⍵[p←⍎12↓⍞]: p ⋄ 2⌷0 0} ⍝ your move
|
||||
m←{((-,⊢)t⍵)@(0,{1=t⍵: y⍵ ⋄ c⍵}⍵)⊢⍵} ⍝ apply current player's move to board
|
||||
w←{∨/3=|+/(0 0⍉B)⍪(0 0⍉⌽B)⍪B⍪⍉B←3 3⍴b⍵} ⍝ has game been won?
|
||||
d←{⍵⊣⎕←' '⍪' '⍪⍨↑(⊣,' ',⊢)/3 3⍴'.XO'[0 1 ¯1⍳b⍵]} ⍝ display board
|
||||
o←{0∊b⍵: 'XO'[1=t⍵],' wins' ⋄ 'tie'} ⍝ determine and print game outcome
|
||||
g←{o d∘m⍣((w∨0~⍤∊b)⊣)10↑¯1} ⍝ game; move & display until won or full
|
||||
{⎕IO B T W WM←0(9⍴0)¯1 0(7 56 448 73 146 292 273 84⊤⍨9⍴2) ⍝ board; turn; win flag; winning trios
|
||||
_←{B[{1=T:{3::∇⊣⎕←'no'⋄⍞←'move (1-9): ' ⍝ your move
|
||||
B[P←¯1+⍎12↓⍞]=0:P⋄2⌷0 0}⍬
|
||||
Z[?≢Z←⍸0=B]}⍬]⊢←T⋄T⊢←-T ⍝ cpu's move; switch turn
|
||||
⊣⎕←' '⍪⍨↑(⊣,' ',⊢)/3 3⍴'.XO'[0 1 ¯1⍳B] ⍝ show board
|
||||
}⍣{(~0∊B)∨W⊢←∨/3=|B+.∧WM}⍬ ⍝ repeat until won or full
|
||||
W:'XO'[1=T],' wins'⋄'tie'}⍬ ⍝ print result
|
||||
|
|
|
|||
1
Task/Tic-tac-toe/APL/tic-tac-toe-10.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-10.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
B[…]⊢←val
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-11.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-11.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
B[…]←val
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-12.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-12.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
⊣⎕←…
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-13.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-13.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
VALUE ERROR
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-14.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-14.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
⍬
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-15.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-15.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
2⌷0 0
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-16.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-16.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
{3::∇⊣⎕←'no'⋄…⋄2⌷0 0}
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-17.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-17.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
B[p←¯1+⍎12↓⍞]
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-18.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-18.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
⎕signal 3
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-19.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-19.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
::
|
||||
|
|
@ -1 +1 @@
|
|||
g←{S←d m⍵ ⋄ w S: 'XO'[1=t S],' wins' ⋄ ~0∊b S: 'tie' ⋄ ∇S}10↑¯1⍨
|
||||
{{B[1=T:you⋄cpu]⊢←T ⋄ T⊢←-T ⋄ display}⍣{tied ∨ won} ⋄ won:winner⋄tie}⍬
|
||||
|
|
|
|||
1
Task/Tic-tac-toe/APL/tic-tac-toe-20.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-20.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
⎕signal
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-21.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-21.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
⎕signal
|
||||
7
Task/Tic-tac-toe/APL/tic-tac-toe-22.apl
Normal file
7
Task/Tic-tac-toe/APL/tic-tac-toe-22.apl
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
g←{⎕io T←0 ¯1⋄c←{Z[?≢Z←⍸0=⍵]} ⍝ turn; cpu's move
|
||||
y←{3::∇⊣⎕←'no'⋄⍞←'move (1-9):'⋄0=⍵[p←¯1+⍎12↓⍞]:p⋄2⌷0 0} ⍝ your move
|
||||
m←{{⍵⊣T⊢←-T}T@({1=T:y⍵⋄c⍵}⍵)⊢⍵} ⍝ apply move to board; switch turn
|
||||
w←{∨/3=|+/(0 0⍉B)⍪(0 0⍉⌽B)⍪B⍪⍉B←3 3⍴⍵} ⍝ has game been won?
|
||||
d←{⍵⊣⎕←' '⍪⍨↑(⊣,' ',⊢)/3 3⍴'.XO'[0 1 ¯1⍳⍵]} ⍝ display board
|
||||
o←{w⍵:'XO'[1=T],' wins'⋄'tie'} ⍝ determine game outcome
|
||||
o d∘m⍣(w⍤⊣∨0~⍤∊⊣)9⍴0} ⍝ move & display until won or full
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-23.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-23.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
S←d m⍵⋄w S:'XO'[1=T],' wins'⋄~0∊S:'tie'⋄∇S}9⍴0⍨
|
||||
8
Task/Tic-tac-toe/APL/tic-tac-toe-24.apl
Normal file
8
Task/Tic-tac-toe/APL/tic-tac-toe-24.apl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
⎕IO B WM←0(2 9⍴0)(7 56 448 73 146 292 273 84⊤⍨9⍴2) ⍝ the board and winning trios
|
||||
{_←{~⍵:{3::∇⊣⎕←'no'⋄⍞←'move (1-9): ' ⍝ your move
|
||||
(∨⌿B)[M←¯1+⍎12↓⍞]:2⌷0 0⋄B[0;M]⊢←1}⍬
|
||||
B[1;Z[?≢Z←⍸~∨⌿B]]⊢←1}⍵ ⍝ cpu's move
|
||||
_←{⎕←↑(⊣,' ',⊢)/⎕AV[3 3⍴⌈⌿(⎕AV⍳'.XO')×⍤¯1⊢B⍪⍨~∨⌿B]}⍣⍵⊢⍬ ⍝ show board after each cpu move
|
||||
W←∨/3=|B[⍵;]+.∧WM⋄F←511=2⊥∨⌿B ⍝ test win and full conditions
|
||||
_←{⎕OFF⊣⎕←' wins',⍨{W:'XO'[⍵]⋄'the cat'}⍵}⍣(W∨F)⊢⍵ ⍝ when game is over, exit and print winner
|
||||
~⍵}⍣{0}1 ⍝ now it's the other player's turn
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-3.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-3.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
{if: then ⋄ else}
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-4.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-4.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
7 56 448 73 146 292 273 84
|
||||
10
Task/Tic-tac-toe/APL/tic-tac-toe-5.apl
Normal file
10
Task/Tic-tac-toe/APL/tic-tac-toe-5.apl
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
7 56 448 73 146 292 273 84⊤⍨9⍴2
|
||||
0 0 1 0 0 1 1 0
|
||||
0 0 1 0 1 0 0 0
|
||||
0 0 1 1 0 0 0 1
|
||||
0 1 0 0 0 1 0 0
|
||||
0 1 0 0 1 0 1 1
|
||||
0 1 0 1 0 0 0 0
|
||||
1 0 0 0 0 1 0 1
|
||||
1 0 0 0 1 0 0 0
|
||||
1 0 0 1 0 0 1 0
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-6.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-6.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
∨/3=|B[⍵;]+.∧WINMASKS
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-7.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-7.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
WINMASKS
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-8.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-8.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
∨/3=|+/(0 0⍉M)⍪(0 0⍉⌽M)⍪M⍪⍉M←3 3⍴B
|
||||
1
Task/Tic-tac-toe/APL/tic-tac-toe-9.apl
Normal file
1
Task/Tic-tac-toe/APL/tic-tac-toe-9.apl
Normal file
|
|
@ -0,0 +1 @@
|
|||
{…}⍣{…}
|
||||
124
Task/Tic-tac-toe/Ada/tic-tac-toe.adb
Normal file
124
Task/Tic-tac-toe/Ada/tic-tac-toe.adb
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
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
|
||||
|
||||
procedure Tic_Tac_Toe is
|
||||
|
||||
type The_Range is range 1 .. 3;
|
||||
type Board_Type is array (The_Range, The_Range) of Character;
|
||||
|
||||
package Rand is new Ada.Numerics.Discrete_Random(The_Range);
|
||||
Gen: Rand.Generator; -- required for the random moves
|
||||
|
||||
procedure Show_Board(Board: Board_Type) is
|
||||
use Ada.Text_IO;
|
||||
begin
|
||||
for Row in The_Range loop
|
||||
for Column in The_Range loop
|
||||
Put(Board(Row, Column));
|
||||
end loop;
|
||||
Put_Line("");
|
||||
end loop;
|
||||
Put_Line("");
|
||||
end Show_Board;
|
||||
|
||||
function Find_Winner(Board: Board_Type) return Character is
|
||||
-- if 'x' or 'o' wins, it returns that, else it returns ' '
|
||||
|
||||
function Three_Equal(A,B,C: Character) return Boolean is
|
||||
begin
|
||||
return (A=B) and (A=C);
|
||||
end Three_Equal;
|
||||
|
||||
begin -- Find_Winner
|
||||
for I in The_Range loop
|
||||
if Three_Equal(Board(I,1), Board(I,2), Board(I,3)) then
|
||||
return Board(I,1);
|
||||
elsif Three_Equal(Board(1,I), Board(2,I), Board(3,I)) then
|
||||
return Board(1,I);
|
||||
end if;
|
||||
end loop;
|
||||
if Three_Equal(Board(1,1), Board(2,2), Board (3,3)) or
|
||||
Three_Equal(Board(3,1), Board(2,2), Board (1,3)) then
|
||||
return Board(2,2);
|
||||
end if;
|
||||
return ' ';
|
||||
end Find_Winner;
|
||||
|
||||
procedure Do_Move(Board: in out Board_Type;
|
||||
New_Char: Character; Computer_Move: Boolean) is
|
||||
Done: Boolean := False;
|
||||
C: Character;
|
||||
use Ada.Text_IO;
|
||||
|
||||
procedure Do_C_Move(Board: in out Board_Type; New_Char: Character) is
|
||||
Found: Boolean := False;
|
||||
X,Y: The_Range;
|
||||
begin
|
||||
while not Found loop
|
||||
X := Rand.Random(Gen);
|
||||
Y := Rand.Random(Gen);
|
||||
if (Board(X,Y) /= 'x') and (Board(X,Y) /= 'o') then
|
||||
Found := True;
|
||||
Board(X,Y) := New_Char;
|
||||
end if;
|
||||
end loop;
|
||||
end Do_C_Move;
|
||||
|
||||
begin
|
||||
if Computer_Move then
|
||||
Do_C_Move(Board, New_Char);
|
||||
else -- read move;
|
||||
Put_Line("Choose your move, " & New_Char);
|
||||
while not Done loop
|
||||
Get(C);
|
||||
for Row in The_Range loop
|
||||
for Col in The_Range loop
|
||||
if Board(Row, Col) = C then
|
||||
Board(Row, Col) := New_Char;
|
||||
Done := True;
|
||||
end if;
|
||||
end loop;
|
||||
end loop;
|
||||
end loop;
|
||||
end if;
|
||||
end Do_Move;
|
||||
|
||||
The_Board : Board_Type := (('1','2','3'), ('4','5','6'), ('7','8','9'));
|
||||
Cnt_Moves: Natural := 0;
|
||||
Players: array(0 .. 1) of Character := ('x', 'o'); -- 'x' begins
|
||||
C_Player: array(0 .. 1) of Boolean := (False, False);
|
||||
Reply: Character;
|
||||
|
||||
begin -- Tic_Tac_Toe
|
||||
|
||||
-- firstly, ask whether the computer shall take over either player
|
||||
for I in Players'Range loop
|
||||
Ada.Text_IO.Put_Line("Shall " & Players(I) &
|
||||
" be run by the computer? (y=yes)");
|
||||
Ada.Text_IO.Get(Reply);
|
||||
if Reply='y' or Reply='Y' then
|
||||
C_Player(I) := True;
|
||||
Ada.Text_IO.Put_Line("Yes!");
|
||||
else
|
||||
Ada.Text_IO.Put_Line("No!");
|
||||
end if;
|
||||
end loop;
|
||||
Rand.Reset(Gen); -- to initalize the random generator
|
||||
|
||||
-- now run the game
|
||||
while (Find_Winner(The_Board) = ' ') and (Cnt_Moves < 9) loop
|
||||
Show_Board(The_Board);
|
||||
Do_Move(The_Board, Players(Cnt_Moves mod 2), C_Player(Cnt_Moves mod 2));
|
||||
Cnt_Moves := Cnt_Moves + 1;
|
||||
end loop;
|
||||
Ada.Text_IO.Put_Line("This is the end!");
|
||||
|
||||
-- finally, output the outcome
|
||||
Show_Board (The_Board);
|
||||
if Find_Winner(The_Board) = ' ' then
|
||||
Ada.Text_IO.Put_Line("Draw");
|
||||
else
|
||||
Ada.Text_IO.Put_Line("The winner is: " & Find_Winner(The_Board));
|
||||
end if;
|
||||
end Tic_Tac_Toe;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
len f[] 9
|
||||
state = 0
|
||||
gtextsize 14
|
||||
gtextsize 13
|
||||
#
|
||||
proc init .
|
||||
glinewidth 2
|
||||
|
|
@ -52,31 +52,31 @@ proc rate &res &done .
|
|||
if f[i] = 0 : cnt += 1
|
||||
.
|
||||
res *= cnt
|
||||
done = 1
|
||||
if res = 0 and cnt > 1 : done = 0
|
||||
done = 0
|
||||
if res <> 0 or cnt = 1 : done = 1
|
||||
.
|
||||
proc minmax player alpha beta &rval &rmov .
|
||||
rate rval done
|
||||
if done = 1
|
||||
if player = 1 : rval = -rval
|
||||
else
|
||||
rval = alpha
|
||||
start = random 9
|
||||
mov = start
|
||||
repeat
|
||||
if f[mov] = 0
|
||||
f[mov] = player
|
||||
minmax (5 - player) (-beta) (-rval) val h
|
||||
val = -val
|
||||
f[mov] = 0
|
||||
if val > rval
|
||||
rval = val
|
||||
rmov = mov
|
||||
.
|
||||
return
|
||||
.
|
||||
rval = alpha
|
||||
start = random 1 9
|
||||
mov = start
|
||||
repeat
|
||||
if f[mov] = 0
|
||||
f[mov] = player
|
||||
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 mod 9 + 1
|
||||
until mov = start or rval >= beta
|
||||
.
|
||||
.
|
||||
proc show_result val .
|
||||
|
|
@ -91,36 +91,36 @@ proc show_result val .
|
|||
.
|
||||
state += 2
|
||||
.
|
||||
proc computer .
|
||||
proc computer_turn .
|
||||
minmax 4 -11 11 val mov
|
||||
f[mov] = 4
|
||||
draw mov
|
||||
rate val done
|
||||
state = 0
|
||||
if done = 1 : show_result val
|
||||
.
|
||||
proc human .
|
||||
mov = floor ((mouse_x - 6) / 28) + 3 * floor ((mouse_y - 16) / 28) + 1
|
||||
if f[mov] = 0
|
||||
f[mov] = 1
|
||||
draw mov
|
||||
state = 1
|
||||
if done = 1
|
||||
timer 0.5
|
||||
else
|
||||
state = 0
|
||||
.
|
||||
.
|
||||
proc human_turn .
|
||||
mov = floor ((mouse_x - 6) / 28) + 3 * floor ((mouse_y - 16) / 28) + 1
|
||||
if f[mov] <> 0 : return
|
||||
f[mov] = 1
|
||||
draw mov
|
||||
state = 1
|
||||
timer 0.5
|
||||
.
|
||||
on timer
|
||||
rate val done
|
||||
if done = 1
|
||||
show_result val
|
||||
else
|
||||
computer
|
||||
computer_turn
|
||||
.
|
||||
.
|
||||
on mouse_down
|
||||
if state = 0
|
||||
if mouse_x > 6 and mouse_x < 90 and mouse_y > 16
|
||||
human
|
||||
.
|
||||
if state = 0 and mouse_x - 6 < 84 and mouse_y > 16
|
||||
human_turn
|
||||
elif state >= 2
|
||||
state -= 2
|
||||
init
|
||||
|
|
|
|||
100
Task/Tic-tac-toe/Euphoria/tic-tac-toe.eu
Normal file
100
Task/Tic-tac-toe/Euphoria/tic-tac-toe.eu
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
include std/console.e
|
||||
include std/text.e
|
||||
include std/search.e
|
||||
include std/sequence.e
|
||||
|
||||
sequence board
|
||||
sequence players = {"X","O"}
|
||||
|
||||
function DisplayBoard()
|
||||
for i = 1 to 3 do
|
||||
for j = 1 to 3 do
|
||||
printf(1,"%s",board[i][j])
|
||||
if j < 3 then
|
||||
printf(1,"%s","|")
|
||||
end if
|
||||
end for
|
||||
if i < 3 then
|
||||
puts(1,"\n-----\n")
|
||||
else
|
||||
puts(1,"\n\n")
|
||||
end if
|
||||
end for
|
||||
|
||||
return 1
|
||||
end function
|
||||
|
||||
function CheckWinner()
|
||||
sequence temp = board
|
||||
for a = 1 to 2 do
|
||||
for i = 1 to 3 do
|
||||
if equal({"X","X","X"},temp[i]) then
|
||||
puts(1,"X wins\n\n")
|
||||
return 1
|
||||
elsif equal({"O","O","O"},temp[i]) then
|
||||
puts(1,"O wins\n\n")
|
||||
return 1
|
||||
end if
|
||||
end for
|
||||
temp = columnize(board)
|
||||
end for
|
||||
if equal({"X","X","X"},{board[1][1],board[2][2],board[3][3]}) or
|
||||
equal({"X","X","X"},{board[1][3],board[2][2],board[3][1]}) then
|
||||
puts(1,"X wins\n")
|
||||
return 1
|
||||
elsif equal({"O","O","O"},{board[1][1],board[2][2],board[3][3]}) or
|
||||
equal({"O","O","O"},{board[1][3],board[2][2],board[3][1]}) then
|
||||
puts(1,"O wins\n")
|
||||
return 1
|
||||
end if
|
||||
|
||||
if moves = 9 then
|
||||
puts(1,"Draw\n\n")
|
||||
return 1
|
||||
end if
|
||||
|
||||
return 0
|
||||
end function
|
||||
|
||||
integer turn, row, column, moves
|
||||
sequence replay
|
||||
while 1 do
|
||||
board = repeat(repeat(" ",3),3)
|
||||
DisplayBoard()
|
||||
turn = rand(2)
|
||||
moves = 0
|
||||
|
||||
while 1 do
|
||||
while 1 do
|
||||
printf(1,"%s's turn\n",players[turn])
|
||||
row = prompt_number("Enter row: ",{})
|
||||
column = prompt_number("Enter column: ",{})
|
||||
if match(board[row][column]," ") then
|
||||
board[row][column] = players[turn]
|
||||
moves += 1
|
||||
exit
|
||||
else
|
||||
puts(1,"Space already taken - pick again\n")
|
||||
end if
|
||||
end while
|
||||
|
||||
DisplayBoard()
|
||||
|
||||
if CheckWinner() then
|
||||
exit
|
||||
end if
|
||||
|
||||
if turn = 1 then
|
||||
turn = 2
|
||||
else
|
||||
turn = 1
|
||||
end if
|
||||
end while
|
||||
|
||||
replay = lower(prompt_string("Play again (y/n)?\n\n"))
|
||||
|
||||
if match(replay,"n") then
|
||||
exit
|
||||
end if
|
||||
|
||||
end while
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
'`c t b'=. (?@#{])@([:I.0=b)`{.`}. NB. cpu's move; extract turn/board
|
||||
i=. (0=]{b@[) ::0 *: ]e.i.@9 NB. invalid posn? (x: state; y: posn)
|
||||
i=. (0=]{b@[) ::0 *: ]e.i.@9 NB. invalid posn? (x: state; y: posn)
|
||||
y=. [ ($:@[ echo@'no')^:i _1+0".1!:1@1@echo@'move (1-9):' NB. your move
|
||||
m=. (-,])@t [`(0,1+c`y@.(1=t)@])} ] NB. apply current player's move to board
|
||||
o=. 'tie'"_`(' wins',~ {&'.XO'@-@t)@.w NB. print game outcome
|
||||
|
|
|
|||
89
Task/Tic-tac-toe/Julia/tic-tac-toe-1.jl
Normal file
89
Task/Tic-tac-toe/Julia/tic-tac-toe-1.jl
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# The state of the game is represented as a vector of moves made so far
|
||||
const TTT = Vector{Int}
|
||||
|
||||
@enum Role N X O # N = 0, neither X nor O
|
||||
role(turn::Int) = isodd(turn) ? X : O
|
||||
|
||||
# game state functions:
|
||||
next_role(moves::TTT) = role(length(moves)+1)
|
||||
available(moves::TTT) = setdiff(1:9, moves)
|
||||
function winner(moves::TTT)
|
||||
wintriples = [
|
||||
[1, 2, 3], [4, 5, 6], [7, 8, 9], # rows
|
||||
[1, 4, 7], [2, 5, 8], [3, 6, 9], # columns
|
||||
[1, 5, 9], [3, 5, 7] ] # diagonals
|
||||
turn = length(moves); XorO = role(turn)
|
||||
inmoves(triple) = all(∈(moves[Int(XorO):2:end]), triple)
|
||||
turn ≥ 5 && any(inmoves, wintriples) && return XorO
|
||||
N
|
||||
end
|
||||
|
||||
# scoring a state of the game with the recursive negamax algorithm
|
||||
negamax(moves::TTT) = winner(moves) ≠ N ? 1 : length(moves) == 9 ? 0 :
|
||||
-maximum(negamax([moves; move]) for move ∈ available(moves))
|
||||
|
||||
scored_options(moves::TTT) =
|
||||
Dict(move => negamax([moves; move]) for move ∈ available(moves))
|
||||
|
||||
# players of X and O with different intelligence
|
||||
abstract type Player end
|
||||
|
||||
struct RandomBot <: Player end
|
||||
select_move(::RandomBot, moves::TTT) = rand(available(moves))
|
||||
|
||||
struct NegamaxBot <: Player end
|
||||
function select_move(::NegamaxBot, moves::TTT)
|
||||
opts = scored_options(moves)
|
||||
maxscore = maximum(values(opts))
|
||||
rand([move for (move, score) ∈ opts if score == maxscore])
|
||||
end
|
||||
|
||||
struct Human <: Player name::String end
|
||||
function select_move(player::Human, moves::TTT)
|
||||
move = 0
|
||||
while move ∉ available(moves)
|
||||
print(player, " as ", next_role(moves), ", enter your move: ")
|
||||
move = try parse(Int, readline()) catch; 0 end
|
||||
end
|
||||
move
|
||||
end
|
||||
|
||||
Base.show(io::IO, player::Player) =
|
||||
print(io, player isa Human ? player.name : typeof(player))
|
||||
|
||||
function displayboard(moves::TTT, hints = false)
|
||||
reset = "\e[0m"; bold = reset * "\e[1m"; faint = reset * "\e[2m"
|
||||
board = fill(" ", 9)
|
||||
fillmove((i, move)) = board[move] = bold * repr(role(i)) * faint
|
||||
foreach(fillmove, enumerate(moves))
|
||||
fillscore((move, score)) =
|
||||
board[move] = isone(score) ? "+" : iszero(score) ? "·" : "-"
|
||||
hints && foreach(fillscore, scored_options(moves))
|
||||
matrix = reshape([n*m for (n, m) in zip("¹²³⁴⁵⁶⁷⁸⁹", board)], 3, 3)
|
||||
to_row(col) = join(col, " │")
|
||||
rows = join(to_row.(eachcol(matrix)), "\n───┼───┼───\n")
|
||||
println(faint, " ╷ ╷\n", rows, "\n ╵ ╵", reset)
|
||||
end
|
||||
|
||||
function ttt(Xplayer::Player, Oplayer::Player; hints = true)
|
||||
moves = TTT(); cast = Dict(X => Xplayer, O => Oplayer)
|
||||
println("\n","-"^40,"\nLet's play TicTacToe")
|
||||
println("Cast: X => $Xplayer, O => $Oplayer\n", "-"^40)
|
||||
while winner(moves) == N && length(moves) < 9
|
||||
displayboard(moves, hints)
|
||||
XorO = next_role(moves)
|
||||
player = cast[XorO]
|
||||
move = select_move(player, moves)
|
||||
player isa Human ||
|
||||
println(player, " as ", XorO, " plays move: ", move)
|
||||
push!(moves, move)
|
||||
end
|
||||
displayboard(moves)
|
||||
XorO = winner(moves)
|
||||
println( XorO == N ? "It's a draw!" :
|
||||
cast[XorO] isa Human ? "Congratulations, $(cast[XorO])! You win!" :
|
||||
"$player as $XorO wins!" )
|
||||
end
|
||||
|
||||
ttt(RandomBot(), NegamaxBot(); hints = false)
|
||||
ttt(RandomBot(), Human("Alice"))
|
||||
41
Task/Tic-tac-toe/Julia/tic-tac-toe-2.jl
Normal file
41
Task/Tic-tac-toe/Julia/tic-tac-toe-2.jl
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# the functions provided above are mandatory
|
||||
|
||||
function result_distribution(moves::TTT, casts::Dict{Role, Player})
|
||||
w = winner(moves)
|
||||
distribution = Dict(p => 0//1 for p in instances(Role))
|
||||
if w ≠ N
|
||||
distribution[w] = 1//1
|
||||
return 1, 1, distribution
|
||||
elseif length(moves) == 9
|
||||
distribution[N] = 1//1
|
||||
return 0, 1, distribution
|
||||
else
|
||||
scores = [result_distribution([moves; move], casts)
|
||||
for move in setdiff(1:9, moves)]
|
||||
maxscore = maximum(s[1] for s in scores)
|
||||
p = role(length(moves)+1)
|
||||
casts[p] isa NegamaxBot && filter!(s -> s[1] == maxscore, scores)
|
||||
n = length(scores)
|
||||
distribution = Dict(p => sum(s[3][p] for s in scores) // n for p in instances(Role))
|
||||
return -maxscore, sum(s[2] for s in scores), distribution
|
||||
end
|
||||
end
|
||||
|
||||
function bot_statistics()
|
||||
casts = [RandomBot(), NegamaxBot()]
|
||||
combinations = Dict{Role, Player}[Dict(X => x, O => o) for x in casts for o in casts]
|
||||
println("--------------------------------------------------------------")
|
||||
println(" as X - as O | games | draws X wins O wins")
|
||||
println("--------------------------------------------------------------")
|
||||
for combi in combinations
|
||||
distrib = result_distribution(Int[], combi)
|
||||
print("$(lpad(combi[X], 10)) - $(rpad(combi[O], 10)) | ", lpad(distrib[2], 6), " | ")
|
||||
for role in [N, X, O]
|
||||
print(" $(lpad(round(100 * distrib[3][role], digits=1), 5))% ")
|
||||
end
|
||||
println()
|
||||
end
|
||||
println("--------------------------------------------------------------")
|
||||
end
|
||||
|
||||
bot_statistics()
|
||||
|
|
@ -2,6 +2,6 @@ b::2 9#0; WINMASKS::((9#2)\)'7 56 448 73 146 292 273 84 / the board a
|
|||
{1}{({`1:"MOVE: ";$[(|/b)m:(`I$-1_1:`)-1;o`0:"NO";b[0;m]::1]} / your move
|
||||
{b[1;*1?&~|/b]::1})[x;] / cpu's move
|
||||
x{`0:" "/'`c$3 3#|/"XO*"*b,,~|/b}/0 / show board after each move
|
||||
w:|/3=0^WINMASKS(+/&)\:b x;t:511=2/|/b / test win and tie conditions
|
||||
$[w|t;{`0:x," won";`exit 0}("XO"x;"the cat")t;] / when game is over, exit and print winner
|
||||
w:|/3=0^WINMASKS(+/&)\:b x;f:511=2/|/b / test win and full conditions
|
||||
$[w|f;[`0:("the cat";"XO"x)[w]," won";`exit 0];] / when game is over, exit and print winner
|
||||
~x}/1 / now it's other player's turn
|
||||
|
|
|
|||
90
Task/Tic-tac-toe/Lua/tic-tac-toe-1.lua
Normal file
90
Task/Tic-tac-toe/Lua/tic-tac-toe-1.lua
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
local player_O, blank, player_X = -1, 0, 1
|
||||
local show_tile = {[player_O]="O", [blank]="-", [player_X]="X"}
|
||||
|
||||
function valid_pos_Q(pos)
|
||||
return type(pos) == "number" and pos%1 == 0 and 1 <= pos and pos <= 9
|
||||
end
|
||||
|
||||
function member_Q(arr, e) -- Does `arr` contain `e`?
|
||||
for _, val in ipairs(arr) do
|
||||
if val == e then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function full_Q(board) return not member_Q(board, blank) end
|
||||
|
||||
function sum(arr, idxs)
|
||||
local result = 0
|
||||
for _,i in ipairs(idxs) do result = result + arr[i] end
|
||||
return result
|
||||
end
|
||||
|
||||
-- rcd stands for rows, columns, and diagonals
|
||||
local rcd = {{1,2,3},{4,5,6},{7,8,9}, {1,4,7},{2,5,8},{3,6,9}, {1,5,9},{3,5,7}}
|
||||
|
||||
function won_Q(board)
|
||||
for _,idxs in ipairs(rcd) do
|
||||
if math.abs(sum(board, idxs)) == 3 then
|
||||
return true
|
||||
end -- if
|
||||
end -- for
|
||||
return false
|
||||
end
|
||||
|
||||
function you(board)
|
||||
local position
|
||||
repeat
|
||||
io.write("Enter a move(1-" .. 9 .. "): ")
|
||||
position = tonumber(io.read("*line"))
|
||||
until valid_pos_Q(position) and board[position] == blank
|
||||
return position
|
||||
end
|
||||
|
||||
function cpu(board)
|
||||
for position, value in ipairs(board) do
|
||||
if value == blank then return position end
|
||||
end
|
||||
end
|
||||
|
||||
function pos(board) -- a players takes a turn, returns chosen position
|
||||
if board[0] == player_O then
|
||||
return cpu(board)
|
||||
else
|
||||
return you(board)
|
||||
end
|
||||
end
|
||||
|
||||
function move(board)
|
||||
assert(not full_Q(board))
|
||||
local position = pos(board)
|
||||
board[position] = board[0]
|
||||
board[0] = -board[0] -- toggle whose turn
|
||||
return board
|
||||
end
|
||||
|
||||
function show(board)
|
||||
for key, val in ipairs(board) do
|
||||
io.write(show_tile[val] .. " ")
|
||||
if key % 3 == 0 then io.write"\n" end
|
||||
end -- for
|
||||
io.write"\n"
|
||||
end
|
||||
|
||||
-- board[0] indicates whose turn it is
|
||||
local the_board = { [0]=player_O }
|
||||
for i = 1, 9 do the_board[i] = blank end
|
||||
|
||||
repeat
|
||||
move(the_board)
|
||||
show(the_board)
|
||||
until won_Q(the_board) or full_Q(the_board)
|
||||
|
||||
if won_Q(the_board) then
|
||||
print (show_tile[-the_board[0]], "wins!")
|
||||
elseif full_Q(the_board) then
|
||||
print("tie!")
|
||||
else
|
||||
print("incomplete game")
|
||||
assert(false) -- this should be logically impossible
|
||||
end -- if
|
||||
190
Task/Tic-tac-toe/Lua/tic-tac-toe-2.lua
Normal file
190
Task/Tic-tac-toe/Lua/tic-tac-toe-2.lua
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
#!/usr/bin/env luajit
|
||||
ffi=require"ffi"
|
||||
local function printf(fmt,...) io.write(string.format(fmt, ...)) end
|
||||
local board="123456789" -- board
|
||||
local pval={1, -1} -- player 1=1 2=-1 for negamax
|
||||
local pnum={} for k,v in ipairs(pval) do pnum[v]=k end
|
||||
local symbol={'X','O'} -- default symbols X and O
|
||||
local isymbol={} for k,v in pairs(symbol) do isymbol[v]=pval[k] end
|
||||
math.randomseed(os.time()^5*os.clock()) -- time-seed the random gen
|
||||
local random=math.random
|
||||
-- usage of ffi variables give 20% speed
|
||||
ffi.cdef[[
|
||||
typedef struct{
|
||||
char value;
|
||||
char flag;
|
||||
int depth;
|
||||
}cData;
|
||||
]]
|
||||
-- draw the "board" in the way the numpad is organized
|
||||
local function draw(board)
|
||||
for i=7,1,-3 do
|
||||
print(board:sub(i,i+2))
|
||||
end
|
||||
end
|
||||
-- pattern for win situations
|
||||
local check={"(.)...%1...%1","..(.).%1.%1..",
|
||||
"(.)%1%1......","...(.)%1%1...","......(.)%1%1",
|
||||
"(.)..%1..%1..",".(.)..%1..%1.","..(.)..%1..%1",
|
||||
}
|
||||
-- calculate a win situation for which player or draw
|
||||
local function win(b)
|
||||
local sub
|
||||
for i=1,#check do
|
||||
sub=b:match(check[i])
|
||||
if sub then break end
|
||||
end
|
||||
sub=isymbol[sub]
|
||||
return sub or 0
|
||||
end
|
||||
-- input only validate moves of not yet filled positions
|
||||
local function input(b,player)
|
||||
char=symbol[pnum[player]]
|
||||
local inp
|
||||
repeat
|
||||
printf("Player %d (\"%s\") move: ",pnum[player],char)
|
||||
inp=tonumber(io.read()) or 0
|
||||
until inp>=1 and inp<=9 and b:find(inp)
|
||||
b=b:gsub(inp,char)
|
||||
return b,inp
|
||||
end
|
||||
-- ask how many human or AI players
|
||||
local function playerselect()
|
||||
local ai={}
|
||||
local yn
|
||||
for i=1,2 do
|
||||
repeat
|
||||
printf("Player %d human (Y/n)? ", i) yn=io.read():lower()
|
||||
until yn:match("[yn]") or yn==''
|
||||
if yn=='n' then
|
||||
ai[pval[i]]=true
|
||||
printf("Player %d is AI\n", i)
|
||||
else
|
||||
printf("Player %d is human\n", i)
|
||||
end
|
||||
end
|
||||
return ai
|
||||
end
|
||||
local function endgame()
|
||||
repeat
|
||||
printf("\nEnd game? (y/n)? ", i) yn=io.read():lower()
|
||||
until yn:match("[yn]")
|
||||
if yn=='n' then
|
||||
return false
|
||||
else
|
||||
printf("\nGOOD BYE PROFESSOR FALKEN.\n\nA STRANGE GAME.\nTHE ONLY WINNING MOVE IS\nNOT TO PLAY.\n\nHOW ABOUT A NICE GAME OF CHESS?\n")
|
||||
return true
|
||||
end
|
||||
end
|
||||
-- AI Routine
|
||||
local function shuffle(t)
|
||||
for i=#t,1,-1 do
|
||||
local rnd=random(i)
|
||||
t[i], t[rnd] = t[rnd], t[i]
|
||||
end
|
||||
return t
|
||||
end
|
||||
-- move generator
|
||||
local function genmove(node, color)
|
||||
return coroutine.wrap(function()
|
||||
local moves={}
|
||||
for m in node:gmatch("%d") do
|
||||
moves[#moves+1]=m
|
||||
end
|
||||
shuffle(moves) -- to make it more interesting
|
||||
for _,m in ipairs(moves) do
|
||||
local child=node:gsub(m,symbol[pnum[color]])
|
||||
coroutine.yield(child, m)
|
||||
end
|
||||
end)
|
||||
end
|
||||
--[[
|
||||
Negamax with alpha-beta pruning and table caching
|
||||
]]
|
||||
local cache={}
|
||||
local best, aimove, tDepth
|
||||
local LOWERB,EXACT,UPPERB=-1,0,1 -- has somebody an idea how to make them real constants?
|
||||
local function negamax(node, depth, color, α, β)
|
||||
color=color or 1
|
||||
α=α or -math.huge
|
||||
β=β or math.huge
|
||||
-- check for cached node
|
||||
local αOrg=α
|
||||
local cData=cache[node]
|
||||
if cData and cData.depth>=depth and depth~=tDepth then
|
||||
if cData.flag==EXACT then
|
||||
return cData.value
|
||||
elseif cData.flag==LOWERB then
|
||||
α=math.max(α,cData.value)
|
||||
elseif cData.flag==UPPERB then
|
||||
β=math.min(β,cData.value)
|
||||
end
|
||||
if α>=β then
|
||||
return cData.value
|
||||
end
|
||||
end
|
||||
|
||||
local winner=win(node)
|
||||
if depth==0 or winner~=0 then
|
||||
return winner*color
|
||||
end
|
||||
local value=-math.huge
|
||||
for child,move in genmove(node, color) do
|
||||
value=math.max(value, -negamax(child, depth-1, -color, -β, -α))
|
||||
if value>α then
|
||||
α=value
|
||||
if depth==tDepth then
|
||||
best=child
|
||||
aimove=move
|
||||
end
|
||||
end
|
||||
if α>=β then break end
|
||||
end
|
||||
-- cache known data
|
||||
--cData={} -- if you want Lua tables instead of ffi you can switch the two lines here, costs 20% speed
|
||||
cData=ffi.new("cData")
|
||||
cData.value=value
|
||||
if value<=αOrg then
|
||||
cData.flag=UPPERB
|
||||
elseif value>=β then
|
||||
cData.flag=LOWERB
|
||||
else
|
||||
cData.flag=EXACT
|
||||
end
|
||||
cData.depth=depth
|
||||
cache[node]=cData
|
||||
return α
|
||||
end
|
||||
-- MAIN
|
||||
do
|
||||
local winner,value
|
||||
local score={[-1]=0, [0]=0, [1]=0}
|
||||
repeat
|
||||
print("\n TIC-TAC-TOE\n")
|
||||
local aiplayer=playerselect()
|
||||
local player=1
|
||||
board="123456789"
|
||||
for i=1,#board do
|
||||
draw(board)
|
||||
tDepth=10-i
|
||||
if aiplayer[player] then
|
||||
negamax(board, tDepth, player, -math.huge, math.huge)
|
||||
board=best
|
||||
printf("AI %d moves %s\n", pnum[player], aimove)
|
||||
else
|
||||
board=input(board,player)
|
||||
end
|
||||
winner=win(board)
|
||||
if winner~=0 then break end
|
||||
player=-player
|
||||
end
|
||||
score[winner]=score[winner]+1
|
||||
if winner and winner~=0 then
|
||||
printf("*** Player %d (%s) has won\n", pnum[winner], symbol[pnum[winner]])
|
||||
else
|
||||
printf("*** No winner\n")
|
||||
end
|
||||
printf("Score Player 1: %d Player 2: %d Draw: %d\n",score[1],score[-1],score[0])
|
||||
draw(board)
|
||||
until endgame()
|
||||
end
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
\( 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
|
||||
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
|
||||
|
|
@ -31,58 +31,58 @@ main (parms):+
|
|||
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
|
||||
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
|
||||
:>
|
||||
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."
|
||||
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
|
||||
:>
|
||||
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
|
||||
points =: points, () \ make it a tuple
|
||||
?# i =: tuple points give values
|
||||
? state[i] = 0
|
||||
state[i] =: 4
|
||||
print "my move:", i
|
||||
:> ?+
|
||||
? state[i] = 0
|
||||
state[i] =: 4
|
||||
print "my move:", i
|
||||
:> ?+
|
||||
:> ?-
|
||||
|
||||
shuffle (points):
|
||||
|
|
@ -94,40 +94,40 @@ shuffle (points):
|
|||
sum of places (state) lane (tpl):
|
||||
s =: 0
|
||||
?# i =: tuple tpl give values
|
||||
v =: state[i]
|
||||
? v ~= 0
|
||||
s =+ state[i]
|
||||
v =: state[i]
|
||||
? v ~= 0
|
||||
s =+ state[i]
|
||||
:> s
|
||||
|
||||
set user (state):
|
||||
?*
|
||||
print "your move: " nonl
|
||||
c =: file stream () get
|
||||
? c = 'q' || c = 'x'
|
||||
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
|
||||
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 ''
|
||||
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
|
||||
|
|
|
|||
26
Task/Tic-tac-toe/Uiua/tic-tac-toe.uiua
Normal file
26
Task/Tic-tac-toe/Uiua/tic-tac-toe.uiua
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
Threes ← [0_1_2 3_4_5 6_7_8 0_3_6 1_4_7 2_5_8 0_4_8 2_4_6]
|
||||
Moves ← ≡(⊂□)⊙(¤□)⊸(≡⍜⊡⋅∘ ⊙¤⊙⊙¤⊚⊸⌕@_)⊙(⨬(@X|@O)=@X)∩°□°⊟
|
||||
RandomMove ← [⊡]⌊×⚂⊸⧻ Moves
|
||||
WasWin ← /↥⊢≡(≡/↧˜⌕⊏Threes)¤∩°□°⊟
|
||||
IsDraw ← ¬/↥⌕@_°□⊢
|
||||
Done ← ↥⊃IsDraw WasWin
|
||||
[] # Score accumulator
|
||||
⍥( # They start
|
||||
⊢path(RandomMove|Done){"_________" @X}
|
||||
# Score each of our moves as winning or losing, save.
|
||||
⨬(◌|⊂≡⊟⊃(≡⊢▽⊸≡◇(=@X°□⊣)|¤□⨬(¯1|1)=@X°□⊣⊣))⊸(¬IsDraw⊣)
|
||||
) 3000
|
||||
# Build map from moves and accumulated scores
|
||||
¤map⍜⍉°⊟⊕(⊂⊃(⊢°□⊢|/+≡◇⊣))⊛⊸≡⊢
|
||||
# Play our *best* moves against their *random* moves.
|
||||
BestMove ← |1 ⨬(RandomMove|[⊢]▽=⊸/↥◡≡(°□⬚0get⊢)Moves)=@O°□⊸⊣
|
||||
# One demo game
|
||||
&p"Sample Game: 'O' starts, playing randomly.\n'X' is trained."
|
||||
≡&p↘1⊢path(BestMove|Done){"_________" @X}
|
||||
|
||||
&p"Thirty results, showing X/O as winner or '=' for draw."
|
||||
⍥( # Let them start
|
||||
⊢path(BestMove|Done){"_________" @X}
|
||||
&p⊟∩□⍥⊙⋅@=¬/↥⊸⌕@_°□°⊟⊣
|
||||
)30
|
||||
◌
|
||||
|
|
@ -1,110 +1,116 @@
|
|||
import rand
|
||||
import os
|
||||
|
||||
__global (
|
||||
b = [3][3]int{}
|
||||
best_i = 0
|
||||
best_j = 0
|
||||
)
|
||||
struct Board {
|
||||
mut:
|
||||
bay [3][3]int
|
||||
best_i int
|
||||
best_j int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut brd := Board{}
|
||||
mut user := false
|
||||
mut yn :=''
|
||||
mut yn :=""
|
||||
for {
|
||||
user = !user
|
||||
print(game(user))
|
||||
print(game(mut brd, user))
|
||||
for (yn != "y" ) && (yn != "n") {
|
||||
yn = os.input('Play again y/n: ').str().to_lower()
|
||||
yn = os.input("Play again y/n: ").str().to_lower()
|
||||
}
|
||||
if yn != "y" {exit(0)} else {yn =''}
|
||||
println('')
|
||||
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}
|
||||
fn game(mut brd Board, user bool) string {
|
||||
mut ubl := user
|
||||
mut move, mut my_move, mut ir, mut jir, mut win := 0, 0, 0, 0, 0
|
||||
for kal in 0..3 {
|
||||
for lal in 0..3 {
|
||||
if brd.bay[kal][lal] != 0 {brd.bay[kal][lal] = 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 kal in 1..9 {
|
||||
if ubl {
|
||||
for move !in [1,2,3,4,5,6,7,8,9] {
|
||||
move = os.input('your move: ').int()
|
||||
move = os.input("your move: ").int()
|
||||
}
|
||||
move--
|
||||
i = move / 3
|
||||
j = move % 3
|
||||
if b[i][j] != 0 {continue}
|
||||
b[i][j] = 1
|
||||
ir = move / 3
|
||||
jir = move % 3
|
||||
if brd.bay[ir][jir] != 0 {continue}
|
||||
brd.bay[ir][jir] = 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
|
||||
if !ubl {
|
||||
if kal == 1 {
|
||||
brd.best_i = (rand.int_in_range(1, 9) or {exit(1)}) % 3
|
||||
brd.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
|
||||
else {test_move(mut brd, -1, 0)}
|
||||
brd.bay[brd.best_i][brd.best_j] = -1
|
||||
my_move = brd.best_i * 3 + brd.best_j + 1
|
||||
println("My move: $my_move")
|
||||
}
|
||||
show_board()
|
||||
win = check_winner()
|
||||
show_board(mut brd)
|
||||
win = check_winner(mut brd)
|
||||
println("win res: $win")
|
||||
if win != 0 {
|
||||
if win == 1 {return "You win" + ".\n\n"}
|
||||
else {return "I win" + ".\n\n"}
|
||||
}
|
||||
u = !u
|
||||
ubl = !ubl
|
||||
}
|
||||
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]}
|
||||
fn check_winner(mut brd Board) int {
|
||||
for ial in 0..3 {
|
||||
if brd.bay[ial][0] != 0 && brd.bay[ial][1] == brd.bay[ial][0] && brd.bay[ial][2] == brd.bay[ial][0] {
|
||||
return brd.bay[ial][0]
|
||||
}
|
||||
if brd.bay[0][ial] != 0 && brd.bay[1][ial] == brd.bay[0][ial] && brd.bay[2][ial] == brd.bay[0][ial] {
|
||||
return brd.bay[0][ial]
|
||||
}
|
||||
}
|
||||
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]}
|
||||
if brd.bay[1][1] == 0 {return 0}
|
||||
if brd.bay[1][1] == brd.bay[0][0] && brd.bay[2][2] == brd.bay[0][0] {return brd.bay[0][0]}
|
||||
if brd.bay[1][1] == brd.bay[2][0] && brd.bay[0][2] == brd.bay[1][1] {return brd.bay[1][1]}
|
||||
return 0
|
||||
}
|
||||
|
||||
fn show_board() {
|
||||
fn show_board(mut brd Board) {
|
||||
mut t := "X O"
|
||||
for i in 0..3 {
|
||||
for j in 0..3 {
|
||||
print("${t[b[i][j] + 1].ascii_str()} ")
|
||||
for ial in 0..3 {
|
||||
for jal in 0..3 {
|
||||
print("${t[brd.bay[ial][jal] + 1].ascii_str()} ")
|
||||
}
|
||||
println('')
|
||||
println("")
|
||||
}
|
||||
println("-----")
|
||||
}
|
||||
|
||||
fn test_move(value int, depth int) int {
|
||||
fn test_move(mut brd Board, value int, depth int) int {
|
||||
mut best := -1
|
||||
mut changed := 0
|
||||
mut score := check_winner()
|
||||
mut score := check_winner(mut brd)
|
||||
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
|
||||
for ial in 0..3 {
|
||||
for jal in 0..3 {
|
||||
if brd.bay[ial][jal] != 0 {continue}
|
||||
brd.bay[ial][jal] = value
|
||||
changed = value
|
||||
score = -test_move(-value, depth + 1)
|
||||
b[i][j] = 0
|
||||
score = -test_move(mut brd, -value, depth + 1)
|
||||
brd.bay[ial][jal] = 0
|
||||
if score <= best {continue}
|
||||
if depth == 0 {
|
||||
best_i = i
|
||||
best_j = j
|
||||
brd.best_i = ial
|
||||
brd.best_j = jal
|
||||
}
|
||||
best = score
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue