lib/codebreaker_vk/game.rb in codebreaker_vk-0.3.1 vs lib/codebreaker_vk/game.rb in codebreaker_vk-1.0.1

- old
+ new

@@ -1,82 +1,75 @@ # frozen_string_literal: true module CodebreakerVk class Game - attr_reader :hints, :attempts, :difficulty, :breaker_numbers, :showed_hints, :player_name + include Output + SECRET_CODE_LENGTH = 4 + RANGE_START = 1 + RANGE_END = 6 + NOT_YET = '-' + GOT_IT = '+' + DIFFICULTY_LEVEL = { + easy: { attempts: 15, hints: 3 }, + medium: { attempts: 10, hints: 2 }, + hell: { attempts: 5, hints: 1 } + }.freeze - INCLUDE_IN_GAME_NUMBERS = (1..6).freeze - CODE_SIZE = 4 + attr_accessor :attempts_total, :attempts, :difficulty, :hints_total, :hints, :name, :secret - GUESS_PLACE = '+' - GUESS_PRESENCE = '-' + def initialize(name:, difficulty:) + @name = name + @difficulty = difficulty + @attempts = DIFFICULTY_LEVEL[difficulty][:attempts] + @hints = DIFFICULTY_LEVEL[difficulty][:hints] + @secret = make_number + @unused_hints = @secret.chars + end - def initialize(difficulty, user) - @breaker_numbers = generate_random_code - @breaker_numbers_copy = @breaker_numbers.clone.shuffle - @hints = difficulty.level[:hints] - @attempts = difficulty.level[:attempts] - @difficulty = difficulty.level - @player_name = user.name - @showed_hints = [] + def make_number(numbers = RANGE_END) + (1..SECRET_CODE_LENGTH).map { rand(RANGE_START..numbers) }.join end - def start_round(user_input) + def check(number) @attempts -= 1 - @game_numbers = { code: @breaker_numbers.clone, input: user_input } - collect_place_guess + collect_presence_guess + @last_result = check_numbers(@secret.chars, number.chars) end - def hint - return if @hints.zero? - - @hints -= 1 - @showed_hints << @breaker_numbers_copy.pop - @showed_hints.last + def win? + @last_result == GOT_IT * SECRET_CODE_LENGTH end - def win?(result) - @breaker_numbers == result - end + def use_hint + return I18n.t(:no_hints) unless @hints.positive? - def lose?(result) - @attempts == 1 && @breaker_numbers != result + @hints -= 1 + hint(@unused_hints) end - def to_h - { - player_name: @player_name, - level: @difficulty[:level], - all_hints: @difficulty[:hints], - all_attempts: @difficulty[:attempts], - left_hints: @hints, - left_attempts: @attempts, - date: Time.now - } - end - private - def collect_place_guess - @game_numbers[:input].map.with_index do |user_num, index| - next if @game_numbers[:code][index] != user_num + def check_numbers(secret, numbers) + exact_matches, non_exact_matches = secret.zip(numbers).partition do |secret_number, input_number| + secret_number == input_number + end - @game_numbers[:code][index] = nil - @game_numbers[:input][index] = nil - GUESS_PLACE - end.compact + result = Array.new(exact_matches.count, GOT_IT) + + find_non_exact_matches(result, non_exact_matches) if non_exact_matches.any? + + result.join end - def collect_presence_guess - @game_numbers[:input].compact.map do |user_num| - next unless @game_numbers[:code].include?(user_num) + def find_non_exact_matches(result, non_exact_matches) + secret, numbers = non_exact_matches.transpose + numbers.each do |number_element| + next unless secret.include? number_element - @game_numbers[:code].delete_at(@game_numbers[:code].index(user_num)) - GUESS_PRESENCE - end.compact + result.push(NOT_YET) && secret.delete_at(secret.index(number_element)) + end end - def generate_random_code - Array.new(CODE_SIZE) { rand(INCLUDE_IN_GAME_NUMBERS) } + def hint(secret) + secret.shuffle.pop end end end