Maxime Buquet avatar Maxime Buquet committed 45fbe9f

Initial commit

Comments (0)

Files changed (1)

+
+type piece =
+  | X
+  | O
+
+type player = {
+  name : string;
+  side : piece
+}
+
+type win =
+  | Turn of int
+  | Draw
+  | Win of player
+
+type board = {
+  gameboard : piece option array;
+  w : int;
+  h : int
+}
+
+type game = {
+  board : board;
+  mutable win : win;
+  player1 : player;
+  player2 : player;
+}
+
+let prompt_players () =
+  let choose_players () =
+    let () = Random.self_init () in
+    match Random.int 2 with
+      n when n mod 2 = 0 -> (X, O)
+      | _ -> (O, X)
+  in
+    let player1 = read_line (print_string "Enter Player1 name: ")
+    and player2 = read_line (print_string "Enter Player2 name: ") in
+      let side1, side2 = choose_players ()
+        in ({ name = player1; side = side1 },
+            { name = player2; side = side2 })
+
+let create_board () =
+  { gameboard = Array.init 9 (fun _ -> None); w = 3; h = 3 }
+
+let create_game () =
+  let player1, player2 = prompt_players ()
+  in { board = create_board (); win = Turn 1;
+       player1 = player1; player2 = player2; }
+
+let win board =
+  let w, h = board.w, board.h in
+  let board = board.gameboard in
+  let horiz x =
+    board.(x * w) = board.(x * w + 1)
+    && board.(x * w + 1) = board.(x * w + 2)
+  in let vert x =
+    board.(x) = board.(x + h) && board.(x + h) = board.(x + h * 2)
+  in let test_obl () =
+    (((board.(0) = board.(4) && board.(4) = board.(8)))
+    || ((board.(2) = board.(4) && board.(4) = board.(6))))
+    && board.(4) != None
+  in
+    let test f =
+      let rec test = function
+        | x when x <= 2 -> (board.(x) != None && f x) || test (x + 1)
+        | _ -> false
+      in test 0
+    in test horiz || test vert || test_obl ()
+
+let display_board ?(numbers = false) board =
+  let piece_to_str = function
+    | Some X -> "X"
+    | Some O -> "O"
+    | None -> " "
+  in
+  let w, h = board.w, board.h
+  and board = board.gameboard in
+    let print border x = match border with
+      | true -> if numbers then Printf.printf "| %d |\n" x
+                else Printf.printf "| %s |\n" (piece_to_str board.(x))
+      | _ -> if numbers then Printf.printf "| %d " x
+             else Printf.printf "| %s " (piece_to_str board.(x))
+    in
+    let rec map = function
+      | x when x >= (w * h) -> ()
+      | x -> print (x mod w = (h - 1)) x; map (x + 1)
+    in Printf.printf " --- --- --- \n"; map 0;
+       Printf.printf " --- --- --- \n\n%!"
+
+let rec prompt_case board =
+  let case = read_line (print_string "Enter a value: ")
+  in try let c = int_of_string case in
+    if c < 0 || c > 8 then
+      invalid_arg "Incorrect value"
+    else if board.(c) != None then
+      failwith "Already set value"
+    else c
+  with Failure "int_of_string" | Invalid_argument _ ->
+      Printf.printf "Incorrect value\n"; prompt_case board
+    | _ -> Printf.printf "Already set value\n"; prompt_case board
+
+let turn_player game = function
+  | x when x mod 2 = 0 -> game.player1
+  | _ -> game.player2
+
+let rec loop game = match game.win with
+  | Draw -> Printf.printf "Draw!\n"; replay ()
+  | Win player -> Printf.printf "%s wins.\n" player.name; replay ()
+  | Turn turn ->
+    Printf.printf "Turn %d:\n" turn;
+    handle_turn game turn; loop game
+
+and replay () =
+  let r = read_line (print_string "Replay? (y/N): ") in
+    if r = "Y" || r = "y" then loop (create_game ())
+
+and handle_turn game turn =
+  let board = game.board in
+  let c = prompt_case board.gameboard in
+  let player = turn_player game turn in
+  let () = board.gameboard.(c) <- (Some player.side) in (
+    if win board then game.win <- (Win player)
+    else if turn = 9 then game.win <- Draw
+      else game.win <- Turn (turn + 1)
+    );
+  display_board board
+
+let rules () =
+  display_board ~numbers:true (create_board ())
+
+let main () =
+  rules ();
+  loop (create_game ())
+
+let () = main ()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.