2011-02-05 118 views
3

我要去,这是建议的解决方案,以处理拿起对象:推进项目地点在通过<a href="http://www.lisperati.com/casting.html" rel="nofollow">Casting SPELs in Lisp</a>铸造SPELs

(define *location* 'living-room) 

(define *object-locations* 
    '((whiskey-bottle living-room) 
    (bucket living-room) 
    (chain garden) 
    (frog garden))) 

(define (pickup-object object) 
    (cond [(is-at? object *location* *object-locations*) 
     (push! (list object 'body) *object-locations*) 
     (string-append "You're now carrying the " (symbol->string object) ".")] 
     [else "There's no such object in here."])) 

我是唯一一个谁认为这效率不高?据我所知,push!函数cons每次玩家拿起一个物体时都会有一个新的pair*object-locations*。虽然这可能不是这样的小游戏中的主要问题,但如果要添加从库存中放下物品的选项,则*object-locations*列表可以无限增长......不应该pickup-object替换的(whiskey-bottle living-room),因为例如,而不是增加pair的另一个副本?

我是Lisp的新手,可能会误解......请问有人可以解释我的假设是否正确,如果是这样,在Lisp文本冒险中处理拾取对象的最佳方法是什么?

回答

1

有几个问题与代码:

  • 名单*对象的位置*是文字。文字不应该被修改。你不能破坏性地改变青蛙的位置。所以你需要在前面推新的位置。
  • 当你走过游戏时,列表会增加。
  • STRING-APPEND为每个拾取动作创建一个新的字符串。

  • 它是简单的和足够的书的例子。
  • 对象位置的堆栈会使某种撤消成为可能。
  • 推动项目和位置的新关联是一项快速操作。
  • 它给本书的读者留下了让代码更高效的机会。

Common Lisp中,很容易改变:

(defvar *object-locations* 
    (copy-tree 
    '((whiskey-bottle living-room) 
    (bucket living-room) 
    (chain garden) 
    (frog garden)))) 

(defun get-location (object) 
    (second (assoc object *object-locations*))) 

(defun set-location (object location) 
    (setf (second (assoc object *object-locations*)) 
     location)) 

CL-USER > (get-location 'frog) 
GARDEN 

CL-USER > (set-location 'frog 'living-room) 
LIVING-ROOM 

CL-USER > (get-location 'frog) 
LIVING-ROOM 

CL-USER > *object-locations* 
((WHISKEY-BOTTLE LIVING-ROOM) 
(BUCKET LIVING-ROOM) 
(CHAIN GARDEN) 
(FROG LIVING-ROOM)) 

见书Common Lisp: A Gentle Introduction to Symbolic Computation by David S. Touretzky为一个真正的基本介绍Lisp的。

+0

在功能语言中处理这种情况的标准/好方法是什么?在C#,JS或AS中,我可以简单地创建一个数组或列表,并在必要时更改单个条目。然而,在函数式编程中,它看起来应该不会在任何可能的情况下改变任何东西......我可以看到解析某些数据或进行计算时是如何可能的,但我真的没有看到有效应用这种范式的方式其他实际应用,这样一个游戏,其中必须1.跟踪各种状态和事件2.改变像库存等东西 – 2011-02-05 12:52:43

相关问题