Ruby - игрок против игрока для игры в рок, бумагу и ножницы - PullRequest
0 голосов
/ 29 октября 2019

Извинения, если я повторяю то, что ранее спрашивали другие. Я прошел через другие вопросы по играм RSP на stackoverflow. Большинство о игроке против компьютера. Может быть, мне нужно прочитать больше теорий, чтобы лучше понять и изменить код в соответствии с моими целями: игрок один против игрока два.

Я пытаюсь Игрок один против Игрока два - игра в ножницы и бумага на камнях в Руби. У меня есть следующие вопросы о следующем коде. - Как мне скрыть каждую запись игрока? - В коде так много повторов, что нарушает принцип СУХОЙ. Как я должен рефакторинг это? - Является ли метод класса лучшим способом игры (наиболее эффективным)? - В настоящее время эта игра предназначена только для каменных ножниц. Если я захочу позже добавить ящерицу, как мне это доказать? или добавить это наиболее эффективным способом? Заранее спасибо!

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

Ответы [ 2 ]

1 голос
/ 29 октября 2019

Вы задали очень самоуверенный, открытый вопрос. Это не лучший вопрос для переполнения стека. Но я сделаю это.

Во-первых, я бы выделил ваш код оценки в функцию. Примерно так:

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" для другого игрока.

Это набор идей, которые вы можете использовать для улучшения своей игры! Удачи, и не стесняйтесь продолжать после того, как вы немного поработали.

0 голосов
/ 29 октября 2019

Вы можете судить о победителе следующими способами:

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
...