Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
141
Task/Honeycombs/Haskell/honeycombs.hs
Normal file
141
Task/Honeycombs/Haskell/honeycombs.hs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
import Data.Char (toUpper)
|
||||
import Data.Function (on)
|
||||
import Data.List (zipWith4)
|
||||
import System.Exit
|
||||
import System.Random
|
||||
|
||||
-- External libraries.
|
||||
import Graphics.Gloss
|
||||
import Graphics.Gloss.Data.Vector
|
||||
import Graphics.Gloss.Geometry
|
||||
import Graphics.Gloss.Interface.IO.Game
|
||||
import System.Random.Shuffle
|
||||
|
||||
-- A record of a hexagon-letter.
|
||||
data Hex =
|
||||
Hex
|
||||
{ hLetter :: Char -- The letter it holds.
|
||||
, hSelected :: Bool -- The flag for if the hexagon has been selected.
|
||||
, hPath :: Path -- The hexagon's vertices.
|
||||
, hCenter :: Point -- The center of the hexagon.
|
||||
}
|
||||
|
||||
-- A record of the world state.
|
||||
data World =
|
||||
World
|
||||
{ wHexes :: [Hex] -- The hexagons to interact with.
|
||||
, wString :: String -- An ordering of picked letters.
|
||||
}
|
||||
|
||||
-- Assorted helper functions.
|
||||
addV, subV :: Vector -> Vector -> Vector
|
||||
addV (a, b) (x, y) = (a + x, b + y)
|
||||
subV (a, b) (x, y) = (a - x, b - y)
|
||||
|
||||
translateP :: Vector -> Path -> Path
|
||||
translateP v = map (addV v)
|
||||
|
||||
translateV :: Vector -> Picture -> Picture
|
||||
translateV (x, y) p = translate x y p
|
||||
|
||||
lightblue, darkblue :: Color
|
||||
lightblue = makeColor 0.5 0.5 1.0 1.0
|
||||
darkblue = makeColor 0.0 0.0 0.5 1.0
|
||||
|
||||
-- Create vertices for an n-gon with the given radius to a vertex
|
||||
ngon :: Int -> Float -> Path
|
||||
ngon n radius =
|
||||
let angle = 2 * pi / fromIntegral n
|
||||
in map (mulSV radius . unitVectorAtAngle . (* angle) . fromIntegral)
|
||||
[0..(n - 1)]
|
||||
|
||||
-- Determine if a point lies on or within a polygon.
|
||||
inPolygon :: Point -> Path -> Bool
|
||||
inPolygon point path =
|
||||
all (>= 0) $ zipWith detV vas vbs
|
||||
where
|
||||
vas = zipWith subV (drop 1 $ cycle path) path
|
||||
vbs = map (subV point) path
|
||||
|
||||
-- Construct all of the hexagons transformed to their screen coordinates
|
||||
-- to make mouse picking easier to solve.
|
||||
mkHexes :: RandomGen g => g -> Float -> World
|
||||
mkHexes gen radius = World hexes ""
|
||||
where
|
||||
letters = take 20 $ shuffle' ['A'..'Z'] 26 gen
|
||||
xs = concatMap (replicate 4) [-2..2]
|
||||
ys = cycle [-2..1]
|
||||
inRad = radius * (cos $ degToRad 30)
|
||||
yOff x = if ((floor x) :: Int) `mod` 2 == 0 then inRad else 0
|
||||
yStep = inRad * 2
|
||||
xStep = radius * 1.5
|
||||
centers = zipWith (\x y -> (x * xStep, yOff x + y * yStep)) xs ys
|
||||
paths = map (flip translateP $ ngon 6 radius) centers
|
||||
hexes = zipWith4 Hex letters (repeat False) paths centers
|
||||
|
||||
-- Draw a single hexagon-letter.
|
||||
drawHex :: Hex -> Picture
|
||||
drawHex (Hex letter selected path center) =
|
||||
pictures [hex, outline, letterPic]
|
||||
where
|
||||
hex = color hcolor $ polygon path
|
||||
outline = color blue $ lineLoop path
|
||||
letterPic = color lcolor
|
||||
$ translateV (addV (-10, -10) center)
|
||||
$ scale 0.25 0.25
|
||||
$ text [letter]
|
||||
(hcolor, lcolor) = if selected
|
||||
then (darkblue, white)
|
||||
else (lightblue, black)
|
||||
|
||||
-- Draw the whole scene.
|
||||
drawWorld :: World -> Picture
|
||||
drawWorld (World hexes string) =
|
||||
pictures [pictures $ map drawHex hexes
|
||||
,pictures $ map drawHighHex hexes
|
||||
,color (light lightblue) $ textPic
|
||||
,scale 1.05 1.05 $ textPic]
|
||||
where
|
||||
drawHighHex hex = color black $ scale 1.05 1.05 $ lineLoop $ hPath hex
|
||||
textPic = translateV (-130, -175) $ scale 0.15 0.15 $ text string
|
||||
|
||||
-- Handle keyboard and mouse events and update the hexagons
|
||||
-- accordingly. This function checks the hexagon states and
|
||||
-- invokes a system exit when all are marked selected.
|
||||
handleInput :: Event -> World -> IO World
|
||||
handleInput event world@(World hexes string) =
|
||||
case event of
|
||||
EventKey key Down _ point ->
|
||||
case key of
|
||||
SpecialKey KeyEsc -> exitSuccess
|
||||
Char char -> hCond (\hex -> hLetter hex == toUpper char)
|
||||
MouseButton _ -> hCond (\hex -> inPolygon point $ hPath hex)
|
||||
_ -> return world
|
||||
_ ->
|
||||
return world
|
||||
where
|
||||
checkWorld w = if all hSelected $ wHexes w then exitSuccess else return w
|
||||
hCond cond = checkWorld $ World newHexes newString
|
||||
where
|
||||
newHexes = flip map hexes
|
||||
(\hex -> if cond hex
|
||||
then hex {hSelected = True}
|
||||
else hex)
|
||||
diff = map fst
|
||||
$ filter (uncurry ((/=) `on` hSelected))
|
||||
$ zip hexes newHexes
|
||||
newString = case diff of
|
||||
[] -> string
|
||||
(hex:_) -> string ++ [hLetter hex]
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
stdGen <- getStdGen
|
||||
playIO
|
||||
(InWindow "Honeycombs" (500, 500) (100, 100))
|
||||
white
|
||||
60
|
||||
(mkHexes stdGen 30)
|
||||
(return . drawWorld)
|
||||
handleInput
|
||||
(\_ x -> return x)
|
||||
134
Task/Honeycombs/Java/honeycombs-1.java
Normal file
134
Task/Honeycombs/Java/honeycombs-1.java
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
|
||||
public class Honeycombs extends JFrame {
|
||||
|
||||
HoneycombsPanel panel;
|
||||
|
||||
public static void main(String[] args) {
|
||||
JFrame f = new Honeycombs();
|
||||
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
f.setVisible(true);
|
||||
}
|
||||
|
||||
public Honeycombs() {
|
||||
Container content = getContentPane();
|
||||
content.setLayout(new BorderLayout());
|
||||
panel = new HoneycombsPanel();
|
||||
content.add(panel, BorderLayout.CENTER);
|
||||
setTitle("Honeycombs");
|
||||
setResizable(false);
|
||||
pack();
|
||||
setLocationRelativeTo(null);
|
||||
}
|
||||
}
|
||||
|
||||
class HoneycombsPanel extends JPanel {
|
||||
|
||||
Hexagon[] comb;
|
||||
|
||||
public HoneycombsPanel() {
|
||||
setPreferredSize(new Dimension(600, 500));
|
||||
setBackground(Color.white);
|
||||
setFocusable(true);
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
for (Hexagon hex : comb)
|
||||
if (hex.contains(e.getX(), e.getY())) {
|
||||
hex.setSelected();
|
||||
break;
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
|
||||
addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
for (Hexagon hex : comb)
|
||||
if (hex.letter == Character.toUpperCase(e.getKeyChar())) {
|
||||
hex.setSelected();
|
||||
break;
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
|
||||
char[] letters = "LRDGITPFBVOKANUYCESM".toCharArray();
|
||||
comb = new Hexagon[20];
|
||||
|
||||
int x1 = 150, y1 = 100, x2 = 225, y2 = 143, w = 150, h = 87;
|
||||
for (int i = 0; i < comb.length; i++) {
|
||||
int x, y;
|
||||
if (i < 12) {
|
||||
x = x1 + (i % 3) * w;
|
||||
y = y1 + (i / 3) * h;
|
||||
} else {
|
||||
x = x2 + (i % 2) * w;
|
||||
y = y2 + ((i - 12) / 2) * h;
|
||||
}
|
||||
comb[i] = new Hexagon(x, y, w / 3, letters[i]);
|
||||
}
|
||||
|
||||
requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics gg) {
|
||||
super.paintComponent(gg);
|
||||
Graphics2D g = (Graphics2D) gg;
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
g.setFont(new Font("SansSerif", Font.BOLD, 30));
|
||||
g.setStroke(new BasicStroke(3));
|
||||
|
||||
for (Hexagon hex : comb)
|
||||
hex.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
class Hexagon extends Polygon {
|
||||
final Color baseColor = Color.yellow;
|
||||
final Color selectedColor = Color.magenta;
|
||||
final char letter;
|
||||
|
||||
private boolean hasBeenSelected;
|
||||
|
||||
Hexagon(int x, int y, int halfWidth, char c) {
|
||||
letter = c;
|
||||
for (int i = 0; i < 6; i++)
|
||||
addPoint((int) (x + halfWidth * Math.cos(i * Math.PI / 3)),
|
||||
(int) (y + halfWidth * Math.sin(i * Math.PI / 3)));
|
||||
getBounds();
|
||||
}
|
||||
|
||||
void setSelected() {
|
||||
hasBeenSelected = true;
|
||||
}
|
||||
|
||||
void draw(Graphics2D g) {
|
||||
g.setColor(hasBeenSelected ? selectedColor : baseColor);
|
||||
g.fillPolygon(this);
|
||||
|
||||
g.setColor(Color.black);
|
||||
g.drawPolygon(this);
|
||||
|
||||
g.setColor(hasBeenSelected ? Color.black : Color.red);
|
||||
drawCenteredString(g, String.valueOf(letter));
|
||||
}
|
||||
|
||||
void drawCenteredString(Graphics2D g, String s) {
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
int asc = fm.getAscent();
|
||||
int dec = fm.getDescent();
|
||||
|
||||
int x = bounds.x + (bounds.width - fm.stringWidth(s)) / 2;
|
||||
int y = bounds.y + (asc + (bounds.height - (asc + dec)) / 2);
|
||||
|
||||
g.drawString(s, x, y);
|
||||
}
|
||||
}
|
||||
184
Task/Honeycombs/Java/honeycombs-2.java
Normal file
184
Task/Honeycombs/Java/honeycombs-2.java
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
package graphics;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import static java.util.Arrays.parallelSetAll;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.stream.IntStream.range;
|
||||
|
||||
public class Honeycombs extends JFrame {
|
||||
HoneycombsPanel panel;
|
||||
|
||||
public static void main(String[] args) {
|
||||
JFrame f = new Honeycombs();
|
||||
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
f.setVisible(true);
|
||||
}
|
||||
|
||||
public Honeycombs() {
|
||||
Container content = getContentPane();
|
||||
content.setLayout(new BorderLayout());
|
||||
panel = new HoneycombsPanel();
|
||||
content.add(panel, BorderLayout.CENTER);
|
||||
setTitle("Honeycombs");
|
||||
setResizable(false);
|
||||
pack();
|
||||
setLocationRelativeTo(null);
|
||||
}
|
||||
}
|
||||
|
||||
class HoneycombsPanel extends JPanel {
|
||||
Hexagon[] comb;
|
||||
|
||||
@FunctionalInterface
|
||||
private static interface MousePressed extends MouseListener {
|
||||
public static MousePressed new_(MousePressed mousePressed) {
|
||||
return mousePressed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public default void mouseClicked(MouseEvent mouseEvent) {}
|
||||
|
||||
@Override
|
||||
public default void mouseEntered(MouseEvent mouseEvent) {}
|
||||
|
||||
@Override
|
||||
public default void mouseExited(MouseEvent mouseEvent) {}
|
||||
|
||||
@Override
|
||||
public default void mouseReleased(MouseEvent mouseEvent) {}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private static interface KeyPressed extends KeyListener {
|
||||
public static KeyPressed new_(KeyPressed keyPressed) {
|
||||
return keyPressed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public default void keyReleased(KeyEvent keyEvent) {}
|
||||
|
||||
@Override
|
||||
public default void keyTyped(KeyEvent keyEvent) {}
|
||||
}
|
||||
|
||||
public HoneycombsPanel() {
|
||||
setPreferredSize(new Dimension(600, 500));
|
||||
setBackground(Color.white);
|
||||
setFocusable(true);
|
||||
|
||||
addMouseListener(MousePressed.new_(e -> {
|
||||
stream(comb)
|
||||
.filter(hex -> hex.contains(e.getX(), e.getY()))
|
||||
.findFirst()
|
||||
.ifPresent(hex -> hex.setSelected())
|
||||
;
|
||||
repaint();
|
||||
}));
|
||||
|
||||
addKeyListener(KeyPressed.new_(e -> {
|
||||
stream(comb)
|
||||
.filter(hex -> hex.letter == Character.toUpperCase(e.getKeyChar()))
|
||||
.findFirst()
|
||||
.ifPresent(hex -> hex.setSelected())
|
||||
;
|
||||
repaint();
|
||||
}));
|
||||
|
||||
char[] letters = "LRDGITPFBVOKANUYCESM".toCharArray();
|
||||
comb = new Hexagon[20];
|
||||
|
||||
int x1 = 150, y1 = 100, x2 = 225, y2 = 143, w = 150, h = 87;
|
||||
parallelSetAll(comb, i -> {
|
||||
int x, y;
|
||||
if (i < 12) {
|
||||
x = x1 + (i % 3) * w;
|
||||
y = y1 + (i / 3) * h;
|
||||
} else {
|
||||
x = x2 + (i % 2) * w;
|
||||
y = y2 + ((i - 12) / 2) * h;
|
||||
}
|
||||
return new Hexagon(x, y, w / 3, letters[i]);
|
||||
});
|
||||
|
||||
requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics gg) {
|
||||
super.paintComponent(gg);
|
||||
Graphics2D g = (Graphics2D) gg;
|
||||
g.setRenderingHint(
|
||||
RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON
|
||||
);
|
||||
|
||||
g.setFont(new Font("SansSerif", Font.BOLD, 30));
|
||||
g.setStroke(new BasicStroke(3));
|
||||
|
||||
stream(comb)
|
||||
.forEach(hex -> hex.draw(g))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class Hexagon extends Polygon {
|
||||
final Color baseColor = Color.yellow;
|
||||
final Color selectedColor = Color.magenta;
|
||||
final char letter;
|
||||
|
||||
private boolean hasBeenSelected;
|
||||
|
||||
Hexagon(int x, int y, int halfWidth, char c) {
|
||||
letter = c;
|
||||
range(0, 6)
|
||||
.forEach(i ->
|
||||
addPoint((int) (x + halfWidth * Math.cos(i * Math.PI / 3)),
|
||||
(int) (y + halfWidth * Math.sin(i * Math.PI / 3)))
|
||||
)
|
||||
;
|
||||
getBounds();
|
||||
}
|
||||
|
||||
void setSelected() {
|
||||
hasBeenSelected = true;
|
||||
}
|
||||
|
||||
void draw(Graphics2D g) {
|
||||
g.setColor(hasBeenSelected ? selectedColor : baseColor);
|
||||
g.fillPolygon(this);
|
||||
|
||||
g.setColor(Color.black);
|
||||
g.drawPolygon(this);
|
||||
|
||||
g.setColor(hasBeenSelected ? Color.black : Color.red);
|
||||
drawCenteredString(g, String.valueOf(letter));
|
||||
}
|
||||
|
||||
void drawCenteredString(Graphics2D g, String s) {
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
int asc = fm.getAscent();
|
||||
int dec = fm.getDescent();
|
||||
|
||||
int x = bounds.x + (bounds.width - fm.stringWidth(s)) / 2;
|
||||
int y = bounds.y + (asc + (bounds.height - (asc + dec)) / 2);
|
||||
|
||||
g.drawString(s, x, y);
|
||||
}
|
||||
}
|
||||
57
Task/Honeycombs/MATLAB/honeycombs.m
Normal file
57
Task/Honeycombs/MATLAB/honeycombs.m
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
function Honeycombs
|
||||
nRows = 4; % Number of rows
|
||||
nCols = 5; % Number of columns
|
||||
nHexs = nRows*nCols; % Number of hexagons
|
||||
rOuter = 1; % Circumradius
|
||||
startX = 0; % x-coordinate of upper left hexagon
|
||||
startY = 0; % y-coordinate of upper left hexagon
|
||||
delX = rOuter*1.5; % Horizontal distance between hexagons
|
||||
delY = rOuter*sqrt(3); % Vertical distance between hexagons
|
||||
offY = delY/2; % Vertical offset between columns
|
||||
genHexX = rOuter.*cos(2.*pi.*(0:5).'./6); % x-coords of general hexagon
|
||||
genHexY = rOuter.*sin(2.*pi.*(0:5).'./6); % y-coords of general hexagon
|
||||
centX = zeros(1, nHexs); % x-coords of hexagon centers
|
||||
centY = zeros(1, nHexs); % y-coords of hexagon centers
|
||||
for c = 1:nCols
|
||||
idxs = (c-1)*nRows+1:c*nRows; % Indeces of hexagons in that column
|
||||
if mod(c, 2) % Odd numbered column - higher y-values
|
||||
centY(idxs) = startY:-delY:startY-delY*(nRows-1);
|
||||
else % Even numbered column - lower y-values
|
||||
centY(idxs) = startY-offY:-delY:startY-offY-delY*(nRows-1);
|
||||
end
|
||||
centX(idxs) = (startX+(c-1)*delX).*ones(1, nRows);
|
||||
end
|
||||
[MCentX, MGenHexX] = meshgrid(centX, genHexX);
|
||||
[MCentY, MGenHexY] = meshgrid(centY, genHexY);
|
||||
HexX = MCentX+MGenHexX; % x-coords of hexagon vertices
|
||||
HexY = MCentY+MGenHexY; % y-coords of hexagon vertices
|
||||
figure
|
||||
hold on
|
||||
letters = char([65:90 97:122]);
|
||||
randIdxs = randperm(26);
|
||||
letters = [letters(randIdxs) letters(26+randIdxs)];
|
||||
hexH = zeros(1, nHexs);
|
||||
for k = 1:nHexs % Create patches individually
|
||||
hexH(k) = patch(HexX(:, k), HexY(:, k), [1 1 0]);
|
||||
textH = text(centX(k), centY(k), letters(mod(k, length(letters))), ...
|
||||
'HorizontalAlignment', 'center', 'FontSize', 14, ...
|
||||
'FontWeight', 'bold', 'Color', [1 0 0], 'HitTest', 'off');
|
||||
set(hexH(k), 'UserData', textH) % Save to object for easy access
|
||||
end
|
||||
axis equal
|
||||
axis off
|
||||
set(gca, 'UserData', '') % List of clicked patch labels
|
||||
set(hexH, 'ButtonDownFcn', @onClick)
|
||||
end
|
||||
|
||||
function onClick(obj, event)
|
||||
axesH = get(obj, 'Parent');
|
||||
textH = get(obj, 'UserData');
|
||||
set(obj, 'FaceColor', [1 0 1]) % Change color
|
||||
set(textH, 'Color', [0 0 0]) % Change label color
|
||||
set(obj, 'HitTest', 'off') % Ignore future clicks
|
||||
currList = get(axesH, 'UserData'); % Hexs already clicked
|
||||
newList = [currList get(textH, 'String')]; % Update list
|
||||
set(axesH, 'UserData', newList)
|
||||
title(newList)
|
||||
end
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
Shoes.app(:height => 700, :width => 800) do
|
||||
Shoes.app(title: "Honeycombs", height: 700, width: 700) do
|
||||
C = Math::cos(Math::PI/3)
|
||||
S = Math::sin(Math::PI/3)
|
||||
Radius = 60
|
||||
Radius = 60.0
|
||||
letters = [
|
||||
%w[L A R N D 1 2],
|
||||
%w[G U I Y T 3 4],
|
||||
|
|
@ -11,11 +11,11 @@ Shoes.app(:height => 700, :width => 800) do
|
|||
]
|
||||
|
||||
def highlight(hexagon)
|
||||
hexagon.style(:fill => magenta)
|
||||
hexagon.style(fill: magenta)
|
||||
end
|
||||
|
||||
def unhighlight(hexagon)
|
||||
hexagon.style(:fill => yellow)
|
||||
hexagon.style(fill: yellow)
|
||||
end
|
||||
|
||||
def choose(hexagon)
|
||||
|
|
@ -25,8 +25,8 @@ Shoes.app(:height => 700, :width => 800) do
|
|||
if chosen.size == @hexagons.size
|
||||
@chosen.text = 'Every hexagon has been chosen.'
|
||||
else
|
||||
@chosen.text = "Chosen: #{chosen.sort.join(',')}" +
|
||||
"\nLast Chosen: #{hexagon.letter}"
|
||||
@chosen.text = "Chosen: #{chosen.sort.join(',')}\n" +
|
||||
"Last Chosen: #{hexagon.letter}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -36,23 +36,22 @@ Shoes.app(:height => 700, :width => 800) do
|
|||
letter_to_hex = {}
|
||||
|
||||
# create the GUI
|
||||
stack(:height => height, :width => width) do
|
||||
stack(height: height, width: width) do
|
||||
@chosen = para("Chosen:\nLast chosen:")
|
||||
|
||||
# draw the hexagrams
|
||||
letters.size.times do |row|
|
||||
letters[0].size.times do |column|
|
||||
x = 60 + column * Radius * 0.75 + (1-S)*Radius
|
||||
y = 80 + row * Radius * S + (column.odd? ? S * Radius * 0.5 : 0)
|
||||
letters.each_index do |row|
|
||||
letters[0].each_index do |column|
|
||||
x = 60 + column * Radius * 0.75 + (1-S) * Radius
|
||||
y = 80 + row * S * Radius + (column.odd? ? S * Radius * 0.5 : 0)
|
||||
h = shape(x-Radius, y-S*Radius) do
|
||||
stroke red
|
||||
strokewidth 3
|
||||
move_to(x-C*Radius, y-S*Radius)
|
||||
line_to(x+C*Radius, y-S*Radius)
|
||||
line_to(x+Radius, y)
|
||||
line_to(x+Radius, y)
|
||||
line_to(x+C*Radius, y+S*Radius)
|
||||
line_to(x-C*Radius, y+S*Radius)
|
||||
line_to(x-Radius, y)
|
||||
line_to(x-Radius, y)
|
||||
line_to(x-C*Radius, y-S*Radius)
|
||||
end
|
||||
|
||||
|
|
@ -65,26 +64,26 @@ Shoes.app(:height => 700, :width => 800) do
|
|||
def choose
|
||||
@state = :chosen
|
||||
end
|
||||
def contains?(px,py)
|
||||
def contains?(px, py)
|
||||
if @x-Radius < px and px <= @x-C*Radius
|
||||
ratio = (px - @x + Radius).to_f/(Radius*(1-C))
|
||||
return (@y - ratio*S*Radius < py and py <= @y + ratio*S*Radius)
|
||||
ratio = (px - @x + Radius)/(Radius*(1-C))
|
||||
@y - ratio*S*Radius < py and py <= @y + ratio*S*Radius
|
||||
elsif @x-C*Radius < px and px <= @x+C*Radius
|
||||
return (@y - S*Radius < py and py < @y + S*Radius)
|
||||
@y - S*Radius < py and py < @y + S*Radius
|
||||
elsif @x+C*Radius < px and px <= @x+Radius
|
||||
ratio = (@x + Radius - px).to_f/(Radius*(1-C))
|
||||
return (@y - ratio*S*Radius < py and py <= @y + ratio*S*Radius)
|
||||
ratio = (@x + Radius - px)/(Radius*(1-C))
|
||||
@y - ratio*S*Radius < py and py <= @y + ratio*S*Radius
|
||||
else
|
||||
return false
|
||||
false
|
||||
end
|
||||
end
|
||||
def inspect
|
||||
'<%s,"%s",%s,%d@%d>' % [self.class, letter, chosen?, x, y]
|
||||
%q(<%s,"%s",%s,%d@%d>) % [self.class, letter, chosen?, x, y]
|
||||
end
|
||||
end
|
||||
|
||||
h.x = x + x-Radius
|
||||
h.y = y + y-S*Radius
|
||||
h.x = x + x - Radius
|
||||
h.y = y + y - S*Radius
|
||||
h.letter = letters[row][column]
|
||||
unhighlight h
|
||||
|
||||
|
|
@ -93,30 +92,29 @@ Shoes.app(:height => 700, :width => 800) do
|
|||
letter_to_hex[h.letter.upcase] = h
|
||||
|
||||
# add the letter to the hexagon
|
||||
para(h.letter) \
|
||||
.style(:size => 56, :stroke => red) \
|
||||
.move(h.x - C*Radius, h.y - S*Radius)
|
||||
para(h.letter).style(size:56, stroke:red) \
|
||||
.move(h.x - C*Radius, h.y - S*Radius)
|
||||
end
|
||||
end
|
||||
|
||||
# highlight the hexagon under the mouse
|
||||
@hex_over = nil
|
||||
hex_over = nil
|
||||
motion do |x, y|
|
||||
hex = @hexagons.find {|h| h.contains?(x,y)}
|
||||
unless hex.nil? or hex.chosen?
|
||||
highlight hex
|
||||
end
|
||||
unless @hex_over == hex or @hex_over.nil? or @hex_over.chosen?
|
||||
unhighlight @hex_over
|
||||
unless hex_over == hex or hex_over.nil? or hex_over.chosen?
|
||||
unhighlight hex_over
|
||||
end
|
||||
@hex_over = hex
|
||||
hex_over = hex
|
||||
end
|
||||
|
||||
# handle mouse clicks
|
||||
click do |button, x, y|
|
||||
info("button #{button} clicked at (#{x}, #{y})")
|
||||
hexagon = @hexagons.find {|h| h.contains?(x,y)}
|
||||
unless hexagon.nil?
|
||||
if hexagon
|
||||
info("clicked hexagon #{hexagon}")
|
||||
choose hexagon
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue