写一个2人的摇滚纸剪刀游戏

时间:2015-11-16 06:13:15

标签: scheme racket

我正在尝试编写函数RPS。

该功能需要2个符号列表(' R' P或' S)并根据石头剪刀规则产生一个字符串,即"玩家1获胜" ,"球员2获胜"或" tie"。

该程序的示例执行是:

(RPS(列表' R' R' P)(列表' R' P' S) - >"播放器2胜" (RPS(列表' R' P)(列表' R' R) - >"玩家1获胜"

到目前为止,这是我的代码:

(define (RPS slst1 slst2)

  (cond

    [(and(empty? slst1)(empty? slst2)) "tie"]

    [(empty? slst2) "player 1 wins"]

    [(empty? slst1) "player 2 wins"]

    [else

      (cond

        [(and(symbol=?(first slst1) 'R)

             (symbol=?(first slst2) 'P))"player 1 wins"]

        [(and(symbol=?(first slst1) 'R)

             (symbol=?(first slst2) 'S))"player 2 wins"]

        [(and(symbol=?(first slst1) 'p)

             (symbol=?(first slst2) 'R))"player 2 wins"]

        [(and(symbol=?(first slst1) 'P)

             (symbol=?(first slst2) 'S))"player 2 wins"]

        [(and(symbol=?(first slst1) 'S)

             (symbol=?(first slst2) 'R))"player 2 wins"]

        [(and(symbol=?(first slst1) 'S)

             (symbol=?(first slst2) 'P))"player 1 wins"]

        [(and(symbol=?(first slst1) 'S)

             (symbol=?(first slst2) 'P))"player 1 wins"]

        [(and(symbol=?(first slst1) 'S)

             (symbol=?(first slst2) 'R))"player 2 wins"])]))

如何使这个函数递归,以便它移动到列表的其余元素?

3 个答案:

答案 0 :(得分:1)

创建一个单独的函数,将一个符号与另一个符号进行比较(当2个符号相等时,不要忘记将这些情况考虑在内,此时你不会这样做)并在{{上调用该函数1}}符号列表。根据比较结果(平局,玩家1胜,玩家2获胜),您可以在原始输入的car上递归调用RPS函数(如果出现平局)或返回在其他情况下获胜的球员。

确保从新功能中返回一些合理的结果,例如0 =平局,1 =球员1胜,2 =球员2胜。

此版本的RPS将持续到玩家赢得1轮或直到符号列表为空。但是,根据你的问题,这是不是很清楚你是否想要它。

您还可以通过2个输入列表cdr新功能,这会生成map'(0 0 2)等列表,向您显示每一轮的结果。根据这些结果,您可以获得整个游戏的胜利者。为了更加聪明,如果玩家1获胜则可以返回-1,如果玩家2获胜则返回+1,那么您可以将地图的结果加起来 - >如果它是正面的,则玩家2赢了,0 =平局,负面意味着玩家1赢了。

- >有关地图的更多信息:http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-ref/Mapping-of-Lists.html

答案 1 :(得分:0)

你可以大大简化这个功能。坦白说,这是一些丑陋的代码。

首先(else (cond ...))永远不是好形式。这意味着如果上述条件不成立,请检查这些其他条件。这是多余的

第二个cond没有else条件,并且您之前未在代码中进行测试以确保输入正确。为[(not (member? (first slst1) '(R P S))) "player 2 wins"]添加slst2和反向可以解决这个问题。至少(else (error ...))将在意外输入时停止程序执行。

第三,你错过了一个非常大的条件,那就是条件条件[(symbol=? (first slst1) (first slst1)) "tie")]或者如果那不是你想要的行为,那就看五个。

第四,你不必比较每个组合。如果没有平局或者球员1没有赢,你可以假设球员2获胜。或者您可以使用if语句作为第二个cond子句,如下所示:[(symbol=?(first slst1) 'R) (if (symbol=? (first slst2) 'P) "player 1 wins" "player 2 wins"]或者您可以创建包含规则的数据结构。 (('R ('R 0) ('P -1) ('S 1)) ...)并通过该查找结果。

第五,当一个列表为空而另一个列表不是'时,你会使用一些非常奇怪的逻辑。通常,您停止计算并忽略较长列表的最后一部分,或对该列表执行特殊操作。额外的输赢规则尚不清楚。产生胜利的第一个配对决定赢家,还是喜欢X中的最佳配对,其中X是(最短|最长)列表的长度?如果它基于分数,则需要将分数作为显式状态传递,并在其中一个或两个列表为空时进行正确比较。如果它是基于您的[(empty? slst1) "player 2 wins"]建议的第一场胜利,那么我的四分中的领带捕手应该使用'cdr RPS slst1 's of slst2` and >

鉴于您想要的行为不清楚,这里有三个版本

首胜的版本

(define (RPS slst1 slst2)
  (cond
    [(and(empty? slst1)(empty? slst2)) "tie"]
    [(empty? slst2) "player 1 wins"]
    [(empty? slst1) "player 2 wins"]
    [(not (member? (first slst2) '(R S P)))
     (if (member? (first slst1) '(R S P))
         "player 1 wins"
         (RPS (rest slst1) (rest slst2)))] ;tie
    [(not (member? (first slst1) '(R S P)))
     "player 2 wins"]
    [(symbol=? (first slst1) (first slst2))
     (RPS (rest slst1) (rest slst2))]
    [(symbol=? (first slst1) 'R)
     (if (symbol=? (first slst2) 'S)
         "player 1 wins"
         "player 2 wins")]
    [(symbol=?(first slst1) 'P)
     (if (symbol=?(first slst2) 'R)         
         "player 1 wins"
         "player 2 wins")]
    [(symbol=?(first slst1) 'S)
     (if (symbol=?(first slst2) 'P)         
         "player 1 wins"
         "player 2 wins")]
    [(else (error "RPS -- unexpected input " slst1 " " slst2))]))

包含数据结构规则的分数保留版

(define *RPS-Rules*
 (list
   (list 'R
         (list 'R  0)  ;;tie
         (list 'P -1)  ;;paper beats rock
         (list 'S  1)) ;;rock beats siscors
   (list 'P
         (list 'R  1)  ;;paper beats rock
         (list 'P  0)  ;;tie
         (list 'S -1)) ;;siscors beat paper
   (list 'S
         (list 'R -1)  ;;rock beats scissors
         (list 'P  1)  ;;paper beats rock
         (list 'S  0)));;tie

(define (RPS-result throw1 throw2)
  (first 
    (rest 
      (assoc throw2 
             (assoc throw1 *RPS-Rules*))))) 
 ;;returns 1,0, or -1

(define (RPS slst1 slst2)
 (RPS-helper slst1 slst2 0 )


(define (RPS-helper sl1 sl2 score)
   (cond
    [(and (empty? sl1)(empty? sl2)) 
     (cond [(> score 0) "player 1 wins"]
           [(< score 0) "player 2 wins"]
           [else "tie"])]
    [(empty? sl1) ;;if you want score based on shortest list
     (RPS-helper sl1 '() (- score (length sl2)))]
    [(empty? sl2) ;;dont do math on score here
     (RPS-helper '() sl2 (+ score (length sl1)))]
    [(not (member? (first sl1) '(R S P)))
     (if  (member? (first sl2) '(R S P))
          (RPS-helper (rest sl1) 
                      (rest sl2)
                      (- score 1))
          (RPS-helper (rest sl1) 
                      (rest sl2)
                      score))]
    [(not (member? (first sl2) '(R S P)))
     (RPS-helpter (rest sl1)
                  (rest sl2)
                  (+ score 1))]
    [Else (RPS-helper (rest sl1)
                      (rest sl2)
                      (+ score
                         (RPS-result (first sl1)
                                     (first sl2))))])

答案 2 :(得分:0)

Rock-paper-scissors-lizard-spock有点偏离主题,但我会在一个单独的答案中作为事后的想法发布,以显示第二个例子中更好的代码组织。

(define (RPS slst1 slst2)
  (compare-game slst2 slst2 *RPS-Rules*))

(define (RPSLS slst1 slst2)
  (compare-game slst2 slsts2 *RPSLK-Rules*))

(define (compare-game game slst1 slst2 rules)
  (define (helper sl1 sl2 score)
    (cond
      [(and (empty? sl1)(empty? sl2)) 
       (cond [(> score 0) "player 1 wins"]
             [(< score 0) "player 2 wins"]
             [else "tie"])]
      [(empty? sl1) 
       (helper sl1 '() (- score (length sl2)))]
      [(empty? sl2) 
       (helper '() sl2 (+ score (length sl1)))]
      [else 
       (helper (rest sl1)
               (rest sl2)
               (+ score
                  (game-result (first sl1)
                               (first sl2)
                               rules)))]))
  (helper slst1 slst2 0))
;if you want score of X to be
;based on length of shortest list
;dont do math on score after the
;[(empty?...] cond clauses


(define (game-result throw1 throw2 rules)
  (let ((assoc1 (assoc throw1 rules))
        (assoc2 (assoc throw2 rules))
        (value (lambda (assoc-elem) (if assoc-pair 
                                        (first (rest (assoc-elem)))
                                        #f))))
    (cond [(not (and assoc1 assoc2))
           (cond [(and (not assoc1) (not assoc2)) 0] 
                 [assoc1 1] 
                 [else  -1])] 
          [(symbol=? throw1 throw2) 0]
          [(value (assoc thow2 (rest assoc1)))]
          [(let ((assoc2.1 (assoc throw1 (rest assoc2))))
             (if assoc2.1 (- (value assoc2.1)) #f))]
          [else (error "compare-game-result failed with args " 
                        throw1 
                        throw2 
                        rules 
                        "Rules incomplete?")])))
 ;returns 0, +-1, +- win value from rules, or error
 ;;playing fast and lose with anything not #f is true
 ;;and one-clause cond statements
 ;;;assumes ties are 0 points
 ;;;assumes default/forfiets are worth 1 point
 ;;;Does not assume all genuine wins are 1 point

(define *RPS-Rules*
 (list
   (list 'R
         (list 'S 1)) ;;rock crushes scissors
   (list 'P
         (list 'R 1)) ;;paper covers rock
   (list 'S
         (list 'P 1)));;scissors cuts paper

(define *RPSLK-Rules*
 (list
   (list 'R
         (list 'S 1)  ;;rock crushes siscors
         (list 'L 1)) ;;rock crushes lizard
   (list 'P
         (list 'R 1)  ;;paper covers rock
         (list 'K 1)) ;;paper disproves spock
   (list 'S
         (list 'P 1)  ;;scissors cut paper
         (list 'L 1)) ;;scissors decapitate lizard 
   (list 'L
         (list 'K 1)  ;;lizard poisons spock
         (list 'P 1)) ;;lizard eats paper
   (list 'K
         (list 'S 1)  ;;spock smashes scissors
         (list 'R 1)));;spock vaporizes rock