Skip to content

Instantly share code, notes, and snippets.

@hdp
Created February 9, 2011 18:36
Show Gist options
  • Save hdp/818982 to your computer and use it in GitHub Desktop.
Save hdp/818982 to your computer and use it in GitHub Desktop.
(* vim: ts=2 sts=2 sw=2:
*)
#directory "+extlib"
#load "extLib.cma"
type mark = X | O
type space =
Empty
| Full of mark
type result =
Continue
| Draw
| Win of mark
exception Space_is_full
exception Game_is_over
exception Out_of_turn
let string_of_mark m =
match m with
X -> "X"
| O -> "O"
let string_of_space s =
match s with
Full(m) -> string_of_mark m
| Empty -> " "
let string_of_result r =
match r with
Win(m) -> "Win(" ^ (string_of_mark m) ^ ")"
| Draw -> "Draw"
| Continue -> "Continue"
class board = object (self)
val b = Array.make 9 Empty
val mutable result = Continue
val mutable last_mark = ref O
val winners = List.flatten [
List.map (fun i -> Array.init 3 (fun j -> i + j)) [ 0; 3; 6 ];
List.map (fun i -> Array.init 3 (fun j -> i + 3 * j)) [ 0; 1; 2 ];
List.map (fun i -> Array.init 3 (fun j -> i * (j - 1) + 1 + 3 * j)) [ 1; -1 ];
]
method calculate_result =
let find_win w =
match Array.map (fun i -> b.(i)) w with
[| Full(x); Full(y); Full(z) |] when x == y && y == z -> Win(x)
| _ -> Continue
in
try List.find (fun w -> w != Continue) (List.map find_win winners)
with Not_found ->
if List.exists (fun s -> s == Empty) (Array.to_list b)
then Continue
else Draw
method make_move i m =
if m == !last_mark
then raise Out_of_turn
else match b.(i) with
Full(_) -> raise Space_is_full
| Empty -> last_mark := m; b.(i) <- Full(m)
method move i m =
if self#calculate_result == Continue
then self#make_move i m
else raise Game_is_over
method display =
let rec grouped a n =
match a with
[||] -> []
| a -> Array.sub a 0 n :: grouped (Array.sub a n (Array.length a - n)) n
in
let string_of_row a =
"[" ^ String.concat "" (List.map string_of_space (Array.to_list a)) ^ "]"
in
String.concat "\n" (List.map string_of_row (grouped b 3)) ^ "\n"
end
let play_game ms =
let b = new board in
List.iter (fun (i, m) -> b#move i m) ms;
print_string b#display;
print_string (string_of_result b#calculate_result ^ "\n");;
let main () =
play_game [(0, X); (4, O); (8, X); (2, O); (6, X); (3, O); (7, X)];
play_game [(0, X); (4, O); (8, X); (2, O); (6, X); (7, O); (3, X)];
play_game [(0, X); (3, O); (4, X); (2, O); (8, X)];
play_game [(0, X); (4, O); (8, X); (3, O); (5, X); (2, O); (6, X); (7, O); (1, X)];
exit 0;;
main ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment