0

hand と呼ばれるリストと、deck と呼ばれる別のリストがあります。ここでの主な目標は、リスト デッキの最初のカード (または要素) を取得し、関数ドローを呼び出したときにそれをリスト ハンドに入れることです...

> (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 '())
4

4 に答える 4

1

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)
于 2010-04-01T04:05:58.957 に答える
0

Vijay は、Scheme に最適なソリューションを提供します。ただし、リストを永続的に変更してこれを機能させたい場合set-car!、 andを使用する必要がありますset-cdr!。これは Scheme では不自然であり、動作させるにはいくつかのハックが必要です:

最初に と を定義handdeckます。

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

hand変更する既存のリスト構造があるように、既存の要素から開始する必要があります。andを nil ( )set-car!と一緒に使用することはできません。set-cdr!'()

今書く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また、何かを行う前に、それが空でないことを確認する必要があります。

于 2010-04-01T13:57:19.090 に答える
0

リストの内容は変更できませんが、名前が参照するリストは変更できます。そう:

(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") および '(aまったく新しいリスト) のそれぞれは変更不可能な ("不変") リストですが、名前 some-list は最初に 1 つを指し、次に別のリストを指します、次に 3 番目。

警告: 多くの問題では、set を避ける必要があります。問題を別の方法で考えてみてください。たとえば、ゲームでワールドとユニバースを 扱う場合 ( http://pre.plt-scheme.org/plt/doc/teachpack/2htdpuniverse.html ) 、アップデーターが世界の新しい状態を返すようにする必要があります。セットを使用するのではなく!古いものを変更します。

于 2010-04-01T03:07:50.187 に答える
0

ああ、次に、関数内で名前が参照するリストを変更しても、関数を呼び出した人の観点からは名前が参照するものは変更されないことがわかります。そう:

(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)
于 2010-04-01T03:13:31.540 に答える