Sokoban: Difference between revisions

(Added Elixir)
(→‎{{header|Ruby}}: refactering)
Line 2,755:
 
=={{header|Ruby}}==
===ShorterSimple Version===
{{trans|Python}}
<lang ruby>require 'set'
Line 2,761:
class Sokoban
def initialize(level)
board = level.each_line.map(&:chomprstrip)
@nrows = board.map(&:size).max
board = board.map!{|line| line.ljust(@nrows)}
board.each_with_index do |row, r|
row.each_char.with_index do |ch, c|
Line 2,769:
end
end
@goal = board.join.tr(' .@#$+*', ' . ..')
@goal = goal .each_char.with_index.select{|ch, c| ch == '.'}.map(&:last)
temp[ps] = '@'.map(&:last)
@databoard = board.join.tr(' .@#$+*', ' @#$ $')
end
Line 2,778 ⟶ 2,779:
end
def push(x, y, dx, dy, databoard) # modify board
return data if databoard[pos(x+2*dx, y+2*dy)] != ' '
databoard[pos(x , y )] = ' '
databoard[pos(x + dx, y + dy)] = '@'
databoard[pos(x+2*dx, y+2*dy)] = '$'
data
end
def solved?(databoard)
@goal.all?{|i| databoard[i] == '$'}
end
DIRS = [[0, -1, 'u', 'U'], [ 1, 0, 'r', 'R'], [0, 1, 'd', 'D'], [-1, 0, 'l', 'L']]
def solve
openqueue = [[@databoard, "", @px, @py]]
visited = Set[@databoard]
until openqueue.empty?
curcurrent, csol, x, y = openqueue.shift
for dx, dy, cmove, cpush in DIRS
tempwork = curcurrent.dup
ps =case work[pos(x+dx, y+dy)] # next character
if temp[ps] ==when '$'
tempnext = unless push(x, y, dx, dy, tempwork)
next ifunless visited.includeadd?(tempwork)
visited.addreturn csol+cpush if solved?(tempwork)
returnqueue csol<< +[work, csol+cpush, x+dx, if solved?(temp)y+dy]
when ' '
open << [temp, csol + cpush, x+dx, y+dy]
else work[pos(x, y)] = ' '
next if @datawork[ps]pos(x+dx, == '#' or temp[psy+dy)] != ' @'
tempqueue << [pos(work, csol+cmove, x+dx, y)+dy] = 'if 'visited.add?(work)
temp[ps] = '@'
next if visited.include?(temp)
visited.add(temp)
open << [temp, csol + cmove, x+dx, y+dy]
end
end
Anonymous user