Guest User

Untitled

a guest
Jun 20th, 2018
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.04 KB | None | 0 0
  1. ;;;; tictactoe.lisp
  2. ;;;;
  3. ;;;; Andrew Levenson
  4. ;;;; 10/27/10
  5. ;;;;
  6. ;;;; Simple two player ASCII Tic Tac Toe Game
  7.  
  8. ;;; First player is X, so initialize the marker to X
  9. (setf *marker* :X)
  10. (setf *player* "Player 1")
  11.  
  12. ;;; Create the board in memory
  13. (defun create-board ()
  14. ;; Board was initially a 3x3 2D Array, for realism.
  15. ;; Changed it to a 9 element Vector for simplification of referencing.
  16. (setf *board* (make-array 9
  17. :initial-contents
  18. '(1 2 3 4 5 6 7 8 9))))
  19.  
  20. ;;; Greet the player and display the board.
  21. (defun welcome-player ()
  22. (format t "Welcome to TicTacToe!~%~%")
  23. (create-board)
  24. (play nil))
  25.  
  26. ;;; Switch the active player.
  27. (defun switch-player ()
  28. (if (equal *marker* :X)
  29. (setf *marker* :O)
  30. (setf *marker* :X))
  31. (if (equal *player* "Player 1")
  32. (setf *player* "Player 2")
  33. (setf *player* "Player 1")))
  34.  
  35. ;;; Draw the board
  36. (defun draw-board ()
  37. ;; (cell-ref #) will be either
  38. ;; 1. The number representing the space (before it is chosen), or
  39. ;; 2. A marker (:X or :O) once the space has been chosen.
  40. (format t " | | ~%")
  41. (format t " ~a | ~a | ~a ~%" (cell-ref 1) (cell-ref 2) (cell-ref 3))
  42. (format t " | | ~%")
  43. (format t "_________________~%")
  44. (format t " | | ~%")
  45. (format t " ~a | ~a | ~a ~%" (cell-ref 4) (cell-ref 5) (cell-ref 6))
  46. (format t " | | ~%")
  47. (format t "_________________~%")
  48. (format t " | | ~%")
  49. (format t " ~a | ~a | ~a ~%" (cell-ref 7) (cell-ref 8) (cell-ref 9))
  50. (format t " | | ~%~%"))
  51.  
  52. ;;; Play a move
  53. (defun play (&optional switch-p)
  54. ;; If the switch predicate is set to true, switch players.
  55. (when switch-p (switch-player))
  56. ;; Go through the motions for selecting a square
  57. ;; and checking for correctness.
  58. (check-choice (read-choice))
  59. ;; If nobody has won and the board is not filled,
  60. ;; then recursively call this function with the switch predicate
  61. ;; so that the next player may go.
  62. (when (and
  63. (not (check-for-win-p))
  64. (not (stalemate)))
  65. (play t))
  66. ;; If someone has won
  67. ;; 1. Alert the players as to which player won
  68. ;; 2. Ask if they want to play again.
  69. ;; If yes, play again. If no, quit.
  70. (when (check-for-win-p)
  71. (progn
  72. (format t "~a has won! " *player*)
  73. (force-output nil)
  74. (if (y-or-n-p "Play again? ")
  75. (play-again)
  76. (quit))))
  77. ;; If there is a stalemate
  78. ;; Ask if the players wish to play again.
  79. ;; If yes, play again. If no, quit.
  80. (when (stalemate)
  81. (if (y-or-n-p "~%~%Stalemate! Play again? ")
  82. (play-again)
  83. (quit))))
  84.  
  85. ;;; Play the game again
  86. ;;; Is only called after a win or a stalemate
  87. (defun play-again ()
  88. ;; Reset the board to all numbers
  89. (create-board)
  90. ;; Switch players, so whoever ended
  91. ;; the last game goes second this game.
  92. (switch-player)
  93. (format t "This game will be started by ~a.~%~%" *player*)
  94. (play))
  95.  
  96. ;;; Allow the player to choose a square
  97. ;;; Or, if they wish, display the board with
  98. ;;; the numbers on it.
  99. (defun read-choice ()
  100. ;; Show their options
  101. (draw-board)
  102. (format t "~a, select a number to choose a square.~%" *player*)
  103. (force-output nil)
  104. ;; Read from STDIN,
  105. ;; parsing an integer out, if there is any.
  106. (parse-integer (read-line *query-io*) :junk-allowed t))
  107.  
  108. ;;; Check to make sure that the cell chosen
  109. ;;; actually exists on the board.
  110. (defun check-choice (choice)
  111. (if
  112. ;; All of the following must be true
  113. (and
  114. ;; Must be a number (der)
  115. (numberp choice)
  116. ;; Must lie between 1 and 9, inclusive
  117. (> choice 0)
  118. (< choice 10))
  119. ;; If it's a valid cell, pass it to (select)
  120. (select choice)
  121. ;; Otherwise, warn the player they made an invalid
  122. ;; selection, and repeat the process.
  123. (progn
  124. (format t "~%Invalid choice.~%")
  125. (check-choice (read-choice)))))
  126.  
  127. ;;; Select their cell, if it hasn't
  128. ;;; already been selected.
  129. (defun select (choice)
  130. ;; If the cell contains a number
  131. ;; (i.e. it has not yet been selected)
  132. (if (numberp (cell-ref choice))
  133. ;; Set the cell to their marker
  134. (set-cell choice)
  135. ;; Otherwise, warn them of an invalid selection
  136. (invalid-selection)))
  137.  
  138. ;;; Warn the player if they choose a spot that is taken.
  139. (defun invalid-selection ()
  140. (format t "That spot is taken. Please choose another spot.~%~%")
  141. (force-output nil)
  142. (check-choice (read-choice)))
  143.  
  144. ;;; Check to see if there are any lines made
  145. ;;; (i.e. someone won)
  146. ;;;
  147. ;;; This function is called every time someone
  148. ;;; selects a cell, to make displaying the winner
  149. ;;; easier.
  150. (defun check-for-win-p ()
  151. ;; If any of these sets of 3 cells form a line,
  152. ;; that means that the active player won the game.
  153. (or (is-line-p 1 2 3)
  154. (is-line-p 1 4 7)
  155. (is-line-p 1 5 9)
  156. (is-line-p 2 5 8)
  157. (is-line-p 3 6 9)
  158. (is-line-p 3 5 7)
  159. (is-line-p 4 5 6)
  160. (is-line-p 7 8 9)))
  161.  
  162. ;;; If the three cell numbers passed to
  163. ;;; (is-line-p) contain identical values,
  164. ;;; then a line has been made.
  165. (defun is-line-p (a b c)
  166. (and
  167. (equal
  168. (cell-ref a)
  169. (cell-ref b))
  170. (equal
  171. (cell-ref a)
  172. (cell-ref c))))
  173.  
  174. ;;; Define what it means for the board to be filled.
  175. ;;;
  176. ;;; This function is always called AFTER (check-for-win-p).
  177. ;;; This ensures that if the last move is a winning move,
  178. ;;; a stalemate is not reported.
  179. (defun stalemate ()
  180. ;; If none of the spaces contain numbers
  181. ;; (i.e. all spaces contain a marker)
  182. ;; and nobody has won, then a stalemate has been reached.
  183. (notany #'numberp *board*))
  184.  
  185. ;;; Mask the implementation of the board
  186. ;;; in terms of referencing a cell.
  187. (defun cell-ref (cell)
  188. ;; (cell-ref cell) now calls an array reference
  189. ;; to the cell number minus one, to compensate
  190. ;; for the fact that the array index starts at 0.
  191. (aref *board* (1- cell)))
  192.  
  193. ;;; Mask the implementation of the board
  194. ;;; in terms of setting a cell value.
  195. (defun set-cell (cell)
  196. ;; (set-cell cell) now calls an array reference
  197. ;; to the cell number minus one, to compensate
  198. ;; for the fact that the array index starts at 0,
  199. ;; and sets that reference to the marker.
  200. (setf (aref *board* (1- cell)) *marker*))
  201.  
  202. ;;; Begin the game.
  203. (welcome-player)
Add Comment
Please, Sign In to add comment