mirror of
https://github.com/correl/hackerrank.git
synced 2024-11-23 11:09:53 +00:00
Level 1 - Tic Tac Toe
This commit is contained in:
parent
5623a927ae
commit
f9bb4cf869
1 changed files with 74 additions and 0 deletions
74
TicTacToe.hs
Normal file
74
TicTacToe.hs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import Data.List (sort, findIndices)
|
||||||
|
import System.Random (randomRIO)
|
||||||
|
|
||||||
|
testboard :: String
|
||||||
|
testboard = "O_X_X_O__"
|
||||||
|
|
||||||
|
getList :: Int -> IO [String]
|
||||||
|
getList n = if n==0 then return [] else do i <- getLine; is <- getList(n-1); return (i:is)
|
||||||
|
|
||||||
|
findEmpty :: String -> [Int]
|
||||||
|
findEmpty board = findIndices (\c -> c == '_') board
|
||||||
|
|
||||||
|
sets :: [[Int]]
|
||||||
|
sets = [[0,1,2],
|
||||||
|
[3,4,5],
|
||||||
|
[6,7,8],
|
||||||
|
|
||||||
|
[0,3,6],
|
||||||
|
[1,4,7],
|
||||||
|
[2,5,8],
|
||||||
|
|
||||||
|
[0,4,8],
|
||||||
|
[2,4,6]]
|
||||||
|
|
||||||
|
findMoves :: String -> Char -> [(Int, Int)]
|
||||||
|
findMoves board player = moves
|
||||||
|
where moves = [(scoreIndex i, i) | i <- indexes]
|
||||||
|
indexes = findEmpty board
|
||||||
|
scoreIndex x = sum $ map (scoreSet player) $ findSets board x
|
||||||
|
|
||||||
|
bestMoves :: [(Int, Int)] -> [Int]
|
||||||
|
bestMoves [] = []
|
||||||
|
bestMoves moves = [snd m | m <- sortedMoves, bestScore == fst m]
|
||||||
|
where sortedMoves = reverse.sort $ moves
|
||||||
|
bestScore = fst $ head sortedMoves
|
||||||
|
|
||||||
|
findSets :: String -> Int -> [String]
|
||||||
|
findSets board index = sets''
|
||||||
|
where sets' = filter (\x -> elem index x) sets
|
||||||
|
sets'' = map chars' sets'
|
||||||
|
chars' = map (\x -> board !! x)
|
||||||
|
|
||||||
|
scoreSet :: Char -> String -> Int
|
||||||
|
scoreSet player set
|
||||||
|
| (elem 'O' set) && (elem 'X' set) = 0
|
||||||
|
| otherwise = 2 ^ (length.filter (\x -> x /= '_') $ set)
|
||||||
|
|
||||||
|
otherPlayer :: Char -> Char
|
||||||
|
otherPlayer 'X' = 'O'
|
||||||
|
otherPlayer 'O' = 'X'
|
||||||
|
|
||||||
|
coords :: Int -> (Int, Int)
|
||||||
|
coords index = (y, x)
|
||||||
|
where y = index `div` 3
|
||||||
|
x = index `rem` 3
|
||||||
|
|
||||||
|
main = do
|
||||||
|
|
||||||
|
-- If player is X, I'm the first player.
|
||||||
|
-- If player is O, I'm the second player.
|
||||||
|
player <- getLine
|
||||||
|
|
||||||
|
-- Read the board now. The board is a list of strings filled with X, O or _.
|
||||||
|
board <- getList 3
|
||||||
|
|
||||||
|
let moves = bestMoves $ findMoves (concat board) (player !! 0)
|
||||||
|
r <- randomRIO (1, length(moves))
|
||||||
|
let nextMove = coords $ moves !! (r - 1)
|
||||||
|
|
||||||
|
-- Proceed with processing and print 2 integers separated by a single space.
|
||||||
|
putStrLn.(\(x, y) -> show x ++ " " ++ show y) $ nextMove
|
||||||
|
|
Loading…
Reference in a new issue