首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将列表值设置为CL中的数字,然后检查它们

将列表值设置为CL中的数字,然后检查它们
EN

Stack Overflow用户
提问于 2010-12-17 19:57:55
回答 2查看 148关注 0票数 2

我正在玩CL,在我尝试处理一个完整的二维版本之前,我制作了一个一维版本的战列舰,我遇到了一个问题。为了检查船是否在那里,我用零表示它,当一个点被击中时,我用星号代替它,这样我就可以用numberp检查列表。但是,当我运行(new-game)时,它立即结束,这告诉我我没有正确输入0,所以它们被识别为数字。我做错了什么?我知道这一定是新手犯的错误。

代码语言:javascript
复制
;;;; 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!")))
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-12-17 20:52:34

您输入的根本不是零,而是字母“O”。

其他注释:

不要在DEFUN中使用DEFPARAMETER。在顶层定义变量,在初始化函数中只需对其执行SETF

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

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

票数 4
EN

Stack Overflow用户

发布于 2010-12-17 20:52:43

以下是更正后的版本:

代码语言:javascript
复制
(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!")))
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4470211

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档