0

如果我重复其他人之前的要求,请道歉。我已经在 stackoverflow 上完成了其他 RSP 游戏问题。大多数是关于播放器与计算机的。可能我需要阅读更多理论以更好地理解并修改代码以适合我的目的,即玩家一与玩家二。

我正在尝试玩家一与玩家二 - Ruby 中的石头剪刀和纸游戏。我对以下代码有以下疑问。- 如何隐藏每个玩家条目?- 代码中有很多重复,因此违反了 DRY 原则。我应该如何重构这个?- 类方法是玩这个游戏的最好方法吗(最有效)?- 目前,此游戏仅适用于石头剪刀布。如果我想稍后添加蜥蜴 spock,我应该如何证明这一点?或以最有效的方式添加它?提前致谢!

options = ["rock", "scissors", "paper"]

while true

    print <<TEXT 
1 - rock
2 - scissors
3 - paper
9 - end game
TEXT

    puts "Player 1, choose rock(1), scissors(2), paper(3). To end the game, enter 9."
    player1_val = gets.to_i

    puts "Player 2, choose rock(1), scissors(2), paper(3). To end the game, enter 9."
    player2_val = gets.to_i

    if player1_val == 9 # I am repeating the same condition for player2. How should I combine? 
        puts "End"
        exit
    end

    if player2_val == 9 
        puts "End"
        exit
    end

    player1 = options[player1_val-1]
    player2 = options[player2_val-1]

    if player1 == player2
        puts "Tie, next throw please"
        redo 
    end 

    if player1 == 1 and player2 == 2
        puts "Rock blunts scissors, you win"

    elsif player1 == 2 and player2 == 1
        puts "Rock blunts scissors, you loose"

    elsif player1 == 2 and player2 == 3
        puts "Scissors cut paper, you win"

    elsif player1 == 3 and player2 == 2
        puts "Scissors cut paper, you loose"

    elsif player1 == 3 and player2 == 1
        puts "Paper covers rock, you win"

    elsif player1 == 1 and player2 == 3
        puts "Paper covers rock, you loose"
    end  
end
4

2 回答 2

1

您可以通过以下方式判断获胜者:

choice1, choice2 = (gets.to_i - 1), (gets.to_i - 1)
winner = %w(none player1 player2)[choice2 - choice1 % 3]

让我们测试一下

winner = proc { |choice1, choice2| %w(none player1 player2)[choice2 - choice1 % 3] }

cases = [[0, 0], [0, 1], [0, 2], [1, 2], [2, 0], [2, 1]]
cases.map(&winner) #=> ["none", "player1", "player2", "player1", "player1", "player2"]

同理,可以简化输出逻辑。

HOW_TO_WIN = ['Rock blunts scissors',
              'Scissors cut paper',
              'Paper covers rock'].freeze

def player(no: num)
  # ...
  choice = (gets.to_i - 1)
  # ...
end

def play
  choice1, choice2 = [1, 2].map { |num| player(no: num) }
  winner = %w[none player1 player2][choice2 - choice1 % 3]
  how_to = HOW_TO_WIN[choice2 - choice1 % 3]

  if winner == 'none'
    puts 'Tie, next throw please'
  else
    puts "#{how_to}, #{winner} win"
  end
end

play
于 2019-10-29T11:01:39.513 回答
1

你问了一个非常有主见、开放式的问题。对于 Stack Overflow,这不是最好的问题。但是,我会试一试。

首先,我会将您的评分代码提取到一个函数中。像这样的东西:

def battle(p1, p2)
  if p1 == p2
    'Tie!'
  elsif p1 == 'paper' && p2 = 'rock'
    'Paper smothers Rock...Player 1 wins!"
  elsif etc..
end 

这会让你的主循环变得非常小......这几乎总是一件好事。当您开始为代码编写单元测试时,这也将使您的生活变得美好。

至于把你的游戏结束测试,用来||一次比较几件事,比如player1_val == 9 || player2_val == 9

我怀疑您的代码不会像当前编写的那样工作。尝试在调试器中逐行运行……或者更简单地说,放在puts "var is #{var}"不同的地方,转储有趣变量的值。任何一种方法都会很快暴露任何错误并使修复变得明显。

至于以 Ruby 方式做事,请考虑在选项数组中使用符号而不是字符串。类似的东西[:paper, :rock, :scissors]。避免代码中出现幻数。任何时候你的代码中有一个字面数字(也许不是 1 或 0),很有可能你有一个幻数,应该努力使它成为一个常数、符号或方程。

redo不是一个常用的 Ruby 命令。(我不得不去查一下它的作用!)你已经有一个循环......你不应该需要重做来完成你的任务。

除了良好的编码实践,我们还可以谈论 UX/UI(用户体验/用户界面)。这对于这款游戏来说是一个大问题……玩家不能看到彼此的输入,这一点很重要。做一些研究getch。还可以考虑给每个玩家一半的键盘...“ASD”代表一个玩家的三个选择,“JKL”代表另一个玩家。

这些是您可以用来提升游戏的一堆想法!祝你好运,在你完成它之后随时跟进。

于 2019-10-29T01:10:01.553 回答