我正在尝试通过遵循“球拍领域”中的代码示例来学习球拍。目前在第8章,我决定重构一些重复的代码以帮助自己更快地学习。具体来说,我正在尝试将游戏图形列表分配给一组符号,但是我总是遇到错误。
这是原始的orc-world.rkt
源文件。该代码可以正常工作。
(require 2htdp/image)
;; compute constants for image frames
(define ORC (bitmap "graphics/orc.png"))
(define HYDRA (bitmap "graphics/hydra.png"))
(define SLIME (bitmap "graphics/slime.bmp"))
(define BRIGAND (bitmap "graphics/brigand.bmp"))
(define PIC-LIST (list ORC HYDRA SLIME BRIGAND))
(define w (apply max (map image-width PIC-LIST)))
(define h (apply max (map image-height PIC-LIST)))
(define PLAYER-IMAGE (bitmap "graphics/player.bmp"))
(define FRAME (rectangle w h 'outline 'white))
(define TARGET (circle (- (/ w 2) 2) 'outline 'blue))
(define ORC-IMAGE (overlay ORC FRAME))
(define HYDRA-IMAGE (overlay HYDRA FRAME))
(define SLIME-IMAGE (overlay SLIME FRAME))
(define BRIGAND-IMAGE (overlay BRIGAND FRAME))
基本上,它是从磁盘读取一堆位图图像并将其分配给符号。有很多代码重复。我正在尝试更改它,以使代码重复最小化,同时更多地了解Racket的标准库如何工作。
我的版本,暂时忽略(overlay)
代码:
(require 2htdp/image)
(define BASEPATH "/Applications/Racket v7.3/share/pkgs/realm/chapter8/graphics/")
(define FILENAMES '("orc.png" "hydra.png" "slime.bmp" "brigand.bmp" "player.bmp"))
(define PATHS (map (lambda (x)(string-append BASEPATH x)) FILENAMES))
(define PICTURES (map (lambda (x)(bitmap/file x)) PATHS))
(define PIC-LIST '(ORC HYDRA SLIME BRIGAND PLAYER-IMAGE))
我希望遍历图片列表,并将每张图片分配给列表中的符号。我可以做一个(define ORC (first PICTURES))
(define HYDRA (second PICTURES))
等但这不是想要的。似乎我们可以使用(map)
,因为两者都是相同长度的列表,但是出现以下错误。
(map (lambda x y)(define x y) PIC-LIST PICTURES) ; error. define: not allowed in an expression context in: define
(map (lambda x y (define-values (x) (values y)) PIC-LIST PICTURES)) ; error. define-values: not allowed in an expression position in: (define-values (x) (values y))
(map (lambda (x y)(define x y))PIC-LIST PICTURES) ; error. begin (possibly implicit): no expression after a sequence of internal definitions in:
; (begin (define x y))
; (define x y)
单独使用(define-values)
也不起作用。
(define-values PIC-LIST (values PICTURES)) ; syntax error because PIC-LIST is a list
希望有人会友善地指出我正确的道路。我忽略了这件事一定很简单,因为这是一项非常常见的任务。
感谢您阅读本文。
答案 0 :(得分:1)
您可以像这样使用match-define
:
(match-define (list ORC HYDRA SLIME BRIGAND PLAYER-IMAGE) IMAGES)
只要事先知道图像数量,它就可以工作,您不能将变量名列表作为参数传递(我们在这里进行 pattern matching 。)>
我想这没关系-因为无论如何,您应该先为图像命名,要拥有多少张图像,并按顺序显示,然后为每个图像分配名称。如果我必须重构原始代码,则外观如下:
#lang racket
(require 2htdp/image)
(define paths '("graphics/orc.png"
"graphics/hydra.png"
"graphics/slime.bmp"
"graphics/brigand.bmp"
"graphics/player.bmp"))
(match-define (list ORC HYDRA SLIME BRIGAND PLAYER-IMAGE)
(map bitmap paths))
(define PIC-LIST (list ORC HYDRA SLIME BRIGAND))
(define w (apply max (map image-width PIC-LIST)))
(define h (apply max (map image-height PIC-LIST)))
(define FRAME (rectangle w h 'outline 'white))
(define TARGET (circle (- (/ w 2) 2) 'outline 'blue))
(match-define (list ORC-IMAGE HYDRA-IMAGE SLIME-IMAGE BRIGAND-IMAGE)
(map (λ (img) (overlay img FRAME)) PIC-LIST))
请注意,这里有三个不同的变量列表,并且我们只对每个变量定义一次,因此代码重复被最小化了。