Task: Honeycombs




Go: package main

import (
    rl "github.com/gen2brain/raylib-go/raylib"
    "math"
    "strings"
)

type hexagon struct {
    x, y     float32
    letter   rune
    selected bool
}

func (h hexagon) points(r float32) []rl.Vector2 {
    res := make([]rl.Vector2, 7)
    for i := 0; i < 7; i++ {
        fi := float64(i)
        res[i].X = h.x + r*float32(math.Cos(math.Pi*fi/3))
        res[i].Y = h.y + r*float32(math.Sin(math.Pi*fi/3))
    }
    return res
}

func inHexagon(pts []rl.Vector2, pt rl.Vector2) bool {
    rec := rl.NewRectangle(pts[4].X, pts[4].Y, pts[5].X-pts[4].X, pts[2].Y-pts[4].Y)
    if rl.CheckCollisionPointRec(pt, rec) {
        return true
    }
    if rl.CheckCollisionPointTriangle(pt, pts[2], pts[3], pts[4]) {
        return true
    }
    if rl.CheckCollisionPointTriangle(pt, pts[0], pts[1], pts[5]) {
        return true
    }
    return false
}

func DrawLineStrip(points []rl.Vector2, pointsCount int32, color rl.Color) {
    for i := int32(0);  i < pointsCount - 1; i++  {
         rl.DrawLineV(points[i], points[i+1], color)
    }
}

func main() {
    screenWidth := int32(600)
    screenHeight := int32(600)
    rl.InitWindow(screenWidth, screenHeight, "Honeycombs")
    rl.SetTargetFPS(60)

    letters := "LRDGITPFBVOKANUYCESM"
    runes := []rune(letters)
    var combs [20]hexagon
    var pts [20][]rl.Vector2

    x1, y1 := 150, 100
    x2, y2 := 225, 143
    w, h := 150, 87
    r := float32(w / 3)
    for i := 0; i < 20; i++ {
        var x, y int
        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
        }
        combs[i] = hexagon{float32(x), float32(y), runes[i], false}
        pts[i] = combs[i].points(r)
    }

    nChosen := 0
    sChosen := "Chosen: "
    lChosen := "Last chosen: "

    for !rl.WindowShouldClose() {
        rl.BeginDrawing()
        rl.ClearBackground(rl.RayWhite)
        for i, c := range combs {
            ctr := pts[i][0]
            ctr.X -= r
            index := -1
            if key := rl.GetKeyPressed(); key > 0 {
                if key >= 97 && key <= 122 {
                    key -= 32
                }
                index = strings.IndexRune(letters, key)
            } else if rl.IsMouseButtonPressed(rl.MouseLeftButton) {
                pt := rl.Vector2{float32(rl.GetMouseX()), float32(rl.GetMouseY())}
                for i := 0; i < 20; i++ {
                    if inHexagon(pts[i], pt) {
                        index = i
                        break
                    }
                }
            }
            if index >= 0 {
                if !combs[index].selected {
                    combs[index].selected = true
                    nChosen++
                    s := string(combs[index].letter)
                    sChosen += s
                    lChosen = "Last chosen: " + s
                    if nChosen == 20 {
                        lChosen += " (All 20 Chosen!)"
                    }
                }
            }
            if !c.selected {
                rl.DrawPoly(ctr, 6, r-1, 30, rl.Yellow)
            } else {
                rl.DrawPoly(ctr, 6, r-1, 30, rl.Magenta)
            }
            rl.DrawText(string(c.letter), int32(c.x)-5, int32(c.y)-10, 32, rl.Black)
            DrawLineStrip(pts[i], 7, rl.Black)
            rl.DrawText(sChosen, 100, 525, 24, rl.Black)
            rl.DrawText(lChosen, 100, 565, 24, rl.Black)
        }
        rl.EndDrawing()
    }

    rl.CloseWindow()
}


Java: import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Honeycombs extends JFrame {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new Honeycombs();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setVisible(true);
        });
    }

    public Honeycombs() {
        add(new HoneycombsPanel(), 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);
    }
}