require "xxhash" # Game logic main class class GameLogic @seed = rand(111_111..999_999) @pos = { board: {}, lost: {}, cache: {}, } # Returns a pseudorandom number between 0 and 100 def self.hash(data) XXhash.xxh32(data.to_s, @seed) % 100 end def self.reset_pos @pos.each_value(&:clear) end def self.reveal(g_x, g_y) l_x = ((g_x % 9) + 9) % 9 l_y = ((g_y % 9) + 9) % 9 s_x = (g_x / 9).floor s_y = (g_y / 9).floor return if @pos.board["#{s_x}:#{s_y}"] == true build_sector(s_x, s_y) if @pos.board["#{s_x}:#{s_y}"].nil? return if @pos.board["#{s_x}:#{s_y}"][l_x][l_y][1] || @pos.board["#{s_x}:#{s_y}"][l_x][l_y][2] if @pos.board["#{s_x}:#{s_y}"][l_x][l_y][0] == -1 @pos.lost["#{s_x}:#{s_y}"] = 1 elsif @pos.board["#{s_x}:#{s_y}"][l_x][l_y][0].zero? (-1..1).each do |x| (-1..1).each do |y| next if x.zero? && y.zero? reveal(g_x + x, g_y + y) end end else @pos.board["#{s_x}:#{s_y}"][l_x][l_y][1] = true end @pos.board["#{s_x}:#{s_y}"] = true if solved?(s_x, s_y) end def self.solved?(s_x, s_y) (0..8).each do |l_x| (0..8).each do |l_y| return false if !@pos.board["#{s_x}:#{s_y}"][l_x][l_y][1] && @pos.board["#{s_x}:#{s_y}"][l_x][l_y][0] != -1 end end true end def self.count(g_x, g_y) sum = 0 (-1..1).each do |x| (-1..1).each do |y| next if x.zero? && y.zero? sum += 1 if mine?(g_x + x, g_y + y) end end sum end def self.build_sector(s_x, s_y) @pos.board["#{s_x}:#{s_y}"] = [] (0..8).each do |l_x| @pos.board["#{s_x}:#{s_y}"][l_x] = [] (0..8).each do |l_y| g_x = l_x + s_x * 9 g_y = l_y + s_y * 9 @pos.board["#{s_x}:#{s_y}"][l_x][l_y] = [ mine?(g_x, g_y) ? -1 : count(g_x, g_y), false, false, ] end end end def self.build_cache(s_x, s_y) return if @pos.cache["#{s_x}:#{s_y}"] return unless @pos.board["#{s_x}:#{s_y}"] == 1 @pos.cache["#{s_x}:#{s_y}"] = [] (0..8).each do |l_x| @pos.cache["#{s_x}:#{s_y}"][l_x] = [] (0..8).each do |l_y| g_x = l_x + s_x * 9 g_y = l_y + s_y * 9 @pos.cache["#{s_x}:#{s_y}"][l_x][l_y] = mine?(g_x, g_y) ? [-1, false, true] : [count(g_x, g_y), true, false] end end end def self.mine?(g_x, g_y) g_x == 4 || g_y == 4 ? false : hash("#{g_x}:#{g_y}") < 17 end end