Игровой проект Ruby Mastermind с ИИ
Я самоучка и новичок в программировании, поэтому создал игру Mastermind на Ruby. Мы будем очень благодарны за любые общие отзывы или советы. Игра сейчас полностью функциональна и имеет простой ИИ. Вначале игрок выбирает, какую роль он хочет выбрать (взломщик кода или создатель кода).
Ура
https://repl.it/repls/WeirdFrankButtons
изменить: фиксированная ссылка
class Game
def initialize
puts "---------------------------------"
puts "Welcome to Mastermind"
puts "The goal is to either create a 4 digit code (Code maker role) containing numbers ranging from 1 through 6 or to guess a code (Codebreaker role) created by the computer within 12 turns to win."
puts "After each guess you will be given an accuracy score indicating how close you were to guessing the code correctly."
puts "The letter \"H\" indicates one of the numbers you guessed is in the correct position. The letter \"h\" indicates you guessed a correct number but it is NOT in the correct position"
puts "----------------------------------"
@game_over = false
@turn = 1
until @comp_guess_mode === "Y" || @comp_guess_mode === "N"
print "Is the computer the code breaker? Y/N"
@comp_guess_mode = gets.chomp.upcase
end
game_mode
turn_sequence
end
def game_mode
if @comp_guess_mode == "Y"
human_code_generator
else
code_generator
end
end
def code_generator
@code = Array.new(4) {rand(1..6)}
end
def human_code_generator
@code = ""
puts "Please enter a 4 digit code"
until @code.length == 4
@code = gets.chomp.each_char.map(&:to_i)
end
end
# computer_guesser method that tests if the computer's guess matches the human's
# by iterating through the array, if a direct match ('H') is found it will keep that number in the next guess
def computer_guesser
@updated_comp_guess = [" "," "," "," "]
if @turn == 1
@guess = Array.new(4) {rand(1..6)}
else
i = 0
while i <4
if @guess[i] == @code[i]
@updated_comp_guess[i] = @guess[i]
i+=1
else
i +=1
end
end
end
@guess = Array.new(4) {rand(1..6)}
@updated_comp_guess.each_with_index do |value, idx|
if value != " "
@guess[idx] = value
end
end
puts "Guess: #{@guess.join}"
end
def codebreaker_guess
@guess = []
until @guess.length == 4
puts "Enter your 4 digit guess"
@guess = gets.chomp.each_char.map(&:to_i)
puts "Guess: #{@guess.join}"
if @guess.length != 4
print "Your guess was not 4 digits long, please guess again \n"
end
end
end
def turn_display
puts "-------------------------"
puts "It's turn number: #{@turn}"
end
#Repeats the following guess/check sequence for 12 turns
# or until the code and guess are matched
def turn_sequence
while @turn <13 && @game_over == false
turn_display
if @comp_guess_mode == "Y"
computer_guesser
else
codebreaker_guess
end
guess_checker
@turn += 1
victory_check
end
end
def guess_checker
@guess_accuracy = []
@i=0
@h_counter = 0
while @i<4
if @guess[@i] == @code[@i]
@guess_accuracy.push("H")
@h_counter += 1
@i+=1
else
@i+=1
end
end
if @i == 4
i = 0
compare_array = @code.clone
while i < 4
if compare_array.include?(@guess[i])
compare_array[(compare_array.index(@guess[i]))]= " "
@guess_accuracy.push("h")
i+=1
else
i+=1
end
end
@guess_accuracy.pop(@h_counter)
puts "Guess accuracy: #{@guess_accuracy.join}"
end
end
def victory_check
if @guess[0..3] == @code[0..3]
puts "Code was guessed correctly, it's #{@code}, codebreaker wins"
@game_over = true
elsif @turn == 13 && @game_over == false
puts "Code was not guessed correctly, code maker wins"
@game_over = true
end
end
end
game = Game.new
```
Ответы
Код 1
while i <4
if @guess[i] == @code[i]
@updated_comp_guess[i] = @guess[i]
i+=1
else
i +=1
end
end
И в if
и else
вы увеличиваете i
на 1. Это можно сделать короче.
while i <4
if @guess[i] == @code[i]
@updated_comp_guess[i] = @guess[i]
end
i += 1
end
Аналогично в guess_checker
нижнем и нижнемcompare_array
Последовательность
Иногда вы используете 1 пробел для отступа, иногда - 2. Иногда вы используете пробелы вокруг операторов, иногда нет, иногда вы используете пробелы с одной стороны оператора, но не с другой. Иногда вы используете пробел после запятой, иногда нет. Иногда вы используете одну пустую строку после метода, иногда две, иногда ни одной.
Вам следует выбрать один стиль и придерживаться его. Если вы редактируете какой-либо существующий код, вам следует адаптировать свой стиль, чтобы он был таким же, как и существующий код. Если вы являетесь частью команды, вам следует адаптировать свой стиль, чтобы он соответствовал остальной части команды.
Большинство сообществ разработали стандартизированные руководства по стилю сообщества. В Ruby таких руководств по стилю несколько. Все они согласны с основами (например, отступ составляет 2 пробела), но они могут не согласиться по более конкретным вопросам (одинарные или двойные кавычки).
Отступ
Стандартный стиль отступа в Ruby - два пробела. В основном вы используете 2 пробела, но есть одно место, где вы используете 1 пробел. Придерживайтесь двух.
Пробелы вокруг операторов
С каждой стороны от оператора должно быть по 1 пробелу. Иногда вы используете 1 пробел, иногда нет места, а иногда только с одной стороны.
Например, здесь у вас есть одно и то же выражение в трех строках с двумя разными стилями интервала:
i+=1
else
i +=1
Они несовместимы с каждым из них, и оба не соответствуют принципам сообщества. Оба они должны быть:
i += 1
Пробел после запятой
После запятой должен быть 1 пробел. Иногда вы используете 1 пробел, иногда нет места.
Например, здесь:
@updated_comp_guess = [" "," "," "," "]
должно быть
@updated_comp_guess = [" ", " ", " ", " "]
Пространство в блоках
В литерале блока должен быть пробел после открывающей фигурной скобки и один перед закрывающей фигурной скобкой:
@code = Array.new(4) { rand(1..6) }
Строки в одинарных кавычках
Если вы не используете интерполяцию строк, полезно использовать одинарные кавычки для ваших строк. Таким образом, сразу становится очевидным, что интерполяция строк не выполняется.
В частности, это также удалит экранирование, которое вам нужно сделать здесь:
puts 'The letter "H" indicates one of the numbers you guessed is in the correct position. The letter "h" indicates you guessed a correct number but it is NOT in the correct position'
Замороженные строковые литералы
Неизменяемые структуры данных и чисто функциональный код всегда предпочтительны, если только для ясности или производительности не требуются изменчивость и побочные эффекты. В Ruby строки всегда изменяемы, но есть волшебный комментарий, который вы можете добавить к своим файлам (также доступный как параметр командной строки для движка Ruby), который автоматически сделает все буквальные строки неизменяемыми:
# frozen_string_literal: true
Обычно рекомендуется добавлять этот комментарий ко всем вашим файлам.
Условные модификаторы
Если у вас есть условие, которое выполняет только одно выражение, вы должны вместо этого использовать форму модификатора, например это:
if value != " "
@guess[idx] = value
end
должно быть
@guess[idx] = value if value != " "
Тоже самое:
until @code.length == 4
@code = gets.chomp.each_char.map(&:to_i)
end
должно быть
@code = gets.chomp.each_char.map(&:to_i) until @code.length == 4
Ненужные скобки
compare_array[(compare_array.index(@guess[i]))]= " "
В круглых скобках compare_array.index(@guess[i])
нет необходимости.
Линтинг
Вы должны запустить какой-то линтер или статический анализатор своего кода. Рубокоп - популярный, но есть и другие.
Rubocop смог обнаружить все нарушения стиля, на которые я указал, а также смог автоматически исправить их все.
Позвольте мне повторить: я только что провел две страницы , указывая, как правильные тонны вещей , которые вы можете на самом деле правильно в течение миллисекунд при нажатии кнопки. Я настроил свой редактор таким образом, что он автоматически запускает Rubocop с автоматическим исправлением, как только я нажимаю «сохранить».
В частности, запустив Rubocop в вашем коде, он обнаруживает 98 нарушений, из которых он может автоматически исправить 76. В результате у вас остается 22 нарушения, из которых 11 очень простые.
Вот как выглядит результат автоматического исправления:
# frozen_string_literal: true
class Game
def initialize
puts '---------------------------------'
puts 'Welcome to Mastermind'
puts 'The goal is to either create a 4 digit code (Code maker role) containing numbers ranging from 1 through 6 or to guess a code (Codebreaker role) created by the computer within 12 turns to win.'
puts 'After each guess you will be given an accuracy score indicating how close you were to guessing the code correctly.'
puts 'The letter "H" indicates one of the numbers you guessed is in the correct position. The letter "h" indicates you guessed a correct number but it is NOT in the correct position'
puts '----------------------------------'
@game_over = false
@turn = 1
until @comp_guess_mode === 'Y' || @comp_guess_mode === 'N'
print 'Is the computer the code breaker? Y/N'
@comp_guess_mode = gets.chomp.upcase
end
game_mode
turn_sequence
end
def game_mode
if @comp_guess_mode == 'Y'
human_code_generator
else
code_generator
end
end
def code_generator
@code = Array.new(4) { rand(1..6) }
end
def human_code_generator
@code = ''
puts 'Please enter a 4 digit code'
@code = gets.chomp.each_char.map(&:to_i) until @code.length == 4
end
# computer_guesser method that tests if the computer's guess matches the human's
# by iterating through the array, if a direct match ('H') is found it will keep that number in the next guess
def computer_guesser
@updated_comp_guess = [' ', ' ', ' ', ' ']
if @turn == 1
@guess = Array.new(4) { rand(1..6) }
else
i = 0
while i < 4
if @guess[i] == @code[i]
@updated_comp_guess[i] = @guess[i]
i += 1
else
i += 1
end
end
end
@guess = Array.new(4) { rand(1..6) }
@updated_comp_guess.each_with_index do |value, idx|
@guess[idx] = value if value != ' '
end
puts "Guess: #{@guess.join}"
end
def codebreaker_guess
@guess = []
until @guess.length == 4
puts 'Enter your 4 digit guess'
@guess = gets.chomp.each_char.map(&:to_i)
puts "Guess: #{@guess.join}"
print "Your guess was not 4 digits long, please guess again \n" if @guess.length != 4
end
end
def turn_display
puts '-------------------------'
puts "It's turn number: #{@turn}"
end
# Repeats the following guess/check sequence for 12 turns
# or until the code and guess are matched
def turn_sequence
while @turn < 13 && @game_over == false
turn_display
if @comp_guess_mode == 'Y'
computer_guesser
else
codebreaker_guess
end
guess_checker
@turn += 1
victory_check
end
end
def guess_checker
@guess_accuracy = []
@i = 0
@h_counter = 0
while @i < 4
if @guess[@i] == @code[@i]
@guess_accuracy.push('H')
@h_counter += 1
@i += 1
else
@i += 1
end
end
if @i == 4
i = 0
compare_array = @code.clone
while i < 4
if compare_array.include?(@guess[i])
compare_array[compare_array.index(@guess[i])] = ' '
@guess_accuracy.push('h')
i += 1
else
i += 1
end
end
@guess_accuracy.pop(@h_counter)
puts "Guess accuracy: #{@guess_accuracy.join}"
end
end
def victory_check
if @guess[0..3] == @code[0..3]
puts "Code was guessed correctly, it's #{@code}, codebreaker wins"
@game_over = true
elsif @turn == 13 && @game_over == false
puts 'Code was not guessed correctly, code maker wins'
@game_over = true
end
end
end
game = Game.new
И вот нарушения, которые Rubocop не может исправить автоматически:
Offenses:
game.rb:3:1: C: Metrics/ClassLength: Class has too many lines. [116/100]
class Game ...
^^^^^^^^^^
game.rb:3:1: C: Style/Documentation: Missing top-level class documentation comment.
class Game
^^^^^
game.rb:4:3: C: Metrics/MethodLength: Method has too many lines. [14/10]
def initialize ...
^^^^^^^^^^^^^^
game.rb:7:121: C: Layout/LineLength: Line is too long. [202/120]
puts 'The goal is to either create a 4 digit code (Code maker role) containing numbers ranging from 1 through 6 or to guess a code (Codebreaker role) created by the computer within 12 turns to win.'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
game.rb:8:121: C: Layout/LineLength: Line is too long. [125/120]
puts 'After each guess you will be given an accuracy score indicating how close you were to guessing the code correctly.'
^^^^^
game.rb:9:121: C: Layout/LineLength: Line is too long. [186/120]
puts 'The letter "H" indicates one of the numbers you guessed is in the correct position. The letter "h" indicates you guessed a correct number but it is NOT in the correct position'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
game.rb:13:28: C: Style/CaseEquality: Avoid the use of the case equality operator ===.
until @comp_guess_mode === 'Y' || @comp_guess_mode === 'N'
^^^
game.rb:13:56: C: Style/CaseEquality: Avoid the use of the case equality operator ===.
until @comp_guess_mode === 'Y' || @comp_guess_mode === 'N'
^^^
game.rb:41:3: C: Metrics/AbcSize: Assignment Branch Condition size for computer_guesser is too high. [<12, 12, 11> 20.22/17]
def computer_guesser ...
^^^^^^^^^^^^^^^^^^^^
game.rb:41:3: C: Metrics/MethodLength: Method has too many lines. [19/10]
def computer_guesser ...
^^^^^^^^^^^^^^^^^^^^
game.rb:50:11: C: Style/IdenticalConditionalBranches: Move i += 1 out of the conditional.
i += 1
^^^^^^
game.rb:52:11: C: Style/IdenticalConditionalBranches: Move i += 1 out of the conditional.
i += 1
^^^^^^
game.rb:80:3: C: Metrics/MethodLength: Method has too many lines. [11/10]
def turn_sequence ...
^^^^^^^^^^^^^^^^^
game.rb:94:3: C: Metrics/AbcSize: Assignment Branch Condition size for guess_checker is too high. [<16, 13, 11> 23.37/17]
def guess_checker ...
^^^^^^^^^^^^^^^^^
game.rb:94:3: C: Metrics/MethodLength: Method has too many lines. [27/10]
def guess_checker ...
^^^^^^^^^^^^^^^^^
game.rb:102:9: C: Style/IdenticalConditionalBranches: Move @i += 1 out of the conditional.
@i += 1
^^^^^^^
game.rb:104:9: C: Style/IdenticalConditionalBranches: Move @i += 1 out of the conditional.
@i += 1
^^^^^^^
game.rb:107:5: C: Style/GuardClause: Use a guard clause (return unless @i == 4) instead of wrapping the code inside a conditional expression.
if @i == 4
^^
game.rb:114:11: C: Style/IdenticalConditionalBranches: Move i += 1 out of the conditional.
i += 1
^^^^^^
game.rb:116:11: C: Style/IdenticalConditionalBranches: Move i += 1 out of the conditional.
i += 1
^^^^^^
game.rb:117:8: W: Layout/EndAlignment: end at 117, 7 is not aligned with if at 111, 8.
end
^^^
game.rb:135:1: W: Lint/UselessAssignment: Useless assignment to variable - game.
game = Game.new
^^^^
1 file inspected, 22 offenses detected
Давайте сначала посмотрим на простые.
Оператор равенства случаев
Вы используете оператор равенства case в нескольких местах. Поскольку для строк определено равенство регистра, ваш код работает «случайно». Вместо этого следует использовать обычный оператор равенства.
Эта:
until @comp_guess_mode === "Y" || @comp_guess_mode === "N"
должно быть это:
until @comp_guess_mode == "Y" || @comp_guess_mode == "N"
Обратите внимание, что здесь вы используете правильный оператор равенства для точно такой же проверки:
if @comp_guess_mode == "Y"
Идентичные выражения во всех ветвях
Есть три места, где у вас есть одно и то же выражение в обеих ветвях условного выражения. Это ненужный беспорядок, вы можете просто вытащить выражение из условного:
if @guess[i] == @code[i]
@updated_comp_guess[i] = @guess[i]
i+=1
else
i +=1
end
должно быть
if @guess[i] == @code[i]
@updated_comp_guess[i] = @guess[i]
end
i +=1
И, как мы сказали выше, условное выражение только с одним выражением должно использовать форму модификатора (обратите внимание, что это преобразование снова будет выполнено автоматически Rubocop, если вы снова запустите его):
@updated_comp_guess[i] = @guess[i] if @guess[i] == @code[i]
i +=1
Неиспользуемая локальная переменная
game = Game.new
game
нигде не используется. Просто удалите это:
Game.new
Охранные оговорки
Если у вас есть случай, когда весь метод или блок заключен в условное выражение, вы можете заменить его «защитным условием» и снизить уровень вложенности.
Например, это:
def something
if foo
bar
baz
quux
else
42
end
end
может стать таким:
def something
return 42 unless foo
bar
baz
quux
end
Есть несколько возможностей сделать это в вашем коде, и еще пара создается, следуя советам Rubocop.
Вот один пример, когда улучшение не очень большое:
def game_mode
if @comp_guess_mode == "Y"
human_code_generator
else
code_generator
end
end
def game_mode
return human_code_generator if @comp_guess_mode == "Y"
code_generator
end
но здесь выигрыш несколько больше:
def guess_checker
@guess_accuracy = []
@i=0
@h_counter = 0
while @i<4
if @guess[@i] == @code[@i]
@guess_accuracy.push("H")
@h_counter += 1
@i+=1
else
@i+=1
end
end
if @i == 4
i = 0
compare_array = @code.clone
while i < 4
if compare_array.include?(@guess[i])
compare_array[(compare_array.index(@guess[i]))]= " "
@guess_accuracy.push("h")
i+=1
else
i+=1
end
end
@guess_accuracy.pop(@h_counter)
puts "Guess accuracy: #{@guess_accuracy.join}"
end
end
def guess_checker
@guess_accuracy = []
@i = 0
@h_counter = 0
while @i < 4
if @guess[@i] == @code[@i]
@guess_accuracy.push('H')
@h_counter += 1
end
@i += 1
end
return unless @i == 4
i = 0
compare_array = @code.clone
while i < 4
if compare_array.include?(@guess[i])
compare_array[compare_array.index(@guess[i])]= ' '
@guess_accuracy.push('h')
end
i += 1
end
@guess_accuracy.pop(@h_counter)
puts "Guess accuracy: #{@guess_accuracy.join}"
end
Избыточные проверки
Но на самом деле все еще проще: поскольку вы выполняете цикл и увеличиваете i
4 раза, это всегда будет 4
, поэтому условие всегда будет истинным, и вы можете просто удалить его полностью.
Равенство с логическими значениями
@game_over == false
@game_over
уже является логическим значением, нет необходимости проверять равенство false
. Это только
!@game_over
Ненужные переменные экземпляра
Переменные экземпляра @updated_comp_guess
, @i
, @h_counter
и @guess_accuracy
только когда - либо использовали в одном методе. Вместо этого они должны быть локальными переменными.
Петли
В Ruby циклы почти не нужны. Фактически, я бы пошел так далеко и сказал, что если вы используете цикл в Ruby, вы делаете это неправильно.
Вот пример:
i = 0
while i < 4
updated_comp_guess[i] = @guess[i] if @guess[i] == @code[i]
i += 1
end
было бы намного лучше написать как
4.times do |i|
updated_comp_guess[i] = @guess[i] if @guess[i] == @code[i]
end
В результате guess_checker
метод будет выглядеть так:
def guess_checker
guess_accuracy = []
h_counter = 0
4.times do |i|
if @guess[i] == @code[i]
guess_accuracy.push('H')
h_counter += 1
end
end
compare_array = @code.clone
4.times do |i|
if compare_array.include?(@guess[i])
compare_array[compare_array.index(@guess[i])] = ' '
guess_accuracy.push('h')
end
end
guess_accuracy.pop(h_counter)
puts "Guess accuracy: #{guess_accuracy.join}"
end
что снова дает нам возможность использовать защитные предложения:
def guess_checker
guess_accuracy = []
h_counter = 0
4.times do |i|
next unless @guess[i] == @code[i]
guess_accuracy.push('H')
h_counter += 1
end
compare_array = @code.clone
4.times do |i|
next unless compare_array.include?(@guess[i])
compare_array[compare_array.index(@guess[i])] = ' '
guess_accuracy.push('h')
end
guess_accuracy.pop(h_counter)
puts "Guess accuracy: #{guess_accuracy.join}"
end
Избыточные выражения
В computer_guesser
случае, если @turn == 1
вы инициализируете @guess
, а затем инициализируете его снова, никогда не используя его между ними. Первую инициализацию можно просто удалить, повернув так:
if @turn == 1
@guess = Array.new(4) { rand(1..6) }
else
4.times do |i|
updated_comp_guess[i] = @guess[i] if @guess[i] == @code[i]
end
end
@guess = Array.new(4) { rand(1..6) }
в это:
unless @turn == 1
4.times do |i|
updated_comp_guess[i] = @guess[i] if @guess[i] == @code[i]
end
end
@guess = Array.new(4) { rand(1..6) }
Дублирование кода
Array.new(4) { rand(1..6) }
Встречается в вашем коде несколько раз. Его нужно извлечь в метод.
length
vs. size
Многие коллекции Рубиновые есть как length
и size
методы, но некоторые из них только один. В общем, IFF в коллекции имеет size
метод, тогда этот метод гарантированно будет «эффективным» (обычно с постоянным временем), тогда как length
может быть или не быть эффективным (линейное время для итерации по коллекции и подсчета всех элементов), в зависимости от Коллекция.
В вашем случае вы используете массивы и строки, для которых оба являются постоянным временем, но если вы хотите гарантировать эффективность, лучше size
вместо этого явно использовать .
Слон в комнате
Одна вещь, которую я до сих пор не затронул и на которую, к сожалению, у меня нет времени, - это фундаментальная конструкция кода. Все, что я упомянул, - это просто косметика.
Вся работа выполняется в инициализаторе. Все, что должен сделать инициализатор, - это инициализировать объект. Он не должен запрашивать ввод пользователя, он не должен ничего печатать, он не должен играть в игры.
Кроме того, вы повсюду смешиваете ввод-вывод и логику. Метод должен либо что-то печатать, либо что-то делать. Ваш дизайн делает невозможным тестирование кода, фактически не играя в игру. Я не могу подготовить файл с кодами и предположениями и передать его тест-раннеру, мне действительно приходится вручную играть в игру.
Также странно, что у вас есть только один «объект», а именно игра, которая что-то делает. Если вы подумаете о том, как обычно ведется игра, разве объекты, которые активно что-то делают, не являются игроками, а не самой игрой? Где игроки в вашем дизайне?
К сожалению, у меня нет времени углубляться в это.
Вот где сейчас стоит код:
# frozen_string_literal: true
class Game
def initialize
puts '---------------------------------'
puts 'Welcome to Mastermind'
puts 'The goal is to either create a 4 digit code (Code maker role) containing numbers ranging from 1 through 6 or to guess a code (Codebreaker role) created by the computer within 12 turns to win.'
puts 'After each guess you will be given an accuracy score indicating how close you were to guessing the code correctly.'
puts 'The letter "H" indicates one of the numbers you guessed is in the correct position. The letter "h" indicates you guessed a correct number but it is NOT in the correct position'
puts '----------------------------------'
@game_over = false
@turn = 1
until @comp_guess_mode == 'Y' || @comp_guess_mode == 'N'
print 'Is the computer the code breaker? Y/N'
@comp_guess_mode = gets.chomp.upcase
end
game_mode
turn_sequence
end
def game_mode
return human_code_generator if @comp_guess_mode == 'Y'
code_generator
end
def code_generator
@code = Array.new(4) { rand(1..6) }
end
def human_code_generator
@code = ''
puts 'Please enter a 4 digit code'
@code = gets.chomp.each_char.map(&:to_i) until @code.size == 4
end
# computer_guesser method that tests if the computer's guess matches the human's
# by iterating through the array, if a direct match ('H') is found it will keep that number in the next guess
def computer_guesser
updated_comp_guess = [' ', ' ', ' ', ' ']
unless @turn == 1
4.times do |i|
updated_comp_guess[i] = @guess[i] if @guess[i] == @code[i]
end
end
@guess = Array.new(4) { rand(1..6) }
updated_comp_guess.each_with_index do |value, idx|
@guess[idx] = value if value != ' '
end
puts "Guess: #{@guess.join}"
end
def codebreaker_guess
@guess = []
until @guess.size == 4
puts 'Enter your 4 digit guess'
@guess = gets.chomp.each_char.map(&:to_i)
puts "Guess: #{@guess.join}"
print "Your guess was not 4 digits long, please guess again \n" if @guess.size != 4
end
end
def turn_display
puts '-------------------------'
puts "It's turn number: #{@turn}"
end
# Repeats the following guess/check sequence for 12 turns
# or until the code and guess are matched
def turn_sequence
while @turn < 13 && !@game_over
turn_display
if @comp_guess_mode == 'Y'
computer_guesser
else
codebreaker_guess
end
guess_checker
@turn += 1
victory_check
end
end
def guess_checker
guess_accuracy = []
h_counter = 0
4.times do |i|
next unless @guess[i] == @code[i]
guess_accuracy.push('H')
h_counter += 1
end
compare_array = @code.clone
4.times do |i|
next unless compare_array.include?(@guess[i])
compare_array[compare_array.index(@guess[i])] = ' '
guess_accuracy.push('h')
end
guess_accuracy.pop(h_counter)
puts "Guess accuracy: #{guess_accuracy.join}"
end
def victory_check
if @guess == @code
puts "Code was guessed correctly, it's #{@code}, codebreaker wins"
@game_over = true
elsif @turn == 13 && !@game_over
puts 'Code was not guessed correctly, code maker wins'
@game_over = true
end
end
end
Game.new
```