Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

executable file 73 lines (58 sloc) 2.166 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#!/usr/bin/env runhaskell
-- TODO: add a way to compute the rating of the cell automatically
module Main (main) where

import Data.List
type CellIdx = (Int, Int)
type Symbol = Char
type Board = [[Symbol]]

blank = '-'
symbols = ['x', 'o']

-- compute_move inp = inp
is_playing_symbol sym = or [sym == x | x <- symbols]
count_symbols board = length $ filter is_playing_symbol board
my_symbol board = symbols !! (mod (count_symbols board) 2)

cell :: Board -> CellIdx -> Symbol
cell board idx = board !! (fst idx) !! (snd idx)

cell_idxs dim = [(i, j) | i <- [0..(dim-1)], j <- [0..(dim-1)]]

blanks board =
  let dim = length board
  in [(i, j) | (i, j) <- cell_idxs dim, cell board (i, j) == blank]

idx_to_pos idx dim =
    (dim * (fst idx)) + (snd idx)

to_board board_string =
    string_to_board board_string dim
    where
      dim = round $ sqrt (fromIntegral $ length board_string)
      string_to_board "" _ = []
      string_to_board board_string dim =
          take dim board_string : (string_to_board (drop dim board_string) dim)

winning_list :: [Symbol] -> Bool
winning_list list =
    let
        first = head list
    in (is_playing_symbol first) && (all (== first) list)
       
board_lines board =
    board ++ (transpose board) ++ [diag1, diag2]
    where
      max_idx = length board - 1
      diag1 = [cell board (i, i) | i <- [0..max_idx]]
      diag2 = [cell board (i, max_idx - i) | i <- [0..max_idx]]
      
winning_board :: Board -> Bool
winning_board board = any winning_list (board_lines board)

make_board board idx sym =
  (take idx board) ++ [sym] ++ (drop (idx + 1) board)
  
next_move board_st =
    let
        my_sym = my_symbol board_st
        board = to_board board_st
        possible_moves = blanks board
        next_blank = head possible_moves
        next_board = make_board board_st (idx_to_pos next_blank (length board)) my_sym
    in
      if (winning_board (to_board next_board))
       then (make_board board_st (idx_to_pos (possible_moves !! 2) (length board)) my_sym)
       else next_board
            
-- recursively ask for a board and output the next one
main = do
  board <- getLine
  putStr $ next_move board
Something went wrong with that request. Please try again.