Snippets

Mariusz Krynski tic-tac-toe.sql

Created by Mariusz Krynski last modified
with recursive rnd_move(move) as (
        select *, random() rnd from generate_series(1, 9) move
), winning_positions(a, b, c) as (
    values (1, 2, 3), (4, 5, 6), (7, 8, 9), -- rows
           (1, 4, 7), (2, 5, 8), (3, 6, 9), -- cols
           (1, 5, 9), (3, 5, 7)             -- diagonals
), game as (
    select 'O' as who_next, ARRAY['.', '.', '.', '.', '.', '.', '.', '.', '.'] as board
    union 
    (
        select case when who_next = 'X' then 'O' else 'X' end as who_next,
               board[:move-1] || who_next || board[move+1:]
        from game, rnd_move where board[move] = '.' order by rnd limit 1
    )
), game_with_winner as (
    select *, lag(a is not null) over () as finished, lag(who_next) over () as who
    from game left join winning_positions on
        board[a] != '.' and board[a] = board[b] and board[a] = board[c]
)
select array_to_string(board[1:3] || chr(10) || board[4:6] || chr(10) || board[7:9] || chr(10), '') board,
       case when a is not null then who || ' wins' end as winner
from game_with_winner where not finished;

Comments (1)