fork download
  1. % main menu
  2. start :-
  3. write('Tic-Tac-Toe'), nl,
  4. write('Laboratory work 7'), nl, nl,
  5. menu.
  6.  
  7. menu :-
  8. write('Select action:'), nl,
  9. write('1. Test best move procedure'), nl,
  10. write('2. Play against computer'), nl,
  11. write('3. Exit'), nl,
  12. write('Your choice (1-3): '),
  13. read(Choice),
  14. handle_choice(Choice).
  15.  
  16. handle_choice(1) :- !, test_best_move, menu.
  17. handle_choice(2) :- !, play_game, menu.
  18. handle_choice(3) :- !, write('Exiting program'), nl.
  19. handle_choice(_) :-
  20. write('Invalid choice'), nl, nl,
  21. menu.
  22.  
  23. % testing best move procedure
  24. test_best_move :-
  25. nl, write('Best move search test'), nl,
  26. Board = [x, x, 3, o, 5, 6, 7, 8, 9],
  27. write('Test board:'), nl,
  28. draw_board(Board),
  29. best_move(Board, x, Row, Col),
  30. write('Best move for X: row '), write(Row),
  31. write(', column '), write(Col), nl, nl.
  32.  
  33. % start new game
  34. play_game :-
  35. nl, write('New game'), nl,
  36. write('You play X, computer plays O'), nl,
  37. write('Enter cell number 1-9'), nl, nl,
  38. Board = [1,2,3,4,5,6,7,8,9],
  39. draw_board(Board),
  40. game_loop(Board, x).
  41.  
  42. % game loop
  43. game_loop(Board, _) :-
  44. check_winner(Board, Winner), !,
  45. write('Winner: '), write(Winner), nl, nl.
  46.  
  47. game_loop(Board, _) :-
  48. check_draw(Board), !,
  49. write('Draw!'), nl, nl.
  50.  
  51. game_loop(Board, x) :-
  52. human_move(Board, NewBoard), !,
  53. draw_board(NewBoard),
  54. game_loop(NewBoard, o).
  55.  
  56. game_loop(Board, o) :-
  57. computer_move(Board, NewBoard), !,
  58. write('Computer move:'), nl,
  59. draw_board(NewBoard),
  60. game_loop(NewBoard, x).
  61.  
  62. % human move
  63. human_move(Board, NewBoard) :-
  64. write('Your move (1-9): '),
  65. read(Pos),
  66. valid_move(Board, Pos),
  67. place_move(Board, Pos, x, NewBoard), !.
  68.  
  69. human_move(Board, NewBoard) :-
  70. write('Invalid move, try again'), nl,
  71. human_move(Board, NewBoard).
  72.  
  73. % computer move
  74. computer_move(Board, NewBoard) :-
  75. best_move(Board, o, Row, Col),
  76. Pos is (Row - 1) * 3 + Col,
  77. place_move(Board, Pos, o, NewBoard).
  78.  
  79. % find best move
  80. best_move(Board, Player, Row, Col) :-
  81. winning_move(Board, Player, Row, Col), !.
  82.  
  83. best_move(Board, Player, Row, Col) :-
  84. opponent(Player, Opp),
  85. blocking_move(Board, Opp, Row, Col), !.
  86.  
  87. best_move(Board, _, Row, Col) :-
  88. strategic_move(Board, Row, Col).
  89.  
  90. % winning move
  91. winning_move(Board, Player, Row, Col) :-
  92. check_line(Board, Player, Row, Col).
  93.  
  94. % blocking move
  95. blocking_move(Board, Opp, Row, Col) :-
  96. check_line(Board, Opp, Row, Col).
  97.  
  98. % check line
  99. check_line(Board, P, Row, Col) :-
  100. line(R1, C1, R2, C2, R3, C3),
  101. pos_value(Board, R1, C1, V1),
  102. pos_value(Board, R2, C2, V2),
  103. pos_value(Board, R3, C3, V3),
  104. two_in_line(V1, V2, V3, P, Row, Col, R1, C1, R2, C2, R3, C3).
  105.  
  106. two_in_line(P, P, V3, P, R3, C3, _, _, _, _, R3, C3) :- number(V3), !.
  107. two_in_line(P, V2, P, P, R2, C2, _, _, R2, C2, _, _) :- number(V2), !.
  108. two_in_line(V1, P, P, P, R1, C1, R1, C1, _, _, _, _) :- number(V1), !.
  109.  
  110. % strategic move
  111. strategic_move(Board, Row, Col) :-
  112. priority(Row, Col),
  113. Pos is (Row - 1) * 3 + Col,
  114. valid_move(Board, Pos), !.
  115.  
  116. % position priority
  117. priority(2, 2).
  118. priority(1, 1).
  119. priority(1, 3).
  120. priority(3, 1).
  121. priority(3, 3).
  122. priority(1, 2).
  123. priority(2, 1).
  124. priority(2, 3).
  125. priority(3, 2).
  126.  
  127. % lines to check
  128. line(1, 1, 1, 2, 1, 3).
  129. line(2, 1, 2, 2, 2, 3).
  130. line(3, 1, 3, 2, 3, 3).
  131. line(1, 1, 2, 1, 3, 1).
  132. line(1, 2, 2, 2, 3, 2).
  133. line(1, 3, 2, 3, 3, 3).
  134. line(1, 1, 2, 2, 3, 3).
  135. line(1, 3, 2, 2, 3, 1).
  136.  
  137. % opponent
  138. opponent(x, o).
  139. opponent(o, x).
  140.  
  141. % check winner
  142. check_winner(Board, Winner) :-
  143. line(R1, C1, R2, C2, R3, C3),
  144. pos_value(Board, R1, C1, Winner),
  145. \+ number(Winner),
  146. pos_value(Board, R2, C2, Winner),
  147. pos_value(Board, R3, C3, Winner), !.
  148.  
  149. % check draw
  150. check_draw(Board) :-
  151. \+ (member(X, Board), number(X)).
  152.  
  153. % valid move check
  154. valid_move(Board, Pos) :-
  155. integer(Pos),
  156. Pos >= 1,
  157. Pos =< 9,
  158. nth1(Pos, Board, Val),
  159. number(Val).
  160.  
  161. % place move
  162. place_move([_|T], 1, Player, [Player|T]) :- !.
  163. place_move([H|T], Pos, Player, [H|R]) :-
  164. Pos > 1,
  165. Pos1 is Pos - 1,
  166. place_move(T, Pos1, Player, R).
  167.  
  168. % get position value
  169. pos_value(Board, Row, Col, Val) :-
  170. Pos is (Row - 1) * 3 + Col,
  171. nth1(Pos, Board, Val).
  172.  
  173. % draw board
  174. draw_board(Board) :-
  175. nth1(1, Board, V1), nth1(2, Board, V2), nth1(3, Board, V3),
  176. nth1(4, Board, V4), nth1(5, Board, V5), nth1(6, Board, V6),
  177. nth1(7, Board, V7), nth1(8, Board, V8), nth1(9, Board, V9),
  178. format(' ~w | ~w | ~w ~n', [V1, V2, V3]),
  179. write('-----------'), nl,
  180. format(' ~w | ~w | ~w ~n', [V4, V5, V6]),
  181. write('-----------'), nl,
  182. format(' ~w | ~w | ~w ~n', [V7, V8, V9]),
  183. nl.
  184.  
  185. start.
  186.  
Success #stdin #stdout #stderr 0.03s 6960KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Warning: /home/QQtqEI/prog:185:
	Clauses of start/0 are not together in the source-file
	  Earlier definition at /home/QQtqEI/prog:2
	  Current predicate: draw_board/1
	  Use :- discontiguous start/0. to suppress this message
ERROR: '$runtoplevel'/0: Undefined procedure: program/0
   Exception: (3) program ? EOF: exit