方案重新定义列表

发布于 2024-08-27 11:04:39 字数 346 浏览 9 评论 0原文

我有一个称为手的列表,另一个称为牌组,这里的主要目标是在我调用功能抽牌时取出列表牌组中的第一张牌(或元素)并将其放入列表手中......

> (draw hand deck)
(2 C)
> (draw hand deck)
(2 C) (3 H) 
> (draw hand deck)
(2 C) (3 H) (K D)

但每次我调用它的手永远不会改变价值...... 我不知道有没有像 O-Object 那样的方法来永久改变手的内容?

我最初定义手牌为空,因为玩家没有牌可以开始。

(define hand '())

I have a list called hand and another one called deck, the main goal here is to take the first card (or element ) in the list deck and put it in the list hand when i call the fnction draw...

> (draw hand deck)
(2 C)
> (draw hand deck)
(2 C) (3 H) 
> (draw hand deck)
(2 C) (3 H) (K D)

but everytime i call it the hand never changes value...
I'm clueless is there a way like in O-Object to change the content of hand permenantly?

and i initialy define hand empty because the player has no card to start.

(define hand '())

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

朕就是辣么酷 2024-09-03 11:04:39

一个功能性的解决方案,draw没有副作用:

;; Returns a cons whose car will be the new hand and cdr being the
;; rest of the original deck
(define (draw deck hand)
    (if (not (null? deck))
        (cons (cons (car deck) hand) (cdr deck))
        (cons hand ())))

;; Gets the new hand from the cons returned by draw.
(define (hand cards) (car cards))

;; Gets the new deck from the cons returned by draw.
(define (deck cards) (cdr cards))

;; test
(define cards (draw '(1 2 3 4 5) ()))
cards
=> ((1) 2 3 4 5)
(hand cards)
=> (1)
(deck cards)
=> (2 3 4 5)
;; draw again
(set! cards (draw (deck cards) (hand cards)))
cards
=> ((2 1) 3 4 5)
(hand cards)
=> (2 1)
(deck cards)
=> (3 4 5)

A functional solution, with draw being side-effect free:

;; Returns a cons whose car will be the new hand and cdr being the
;; rest of the original deck
(define (draw deck hand)
    (if (not (null? deck))
        (cons (cons (car deck) hand) (cdr deck))
        (cons hand ())))

;; Gets the new hand from the cons returned by draw.
(define (hand cards) (car cards))

;; Gets the new deck from the cons returned by draw.
(define (deck cards) (cdr cards))

;; test
(define cards (draw '(1 2 3 4 5) ()))
cards
=> ((1) 2 3 4 5)
(hand cards)
=> (1)
(deck cards)
=> (2 3 4 5)
;; draw again
(set! cards (draw (deck cards) (hand cards)))
cards
=> ((2 1) 3 4 5)
(hand cards)
=> (2 1)
(deck cards)
=> (3 4 5)
数理化全能战士 2024-09-03 11:04:39

您无法更改列表的内容,但可以更改名称引用的列表。所以:

(let ((some-list '("post")))
 (display "initially: ")
 (display some-list)
 (newline)
 (set! some-list (cons "first" some-list))
 (display "added first: ")
 (display some-list)
 (newline)
 (set! some-list '(a completely new list))
 (display "finally: ")
 (display some-list)
 (newline)
 some-list)

现在每个列表 '("post") '("first" "post") 和 '(一个全新的列表) 都是不可更改的(“不可变”)列表,但名称 some-list first 指向一个,然后是另一个,然后是第三个。

警告:对于许多问题,您需要避免设置!并尝试以不同的方式思考问题。例如,如果您在游戏中使用世界和宇宙,
http://pre.plt-scheme.org/plt/doc/ teachingpack/2htdpuniverse.html
那么你会希望你的更新程序返回一个新的世界状态而不是使用 set!修改旧的。

You cannot change the contents of a list, but you can change which list a name refers to. So:

(let ((some-list '("post")))
 (display "initially: ")
 (display some-list)
 (newline)
 (set! some-list (cons "first" some-list))
 (display "added first: ")
 (display some-list)
 (newline)
 (set! some-list '(a completely new list))
 (display "finally: ")
 (display some-list)
 (newline)
 some-list)

Now each of the lists '("post") '("first" "post") and '(a completely new list) are unchangeable ("immutable") lists, but the name some-list first points to one, then another, then the third.

Caveat: For many problems, you will want to avoid set! and try to think about the problem a different way. For example, if you work with worlds and universes for your game,
http://pre.plt-scheme.org/plt/doc/teachpack/2htdpuniverse.html
then you'll want your updaters to return a new state of the world rather than using set! to modify the old one.

﹉夏雨初晴づ 2024-09-03 11:04:39

哦,接下来你会发现,从调用该函数的人的角度来看,更改函数内名称所指的列表不会改变该名称所指的内容。所以:

(define (foo lst)
  (set! lst '(hi))
  (display "within foo: ")
  (display lst)
  (newline)
  lst)
(define my-list '(hello))
(foo my-list)
(display "after foo: ") 
(display my-list)
(newline)
(set! my-list (foo my-list))
(display "using the result of foo: ")
(display my-list)
(newline)

Oh, and next you will find that changing what list a name refers to inside a function will not change what the name refers to from the perspective of whoever called the function. So:

(define (foo lst)
  (set! lst '(hi))
  (display "within foo: ")
  (display lst)
  (newline)
  lst)
(define my-list '(hello))
(foo my-list)
(display "after foo: ") 
(display my-list)
(newline)
(set! my-list (foo my-list))
(display "using the result of foo: ")
(display my-list)
(newline)
心的位置 2024-09-03 11:04:39

Vijay 为Scheme 提供了最佳解决方案。但是,如果您确实想要通过永久更改列表来实现此目的,则需要使用 set-car!set-cdr!代码>.这在Scheme中并不自然,需要一些技巧才能使其工作:

首先定义handdeck

(define hand '(dummy))
(define deck '((2 C) (3 H) (K D)))

hand必须以现有元素,以便它有一些现有的列表结构需要修改。您不能将 set-car!set-cdr! 与 nil ( '() ) 一起使用。

现在写draw

(define (draw from to)
  ; push the top element of `from` onto `to`
  (set-cdr! to (copy to))
  (set-car! to (car from))
  ; pop the top element of `from` off
  (set-car! deck (cadr deck))
  (set-cdr! deck (cddr deck)))
; also we need to define copy
(define (copy l)
  (map (lambda (x) x) l))

这意味着你手上的最后一个元素将始终是虚拟的。最好添加对初始情况的检查并覆盖它而不是推送:

(define (draw from to)
  ; push the top element of `from` onto `to` (just overwrite the first time)
  (when (pair? (cdr to))
    (set-cdr! to (copy to)))
  (set-car! to (car from))
  ; pop the top element of `from` off
  (set-car! deck (cadr deck))
  (set-cdr! deck (cddr deck)))

此外,您应该在执行任何操作之前检查 from 是否为空。

Vijay has the best solution for Scheme. However, if you really want to make this work by changing the lists permanently, you'll need to use set-car! and set-cdr!. This is not natural in Scheme, and requires a couple of hacks to make it work:

First define hand and deck:

(define hand '(dummy))
(define deck '((2 C) (3 H) (K D)))

hand has to start with an existing element so that it has some existing list structure to modify. You can't use set-car! and set-cdr! with nil ( '() ).

Now write draw:

(define (draw from to)
  ; push the top element of `from` onto `to`
  (set-cdr! to (copy to))
  (set-car! to (car from))
  ; pop the top element of `from` off
  (set-car! deck (cadr deck))
  (set-cdr! deck (cddr deck)))
; also we need to define copy
(define (copy l)
  (map (lambda (x) x) l))

This means the last element of your hand will always be dummy. It would be better to add a check for the initial case and overwrite it instead of pushing:

(define (draw from to)
  ; push the top element of `from` onto `to` (just overwrite the first time)
  (when (pair? (cdr to))
    (set-cdr! to (copy to)))
  (set-car! to (car from))
  ; pop the top element of `from` off
  (set-car! deck (cadr deck))
  (set-cdr! deck (cddr deck)))

Also you should check that from isn't empty before doing anything.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文