@noel I suppose there is no need to congratulate winner as it is obvious when you succeed, here is my JRubyArt version, I’ve stolen look and feel from your version:-
DIM = 100
NUMBER_CELLS = 16
attr_reader :tile, :bcolor, :dark, :light, :tcolor, :space, :blank
attr_reader :list, :inside, :target
def settings
size(400, 400)
end
def setup
sketch_title 'Fifteen Tile Puzzle'
positions = []
@list = []
grid(width, height, DIM, DIM) do |y, x|
positions << Vect.new(x, y)
end
positions.shuffle!
positions.each_with_index do |pos, idx|
list << Tile.new(idx.succ % 16, pos)
end
@tcolor = color(255, 175, 0)
@bcolor = color(235, 231, 178)
@dark = color(206, 141, 0)
@light = color(255, 214, 126)
text_size(DIM / 2.7)
text_align(CENTER)
end
def draw
list.each(&:draw)
end
def mouse_clicked
update
source = inside.pos
if (source.x - target.pos.x).abs == DIM && source.y == target.pos.y
inside.position(target.pos)
target.position(source)
elsif (source.y - target.pos.y).abs == DIM && source.x == target.pos.x
inside.position(target.pos)
target.position(source)
end
end
def update
@inside = list.find { |tile| tile.include?(Vect.new(mouse_x, mouse_y)) }
@target = list.find { |tile| tile.number.zero? }
end
# Lightweight container for position
Vect = Struct.new(:x, :y)
# Our Tile Boundary Class
class Boundary
attr_reader :low, :high
def initialize(low, high)
@low = low
@high = high
end
def include?(val)
return false unless (low.x...high.x).cover? val.x
return false unless (low.y...high.y).cover? val.y
true
end
end
# Holds Tile logic and draw (Processing::Proxy give access to Sketch methods)
class Tile
include Processing::Proxy
attr_reader :boundary, :number, :pos
def initialize(piece_nr, pos)
@number = piece_nr
@pos = pos
@boundary = Boundary.new(pos, Vect.new(pos.x + DIM, pos.y + DIM))
end
def position(pos)
@pos = pos
end
def draw_empty
fill(bcolor)
rect(pos.x + 1, pos.y + 1, DIM - 1, DIM - 1)
end
def draw_tile
rect(pos.x + 1, pos.y + 1, DIM - 1, DIM - 1)
fill(0) # Black text shadow
text(number.to_s, pos.x + DIM / 2 + 1, pos.y + DIM / 2 + text_ascent / 2)
fill(255)
text(number.to_s, pos.x + DIM / 2, pos.y + DIM / 2 + text_ascent / 2)
stroke(dark)
line(pos.x + DIM - 1, pos.y + 1, pos.x + DIM - 1, pos.y + DIM - 2) # Right side shadow
line(pos.x + 2, pos.y + DIM, pos.x + DIM - 1, pos.y + DIM - 2) # Bottom side shadow
stroke(light)
line(pos.x + 2, pos.y - 1, pos.x + 2, pos.y + DIM - 1) # Left bright
line(pos.x + 2, pos.y + 1, pos.x + DIM - 1, pos.y + 1) # Upper bright
end
def include?(vec)
boundary.include?(vec)
end
def draw
no_stroke
return draw_empty if number.zero?
fill(tcolor)
draw_tile
end
end