USING: arrays sequences kernel io prettyprint generalizations namespaces math math.parser math.order splitting combinators combinators.short-circuit ; IN: tic-tac-toe SYMBOLS: X O ; : at ( n n g -- x ) nth nth ; : draw ( grid -- grid ) dup [ . ] each ; : row ( e -- seq ) 3 swap ; : create-grid ( -- grid ) 3 [ f row ] replicate ; : inside? ( x y grid -- ? ) drop [ 0 2 between? ] both? ; : free? ( x y grid -- ? ) at f = ; : check ( ? s -- ? ) over [ drop ] [ . ] if ; : valid? ( x y g -- ? ) { [ inside? "Outside" check ] [ free? "Occupied" check ] } 3&& ; : read-tuple ( -- n n ) readln "," split [ string>number ] map first2 ; : ask ( -- n n ) "Enter a position: " write read-tuple ; : read-pos ( g -- n n g ) [ ask rot 3dup valid? ] [ 2nip ] until ; : update-case ( a x y g -- ) nth set-nth ; : play ( p g -- p g ) 2dup read-pos update-case ; : diag ( grid -- seq ) [ swap nth ] map-index ; : diags ( grid -- seq ) [ diag ] [ reverse diag ] bi 2array ; : complete? ( seq -- ? ) X row O row 2array member? ; : full? ( g -- ? ) concat f swap member? not ; : 3-aligned? ( g -- ? ) dup flip dup diags append append [ complete? ] any? ; : game-over? ( g -- ? ) { [ full? ] [ 3-aligned? ] } 1|| ; : game ( -- ) X O create-grid ! push the initial values on the stack [ dup game-over? ] [ draw swapd play ] until "Game over." print 3drop ;