Created
February 9, 2011 18:36
-
-
Save hdp/818982 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* 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