2010-12-17 105 views
2

我在CL中玩耍,在尝试处理完整的二维版本之前制作战舰的一维版本,并且我已经打了一个挂断。为了检查船是否在那里,我用零表示它,当一个点击中时,我用星号替换它,所以我可以用numberp检查这个列表。但是,当我运行(new-game)时,它立即结束,这告诉我,我没有正确输入零,因此它们被识别为数字。我究竟做错了什么?我知道这肯定是一个新秀的错误。将列表值设置为CL中的数字,然后检查它们

;;;; Suez-Canal.lisp 
;;;; 
;;;; A simple, 1-Dimensional version of Battleship 
;;;; The computer places a boat randomly, and you must sink it. 

(setf *random-state* (make-random-state t)) 
(defparameter *boat-length* 3) 
(defparameter *canal-length* 10) 
(defparameter *shots-fired* 0) 

(defun new-game() 
    (init-canal *canal-length*) 
    (place-boat) 
    (game-loop) 
    (format t "It took you ~a shots to sink the boat." *shots-fired*)) 

(defun init-canal (len) 
    (defparameter *canal* (make-list len))) 

(defun place-boat() 
    (let ((pos (random-spot))) 
    (setf (nth pos *canal*) 'O) 
    (setf (nth (+ pos 1) *canal*) 'O) 
    (setf (nth (+ pos 2) *canal*) 'O))) 

(defun random-spot() 
    (let ((x (random 7))) 
    x)) 

(defun game-loop() 
    (loop until (notany #'numberp *canal*) 
     do (progn 
     (prompt-for-guess) 
     (check-guess (read-guess)) 
     (incf *shots-fired*)))) 

(defun prompt-for-guess() 
    (format t "~&Enter in a number between 1 and 10 to fire a shot.~&")) 

(defun read-guess() 
    (parse-integer (read-line *query-io*) :junk-allowed t)) 

(defun check-guess (guess) 
    (if (and (<= guess 9) 
     (>= guess 0)) 
     (fire-shot guess) 
     (progn 
     (format t "~&Invalid selection~&") 
     (check-guess (read-guess))))) 

(defun fire-shot (pos) 
    (if (= (nth (- pos 1) *canal*) 0) 
     (progn 
     (setf (nth (- pos 1) *canal*) #\*) 
     (print "Hit!")) 
     (print "Miss!"))) 
+0

+1你的游戏的名称。 :-) – 2010-12-17 12:04:33

回答

4

您根本没有输入零,而是输入了字母'O'。

其他说明:

不要使用DEFPARAMETERDEFUN。在顶层定义变量,并且在初始化函数里面只有SETF它。

不要使用列表进行随机访问。使用arrays

Numerical comparison operators将在给出非数字值时发出错误信号。使用EQL进行一般比较。

2

这里是一个修正版本:

(setf *random-state* (make-random-state t)) 
(defparameter *boat-length* 3) 
(defparameter *canal-length* 10) 
(defparameter *shots-fired* 0) 

;;; you need to declare *canal* at toplevel. 
(defparameter *canal* nil) 

(defun new-game() 
    (init-canal *canal-length*) 
    (place-boat) 
    (game-loop) 
    (format t "It took you ~a shots to sink the boat." *shots-fired*)) 

;;; just set the the variable. 
(defun init-canal (length) 
    (setq *canal* (make-list length))) 

;;; you need to set those positions to 0 and not to O 
(defun place-boat() 
    (let ((pos (random-spot))) 
    (setf (nth pos  *canal*) 0) 
    (setf (nth (+ pos 1) *canal*) 0) 
    (setf (nth (+ pos 2) *canal*) 0))) 

;;; no need for a LET 
(defun random-spot() 
    (random 7)) 

;;; no need for progn 
;;; you could also replace UNTIL NOTANY with WHILE SOME 
(defun game-loop() 
    (loop until (notany #'numberp *canal*) 
     do 
     (prompt-for-guess) 
     (check-guess (read-guess)) 
     (incf *shots-fired*))) 

(defun prompt-for-guess() 
    (format t "~&Enter in a number between 1 and 10 to fire a shot.~&")) 

(defun read-guess() 
    (parse-integer (read-line *query-io*) :junk-allowed t)) 

;;; <= can take more than two arguments 
;;; typically this recursive version might be replaced with a LOOP 
(defun check-guess (guess) 
    (if (<= 0 guess 9) 
     (fire-shot guess) 
    (progn 
     (format t "~&Invalid selection~&") 
     (check-guess (read-guess))))) 

;;; use EQL, = only compares numbers 
(defun fire-shot (pos) 
    (if (eql (nth (- pos 1) *canal*) 0) 
     (progn 
     (setf (nth (- pos 1) *canal*) #\*) 
     (print "Hit!")) 
     (print "Miss!"))) 
相关问题