별의 공부 블로그 🧑🏻‍💻
728x90
728x170
;; Defining global varaibles and constants

(defconstant One 1) ;; human
(defconstant TheOther 10) ;; computer

(defvar *Opponent* One)
(defvar *Computer* TheOther)

(defvar *Triplets*
'((1 2 3) (4 5 6) (7 8 9) ;; Horizontal Line
(1 4 7) (2 5 8) (3 6 9) ;; Vertical Line
(1 5 9) (3 5 7))) ;; Diagonal Line

;; Main

;; Initialization: Creating a board

(defun makeBoard ()
(list 'Board 0 0 0 0 0 0 0 0 0))

(defun convert-to-letter (v)
(cond ((equal v One) "O")
((equal v TheOther) "X")
(t " ")))

(defun print-row (x y z)
(format t "~& ~A │ ~A │ ~A"
(convert-to-letter x)
(convert-to-letter y)
(convert-to-letter z)))

(defun printBoard (board)
(format t "~%")
(print-row (nth 1 board) (nth 2 board) (nth 3 board))
(format t "~& ------------")
(print-row (nth 4 board) (nth 5 board) (nth 6 board))
(format t "~& ------------")
(print-row (nth 7 board) (nth 8 board) (nth 9 board))
(format t "~%~%"))

(defun makeMove (Player Pos Board)
(setf (nth Pos Board) Player) Board)

(defun sumTriplet (Board Triplet)
(+ (nth (first Triplet) Board)
(nth (second Triplet) Board)
(nth (third Triplet) Board)))

(defun computeSums (Board)
(mapcar #'(lambda (Triplet)
(sumTriplet Board Triplet))
*Triplets*))

(defun winnerP (Board)
(let ((Sums (computeSums Board)))
(or (member (* 3 *Computer*) Sums)
(member (* 3 *Opponent*) Sums))))

(defun playOneGame ()
(if (y-or-n-p "Do you like to go first? ")
(opponentMove (makeBoard))
(computerMove (makeBoard))))

(defun opponentMove (Board)
(let* ((Pos (readALegalMove Board))
(NewBoard (makeMove *Opponent* Pos Board)))
(printBoard NewBoard)
(cond ((winnerP NewBoard) 'YouWin)
((boardFullP NewBoard) 'TieGame)
(t (computerMove NewBoard)))))

(defun readALegalMove (Board)
(format t "~& Your move: ")
(let ((Pos (read)))
(cond ((not (and (integerp Pos)))
(format t "~& Invalid input.")
(readALegalMove Board))
((not (zerop (nth Pos Board)))
(format t "~& Already occupied.")
(readALegalMove Board))
(t Pos))))

(defun boardFullP (Board)
(not (member 0 Board)))

(defun computerMove (Board)
(let* ((BestMove (chooseBestMove Board))
(Pos (first BestMove))
(Strategy (second BestMove))
(NewBoard (makeMove *Computer* Pos Board)))
(format t "~&My move: ~S" Pos)
(format t "~&My strategy: ~A~%" Strategy)
(printBoard NewBoard)
(cond ((winnerP NewBoard) 'IWin)
((boardFullP NewBoard) 'TieGame)
(t (opponentMove NewBoard)))))

(defun chooseBestMove (Board)
"1st version"
(randomMoveStrategy Board))

(defun randomMoveStrategy (Board)
(list (pickRandomEmptyPosition Board) "Random Move"))

(defun pickRandomEmptyPosition (Board)
(let ((Pos (+ 1 (random 9))))
(if (zerop (nth Pos Board)) Pos (pickRandomEmptyPosition Board))))

(defun makeThree (Board)
(let ((Pos (winOrBlock Board (* 2 *Computer*)))) ;; 2 * 10
(and Pos (list Pos "make three in a row"))))

(defun blockOpponentWin (Board)
(let ((Pos (winOrBlock Board (* 2 *Opponent*)))) ;; 2 * 1
(and Pos (list Pos "block the opponent"))))

(defun winOrBlock (Board TargetSum)
(let ((Triplet ;; Triplet ? a specific triplet, e.g., (1 2 3)
(find-if #'(lambda (Tri)
(equal (sumTriplet Board Tri) TargetSum)) *Triplets*)))
(when Triplet (findEmptyPosition Board Triplet))))

(defun findEmptyPosition (Board Cells) ;; Cells in a triplet, (1 2 3)
(find-if #'(lambda (Pos) (zerop (nth Pos Board))) Cells))

(defun chooseBestMove (Board)
"2nd version"
(or (makeThree Board)
(blockOpponentWin Board)
(randomMoveStrategy Board)))


728x90
그리드형(광고전용)

'Source Code > LISP (CL)' 카테고리의 다른 글

Block's World  (0) 2017.06.08
samesetp  (0) 2017.05.31
입출력 (INPUT / OUTPUT)  (0) 2017.05.18
순환 (Recursion)  (0) 2017.05.16
Checking whether an input element is a number or not with using DO macro. (Infinite Loop)  (0) 2017.04.21
⚠️AdBlock이 감지되었습니다. 원할한 페이지 표시를 위해 AdBlock을 꺼주세요.⚠️
starrykss
starrykss
별의 공부 블로그 🧑🏻‍💻


📖 Contents 📖