Advertisement
Guest User

Untitled

a guest
May 19th, 2018
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.56 KB | None | 0 0
  1. (* Game Player Data Types and Functions *)
  2.  
  3. type piece = X | O | Empty;;
  4.  
  5. type board = (piece list) list;;
  6.  
  7. type game = NillGame | Level of (board * game list);;
  8.  
  9. type status = X_wins | O_wins | Draw | Unfinished;;
  10.  
  11. exception CannotPlacePiece;;
  12.  
  13. type move_status = Updated of board | NotAllowed;;
  14.  
  15. let table = [[Empty;Empty;Empty];[Empty;Empty;Empty];[Empty;Empty;Empty]];;
  16.  
  17. (* make_move takes a player's piece, the position that they want to put in on and the board *)
  18. (* make_move returns an updated board with that piece in the position if possible, does nothing otherwise *)
  19.  
  20. let make_move piece (x,y) board =
  21. let rec walk_down i board =
  22. match board with
  23. [] -> raise CannotPlacePiece
  24. | (h::t) ->
  25. if i=1
  26. then ([],h,t)
  27. else
  28. let (pre,row,rest) = walk_down (i-1) t
  29. in (h::pre,row,rest) in
  30. let rec walk_acc j row =
  31. match row with
  32. [] -> raise CannotPlacePiece
  33. | (h::t) ->
  34. if j=1
  35. then
  36. match h with
  37. Empty -> ([],piece,t)
  38. | _ -> ([],h,t)
  39. else
  40. let (pre,item,rest) = walk_acc (j-1) t
  41. in (h::pre,item,rest) in
  42. let (prerows,r,postrows) = walk_down x board in
  43. let (pcol,c,postcols) = walk_acc y r in
  44. let newrow = pcol @ (c::postcols) in
  45. let board2 = prerows @ (newrow::postrows)
  46. in if board=board2
  47. then NotAllowed
  48. else Updated board2;;
  49.  
  50.  
  51.  
  52. (* gen_moves takes a piece and a board *)
  53. (* It returns a list of boards in which that piece has been placed *)
  54.  
  55. let gen_moves piece board =
  56. let rec place_cols (i,j) =
  57. if j<=3
  58. then (make_move piece (i,j) board)::(place_cols (i,j+1))
  59. else [] in
  60. let rec place_rows i =
  61. if i<=3
  62. then (place_cols (i,1)) @ (place_rows (i+1))
  63. else [] in
  64. let rec filter_moves bds =
  65. match bds with
  66. [] -> []
  67. | ((Updated b)::rst) -> b::(filter_moves rst)
  68. | (NotAllowed::rst) -> filter_moves rst in
  69. let boards = place_rows 1
  70. in filter_moves boards;;
  71.  
  72. type status = X_wins | O_wins | Draw | Unfinished;;
  73.  
  74. (* is_EmptyPos returns true if there is an Empty position on the board *)
  75.  
  76. let is_EmptyPos board =
  77. let rec check_row r =
  78. match r with
  79. [] -> false
  80. | (Empty::t) -> true
  81. | (_::t) -> check_row t in
  82. let rec check_rows b =
  83. match b with
  84. [] -> false
  85. | (h::t) -> (check_row h) || check_rows t
  86. in check_rows board;;
  87.  
  88. (* is_win takes a piece and a board and returns true if that piece does indeed have three in a row *)
  89.  
  90. let is_win piece board =
  91. let id x = x in
  92. let add1 x = x+1 in
  93. let sub1 x = x-1 in
  94. let rec check_row r =
  95. match r with
  96. [] -> true
  97. | (h::t) -> (h=piece) && check_row t in
  98. let rec is_row rs =
  99. match rs with
  100. [] -> false
  101. | (h::t) -> (check_row h) || is_row t in
  102. let rec test_row pos r =
  103. match (pos,r) with
  104. (p,[]) -> false
  105. | (1,(h::t)) -> (h=piece)
  106. | (n,(h::t)) -> test_row (n-1) t in
  107. let rec is_column pos f b =
  108. match b with
  109. [] -> true
  110. | (h::t) -> test_row pos h && is_column (f pos) f t in
  111. let is_col b = (is_column 1 id b) || (is_column 2 id b) || (is_column 3 id b) in
  112. let is_left_diag b = is_column 1 add1 b in
  113. let is_right_diag b = is_column 3 sub1 b in
  114. let is_diag b = is_left_diag b || is_right_diag b
  115. in is_row board || is_col board || is_diag board;;
  116.  
  117.  
  118. (* calc_status takes a board and returns the status of the board *)
  119.  
  120. let calc_status board =
  121. if (is_win X board)
  122. then X_wins
  123. else (if (is_win O board)
  124. then O_wins
  125. else (if (is_EmptyPos board)
  126. then Unfinished
  127. else Draw));;
  128.  
  129. let completed bd = not ((calc_status bd) = Unfinished);;
  130.  
  131. let swap_piece p =
  132. match p with
  133. X -> O
  134. | O -> X;;
  135.  
  136. (* gen_games generates all the games from the current board with piece moving first *)
  137.  
  138. let rec gen_games piece bd =
  139. if completed bd
  140. then
  141. Level (bd,[])
  142. else
  143. let ms = gen_moves piece bd in
  144. let gs = gen_nextlevel piece ms
  145. in Level (bd,gs)
  146.  
  147. and gen_nextlevel piece ms =
  148. match ms with
  149. [] -> []
  150. | (b::bs) ->
  151. let g = gen_games (swap_piece piece) b
  152. in g::(gen_nextlevel piece bs);;
  153.  
  154. (* gen_limited_games generates all the games to the given depth *)
  155.  
  156. let rec gen_limited_games piece bd depth =
  157. if (completed bd) || (depth=0)
  158. then
  159. Level (bd,[])
  160. else
  161. let ms = gen_moves piece bd in
  162. let gs = gen_next_limited_level piece ms (depth-1)
  163. in Level (bd,gs)
  164.  
  165. and gen_next_limited_level piece ms depth =
  166. match ms with
  167. [] -> []
  168. | (b::bs) ->
  169. let g = gen_limited_games (swap_piece piece) b depth
  170. in g::(gen_next_limited_level piece bs depth);;
  171.  
  172. let rec help game_list player =
  173. match game_list with
  174. [] -> false
  175. | h::t -> can_win h player || help t player
  176.  
  177.  
  178. and can_win game_tree player =
  179. match game_tree with
  180. Level ([],_) -> false
  181. | Level (x,[]) -> (calc_status x = X_wins && player = X) || (calc_status x = O_wins && player = O)
  182. | Level (board,h::t) -> can_win h player || help t player;;
  183.  
  184. let rec add_to_front v l =
  185. match l with
  186. [] -> []
  187. | h::t -> if h = [] then add_to_front v t else (v::h)::add_to_front v t;;
  188.  
  189. let rec all_winning_moves_tree tree player =
  190. match tree with
  191. Level(board, []) -> if (can_win (Level (board,[])) player) then [[board]] else [[]]
  192. | Level(board, x) -> add_to_front board (all_winning_moves_list x player)
  193.  
  194.  
  195. and all_winning_moves_list game_list player =
  196. match game_list with
  197. [] -> [[]]
  198. | h::t -> (all_winning_moves_tree h player)
  199. @ all_winning_moves_list t player;;
  200.  
  201. let all_winning_moves board player =
  202. all_winning_moves_tree (gen_games player board) player;;
  203.  
  204.  
  205. let rec likely_help winlist player =
  206. match winlist with
  207. [] -> []
  208. | (h::(h1::t1))::t2 ->
  209. if List.length(all_winning_moves h1 player) > List.length(likely_help t2 player)
  210. then h::(h1::t1)
  211. else likely_help t2 player
  212.  
  213. let likely board player =
  214. List.nth (likely_help (all_winning_moves board player) player) 1;;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement