Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class Game_Player #Эти методы дергать в Вызов скрипта
- attr_reader :puzzle
- def sudoku_new_puzzle(level = 3)#Сложность генератора, от 1 до 5
- @puzzle = Game_Sudoku.new
- p "Created!"
- @puzzle.generate_puzzle(level)
- p "Generated!"
- end
- def sudoku_state #сутус судоку
- @puzzle.current_state
- end
- def sudoku_solve #решить судоку
- @puzzle.solve
- end
- def sudoku_solved? #решено ли судоку?
- @puzzle.solved?
- end
- def sudoku_set(x, y, num)
- #str = @puzzle.get_str
- #str[y*9 + x] = num.to_s
- #@puzzle.upload(str)
- @puzzle.sudarr[x*9 + y] = num
- end
- def sudoku_debug#Вывод в консоль
- p @puzzle.sudarr
- p @puzzle.get_str
- puts @puzzle.sudoku_print
- end
- end
- class Game_Sudoku
- attr_accessor :sudarr
- def initialize(puzzle_str = '0' * 81)
- valid?(puzzle_str) ? upload(puzzle_str) : raise(ArgumentError, error_m)
- end
- def get_str
- retstr = ""
- @sudarr.each{ |num|
- retstr << num.to_s
- }
- return retstr
- end
- def upload(puzzle_str)#конвертация строки
- @sudarr = puzzle_str.chars.map(&:to_i)
- end
- def rows
- @sudarr.each_slice(9).to_a
- end
- def columns
- rows.transpose
- end
- def peers_of(index)
- peers = [rows[index/9], columns[index%9], boxes[box_of(index)]]
- peers.flatten.uniq.reject { |value| value == (0 || value_of(index)) }
- end
- def boxes(values = rows)
- (0..2).inject([]) do |boxes, index|
- boxes + values.slice(3 * index, 3).transpose.each_slice(3).map(&:flatten)
- end
- end
- def box_of(index)
- boxes(indexed).map { |boxes| boxes & [index] }.index([index])
- end
- def indexed
- @sudarr.map.with_index { |_, index| index }.each_slice(9).to_a
- end
- def current_state
- @sudarr.join
- end
- def sudoku_print #Форматирует для вывода в коноль или в файл, для теста
- separator = '-' * 21 + "\n"
- squares = rows.each { |row| row.insert(3, '|').insert(7, '|').insert(11, "\n").join(' ') }
- squares.insert(3, separator).insert(7, separator).join(' ').prepend("\n ").concat("\n")
- end
- def valid?(puzzle_str) #Если стрка судоки валидная
- (/^\d{81}$/) === puzzle_str ? true : false
- end
- def str_err_msg
- 'Argument must be String of 81 digits'
- end
- #Логика генератора
- def generate_puzzle(level = 3)
- raise(ArgumentError, lev_err) unless (1..5).include?(level)
- p "Good!"
- delete_puzzle
- create_seed
- p "Seed generated!"
- solve ? punch_to(level) : generate_puzzle(level)
- end
- def delete_puzzle
- @sudarr = Array.new(81, 0)
- end
- def create_seed
- for sead_box in seed_indices
- seed_values = (1..9).to_a.shuffle
- sead_box.each_with_index { |seed, index| @sudarr[seed] = seed_values[index] }
- end
- end
- def seed_indices
- boxes(indexed).select.with_index { |box, index| box if [0, 4, 8].include?(index) }
- end
- def punch_to(level)
- num_of_punches = level * 10 + 21
- p num_of_punches
- while num_of_punches > 0
- rnd = Random.new(Time.new.usec)#Генератор случайнх ческл с семенеем
- random_square = rnd.rand(0..80)
- p random_square
- (sudarr[random_square] = 0 and num_of_punches -= 1) if solved_at?(random_square)
- end
- p "Punched!"
- end
- def lev_err
- 'Argument must be Fixnum between 1-5'
- end
- #Логика решателя
- attr_reader :solution_arr
- def solve #Пытаемся решить
- first_try
- second_try unless solved?
- solved? ? (set_solution and return true) : false
- end
- def first_try#Первый способ
- current_puzzle_state, stop_looping = 81, false
- until solved? || stop_looping
- solve_all_squares
- stop_looping = true if current_puzzle_state == solved_squares_count
- current_puzzle_state = solved_squares_count
- end
- end
- def second_try#Второй, если первый не помог
- unsolved_index = first_unsolved_square
- candidates_for(unsolved_index).each do |candidate|
- sudarr[unsolved_index] = candidate
- puzzle_clone = self.class.new(current_state)
- self.upload(puzzle_clone.current_state) and return if puzzle_clone.solve
- end
- end
- def solve_all_squares
- sudarr.each_index { |index| solve_at(index) }
- end
- def solve_at(index)
- solutions = candidates_for(index) || []
- sudarr[index] = solutions.first if solutions.count == 1
- end
- def solved_squares_count
- sudarr.count { |square| square != 0 }
- end
- def first_unsolved_square
- sudarr.index(0)
- end
- def candidates_for(index)
- candidates = (1..9).to_a - peers_of(index)
- candidates.sort unless solved_at?(index)
- end
- def solved_at?(index)
- sudarr[index] != 0
- end
- def solved?
- (rows + columns + boxes).map { |values| values.sort == (1..9).to_a }.all?
- end
- def set_solution
- @solution_arr = sudarr.join.chars.map(&:to_i)
- end
- def solution_str
- solution_arr ? solution_arr.join : ''
- end
- end
- class String #в ргсс3 руби 1.9.2, метода препенд нет(
- def prepend(str)
- str + self
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement