require('Tk') class Honeycombs( Number size = 36, Array letters = @('A' .. 'Z').shuffle.first(20), ) { define tk = %S has changed = Hash() func altitude(n) { sqrt(3/4) * n } method polygon_coordinates(x, y, size) { var alt = altitude(size) return (x - size, y, x - size/2, y - alt, x + size/2, y - alt, x + size, y, x + size/2, y + alt, x - size/2, y + alt, ); } method change(canvas, id, letter_id) { return { canvas.itemconfigure(id, '-fill' => 'magenta') canvas.itemconfigure(letter_id, '-fill' => 'black') changed{id} = true if (20 == changed.len) { say "All letters pressed." canvas.MainWindow.after(10, { tk.exit }) } } } method comb(canvas, fromx, fromy, size, count) { for x,y in ( RangeNum(fromx, 3*count*size - 1, 3*size) ~X RangeNum(fromy, 7.5*size - 1, 2*altitude(size)) ) { var id = canvas.createPolygon( self.polygon_coordinates(x, y, size), '-outline' => 'black', '-fill' => 'yellow', '-width' => 2, ) var letter = letters.shift var letter_id = canvas.createText(x, y, '-fill' => 'red', '-text' => letter, '-font' => "{sans} #{size * 0.9}", ) canvas.MainWindow.bind('all', letter.lc, self.change(canvas, id, letter_id)) [id, letter_id].each { |b| canvas.bind(b, '', self.change(canvas, id, letter_id)) } } } method display(title) { { var mw = %s'MainWindow'.new('-title' => title) var canvas = mw.Canvas('-width' => 8*size, '-height' => 8*size).pack self.comb(canvas, size, size, size, 3) self.comb(canvas, size * 2.5, size + altitude(size), size, 2) var btn = mw.Button('-text' => 'Quit', '-underline' => 0, '-command' => { tk.exit }, ).pack mw.bind('', { btn.invoke }) tk.MainLoop() }.fork } } Honeycombs().display(title: 'Honeycombs')