我正在制作游戏,我有这个:
(define b "black piece") (define w "white piece")
(define (board)
(lambda (matrix)
(list ((b w b w b w b w)
(w b w b w b w b)
(b w b w b w b w)
(w b w b w b w b)
(b w b w b w b w)
(w b w b w b w b)
(b w b w b w b w)
(w b w b w b w b)))))
board
列出了8行和8列黑白作品。
如何访问和更改电路板的元素?如何使用递归来执行过程矩阵?
答案 0 :(得分:0)
首先注意几点:
(define f (lambda (x) l ))
与。相同
(define (f x) l ))
然而,你将它们与
结合起来
(define (board) (lambda (matrix) l ))
这与
相同
(define board (lambda () (lambda (matrix) l )))
区别很重要。前两个我已经将bind f列为一个函数,该函数接受一个参数并返回l。我猜这就是你想要做的。在接下来的两个中,你将板绑定到一个不带参数的函数,并返回一个带有1个参数矩阵的函数(它似乎没有做任何事情),并返回一个l。
第二个问题,(list ((b w....) ...))
无效,因为它会尝试评估(b w ...)
。您需要在电路板的每一行的函数应用程序位置都有列表,如(list (list b w ...) (list w b ...) ...)
,以便您编码甚至编译。
关于你的问题。 link-ref包含在racket / base中,当您知道列表中的索引时,它用于引用列表中的元素。
(list-ref 2(列出'a'b'c'd))
将返回'c。索引从0开始。由于您有一个列表列表,您需要两次应用list-ref来检索'b或'w。
至于改变它,你不能。从r6rs开始,对(组成列表)是不可变的。在可能的情况下,建议的做法是返回包含更改的新列表。你可以使用这个效率低下的list-set
版本,它会在索引处返回一个带有新值的列表副本。
(define (list-set lis idx val)
(map (lambda (e i)
(if (= i idx) val e))
lis
(iota (length lis))))
但是,在这种情况下,我建议切换到更适合手头任务的不同数据结构,因为您可能希望O(1)访问板中的元素。查看vectors,其行为与列表非常相似,但用于持续查找和更新。有一个内置的vector-ref
和vector-set!
操作,您应该使用它而不是我的上述功能。
如果这是一个较大问题的一部分,并且您已经在任何地方使用列表,则可以使用vector->list
和list->vector
函数来回转换。此外,您可以使用mutable lists但不能使用。
更好的是srfi/25中提供的多维数组库,但这可能会更复杂。
问题的第二部分是如何递归地构建电路板。好吧,这是一个使用map的版本。
(require (lib "1.ss" "srfi"))
(define (board)
(map (lambda (x)
(map (lambda (y)
(if (odd? (+ x y)) b w))
(iota 8)))
(iota 8)))
这是一个递归版本
(define (board)
(letrec ((board-helper
(lambda (x)
(if (eq? x 8) '()
(cons (row-helper x 0) (board-helper (+ 1 x))))))
(row-helper
(lambda (x y)
(if (eq? y 8) '()
(cons (if (odd? (+ x y)) b w) (row-helper x (+ 1 y)))))))
(board-helper 0)))