Lisp Крестики Нолики

Узнай цену своей работы

Формулировка задачи:

Друзья просьба помочь : есть код, но где-то закралась ошибка пишет "Не сбалансированы скобки S-выражения" Не могу запустить на Homelisp ее
(defpackage :xo (:use :cl) (:export :start-game)) (in-package :xo) (defvar *game-space* (make-array '(3 3))) (defvar *turns-history*) (defmacro other-player (who) `(if (eql ,who :X) :0 :X)) (defmacro first-possible (&rest forms) (if forms `(if ,(car forms) ,(car forms) (first-possible ,@(cdr forms))))) (defvar *printing* t) (defvar *ai* nil) ;;; Printing section ;;; (defun print-game-space () (princ " - 1 - 2 - 3 -") ;; X indexes (princ #\Newline) (princ "- -------------") (loop for i upto 2 doing (princ #\Newline) (princ (+ 1 i)) (princ " |") ;; Y indexes (loop for j upto 2 doing (format t " ~a |" (first-possible (aref *game-space* i j) " "))) (princ #\Newline) (princ "- -------------")) (princ #\Newline) nil)( (defun print-turns-history () (princ #\Newline) (princ "The turns were:") (princ #\Newline) (let ((who :X)) (loop for i upto 9 for (x y) in (reverse *turns-history*) doing (format t "~d. The ~a turn was: x - ~d, y - ~d.~%" (+ i 1) who (+ x 1) (+ y 1)) (setf who (other-player who))))) (defun win (who &optional technical) (when *printing* (print-game-space) (format t "~a is winner!" who) (if technical (progn (princ " Technical victory!") nil) (print-turns-history))) (list who technical)) (defun draw () (when *printing* (print-game-space) (princ "Draw! Nobody wins.") (print-turns-history)) nil) ;;; end Printing section ;;; ;;; AI section ;;; (defun ensure-row (how-many who row) (if (= how-many (loop for i upto 2 summing (if (eql who (elt (second row) i)) 1 (if (eql (other-player who) (elt (second row) i)) -2 0)))) (first row))) (defun row (game-space n &optional (column nil)) (let ((indexes (loop for i to 2 collecting (list (if column n i) (if column i n))))) (list indexes (loop for i in indexes collecting (aref game-space (first i) (second i)))))) (defun diagonal (game-space &optional (minus nil)) (let ((indexes (loop for i to 2 collecting (list (if minus (- 2 i) i) i)))) (list indexes (loop for index in indexes collecting (aref game-space (first index) (second index)))))) (defun search-for-all-empties (list-of-cells game-space) (remove-if-not #'(lambda (x) (null (aref game-space (first x) (second x)))) list-of-cells)) (defun the-most-frequent (minimum &rest lists) (let ((great-list (apply #'concatenate 'list lists))) (nth (first-possible (position (if (<= minimum (loop for cell in great-list maximize (count cell great-list :test #'equal))) (loop for cell in great-list maximize (count cell great-list :test #'equal)) nil) (loop for cell in great-list collecting (count cell great-list :test #'equal))) 99) great-list))) (defun whole-space (game-space) (concatenate 'list (first (row game-space 0)) (first (row game-space 1)) (first (row game-space 2)))) (defun all-space (game-space) (list (row game-space 0) (row game-space 1) (row game-space 2) (row game-space 0 t) (row game-space 1 t) (row game-space 2 t) (diagonal game-space) (diagonal game-space t))) (defun ai-find-turn (who game-space &optional aim) (cond ((eql aim :win) (setf aim 2)) ((eql aim :trapping) (setf aim 1)) (t (setf aim 0))) (search-for-all-empties (apply #'concatenate 'list (remove-if #'null (loop for row in (all-space game-space) collecting (ensure-row aim who row)))) game-space)) (defun ai-find-good-turn (who game-space) ;; this is bad (first-possible (the-most-frequent 1 (ai-find-turn who game-space :trapping) (ai-find-turn who game-space) (ai-find-turn who game-space)))) (defun ai-find-trap (who game-space &optional of-enemy) ;; this is better (if of-enemy (setf who (other-player who))) (first-possible (the-most-frequent (if of-enemy 3 2) (ai-find-turn who game-space :trapping) (if of-enemy ;; to block a trap with attack (ai-find-turn (other-player who) game-space :trapping))))) (defun ai-find-any (game-space) (search-for-all-empties (whole-space game-space) game-space)) (defun ai (who game-space level) (first-possible (if (> level 0) (car (ai-find-turn who game-space :win))) (if (> level 1) (car (ai-find-turn (other-player who) game-space :win))) (if (> level 3) (ai-find-trap who game-space)) (if (> level 4) (ai-find-trap who game-space t)) (if (> level 2) (ai-find-good-turn who game-space)) (first (ai-find-any game-space)))) ;;; end AI section ;;; ;;; X0 section ;;; ;; WARNING This function uses some functions from AI section (defun check-for-victory (who) (find-if-not #'null (loop for row in (all-space *game-space*) collecting (ensure-row 3 who row)))) (defun check-for-correctness (x y) (and (and (find x '(1 2 3)) (find y '(1 2 3))) ;; If some other symbol inserted (null (aref *game-space* (- x 1) (- y 1))))) ;; If already exists (defun check-for-draw () (= 0 (loop for i upto 2 summing (loop for j upto 2 summing (if (null (aref *game-space* i j)) 1 0))))) (defun ask-for-input (who) (cond ((eql who (first *ai*)) (ai who *game-space* (second *ai*))) ((eql :X0 (first *ai*)) (ai who *game-space* (if (eql :X who) (first (second *ai*)) (second (second *ai*))))) (t (let ((x (read)) (y (read))) (if (eql :ai x) (ai who *game-space* y) (if (check-for-correctness x y) (list (decf x) (decf y)))))))) ;; Make input numbers indexes. (defun turn (&optional (who :X)) (when *printing* (princ "It is the turn of ") (princ (if (eql :X who) "X!" "0!")) (princ #\Newline) (print-game-space)) (let ((input (ask-for-input who))) (if (null input) (win (other-player who) t) ;; Exit variant #1 -- not win. (let ((x (first input)) (y (second input))) (push (list x y) *turns-history*) (setf (aref *game-space* x y) who) (if (check-for-victory who) (win who) ;; Exit variant #2 -- win. (if (check-for-draw) (draw) ;; Exit variant #3 -- draw. (turn (other-player who)))))))) ;; Recursive call! (defun start-game (&optional (ai nil) (printing t)) (setf *printing* printing) (setf *ai* ai) (setf *turns-history* nil) ;; Turns history clearing. (loop for i upto 2 doing (loop for j upto 2 doing (setf (aref *game-space* 3 3) nil))) ;; Game space clearing. (turn)) ;;; end X0 section ;;;

Решение задачи: «Lisp Крестики Нолики»

textual
Листинг программы
  1. (defpackage :xo (:use :cl) (:export :start-game))
  2.  
  3. (in-package :xo)
  4.  
  5. (defvar *game-space* (make-array '(3 3)))
  6.  
  7. (defvar *turns-history*)
  8.  
  9. (defmacro other-player (who)
  10. `(if (eql ,who :X)
  11. :0 :X))
  12.  
  13. (defmacro first-possible (&rest forms)
  14. (if forms
  15. `(if ,(car forms) ,(car forms)
  16. (first-possible ,@(cdr forms)))))
  17.  
  18. (defvar *printing* t)
  19.  
  20. (defvar *ai* nil)
  21.  
  22. ;;; Printing section ;;;
  23.  
  24. (defun print-game-space ()
  25. (princ " - 1 - 2 - 3 -") ;; X indexes
  26. (princ #\Newline)
  27. (princ "- -------------")
  28. (loop for i upto 2 doing
  29. (princ #\Newline)
  30. (princ (+ 1 i)) (princ " |") ;; Y indexes
  31. (loop for j upto 2 doing
  32. (format t " ~a |"
  33. (first-possible
  34. (aref *game-space* i j)
  35. " ")))
  36. (princ #\Newline)
  37. (princ "- -------------"))
  38. (princ #\Newline) nil)
  39.  
  40. (defun print-turns-history ()
  41. (princ #\Newline)
  42. (princ "The turns were:")
  43. (princ #\Newline)
  44. (let ((who :X))
  45. (loop
  46. for i upto 9
  47. for (x y) in (reverse *turns-history*) doing
  48. (format t "~d. The ~a turn was: x - ~d, y - ~d.~%"
  49. (+ i 1) who (+ x 1) (+ y 1))
  50. (setf who (other-player who)))))
  51.  
  52. (defun win (who &optional technical)
  53. (when *printing*
  54. (print-game-space)
  55. (format t "~a is winner!" who)
  56. (if technical
  57. (progn (princ " Technical victory!") nil)
  58. (print-turns-history)))
  59. (list who technical))
  60.  
  61. (defun draw ()
  62. (when *printing*
  63. (print-game-space)
  64. (princ "Draw! Nobody wins.")
  65. (print-turns-history))
  66. nil)
  67.  
  68. ;;; end Printing section ;;;
  69.  
  70. ;;; AI section ;;;
  71.  
  72. (defun ensure-row (how-many who row)
  73. (if (= how-many (loop for i upto 2 summing
  74. (if (eql who
  75. (elt (second row) i))
  76. 1 (if (eql (other-player who)
  77. (elt (second row) i))
  78. -2 0))))
  79. (first row)))
  80.  
  81. (defun row (game-space n &optional (column nil))
  82. (let ((indexes
  83. (loop for i to 2 collecting
  84. (list (if column n i) (if column i n)))))
  85. (list indexes
  86. (loop for i in indexes collecting
  87. (aref game-space (first i) (second i))))))
  88.  
  89. (defun diagonal (game-space &optional (minus nil))
  90. (let ((indexes
  91. (loop for i to 2 collecting
  92. (list (if minus (- 2 i) i) i))))
  93. (list indexes
  94. (loop for index in indexes collecting
  95. (aref game-space (first index) (second index))))))
  96.  
  97. (defun search-for-all-empties (list-of-cells game-space)
  98. (remove-if-not #'(lambda (x) (null (aref game-space
  99. (first x)
  100. (second x)))) list-of-cells))
  101.  
  102. (defun the-most-frequent (minimum &rest lists)
  103. (let ((great-list
  104. (apply #'concatenate 'list lists)))
  105. (nth (first-possible
  106. (position (if (<= minimum
  107. (loop for cell in great-list maximize
  108. (count cell great-list :test #'equal)))
  109. (loop for cell in great-list maximize
  110. (count cell great-list :test #'equal))
  111. nil)
  112. (loop for cell in great-list collecting
  113. (count cell great-list :test #'equal)))
  114. 99)
  115. great-list)))
  116.  
  117. (defun whole-space (game-space)
  118. (concatenate 'list
  119. (first (row game-space 0))
  120. (first (row game-space 1))
  121. (first (row game-space 2))))
  122.  
  123. (defun all-space (game-space)
  124. (list
  125. (row game-space 0)
  126. (row game-space 1)
  127. (row game-space 2)
  128. (row game-space 0 t)
  129. (row game-space 1 t)
  130. (row game-space 2 t)
  131. (diagonal game-space)
  132. (diagonal game-space t)))
  133.  
  134. (defun ai-find-turn (who game-space &optional aim)
  135. (cond
  136. ((eql aim :win) (setf aim 2))
  137. ((eql aim :trapping) (setf aim 1))
  138. (t (setf aim 0)))
  139. (search-for-all-empties
  140. (apply #'concatenate 'list
  141. (remove-if #'null
  142. (loop for row in
  143. (all-space game-space)
  144. collecting
  145. (ensure-row aim who row)))) game-space))
  146.  
  147. (defun ai-find-good-turn (who game-space) ;; this is bad
  148. (first-possible
  149. (the-most-frequent 1
  150. (ai-find-turn who game-space :trapping)
  151. (ai-find-turn who game-space)
  152. (ai-find-turn who game-space))))
  153.  
  154. (defun ai-find-trap (who game-space &optional of-enemy) ;; this is better
  155. (if of-enemy (setf who (other-player who)))
  156. (first-possible
  157. (the-most-frequent (if of-enemy 3 2)
  158. (ai-find-turn who game-space :trapping)
  159. (if of-enemy ;; to block a trap with attack
  160. (ai-find-turn (other-player who)
  161. game-space :trapping)))))
  162.  
  163. (defun ai-find-any (game-space)
  164. (search-for-all-empties (whole-space game-space) game-space))
  165.  
  166. (defun ai (who game-space level)
  167. (first-possible
  168. (if (> level 0)
  169. (car (ai-find-turn who game-space :win)))
  170. (if (> level 1)
  171. (car (ai-find-turn (other-player who) game-space :win)))
  172. (if (> level 3)
  173. (ai-find-trap who game-space))
  174. (if (> level 4)
  175. (ai-find-trap who game-space t))
  176. (if (> level 2)
  177. (ai-find-good-turn who game-space))
  178. (first
  179. (ai-find-any game-space))))
  180.  
  181. ;;; end AI section ;;;
  182.  
  183. ;;; X0 section ;;;
  184.  
  185. ;; WARNING This function uses some functions from AI section
  186. (defun check-for-victory (who)
  187. (find-if-not #'null
  188. (loop for row in (all-space *game-space*) collecting
  189. (ensure-row 3 who row))))
  190.  
  191. (defun check-for-correctness (x y)
  192. (and (and (find x '(1 2 3))
  193. (find y '(1 2 3))) ;; If some other symbol inserted
  194. (null (aref *game-space* (- x 1) (- y 1))))) ;; If already exists
  195.  
  196. (defun check-for-draw ()
  197. (= 0
  198. (loop for i upto 2
  199. summing
  200. (loop for j upto 2
  201. summing
  202. (if (null (aref *game-space* i j)) 1 0)))))
  203.  
  204. (defun ask-for-input (who)
  205. (cond
  206. ((eql who (first *ai*)) (ai who *game-space* (second *ai*)))
  207. ((eql :X0 (first *ai*)) (ai who *game-space*
  208. (if (eql :X who)
  209. (first (second *ai*))
  210. (second (second *ai*)))))
  211. (t (let ((x (read)) (y (read)))
  212. (if (eql :ai x)
  213. (ai who *game-space* y)
  214. (if (check-for-correctness x y)
  215. (list (decf x) (decf y)))))))) ;; Make input numbers indexes.
  216.  
  217. (defun turn (&optional (who :X))
  218. (when *printing*
  219. (princ "It is the turn of ")
  220. (princ (if (eql :X who) "X!" "0!"))
  221. (princ #\Newline)
  222. (print-game-space))
  223. (let ((input (ask-for-input who)))
  224. (if (null input)
  225. (win (other-player who) t) ;; Exit variant #1 -- not win.
  226. (let ((x (first input)) (y (second input)))
  227. (push (list x y) *turns-history*)
  228. (setf (aref *game-space* x y) who)
  229. (if (check-for-victory who)
  230. (win who) ;; Exit variant #2 -- win.
  231. (if (check-for-draw)
  232. (draw) ;; Exit variant #3 -- draw.
  233. (turn (other-player who)))))))) ;; Recursive call!
  234.  
  235. (defun start-game (&optional (ai nil) (printing t))
  236. (setf *printing* printing)
  237. (setf *ai* ai)
  238. (setf *turns-history* nil) ;; Turns history clearing.
  239. (loop for i upto 2 doing
  240. (loop for j upto 2 doing
  241. (setf (aref *game-space* 3 3) nil))) ;; Game space clearing.
  242. (turn))
  243.  
  244. ;;; end X0 section ;;;

Объяснение кода листинга программы

В коде представлена реализация игры Крестики-нолики на языке Lisp. Ниже представлен комментарий к каждому из пунктов:

  1. (defpackage :xo (:use :cl) (:export :start-game)) - Эта строка определяет пакет с именем :xo, который использует модуль :cl (Common Lisp). Также экспортируется функция :start-game.
  2. (in-package :xo) - Эта строка указывает, что весь следующий код будет работать в пакете :xo.
  3. (defvar game-space (make-array '(3 3))) - Здесь определяется переменная game-space, которая представляет собой массив размером 3x3, используемый для представления игрового поля.
  4. (defvar turns-history) - Здесь определяется переменная turns-history, которая будет хранить историю ходов.
  5. (defmacro other-player (who) (if (eql ,who :X) :0 :X)) - Эта строка определяет макрос other-player, который возвращает :0, если игрок, чей ход был сделан, играл закрестики, и :X, если занолики`.
  6. (defmacro first-possible (&rest forms) (if forms `(if ,(car forms) ,(car forms) (first-possible ,@(cdr forms))))) - Эта строка определяет макрос first-possible, который принимает список форм и возвращает первую возможную форму.
  7. (defvar printing t) - Здесь определяется переменная printing, которая по умолчанию установлена в true и используется для контроля вывода на печать.
  8. (defvar ai nil) - Здесь определяется переменная ai, которая будет использоваться для хранения информации об искусственном интеллекте (если он будет использоваться).
  9. (defun print-game-space () ...) - Эта функция печатает текущее состояние игрового поля.
  10. (defun print-turns-history () ...) - Эта функция печатает историю ходов.
  11. (defun win (who &optional technical) ...) - Эта функция проверяет, выиграл ли кто-то в игре, и выводит соответствующее сообщение.
  12. (defun draw () ...) - Эта функция проверяет, является ли игра ничьей, и выводит соответствующее сообщение.
  13. (defun ai-find-turn (who game-space &optional aim) ...) - Эта функция используется искусственным интеллектом для поиска наилучшего хода.
  14. (defun ai-find-good-turn (who game-space) ...) - Эта функция используется искусственным интеллектом для поиска хорошего хода.
  15. (defun ai-find-trap (who game-space &optional of-enemy) ...) - Эта функция используется искусственным интеллектом для поиска хода, который может привести к ловушке для противника.
  16. (defun ai-find-any (game-space) ...) - Эта функция используется искусственным интеллектом для поиска любого возможного хода.
  17. (defun ask-for-input (who) ...) - Эта функция запрашивает у игрока его ход.
  18. (defun turn (&optional (who :X)) ...) - Эта функция представляет основной цикл игры, который продолжается до тех пор, пока не будет достигнут победитель или ничья.
  19. (defun start-game (&optional (ai nil) (printing t)) ...) - Эта функция запускает игру, инициализируя игровое поле и историю ходов.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут