# frozen_string_literal: true require 'codebreaker/version' require_relative 'dependency' module Codebreaker class Game STATE = { continue: 'continue', win: 'win', lose: 'lose' }.freeze VALID_NUMBERS = (1..6).freeze LENGTH_CODE = 4 CORRECT_SYMBOL = '+' INCORRECT_SYMBOL = '-' attr_reader :hints, :attempts, :state, :number def initialize(player, difficulties) @player = player @difficulties = difficulties @attempts = @difficulties.attempts @hints = @difficulties.hints @number = generator_secret_code @available_hints = @number.clone @state = STATE[:continue] end def hint @hints -= 1 @available_hints.delete_at(rand(@available_hints.size)) end def check_code(code) return nil unless valid_code?(code) @attempts -= 1 temp_code = code.chars guess_number = Array.new(LENGTH_CODE) { 0 } calc_and_mark_correct(temp_code, guess_number) + calc_and_mark_incorrect(temp_code, guess_number) end def to_h { player: @player.name, difficulties: @difficulties.level, attempts_total: @difficulties.attempts, hints_total: @difficulties.hints, attempts_used: @difficulties.attempts - @attempts, hints_used: @difficulties.hints - @hints, state: @state } end def win?(code) return false unless code == @number.join @state = STATE[:win] true end def hints? !@hints.zero? end def lose? return false unless @attempts.zero? @state = STATE[:lose] true end private def calc_and_mark_correct(code, used) result = '' code.each_index do |index| next unless number[index] == code[index] result += CORRECT_SYMBOL code[index], used[index] = nil end result end def calc_and_mark_incorrect(code, used) result = '' number.each_index do |number_index| code_index = code.index(number[number_index]) next if code_index.nil? || used[number_index].nil? result += INCORRECT_SYMBOL code[code_index], used[number_index] = nil end result end def generator_secret_code Array.new(4) { rand(VALID_NUMBERS).to_s } end def valid_code?(code) Verifier.verify_valid_code(code) end end end