From: Dennis Ranke Date: 2004-11-01T23:23:50+09:00 Subject: Re: [QUIZ][SOLUTION] Re: Sokoban (#5) Here is my very simple solution, you controll the player using WASD for moving up, left, down and right and R for restarting the game. It should run on any Ruby 1.8. class Level def initialize(level) @level = level end def play while count_free_crates > 0 printf "\n%s\n\n> ", self c = gets c.each_byte do |command| case command when ?w move(0, -1) when ?a move(-1, 0) when ?s move(0, 1) when ?d move(1, 0) when ?r return false end end end printf "\n%s\nCongratulations, on to the next level!\n", self return true end private def move(dx, dy) x, y = find_player dest = self[x+dx, y+dy] case dest when ?# return when ?o, ?* dest2 = self[x+dx*2, y+dy*2] if dest2 == 32 self[x+dx*2, y+dy*2] = ?o elsif dest2 == ?. self[x+dx*2, y+dy*2] = ?* else return end dest = (dest == ?o) ? 32 : ?. end self[x+dx, y+dy] = (dest == 32) ? ?@ : ?+ self[x, y] = (self[x, y] == ?@) ? 32 : ?. end def count_free_crates @level.scan(/o/).size end def find_player pos = @level.index(/@|\+/) return pos % 19, pos / 19 end def [](x, y) @level[x + y * 19] end def []=(x, y, v) @level[x + y * 19] = v end def to_s (0...16).map {|i| @level[i * 19, 19]}.join("\n") end end levels = File.readlines('sokoban_levels.txt') levels = levels.map {|line| line.chomp.ljust(19)}.join("\n") levels = levels.split(/\n {19}\n/).map{|level| level.gsub(/\n/, '')} levels.each do |level| redo unless Level.new(level.ljust(19*16)).play end -- exoticorn/farbrausch