fork download
BlockClosure extend [ valueWithExit [ self value: [^self] ] ]

| board showBoard patterns get message |

board := #(('.' '.' '.') ('.' '.' '.') ('.' '.' '.')) deepCopy.
showBoard := [board do: [:line | line do: [:cell | cell display]. stdout nl]].

patterns := board,
	({[:i | 1]. [:i | 2]. [:i | 3]. [:i | i]. [:i | 4-i]} collect: [:spec |
		(1 to: 3) collect: [:idx | (board at: idx) at: (spec value: idx)]]).

get := [:xy |
	| v |
	[(xy, '?') display. (v := stdin nextLine asInteger) displayNl between: 1 and: 3] whileFalse. 
	v
].

message := '[draw]'.
[:exit |
	| rest |
	[(rest := (board gather: [:line | line]) count: [:each | each = '.']) > 0] whileTrue: [
		| player x y |
		player := #('x' 'o') at: rest \\ 2 + 1.
		('[<', player asString, '>''s turn]') displayNl.
		showBoard value.
		[	x := get value: 'x'.
			y := get value: 'y'.
			((board at: y) at: x) ~= '.'] whileTrue.
		((board at: y) at: x) at: 1 put: player first.
		(patterns anySatisfy: [:pat | (pat count: [:each | each = player]) = 3]) ifTrue: [
			message := '[<', player asString, '> won!]'.
			exit value].
	]
] valueWithExit.
message displayNl.
showBoard value.
'[game over]' displayNl.
Success #stdin #stdout 0s 171456KB
stdin
1
1
2
2
3
3
2
1
2
3
1
3
3
1
1
2
3
2
stdout
[<o>'s turn]
...
...
...
x?1
y?1
[<x>'s turn]
o..
...
...
x?2
y?2
[<o>'s turn]
o..
.x.
...
x?3
y?3
[<x>'s turn]
o..
.x.
..o
x?2
y?1
[<o>'s turn]
ox.
.x.
..o
x?2
y?3
[<x>'s turn]
ox.
.x.
.oo
x?1
y?3
[<o>'s turn]
ox.
.x.
xoo
x?3
y?1
[<x>'s turn]
oxo
.x.
xoo
x?1
y?2
[<o>'s turn]
oxo
xx.
xoo
x?3
y?2
[<o> won!]
oxo
xxo
xoo
[game over]