0

这个 Python 代码的等价物是什么:

class Player:
    def __init__(self): 
        self.hp = 10
        self.pos = [0,0,0]
        self.items = []
    def damage(self,dmg):
        self.hp -= dmg

player = Player()
player.damage(3)
player.pos[0] += 5
player.items.append("banana")

print player.hp, player.pos, player.items
>> 3 [5,0,0] ["banana"]

在 Clojure(或其他 Lisps)中?

4

4 回答 4

3

在 Clojure 中:

(def player {
    :hp 10
    :pos [0 0 0]
    :items [] })

(defn damage [player amount]
    (update-in player [:hp] - amount))

(defn move [player direction]
    (update-in player [:pos] #(map + % direction)))

(defn give [player item]
    (update-in player [:items] conj item))

(-> player
    (damage 3)
    (move [5 0 0])
    (give "banana"))

; Output: {:hp 7, :pos (5 0 0), :items ["banana"]}
于 2012-06-26T22:25:00.203 回答
3

在 Clojure 中,您通常不会使用可变数据结构,而是创建一个描述玩家当前状态的不可变数据。对播放器的更新将创建一条描述更新状态的新数据。马特的回答给出了一个很好的例子。

如果你想随着时间的推移保持一个“玩家”身份并随着时间的推移而发生多次状态变化,你可以用一个原子来做到这一点,如下所示:

(def initial-player-state 
 {:hp 10
  :pos [0 0 0]
  :items []})

(def player (atom initial-player-state))

;; Define some update functions

(defn damage [player dmg]
  (update-in player [:hp] + dmg))

(defn move [player dir]
  (update-in player [:pos] #(vec (map + % dir))))

(defn add-item [player item]
  (update-in player [:items] conj item))

;;  Make some changes

(swap! player move [5 0 0])
(swap! player damage -3)
(swap! player add-item "Apple")

;; view the current player state by dereferencing the atom

@player
=> {:hp 10, :pos [0 0 0], :items ["Apple"]}

请注意,在真正的游戏中,您可能在单个原子中拥有整个不可变的游戏状态,而不仅仅是玩家。

于 2012-06-26T22:37:23.740 回答
3

在 Common Lisp 中:

(defclass player ()
  ((hp :accessor hp :initform 10)
   (pos :accessor pos :initform (list 0 0 0))
   (items :accessor items :initform nil)))

(defmethod damage ((a-player player) damage)
  (decf (hp a-player) damage))

在 REPL

; compiling (DEFCLASS PLAYER ...)
; compiling (DEFMETHOD DAMAGE ...)
CL-USER> (defparameter *player* (make-instance 'player))

*PLAYER*
CL-USER> (damage *player* 3)
7
CL-USER> (incf (car (pos *player*)) 5)
5
CL-USER> (push :banana (items *player*))
(:BANANA)
CL-USER> (list (hp *player*) (pos *player*) (items *player*))
(7 (5 0 0) (:BANANA))
CL-USER> 

就个人而言,我会分解pos成单独x的 ,yz, 并且可能定义一些方法来将东西放入和取出库存,以防我以后决定更改表示。

于 2012-06-26T23:10:59.560 回答
3

球拍中:

#lang racket

(define player%
  (class object%
    (init-field [hp 10] [pos '(0 0 0)] [items '()])

    (define/public (damage dmg)
      (set! hp (- hp dmg)))

    (define/public (move dx dy dz)
      (set! pos (list (+ (first pos) dx)
                      (+ (second pos) dy)
                      (+ (third pos) dz))))

    (define/public (add-item item)
      (set! items (cons item items)))

    (super-new)))

(send* (new player%)
       (damage 3)
       (move 5 0 0)
       (add-item "banana"))

如果您使用 Racket,您可能希望以更具功能性的风格进行编程,在这种情况下,您可以编写这样的方法来避免突变:

(define/public (damage dmg)
  (new this% [hp (- hp dmg)] [pos pos] [items items]))
于 2012-06-26T22:52:06.253 回答