Skip to content

Instantly share code, notes, and snippets.

@Frityet
Created February 9, 2024 22:40
Show Gist options
  • Save Frityet/83db3e2b4ae5e39e7bad5975731cb73a to your computer and use it in GitHub Desktop.
Save Frityet/83db3e2b4ae5e39e7bad5975731cb73a to your computer and use it in GitHub Desktop.
// tic tac toe in F#
open System
module TicTacToe =
type Player = X | O
type Cell = Empty | Checked of Player
type Board = Cell list list
let cellToString cell =
match cell with
| Empty -> " "
| Checked X -> "X"
| Checked O -> "O"
let nextPlayer prev = match prev with | X -> O | O -> X
let boardToString board =
board |> List.map (fun x -> x |> List.map cellToString |> String.concat " | ") |> String.concat "\n--+---+--\n"
let markPart x y board player =
let row = board |> List.item y
let newRow = row |> List.mapi (fun i cell -> if i = x then Checked player else cell)
List.mapi (fun i row -> if i = y then newRow else row) board
type Input = Move of int * int | Exit
let rec readMove () =
let line = Console.ReadLine()
match line with
| "exit" -> Exit
| _ ->
let parts = line.Split ' '
if parts.Length <> 2 then
printfn "Invalid input, please try again."
readMove ()
else
let x = Int32.Parse parts.[0]
let y = Int32.Parse parts.[1]
if x >= 0 && x <= 2 && y >= 0 && y <= 2 then
Move(x, y)
else
printfn "Invalid coordinates, please try again."
readMove ()
let checkRow row =
match row with
| [Checked p1; Checked p2; Checked p3] when p1 = p2 && p2 = p3 -> true
| _ -> false
let checkColumn board i =
checkRow (board |> List.map (fun row -> List.item i row))
let checkDiagonals (board: Board) =
let diag1 = [board.[0].[0]; board.[1].[1]; board.[2].[2]]
let diag2 = [board.[0].[2]; board.[1].[1]; board.[2].[0]]
checkRow diag1 || checkRow diag2
let checkState board =
let rows = board |> List.map checkRow
let cols = [0..2] |> List.map (checkColumn board)
let diags = checkDiagonals board
(rows |> List.exists (fun x -> x)) || (cols |> List.exists (fun x -> x)) || diags
let rec main player board =
printfn "%s" (boardToString board)
printfn "Player %s" (cellToString (Checked player))
printf "Enter the coordinates of your move (x y), or 'exit' to stop the game: "
let mov = readMove ()
match mov with
| Exit ->
printf "Goodbye!"
()
| Move(x, y) ->
let newBoard = markPart x y board player
if checkState newBoard then
printfn "Player %s wins!" (cellToString (Checked player))
()
else
main (nextPlayer player) newBoard
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment