最初の問題: ファイルを開きますが、決して閉じません。を使用するときは、後でopen
覚えておく必要があります。close
これは非常に一般的であるため、with-open-file
自動的に閉じる があります (ドキュメントについては CLHS を参照してください)。
(defvar *N*)
(defvar *M*)
(defvar *Goal*)
(defvar *Start*)
(defvar *Matrix*)
(defun read-matrix (file)
(with-open-file (in file
:direction :input)
(read-line in nil)
(setq *N* (parse-integer (read-char in)))
(read-line in nil)
(read-line in nil)
(setq *M* (parse-integer (read-line in)))
(read-line in nil)
(read-line in nil)
(setq *Matrix* (make-array '(*N* *M*) :initial-element 1))
(loop for i from 0 to *N*
do (loop for j from 0 to *M*
do (setf (aref *Matrix* i j)
(read-char in))))
(read-line in nil)
(setq *Start* (read-line in))
(read-line in nil)
(setq *Goal* (read-line in))))
2 番目の問題:read-char
文字を返し、文字に対してparse-integer
定義されていません。行全体を簡単に読むことができるようです。
(defvar *N*)
(defvar *M*)
(defvar *Goal*)
(defvar *Start*)
(defvar *Matrix*)
(defun read-matrix (file)
(with-open-file (in file
:direction :input)
(read-line in nil)
(setq *N* (parse-integer (read-line in)))
(read-line in nil)
(read-line in nil)
(setq *M* (parse-integer (read-line in)))
(read-line in nil)
(read-line in nil)
(setq *Matrix* (make-array '(*N* *M*) :initial-element 1))
(loop for i from 0 to *N*
do (loop for j from 0 to *M*
do (setf (aref *Matrix* i j)
(read-char in))))
(read-line in nil)
(setq *Start* (read-line in))
(read-line in nil)
(setq *Goal* (read-line in))))
3 番目の問題: 必要な行の間の行を破棄しすぎているようです。
(defvar *N*)
(defvar *M*)
(defvar *Goal*)
(defvar *Start*)
(defvar *Matrix*)
(defun read-matrix (file)
(with-open-file (in file
:direction :input)
(read-line in nil) ; "ROWS"
(setq *N* (parse-integer (read-line in)))
(read-line in nil) ; "COLUMNS"
(setq *M* (parse-integer (read-line in)))
(read-line in nil) ; "MATRIX"
(setq *Matrix* (make-array '(*N* *M*) :initial-element 1))
(loop for i from 0 to *N*
do (loop for j from 0 to *M*
do (setf (aref *Matrix* i j)
(read-char in))))
(read-line in nil) ; "START"
(setq *Start* (read-line in))
(read-line in nil) ; "GOAL"
(setq *Goal* (read-line in))))
第 4 の問題: make-array フォームは次元を設定するために数値を必要としますが、代わりに 2 つのシンボルを指定します。必要な値を取得するには、これらのシンボルを評価する必要があります。
(defvar *N*)
(defvar *M*)
(defvar *Goal*)
(defvar *Start*)
(defvar *Matrix*)
(defun read-matrix (file)
(with-open-file (in file
:direction :input)
(read-line in nil) ; "ROWS"
(setq *N* (parse-integer (read-line in)))
(read-line in nil) ; "COLUMNS"
(setq *M* (parse-integer (read-line in)))
(read-line in nil) ; "MATRIX"
(setq *Matrix* (make-array (list *N* *M*) :initial-element 1))
(loop for i from 0 to *N*
do (loop for j from 0 to *M*
do (setf (aref *Matrix* i j)
(read-char in))))
(read-line in nil) ; "START"
(setq *Start* (read-line in))
(read-line in nil) ; "GOAL"
(setq *Goal* (read-line in))))
5 番目の問題: 行列にビットを含めたいようですが、文字だけを入れます。その上、行列には (数値)が期待される#\1
(文字) と が期待される場所さえ含まれず、代わりに次の (Unix スタイルの改行を想定) が含まれます。1
#\0
0
#2A((#\1 #\Space #\1 #\Space #\1)
(#\Space #\1 #\Space #\1 #\Newline)
(#\1 #\Space #\1 #\Space #\0)
(#\Space #\1 #\Space #\1 #\Newline)
(#\1 #\Space #\1 #\Space #\0))
あなたが望むことを達成するために、私は行列の行を読んでから、それらをスペースで分割し、フィールドを解析することを提案します。そのための便利なライブラリはsplit-sequence
.
(defvar *N*)
(defvar *M*)
(defvar *Goal*)
(defvar *Start*)
(defvar *Matrix*)
(defun read-matrix (file)
(with-open-file (in file
:direction :input)
(read-line in nil) ; "ROWS"
(setq *N* (parse-integer (read-line in)))
(read-line in nil) ; "COLUMNS"
(setq *M* (parse-integer (read-line in)))
(read-line in nil) ; "MATRIX"
(setq *Matrix* (make-array (list *N* *M*) :initial-element 1))
(loop :for i :from 0 :to *N*
:do (let* ((line (read-line in))
(fields (split-sequence:split-sequence #\Space line))))
(loop :for field :in fields
:for j :upfrom 0
:do (setf (aref *matrix* i j)
(parse-integer field))))
(read-line in nil) ; "START"
(setq *Start* (read-line in))
(read-line in nil) ; "GOAL"
(setq *Goal* (read-line in))))
この時点で、これは「作業」の値に対して「機能」するはずです(ただし、テストしていません)。
しかし、情報の転送にグローバル変数を使用することは、約 30 年前に不自然なものとして確立されました。これを堅牢なプログラムにより適したスタイルにするための最初のステップは、代わりに関数から値を返すことです。
(defun read-matrix (file)
(let (n m goal start matrix)
(with-open-file (in file
:direction :input)
(read-line in nil) ; "ROWS"
(setf n (parse-integer (read-line in)))
(read-line in nil) ; "COLUMNS"
(setf m (parse-integer (read-line in)))
(read-line in nil) ; "MATRIX"
(setf matrix (make-array (list n m) :initial-element 1))
(loop :for i :from 0 :to n
:do (let* ((line (read-line in))
(fields (split-sequence:split-sequence #\Space line))))
(loop :for field :in fields
:for j :upfrom 0
:do (setf (aref matrix i j)
(parse-integer field))))
(read-line in nil) ; "START"
(setf start (read-line in))
(read-line in nil) ; "GOAL"
(setf goal (read-line in)))
(values n m goal start matrix)))
本当に必要なのは、ここで読んでいるものの構造体またはクラスだと思います。と呼ばれることもありますgame-state
。
(defclass game-state ()
((rows :accessor rows :initarg :rows)
(columns :accessor columns :initarg :columns)
(goal :accessor goal :initarg :goal)
(start :accessor start :initarg :start)
(board :accessor board :initarg board)))
次に、関数に名前を付けread-game-state
て、このクラスのオブジェクトを返す必要があります。