1

私は、教育目的で、機能的な方法でラケットに数字当てゲームを実装しようとしています。私の問題は、のようにエラーで関数を停止しなければならないこと(error "YOU GUESSED!")です。エラー関数は、ラケットのドキュメントで見つけたものです。この条件を停止するエラーのない方法はありますか?

注: stop-whenについて読みましたが、まだビッグバンには行きたくありません。

(define guess-my-number (lambda ()
  (letrec ([my-number (random 100)]
           [choices-left 7]
           [game (lambda (choices-left)
                (if (> choices-left 0)
                    (let ([user-guess (read)])
                      (cond [(> user-guess my-number) (display "That was too high!")]
                            [(< user-guess my-number) (display "That was too small!")]
                            [(= user-guess my-number) (error "YOU GUESSED!")])
                    (game (- choices-left 1)))
                    (display "Here ends the game!!")))])
    (game choices-left))))
4

2 に答える 2

2

クリスの答えは完璧です。これは実際にはコメントです。ただし、少し長いため、ここでコメントにコード ブロックを含めることはできません。

あなたがそれをコーディングしている方法は、Racket が「低レベル」でどのように機能するかを理解するための優れた方法であり、Scheme でこれをコーディングする非常に伝統的な方法です。

もう 1 つの従来の Scheme の方法は、いくつかの機能を使用することです。

  • 関数を定義する簡単な方法。

  • let典型的な name を使用した名前付きloop

そのバージョン:

(define (guess-my-number-v2)
  (let ([number (random 100)])
    (let loop ([guesses-left 7])
      (cond [(> guesses-left 0)
             (define user-guess (read))
             (cond [(> user-guess number)
                    (display "That was too high!")
                    (loop (sub1 guesses-left))]
                   [(< user-guess number)
                    (display "That was too low!")
                    (loop (sub1 guesses-left))]
                   [else (display "YOU GUESSED!")])]
            [else
             (displayln "Here ends the game!!")]))))

興味深いのは、これが最初のバージョンとほぼ同じものに展開されることです。

フォームは基本的に、元のという名前の関数と同じように、(let loop (guesses-left 7]) ...)という名前の関数を定義しています。(実際、あなたも言うことができます。)loopgame(let game ([guesses-left 7]) ...)

利点の 1 つは、インデントが深くなく、画面の右側からはみ出さないことです。

最後に、より多くのdefine.

(define (guess-my-number-v3)
  (define number (random 100))
  (define (guess guesses-left)
    (cond [(> guesses-left 0)
           (define user-guess (read))
           (cond [(> user-guess number)
                  (display "That was too high!")
                  (guess (sub1 guesses-left))]
                 [(< user-guess number)
                  (display "That was too low!")
                  (guess (sub1 guesses-left))]
                 [else (display "YOU GUESSED!")])]
          [else
           (displayln "Here ends the game!!")]))
  (guess 7))

これはより「現代的な」ラケット スタイルですが、本質的に「優れた」ものではありません。それも、オリジナルとほぼ同じものに拡張されます。実際、ほとんどの Racket プログラマーは、3 つのスタイルすべてを理解しやすいと感じるでしょう。

とにかく、すでに行っていたように、関数を再帰的に呼び出すことにより、3つのバージョンすべてが「ループ」します。「ループを終了する」方法は単純です...関数を再度呼び出さないでください。それがクリスの答えの重要なポイントです。

于 2013-11-12T00:11:58.503 に答える