Honeycombs: Difference between revisions

50,689 bytes added ,  5 months ago
m
→‎{{header|Wren}}: Changed to Wren S/H
(Added Sidef)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(35 intermediate revisions by 14 users not shown)
Line 14:
 
Honeycomb class:
<syntaxhighlight lang="actionscript3">
<lang ActionScript3>
package {
Line 229:
 
}
</syntaxhighlight>
</lang>
 
Document (main) class:
<syntaxhighlight lang="actionscript3">
<lang ActionScript3>
package {
Line 399:
 
}
</syntaxhighlight>
</lang>
 
=={{header|Ada}}==
{{libheader|SDLAda}}
<syntaxhighlight lang="ada">with Ada.Numerics.Elementary_Functions;
with Ada.Numerics.Discrete_Random;
 
with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Video.Surfaces;
with SDL.Video.Rectangles;
with SDL.TTFs.Makers;
with SDL.Events.Events;
with SDL.Events.Keyboards;
with SDL.Events.Mice;
 
procedure Honeycombs is
use SDL.Video.Rectangles;
use SDL.C;
 
Width : constant := 560;
Height : constant := 595;
Offset_X : constant := 10.0;
Offset_Y : constant := 40.0;
Radius : constant := 60.0;
Rows : constant := 4;
Cols : constant := 5;
TTF_File : constant String := "NotoSans-Bold.ttf";
TTF_Size_Cell : constant := 72;
TTF_Size_Sum : constant := 38;
Offset_Sum_X : constant := 35;
Offset_Sum_Y : constant := 530;
 
type Node_Id is mod 6;
type Shape_List is array (Node_Id) of Point;
 
type Cell_Info is record
Center : Point;
Marked : Boolean;
Label : String (1 .. 1);
end record;
type Cell_List is array (Positive range <>) of Cell_Info;
 
function Make_Shape return Shape_List is
use Ada.Numerics.Elementary_Functions;
Shape : Shape_List;
begin
for I in Shape'Range loop
Shape (I) := (X => int (Radius * Cos (Float (I), Cycle => 6.0)),
Y => int (Radius * Sin (Float (I), Cycle => 6.0)));
end loop;
return Shape;
end Make_Shape;
 
function Make_Cells (Rows, Cols : in Positive) return Cell_List is
subtype Label_Type is Character range 'A' .. 'Z';
package Randoms is new Ada.Numerics.Discrete_Random (Label_Type);
use Randoms;
Y_Scale : constant Float := Ada.Numerics.Elementary_Functions.Sqrt (3.0);
List : Cell_List (1 .. Rows * Cols);
Info : Cell_Info;
Gen : Generator;
begin
Reset (Gen);
for R in 1 .. Rows loop
for C in 1 .. Cols loop
Info.Center.X := int (Offset_X + Radius * 1.5 * Float (C));
Info.Center.Y := int (Offset_Y + Radius * Y_Scale * (Float (R) -
Float (C mod 2) / 2.0));
Info.Marked := False;
Info.Label (1) := Random (Gen);
List ((R - 1) * Cols + C) := Info;
end loop;
end loop;
return List;
end Make_Cells;
 
Window : SDL.Video.Windows.Window;
Win_Surf : SDL.Video.Surfaces.Surface;
Renderer : SDL.Video.Renderers.Renderer;
Font_Cell : SDL.TTFs.Fonts;
Font_Sum : SDL.TTFs.Fonts;
 
Cells : Cell_List := Make_Cells (Rows, Cols);
Shape : constant Shape_List := Make_Shape;
Sum_Text : String (1 .. Rows * Cols);
Sum_Last : Natural := Sum_Text'First - 1;
 
function Orient_2D (A, B, C : Point) return int is
((B.X - A.X) * (C.Y - A.Y) - (B.Y - A.Y) * (C.X - A.X));
 
function "+" (Left, Right : Point) return Point is
((Left.X + Right.X, Left.Y + Right.Y));
 
function Inside (P : Point; Cell : Cell_Info) return Boolean is
Count : Natural := 0;
begin
for Node in Shape'Range loop
Count := Count +
(if Orient_2D (Cell.Center + Shape (Node),
Cell.Center + Shape (Node + 1),
P) > 0 then 1 else 0);
end loop;
return Count = 6;
end Inside;
 
procedure Draw (Cell : Cell_Info) is
Surface : constant SDL.Video.Surfaces.Surface :=
Font_Cell.Render_Solid (Cell.Label, (30, 230, 230, 255));
Self_Area : SDL.Video.Rectangles.Rectangle;
Source_Area : SDL.Video.Rectangles.Rectangle := (0, 0, 0, 0);
begin
-- Fill
for Y in int (-Radius) .. int (Radius) loop
for X in int (-Radius) .. int (Radius) loop
if Inside (Cell.Center + (X, Y), Cell) then
Renderer.Draw (Point => Cell.Center + (X, Y));
end if;
end loop;
end loop;
 
-- Label
Self_Area := (Cell.Center.X - Surface.Size.Width / 2,
Cell.Center.Y - Surface.Size.Height / 2, 0, 0);
Win_Surf.Blit (Self_Area, Surface, Source_Area);
 
-- Outline
Renderer.Set_Draw_Colour ((0, 0, 0, 255));
for Id in Shape'Range loop
Renderer.Draw (Line => (Cell.Center + Shape (Id),
Cell.Center + Shape (Id + 1)));
end loop;
end Draw;
 
procedure Find_And_Mark (Click : Point; Key : String) is
Self_Area : SDL.Video.Rectangles.Rectangle;
Source_Area : SDL.Video.Rectangles.Rectangle := (0, 0, 0, 0);
begin
for Cell of Cells loop
if not Cell.Marked and then (Inside (Click, Cell) or Cell.Label = Key) then
Cell.Marked := True;
Sum_Last := Sum_Last + 1;
Sum_Text (Sum_Last) := Cell.Label (1);
Renderer.Set_Draw_Colour ((230, 20, 220, 255));
Draw (Cell);
 
-- Update sum text
Self_Area := (Offset_Sum_X, Offset_Sum_Y, 0, 0);
Win_Surf.Blit
(Self_Area, Font_Sum.Render_Solid (Sum_Text (Sum_Text'First .. Sum_Last),
(0, 200, 200, 255)), Source_Area);
Window.Update_Surface;
exit;
end if;
end loop;
end Find_And_Mark;
 
procedure Wait is
use type SDL.Events.Event_Types;
use SDL.Events.Keyboards;
Event : SDL.Events.Events.Events;
begin
loop
SDL.Events.Events.Wait (Event);
case Event.Common.Event_Type is
when SDL.Events.Quit => return;
when SDL.Events.Mice.Button_Down =>
Find_And_Mark
((Event.Mouse_Button.X,
Event.Mouse_Button.Y), "");
when SDL.Events.Keyboards.Key_Down =>
Find_And_Mark
((0, 0), Image (Event.Keyboard.Key_Sym.Key_Code));
null;
when others => null;
end case;
end loop;
end Wait;
 
begin
if not SDL.Initialise (Flags => SDL.Enable_Screen) then
return;
end if;
if not SDL.TTFs.Initialise then
null;
end if;
SDL.TTFs.Makers.Create (Font_Cell, TTF_File, TTF_Size_Cell);
SDL.TTFs.Makers.Create (Font_Sum, TTF_File, TTF_Size_Sum);
 
SDL.Video.Windows.Makers.Create (Win => Window,
Title => "Honeycombs",
Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
Size => SDL.Positive_Sizes'(Width, Height),
Flags => 0);
Win_Surf := Window.Get_Surface;
SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
Renderer.Set_Draw_Colour ((0, 0, 0, 255));
Renderer.Fill (Rectangle => (0, 0, Width, Height));
 
for Cell of Cells loop
Renderer.Set_Draw_Colour ((230, 230, 0, 255));
Draw (Cell);
end loop;
Window.Update_Surface;
 
Wait;
Window.Finalize;
SDL.Finalise;
end Honeycombs;</syntaxhighlight>
=={{header|AutoHotkey}}==
Requires [https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6517&start=320 Gdip Library]
<syntaxhighlight lang="autohotkey">Columns := 5 ; cater for a different number of columns
hexPerCol := 4 ; cater for a different number of hexagons
size := 40
 
w := sqrt(3) * size
h := 2 * size
Coord := [], Chosen := [], Seq:= ""
Letters := StrSplit("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
x := A_ScreenWidth/2 - w*(Columns/2) + w/2
y := A_ScreenHeight/2 - h*(hexPerCol/2) + h/2
x1:= x, y1:=y
 
Gdip()
; Draw High Columns
loop % Ceil(Columns/2)
{
col := A_Index
loop % hexPerCol
{
Random, rnd, 1, % Letters.count()
letter := Letters.RemoveAt(rnd)
Draw_Hexagon(x,y,size,Letter)
y += sqrt(3) * size
}
x:=x1, y:=y1
x+= col*3*size
}
 
; Draw Low Columns
x:= x1, y:=y1
x+= size*1.5, y += sqrt(3) * size/2
loop % Floor(Columns/2)
{
col := A_Index
loop % hexPerCol
{
Random, rnd, 1, % Letters.count()
letter := Letters.RemoveAt(rnd)
Draw_Hexagon(x,y,size,Letter)
y += sqrt(3) * size
}
x:=x1, y:=y1
x+= size*1.5, y += sqrt(3) * size/2
x+= col*3*size
}
OnExit, Exit
Return
;---------------------------------------------------------------
~LButton::
CoordMode, Mouse, Screen
MouseGetPos, mx, my, mc, mw
if (mc <> hwnd1)
return
minD := []
for L, c in coord
{
x := c.x
y := c.y
D := Sqrt((x-mx)**2 + (y-my)**2)
minD[D] := L
min := A_Index = 1 ? D : min < D ? min : D
}
thisLetter := minD[min]
gosub SelectHex
return;
;---------------------------------------------------------------
KeyPress:
thisLetter := A_ThisHotkey
gosub, SelectHex
return
;---------------------------------------------------------------
SelectHex:
if Chosen[thisLetter]
return
Chosen[thisLetter] := true ; record of chosen letters
Seq .= thisLetter ; record of the chosen letters in order chosed
pBrush := Gdip_BrushCreateSolid(0xFFFF00FF)
x := coord[thisLetter, "x"]
y := coord[thisLetter, "y"]
Draw_Hexagon(x,y,size,thisLetter, "FF000000")
Progress, % "m2 b fs16 zh0 y0 w400 x" A_ScreenWidth/2-200, % Seq,,, Courier New
if (Chosen.Count() = Columns * hexPerCol)
ExitApp
return
;---------------------------------------------------------------
Draw_Hexagon(x,y,size,Letter,TextColor:="FFFF0000"){
global
deg2rad := 3.141592653589793/180
a := x + Size "," y
b := x+ Size*Cos(60*deg2rad) "," y + Size*Sin(60*deg2rad)
c := x+ Size*Cos(120*deg2rad) "," y + Size*Sin(120*deg2rad)
d := x - Size "," y
e := x+ Size*Cos(240*deg2rad) "," y + Size*Sin(240*deg2rad)
f := x+ Size*Cos(300*deg2rad) "," y + Size*Sin(300*deg2rad)
Gdip_FillPolygon(G, pBrush, a "|" b "|" c "|" d "|" e "|" f)
Gdip_DrawLines(G, pPen, a "|" b "|" c "|" d "|" e "|" f "|" a)
Font := "Arial", Gdip_FontFamilyCreate(Font)
Options := "x" x-size/2 " y" y-size/2 "c" TextColor " Bold s" size
Gdip_TextToGraphics(G, Letter, Options, Font)
UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height)
Hotkey, % letter, KeyPress
Coord[letter, "x"] := x
Coord[letter, "y"] := y
}
;---------------------------------------------------------------
gdip(){
global
Gdip_Startup()
Width := A_ScreenWidth, Height := A_ScreenHeight
Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop
Gui, 1: Show, NA
hwnd1 := WinExist()
hbm := CreateDIBSection(Width, Height)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetSmoothingMode(G, 4)
pBrush := Gdip_BrushCreateSolid(0xFFFFFF00)
pPen := Gdip_CreatePen(0xFF000000, 3)
}
;---------------------------------------------------------------
Exit:
Gdip_DeleteBrush(pBrush)
Gdip_DeletePen(pPen)
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
ExitApp
Return
;---------------------------------------------------------------</syntaxhighlight>
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> ALTERNATE = 1
VDU 23,22,252;252;8,16,16,128
*FONT Arial,24,B
Line 487 ⟶ 827:
SYS "TextOut", @memhdc%, x%-size.dx%/2, y%-size.dy%/2, text$, LEN(text$)
SYS "CreatePolygonRgn", ^pt%(0,0), 6, ALTERNATE TO hrgn%
= hrgn%</langsyntaxhighlight>
[[File:honeycombs_bbc.gif]]
 
=={{header|C}}==
 
<syntaxhighlight lang="c">
<lang C>
 
/* Program for gtk3 */
Line 762 ⟶ 1,102:
return EXIT_SUCCESS;
}
</syntaxhighlight>
</lang>
 
=={{header|C sharp}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 962 ⟶ 1,302:
}
}
}</langsyntaxhighlight>
XAML:
<langsyntaxhighlight lang="xml"><Window x:Class="Honeycombs.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Line 976 ⟶ 1,316:
<Canvas x:Name="HoneycombCanvas" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Window></langsyntaxhighlight>
[[File:CSharpHoneycomb.jpg]]
 
 
 
=={{header|C++}}==
{{libheader|Qt}}
<syntaxhighlight lang="cpp">//
// honeycombwidget.h
//
#ifndef HONEYCOMBWIDGET_H
#define HONEYCOMBWIDGET_H
 
#include <QWidget>
#include <vector>
 
class HoneycombWidget : public QWidget {
Q_OBJECT
public:
HoneycombWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
private:
struct Cell {
Cell(const QPolygon& p, int l, char ch)
: polygon(p), letter(l), character(ch), selected(false) {}
QPolygon polygon;
int letter;
char character;
bool selected;
};
std::vector<Cell> cells;
};
 
#endif // HONEYCOMBWIDGET_H</syntaxhighlight>
<syntaxhighlight lang="cpp">//
// honeycombwidget.cpp
//
#include "honeycombwidget.h"
#include <QtWidgets>
#include <algorithm>
#include <cmath>
#include <numeric>
#include <random>
 
HoneycombWidget::HoneycombWidget(QWidget *parent)
: QWidget(parent) {
setWindowTitle(tr("Honeycombs"));
 
const int rows = 4;
const int columns = 5;
const int margin = 15;
const int cellWidth = 90;
 
std::random_device dev;
std::mt19937 engine(dev());
char letters[26];
std::iota(std::begin(letters), std::end(letters), 0);
std::shuffle(std::begin(letters), std::end(letters), engine);
 
const double pi = 3.14159265358979323846264338327950288;
double x = cellWidth * std::sin(pi/6), y = cellWidth * std::cos(pi/6);
double cx = margin + cellWidth/2;
int i = 0;
for (int column = 0; column < columns; ++column) {
double cy = margin + y/2;
if (column % 2 == 1)
cy += y/2;
for (int row = 0; row < rows; ++row) {
QPolygon polygon(7);
polygon.setPoint(0, cx + x/2, cy - y/2);
polygon.setPoint(1, cx + cellWidth/2, cy);
polygon.setPoint(2, cx + x/2, cy + y/2);
polygon.setPoint(3, cx - x/2, cy + y/2);
polygon.setPoint(4, cx - cellWidth/2, cy);
polygon.setPoint(5, cx - x/2, cy - y/2);
polygon.setPoint(6, cx + x/2, cy - y/2);
int c = letters[i++];
cells.push_back(Cell(polygon, Qt::Key_A + c, 'A' + c));
cy += y;
}
cx += (x + cellWidth)/2;
}
int totalHeight = margin * 2 + y/2 + rows * y;
int totalWidth = margin * 2 + cellWidth + (columns-1) * (x + cellWidth)/2;
resize(totalWidth, totalHeight);
}
 
void HoneycombWidget::paintEvent(QPaintEvent *event) {
const QColor backgroundColor(255, 255, 255);
const QColor borderColor(0, 0, 0);
const QColor cellColor(255, 255, 0);
const QColor textColor(255, 0, 0);
const QColor selectedCellColor(255, 0, 255);
const QColor selectedTextColor(0, 0, 0);
 
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.fillRect(event->rect(), backgroundColor);
QFont font("Helvetica");
font.setPixelSize(40);
painter.setFont(font);
for (const Cell& cell : cells) {
QPainterPath path;
path.addPolygon(cell.polygon);
QPen pen(borderColor, 3);
painter.setPen(pen);
painter.setBrush(cell.selected ? selectedCellColor : cellColor);
painter.drawPath(path);
painter.setPen(cell.selected ? selectedTextColor : textColor);
painter.drawText(cell.polygon.boundingRect(),
Qt::AlignCenter, QString(cell.character));
}
}
 
void HoneycombWidget::mouseReleaseEvent(QMouseEvent *event) {
QPoint point = event->pos();
auto cell = std::find_if(cells.begin(), cells.end(),
[point](const Cell& c) {
return c.polygon.containsPoint(point, Qt::OddEvenFill);
});
if (cell != cells.end() && !cell->selected) {
cell->selected = true;
update(cell->polygon.boundingRect());
}
}
 
void HoneycombWidget::keyPressEvent(QKeyEvent *event) {
int key = event->key();
auto cell = std::find_if(cells.begin(), cells.end(),
[key](const Cell& c) { return c.letter == key; });
if (cell != cells.end() && !cell->selected) {
cell->selected = true;
update(cell->polygon.boundingRect());
}
}</syntaxhighlight>
<syntaxhighlight lang="cpp">//
// main.cpp
//
#include <QApplication>
#include "honeycombwidget.h"
 
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
HoneycombWidget w;
w.show();
return a.exec();
}</syntaxhighlight>
 
{{out}}
[[Media:Honeycombs_qt.png]]
 
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
[[File:DelphiHoneycomb.png|frame|none]]
 
You can click on any hexagon in the honeycomb and it will be highlighted purple.
 
<syntaxhighlight lang="Delphi">
 
 
{Structure containing information for one hexagon}
 
type THexagon = record
Points: array [0..6-1] of TPoint;
Center: TPoint;
Letter: Char;
Selected: boolean;
end;
 
{Array of hexagons}
 
var Hexagons: array of array of THexagon;
 
 
function PointInPolygon(Point: TPoint; const Polygon: array of TPoint): Boolean;
{Test if point is in the polygon}
var Rgn: HRGN;
begin
Rgn := CreatePolygonRgn(Polygon[0], Length(Polygon), WINDING);
Result := PtInRegion(rgn, Point.X, Point.Y);
DeleteObject(rgn);
end;
 
 
function HitTest(X,Y: integer; var Col,Row: integer): boolean;
{Find hexagon that X,Y may be in}
{Return a hexagon found, Hexagon is in specified by Col, Row}
var C,R: integer;
begin
Result:=True;
for R:=0 to High(Hexagons[0]) do
for C:=0 to High(Hexagons) do
if PointInPolygon(Point(X,Y),Hexagons[C,R].Points) then
begin
Col:=C; Row:=R;
exit;
end;
Result:=False;
end;
 
 
 
procedure BuildHoneyComb(Pos: TPoint; Radius: integer);
{Build honeycombo from hexagons}
var XStep,YStep: integer;
var Off: TPoint;
var Col,Row: integer;
var Cnt: integer;
 
procedure SetHexagon(var Hex: THexagon; Pos: TPoint);
{Set the points for one hexagon}
begin
Hex.Center:=Pos;
Hex.Points[0]:=Point(Pos.X-Radius,Pos.Y);
Hex.Points[1]:=Point(Pos.X-XStep,Pos.Y-YStep);
Hex.Points[2]:=Point(Pos.X+XStep,Pos.Y-YStep);
Hex.Points[3]:=Point(Pos.X+Radius,Pos.Y);
Hex.Points[4]:=Point(Pos.X+XStep,Pos.Y+YStep);
Hex.Points[5]:=Point(Pos.X-XStep,Pos.Y+YStep);
{Assign one char to hexagon, A..Z in order created}
Hex.Letter:=Char(Cnt+$41);
{Deselect hexagon}
Hex.Selected:=False;
Inc(Cnt);
end;
 
procedure RandomizeChars;
{Randomize the characters}
var X1,Y1,X2,Y2: integer;
var C: char;
begin
for X1:=0 to High(Hexagons) do
for Y1:=0 to High(Hexagons[0]) do
begin
X2:=Random(Length(Hexagons));
Y2:=Random(Length(Hexagons[0]));
C:=Hexagons[X1,Y1].Letter;
Hexagons[X1,Y1].Letter:=Hexagons[X2,Y2].Letter;
Hexagons[X2,Y2].Letter:=C;
end;
end;
 
 
begin
Cnt:=0;
{Set number of hexagons in honey comb}
SetLength(Hexagons,5,4);
{Values to set the corners of the hexagon}
XStep:=Round(Radius / 2);
YStep:=Round(Radius * 0.866025403784438646);
for Col:=0 to High(Hexagons) do
for Row:=0 to High(Hexagons[0]) do
begin
{Calculate the position of hexagon in honeycomb}
Off.X:=Pos.X+(Radius+XStep) * Col;
Off.Y:=Pos.Y+YStep*Row*2;
if (Col and 1)=1 then Off.Y:=Off.Y + YStep;
{Set hexagon in honeycomb}
SetHexagon(Hexagons[Col,Row],Off);
end;
RandomizeChars;
end;
 
 
procedure DrawHoneyComb(Canvas: TCanvas);
{Draw polygons describing honeycomb}
var Col,Row: integer;
var Hex: THexagon;
var FS: TSize;
begin
Canvas.Pen.Width:=4;
Canvas.Font.Size:=20;
Canvas.Font.Style:=[fsBold];
Canvas.Font.Name:='Arial';
FS:=Canvas.TextExtent('M');
for Col:=0 to High(Hexagons) do
for Row:=0 to High(Hexagons[0]) do
begin
Hex:=Hexagons[Col,Row];
if Hex.Selected then Canvas.Brush.Color:=clFuchsia
else Canvas.Brush.Color:=clYellow;
Canvas.Polygon(Hex.Points);
Canvas.TextOut(Hex.Center.X-FS.CX div 2,Hex.Center.Y-FS.CY div 2,Hex.Letter);
end;
end;
 
 
 
procedure ShowHoneycomb(Image: TImage);
var MW: TMouseWaiter;
var MI: TMouseData;
var Row,Col: integer;
begin
MW:=TMouseWaiter.Create(TWinControl(Image));
Image.Canvas.Pen.Width:=3;
BuildHoneyComb(Point(140,90),40);
DrawHoneyComb(Image.Canvas);
Image.Canvas.Brush.Color:=clWhite;
Image.Canvas.TextOut(10,10,'Click outside honeycomb to terminate');
Image.Invalidate;
while true do
begin
MI:=MW.WaitForMouse;
if HitTest(MI.X,MI.Y,Col,Row) then
begin
Hexagons[Col,Row].Selected:=True;
DrawHoneyComb(Image.Canvas);
Image.Invalidate;
end
else break;
if Application.Terminated then break;
end;
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
 
</pre>
 
=={{header|Go}}==
{{libheader|raylib-go}}
<syntaxhighlight lang="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()
}</syntaxhighlight>
 
=={{header|Haskell}}==
{{libheader|gloss}}
{{libheader|random-shuffle}}
<langsyntaxhighlight Haskelllang="haskell">import Data.Char (toUpper)
import Data.Function (on)
import Data.List (zipWith4)
Line 1,122 ⟶ 1,912:
(return . drawWorld)
handleInput
(\_ x -> return x)</langsyntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
Line 1,133 ⟶ 1,923:
 
Label selection is straight forward. Mouse selection first determines if x,y is within the widgets rectangular outer bounds. The x,y point is then reflected into the north west quadrant of the cell and the helper data is used to calculate an abbreviated cross-product (x and y will always be 0). The direction of the resultant z indicates if the point is inside or outside of the widgets inner bounds.
<langsyntaxhighlight Iconlang="icon">link printf
 
procedure main(A)
Line 1,240 ⟶ 2,030:
return W
}
end</langsyntaxhighlight>
 
{{libheader|Icon Programming Library}}
[http://www.cs.arizona.edu/icon/library/src/procs/printf.icn printf.icn provides formatting]
 
=={{header|J}}==
 
<syntaxhighlight lang="j">require'ide/qt/gl2'
coinsert'jgl2'
 
NB. corners of a unit hexagon
ucorn=: +.^j.2p1*(%~i.)6
 
NB. center to center offset for columns and rows
uof=: %:2.3 3
 
shape=: 4 5
scale=: 50
scorn=: scale*ucorn
centers=: scale*(((%:0 0.75)*/~2|{:"1)+uof*"1 1:+|."1)shape#:i.shape
 
honeycomb=: {{)n
pc honeycomb nosize closeok;
minwh 460 460;
cc hex isidraw flush;
pshow;
}}{{
sel=: 0"0 grid=: shape$u:65+(*/shape)?26
txt=:''
wd m
draw y
}}
 
draw=: {{
glfill 0 0 0 255
hex"0 i.$grid
gltextcolor glrgb 0 0 255
glfont 'courier 24'
gltextxy 60 10
glpaint gltext txt
}}
 
hex=: {{
coord=. <shape#:y
center=. coord{centers
glbrush glrgb (-coord{sel)|.255 255 0
glrgb 255 255 255
glpen 3,PS_SOLID
glpolygon,<.center+"1 scorn
gltextcolor glrgb 255 0 0
glfont 'courier 24 bold'
gltextxy <.center-10
gltext coord{grid
}}
 
select_character=: {{
if. -. y{,sel do. NB. the selected character has been determined
txt=:txt, y{,grid
end.
draw sel=: 1 (y"_)} sel
}}
 
honeycomb_hex_char=: {{
ch=. toupper {.sysdata
if. ch e. ,grid do. select_character (,grid)i.ch end.
}}
 
honeycomb_hex_mbldown=:{{
xy=. 2{.".sysdata
k=. (i.<./)dist=.,+/&.:*:"1 centers-"1 xy
if. scale > k{dist do.select_character k end.
}}
 
honeycomb''</syntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
Line 1,376 ⟶ 2,236:
g.drawString(s, x, y);
}
}</langsyntaxhighlight>
 
=={{header|Julia}}==
Uses Cairo and Gtk for graphics. Tasks done include the optional one of recording and then displaying letters as chosen with mouse or keyboard on exit once all letters are chosen.
<syntaxhighlight lang="julia">using Gtk.ShortNames, GtkReactive, Graphics, Cairo, Colors, Random
 
mutable struct Hexagon
center::Point
radius::Int
letter::String
color::Colorant
end
 
const offset = 50
const hgt = 450
const wid = 400
const hcombdim = (rows = 5, cols = 4)
const randletters = reshape(string.(Char.(shuffle(UInt8('A'):UInt8('Z'))))[1:20], Tuple(hcombdim))
const win = Window("Honeycombs", wid, hgt)
const can = Canvas()
const honeycomb = Dict{Point, Hexagon}()
const chosen = Vector{String}()
 
function hexmat(p, rad)
shor = rad * 0.5
long = rad * sqrt(3.0) / 2.0
mat = reshape([shor, long, -shor, long, Float64(-rad), 0.0, -shor, -long, shor, -long, Float64(rad), 0.0], 2, 6)
[Point(mat[1, n] + p.x, mat[2, n] + p.y) for n in 1:6]
end
 
function whichclicked(clickpos)
centers = [c for c in keys(honeycomb)]
(maybeclicked, idx) = findmin(map(c -> sqrt((clickpos.x - c.x)^2 + (clickpos.y - c.y)^2), centers))
return maybeclicked < offset * sqrt(3) / 2.0 ? centers[idx] : nothing
end
 
whichtyped(ch) = (for (k, v) in honeycomb if v.letter == ch return k end end; nothing)
 
function hexagon(ctx, pos, rad, ltr, colr = colorant"yellow")
set_source(ctx, colr)
points = hexmat(pos, rad)
set_line_width(ctx, 4)
polygon(ctx, points)
close_path(ctx)
fill(ctx)
set_source(ctx, colorant"black")
polygon(ctx, points)
close_path(ctx)
stroke(ctx)
move_to(ctx, pos.x - (ltr == "I" ? 7 : 18), pos.y + 15)
set_source(ctx, colr == colorant"yellow" ? colorant"red" : colorant"black")
set_font_size(ctx, offset)
show_text(ctx, ltr)
Hexagon(pos, rad, ltr, colr)
end
 
hexagon(ctx, h::Hexagon) = hexagon(ctx, h.center, h.radius, h.letter, h.color)
 
function makehoneycomb(ctx)
centers = fill(Point(0, 0), hcombdim.rows, hcombdim.cols)
xdelta = 75.0
ydelta = 90.0
for i in 1:hcombdim.rows, j in 1:hcombdim.cols
center = Point((i - 1) * xdelta + offset, (j - 1) * ydelta + ((i - 1 ) % 2 + 1) * offset)
centers[i, j] = center
honeycomb[center] = hexagon(ctx, center, offset, randletters[i, j])
end
centers
end
 
@guarded draw(can) do widget
ctx = getgc(can)
if length(honeycomb) == 0
makehoneycomb(ctx)
else
map(c -> hexagon(ctx, honeycomb[c]), collect(keys(honeycomb)))
end
end
 
""" At entry to this function we have just found out what letter was chosen."""
function changecolor(colr)
h = honeycomb[colr]
h.color = colorant"violet"
hexagon(getgc(can), h)
reveal(win, true)
push!(chosen, h.letter)
if all(map(k -> honeycomb[k].color == colorant"violet", collect(keys(honeycomb))))
println("All hexagons ($chosen, and the last letter was $(chosen[end])) have been chosen. Exiting.")
exit(0)
end
end
 
signal_connect(win, "key-press-event") do widget, event
if (whichhexgon = whichtyped(string(uppercase(Char(event.keyval))))) != nothing
changecolor(whichhexgon)
end
end
 
can.mouse.button1press = @guarded (widget, event) -> begin
if (whichhexgon = whichclicked(Point(event.x, event.y))) != nothing
changecolor(whichhexgon)
end
end
 
push!(win, can)
show(can)
condition = Condition()
endit(w) = notify(condition)
signal_connect(endit, win, :destroy)
show(win)
wait(condition)
exit()
 
</syntaxhighlight>
 
=={{header|Kotlin}}==
This is a translation of the Java entry except that code has been added to end the program automatically when all the hexagons have been selected.
<syntaxhighlight lang="scala">// version 1.1.4
 
import java.awt.BasicStroke
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Dimension
import java.awt.Font
import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.Polygon
import java.awt.RenderingHints
import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.WindowEvent
import javax.swing.JFrame
import javax.swing.JPanel
import javax.swing.SwingUtilities
 
class Honeycombs : JPanel() {
private val comb: Array<Hexagon?> = arrayOfNulls(20)
 
init {
preferredSize = Dimension(600, 500)
background = Color.white
isFocusable = true
 
addMouseListener(object : MouseAdapter() {
override fun mousePressed(e: MouseEvent) {
for (hex in comb)
if (hex!!.contains(e.x, e.y)) {
hex.setSelected()
checkForClosure()
break
}
repaint()
}
})
 
addKeyListener(object : KeyAdapter() {
override fun keyPressed(e: KeyEvent) {
for (hex in comb)
if (hex!!.letter == e.keyChar.toUpperCase()) {
hex.setSelected()
checkForClosure()
break
}
repaint()
}
})
 
val letters = "LRDGITPFBVOKANUYCESM".toCharArray()
val x1 = 150
val y1 = 100
val x2 = 225
val y2 = 143
val w = 150
val h = 87
 
for (i in 0 until comb.size) {
var x: Int
var 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
}
comb[i] = Hexagon(x, y, w / 3, letters[i])
}
 
requestFocus()
}
 
override fun paintComponent(gg: Graphics) {
super.paintComponent(gg)
val g = gg as Graphics2D
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON)
g.font = Font("SansSerif", Font.BOLD, 30)
g.stroke = BasicStroke(3.0f)
for (hex in comb) hex!!.draw(g)
}
 
private fun checkForClosure() {
if (comb.all { it!!.hasBeenSelected } ) {
val f = SwingUtilities.getWindowAncestor(this) as JFrame
f.dispatchEvent(WindowEvent(f, WindowEvent.WINDOW_CLOSING))
}
}
}
 
class Hexagon(x: Int, y: Int, halfWidth: Int, c: Char) : Polygon() {
private val baseColor = Color.yellow
private val selectedColor = Color.magenta
var hasBeenSelected = false
val letter = c
 
init {
for (i in 0..5)
addPoint((x + halfWidth * Math.cos(i * Math.PI / 3.0)).toInt(),
(y + halfWidth * Math.sin(i * Math.PI / 3.0)).toInt())
getBounds()
}
 
fun setSelected() {
hasBeenSelected = true
}
 
fun draw(g: Graphics2D) {
with(g) {
color = if (hasBeenSelected) selectedColor else baseColor
fillPolygon(this@Hexagon)
color = Color.black
drawPolygon(this@Hexagon)
color = if (hasBeenSelected) Color.black else Color.red
drawCenteredString(g, letter.toString())
}
}
 
private fun drawCenteredString(g: Graphics2D, s: String) {
val fm = g.fontMetrics
val asc = fm.ascent
val dec = fm.descent
val x = bounds.x + (bounds.width - fm.stringWidth(s)) / 2
val y = bounds.y + (asc + (bounds.height - (asc + dec)) / 2)
g.drawString(s, x, y)
}
}
 
fun main(args: Array<String>) {
SwingUtilities.invokeLater {
val f = JFrame()
with(f) {
defaultCloseOperation = JFrame.EXIT_ON_CLOSE
add(Honeycombs(), BorderLayout.CENTER)
title = "Honeycombs"
isResizable = false
pack()
setLocationRelativeTo(null)
isVisible = true
}
}
}</syntaxhighlight>
 
=={{header|Liberty BASIC}}==
By Andy Amaya, Sept. 24, 2015 -- with thanks from the Liberty BASIC Community.
<syntaxhighlight lang="lb">
NoMainWin
Dim hxc(20,2), ltr(26)
Global sw, sh, radius, radChk, mx, my, h$, last
h$="#g": radius = 40: radChk = 35 * 35: last = 0
sw = 400: sh = 380: WindowWidth = sw+6: WindowHeight= sh+32
Open "Liberty BASIC - Honeycombs" For graphics_nsb_nf As #g
#g "Down; Cls; TrapClose xit"
 
Call shuffle
Call grid 75, 15, "0 0 0", "255 215 32", "0 0 0"
 
#g "SetFocus; when characterInput getKey; when leftButtonDown chkClick"
Wait
 
Sub xit h$
Close #h$:End
End Sub
 
'Assign ASCII values of A thru Z to ltr() array and randomize order of letters
Sub shuffle
For i = 1 To 26
ltr(i) = i+64
Next
For i = 1 To 77
r1 = Int(Rnd(1)*26)+1
r2 = Int(Rnd(1)*26)+1
temp = ltr(r1): ltr(r1) = ltr(r2): ltr(r2) = temp
Next
End Sub
 
'Draw the hex cells and fill with 20 out of 26 random letters
Sub grid ox, oy, fc$, bc$, tc$
cx = ox: cy = oy
For i = 1 To 5
If (i And 1)=0 Then cy = oy + 76 Else cy = oy + 42
For j = 1 To 4
count = count + 1: letter$ = Chr$(ltr(count))
Call cell, cx, cy, fc$, bc$, tc$, letter$
hxc(count,0)=cx: hxc(count,1)=cy: cy = cy + 70
Next
cx = cx + 61
Next
End Sub
 
'Draw a filled hex cell and printed the letter associated with cell
Sub cell cx, cy, fc$, bc$, tc$, lt$
lastx = cx + radius: lasty = cy
For f = 1.04719755 To 6.2831853 Step 1.0471955
nx = Cos(f)*radius+cx: ny = Sin(f)*radius+cy
#g "Size 2; Color ";bc$;";BackColor ";bc$
Call triFill cx, cy, lastx, lasty, nx, ny
#g "Size 5; Color ";fc$
#g "Line ";lastx;" ";lasty;" ";nx;" ";ny;";Size 1"
lastx = nx: lasty = ny
Next
#g "Font Courier_New 36 Bold"
#g "Color ";tc$;";BackColor ";bc$
#g "Place ";cx-15;" ";cy+15;";\";lt$
End Sub
 
'Check for a mouse click in a hex cell
Sub chkClick h$, x, y
mx = MouseX
my = MouseY
For i = 1 To 20
If pnc(mx,my,hxc(i,0),hxc(i,1)) = 1 Then 'selected hex cell found
If hxc(i,2)=0 Then
hxc(i,2)=1 'when set to 1, hex cell & letter no longer selectable
key$ = Chr$(ltr(i))
Call cell hxc(i,0),hxc(i,1),"0 0 0","80 0 128","255 255 255",key$
Call showLetter key$
Exit For
End If
End If
Next
End Sub
 
'Allow letter selection via keyboard
Sub getKey h$, char$
key$ = Upper$(Inkey$)
'Poll ESC key to exit at any time
If key$=Chr$(27) Then Call xit h$
idx = Instr("ABCDEFGHIJKLMNOPQRSTUVWXYZ",key$)
If idx <> 0 Then
For i = 1 To 20
If idx+64 = ltr(i) Then 'letter matching key press found
If hxc(i,2)=0 Then
hxc(i,2)=1 'when set to 1, hex cell & letter no longer selectable
Call cell hxc(i,0),hxc(i,1),"0 0 0","80 0 128","255 255 255",key$
Call showLetter key$
Exit For
End If
End If
Next
End If
End Sub
 
'Print letters selected at bottom of screen
Sub showLetter key$
#g "Font Courier_New 18 Bold"
#g "Color Black;BackColor white"
#g "Place ";last*18+20;" 365;\"; key$
last = last + 1
'When 20th letter selected; exit
If last > 19 Then Call xit h$
End Sub
 
'Draw a filled triangle
Sub triFill x1,y1, x2,y2, x3,y3
If x2<x1 Then x=x2: y=y2: x2=x1: y2=y1: x1=x: y1=y
If x3<x1 Then x=x3: y=y3: x3=x1: y3=y1: x1=x: y1=y
If x3<x2 Then x=x3: y=y3: x3=x2: y3=y2: x2=x: y2=y
If x1<>x3 Then slope1=(y3-y1)/(x3-x1)
length=x2-x1
If length<>0 Then
slope2=(y2-y1)/(x2-x1)
For x = 0 To length
#g "Line ";Int(x+x1);" ";Int(x*slope1+y1);" ";Int(x+x1);" ";Int(x*slope2+y1)
Next
End If
y = length*slope1+y1 :length=x3-x2
If length<>0 Then
slope3=(y3-y2)/(x3-x2)
For x = 0 To length
#g "Line ";Int(x+x2);" ";Int(x*slope1+y);" ";Int(x+x2);" ";Int(x*slope3+y2)
Next
End If
End Sub
 
'Point in Circle function
Function pnc(ax, ay, bx, by)
If (bx-ax)*(bx-ax)+(by-ay)*(by-ay) <= radChk Then
pnc=1
Else
pnc=0
End If
End Function
</syntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Two players, 5 by 4.
<langsyntaxhighlight Mathematicalang="mathematica">hexagon[{x_, y_}] :=
Polygon[Transpose[{{1/2, 1/4, -1/4, -1/2, -1/4, 1/4} +
x, {0, Sqrt[3]/4, Sqrt[3]/4, 0, -Sqrt[3]/4, -Sqrt[3]/4} + y}]];
Line 1,412 ⟶ 2,677:
cols, {If[blue, Blue, Red],
Nearest[locs, MousePosition["Graphics"]][[1]]}];
blue = ! blue]}]]</langsyntaxhighlight>
 
=={{header|MATLAB}}==
Line 1,423 ⟶ 2,688:
*Works for up to 26 hexagons before using lowercase labels, 52 hexagons before repeating letters
*Works off of mouse-click events, so program doesn't need to "quit" as it is not really running constantly
<langsyntaxhighlight MATLABlang="matlab">function Honeycombs
nRows = 4; % Number of rows
nCols = 5; % Number of columns
Line 1,479 ⟶ 2,744:
set(axesH, 'UserData', newList)
title(newList)
end</langsyntaxhighlight>
 
=={{header|Nim}}==
{{libheader|gintro}}
This program is largely inspired by the C version, but this is not a direct translation. We have reused many parts of the C version, for instance the computations and the way to draw the cells. But we have also introduced a “honeycomb” object, improved somewhat the drawing of the labels and taken advantage of the high level binding to Gtk3 provided by “gintro”.
 
<syntaxhighlight lang="nim">import lenientops, math, random, sequtils, strutils, tables
 
import gintro/[gobject, gdk, gtk, gio, cairo]
import gintro/glib except PI
 
const
Size = 308 # Size of drawing area.
NHexagons = 20 # Number of hexagons.
Radius = 30.0
XOffset = 1 + sin(PI / 6)
YOffset = cos(PI / 6)
 
type
 
Letter = range['A'..'Z']
 
# Description of a hexagon.
Hexagon = object
cx, cy: float
letter: Letter
selected: bool
 
# Description of the honeycomb.
HoneyComb = ref object
hexagons: array[NHexagons, Hexagon] # List of hexagons.
indexes: tables.Table[char, int] # Mapping letter -> index of hexagon.
archive: seq[Letter] # List of selected letters.
label: Label # Label displaying the selected letters.
 
#---------------------------------------------------------------------------------------------------
 
proc newHoneyComb(): HoneyComb =
## Create a honeycomb.
 
new(result)
var letters = toSeq('A'..'Z')
letters.shuffle()
 
for i in 0..<NHexagons:
result.hexagons[i].letter = letters[i]
result.indexes[letters[i]] = i
# Compute position of hexagon center.
let q = i div 4
let m = i mod 4
result.hexagons[i].cx = Radius * (2 + q * XOffset)
result.hexagons[i].cy = Radius * (2 * (1 + m * YOffset) + (q and 1) * YOffset)
 
#---------------------------------------------------------------------------------------------------
 
proc drawHexagons(context: Context; honeyComb: HoneyComb; select: bool) =
## Draw a hexagon (content or border).
 
for hex in honeyComb.hexagons:
if select == hex.selected:
let cx = hex.cx
let cy = hex.cy
context.moveTo(cx + Radius, cy)
for i in 1..5:
let x = cx + Radius * cos(i * PI / 3)
let y = cy + Radius * sin(i * PI / 3)
context.lineTo(x, y)
 
#---------------------------------------------------------------------------------------------------
 
proc drawLabels(context: Context; honeyComb: HoneyComb; select: bool) =
## Draw the labels of the hexagons.
 
for hex in honeyComb.hexagons:
if select == hex.selected:
let letter = $hex.letter
var extents: TextExtents # Used to adjust letter position in hexagon.
context.getTextExtents(letter, extents)
context.moveTo(hex.cx - extents.width / 2, hex.cy + extents.height / 2)
context.showText(letter)
 
#---------------------------------------------------------------------------------------------------
 
proc onDraw(area: DrawingArea; context: Context; honeyComb: HoneyComb): bool =
## Callback to draw/redraw the drawing area contents.
 
# Fill unselected in yellow.
context.setSource(0.8, 0.8, 0.0, 1.0)
context.drawHexagons(honeyComb, false)
context.fill()
 
# Fill selected in purple.
context.setSource(0.8, 0.0, 0.8, 1.0)
context.drawHexagons(honeyComb, true)
context.fill()
 
# Draw border.
context.setLineWidth(3.0)
context.setSource(0.7, 0.7, 0.7, 0.7)
context.drawHexagons(honeyComb, false)
context.stroke()
 
# Prepare label drawing.
context.selectFontFace("cairo:monospace", FontSlant.normal, FontWeight.bold)
context.setFontSize(14.0)
 
# Draw labels for selected hexagons.
context.setSource(0, 0, 0, 1)
context.drawLabels(honeyComb, true)
context.stroke()
 
# Draw labels for unselected hexagons.
context.setSource(0, 0, 1, 1)
context.drawLabels(honeyComb, false)
context.stroke()
 
result = true
 
#---------------------------------------------------------------------------------------------------
 
proc select(honeyComb: HoneyComb; hex: var Hexagon) =
## Select a hexagon.
 
hex.selected = true
honeyComb.archive.add(hex.letter)
honeyComb.label.setText(honeyComb.label.text() & hex.letter)
 
#---------------------------------------------------------------------------------------------------
 
proc onButtonPress(area: DrawingArea; event: Event; honeyComb: HoneyComb): bool =
## Callback to process a button press event.
 
var xwin, ywin: float
if not event.getCoords(xwin, ywin): return false
 
# Search the hexagon selected.
for hex in honeyComb.hexagons.mitems:
if hypot(xwin - hex.cx, ywin - hex.cy) < Radius * cos(PI / 15):
if not hex.selected:
honeyComb.select(hex)
area.window().invalidateRect()
break
return true
 
#---------------------------------------------------------------------------------------------------
 
proc onKeyPress(area: DrawingArea; event: Event; honeyComb: HoneyComb): bool =
## Callbakc to process a key press event.
 
var keyval: int
if not event.getKeyval(keyval): return false
if keyval notin ord('a')..ord('z'): return false # For ASCII letters, keyvals are ASCII codes.
let letter = chr(keyval).toUpperAscii() # We want the uppercase letter.
if letter notin honeyComb.indexes: return false
let idx = honeyComb.indexes[letter]
if not honeyComb.hexagons[idx].selected:
honeyComb.select(honeyComb.hexagons[idx])
area.window().invalidateRect()
 
#---------------------------------------------------------------------------------------------------
 
proc activate(app: Application) =
## Activate the application.
 
var honeyComb = newHoneyComb()
 
let window = app.newApplicationWindow()
window.setTitle("Honeycombs")
 
let vbox = newBox(Orientation.vertical, 1)
window.add(vbox)
 
honeyComb.label = newLabel()
vbox.packEnd(honeyComb.label, false, false, 4)
 
# Create the drawing area.
let area = newDrawingArea()
area.setEvents({EventFlag.buttonPress, EventFlag.keyPress, EventFlag.exposure})
vbox.packStart(area, true, true, 4)
area.setSizeRequest(Size, Size)
area.setCanFocus(true)
 
# Connect events.
discard area.connect("draw", ondraw, honeyComb)
discard area.connect("button-press-event", onButtonPress, honeyComb)
discard area.connect("key-press-event", onKeyPress, honeyComb)
 
window.showAll()
 
#———————————————————————————————————————————————————————————————————————————————————————————————————
 
randomize()
let app = newApplication(Application, "Rosetta.honeycombs")
discard app.connect("activate", activate)
discard app.run()</syntaxhighlight>
 
 
=={{header|Perl}}==
Line 1,485 ⟶ 2,945:
The programme uses the ''Tk'' GUI toolkit.
 
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
use warnings;
use strict;
Line 1,574 ⟶ 3,034:
)->pack;
$mw->bind('<Alt-q>', sub { $btn->invoke });
MainLoop();</langsyntaxhighlight>
 
=={{header|Phix}}==
Line 1,580 ⟶ 3,040:
In the 2 player game, the string chosen contains the selections of both players: odd chars = player 1, even chars = player 2.<br>
Included in the distribution as demo\rosetta\honeycomb.exw
<langsyntaxhighlight Phixlang="phix">include ..\arwen\arwen.ew
include ..\arwen\axtra.ew
 
Line 1,770 ⟶ 3,230:
setHandler(main,routine_id("mainHandler"))
 
WinMain(main, SW_NORMAL)</langsyntaxhighlight>
 
=={{header|Prolog}}==
Works with SWI-Prolog and XPCE.
<langsyntaxhighlight Prologlang="prolog">honeycomb :-
new(W, window('Honeycomb')),
new(Counter, counter(20)),
Line 1,989 ⟶ 3,449:
:- pce_end_class(cell).
 
</syntaxhighlight>
</lang>
[[File:Prolog_honeycombs.png|400px]]
 
=={{header|PureBasic}}==
Requires PureBasic v4.60. Screen controls in PureBasic are referred to as 'gadgets'.
<langsyntaxhighlight PureBasiclang="purebasic">Structure hexGadget
text.s
Status.i ;nonselected = 0, selected = 1
Line 2,196 ⟶ 3,656:
FreeGadget(honeycomb\gadgetID)
CloseWindow(0)
EndIf</langsyntaxhighlight>
[[File:PureBasic_Honeycomb.png]]
 
Line 2,203 ⟶ 3,663:
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
 
(struct Hex (x y letter clicked?) #:mutable #:transparent)
Line 2,263 ⟶ 3,723:
 
(displayln "The letters were chosen in the order:")
(for-each display (add-between (reverse letters-chosen) " "))</langsyntaxhighlight>
 
=={{header|Ruby}}==
{{libheader|Shoes}}
<langsyntaxhighlight lang="ruby">Shoes.app(title: "Honeycombs", height: 700, width: 700) do
C = Math::cos(Math::PI/3)
S = Math::sin(Math::PI/3)
Line 2,401 ⟶ 3,861:
end
end
end</langsyntaxhighlight>
 
=={{header|Scala}}==
===Java Swing Interoperability===
{{libheader|Scala Java Swing interoperability}}
{{works with|Scala|2.13}}
<syntaxhighlight lang="scala">import java.awt.{BasicStroke, BorderLayout, Color, Dimension,
Font, FontMetrics, Graphics, Graphics2D, Point, Polygon, RenderingHints}
import java.awt.event.{KeyAdapter, KeyEvent, MouseAdapter, MouseEvent}
 
import javax.swing.{JFrame, JPanel}
 
import scala.math.{Pi, cos, sin}
 
object Honeycombs extends App {
private val (letters, x1, y1, x2, y2, h, w) = ("LRDGITPFBVOKANUYCESM", 150, 100, 225, 143, 87, 150)
 
private class HoneycombsPanel() extends JPanel {
private val comb: IndexedSeq[Hexagon] =
for {i <- 0 until 20
(x: Int, y: Int) =
if (i < 12) (x1 + (i % 3) * w, y1 + (i / 3) * h)
else (x2 + (i % 2) * w, y2 + ((i - 12) / 2) * h)
} yield Hexagon(x, y, w / 3, letters(i))
 
override def paintComponent(gg: Graphics): Unit = {
super.paintComponent(gg)
val g = gg.asInstanceOf[Graphics2D]
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
g.setFont(new Font("SansSerif", Font.BOLD, 30))
g.setStroke(new BasicStroke(3))
comb.foreach(_.draw(g))
}
 
case class Hexagon(x: Int, y: Int, halfWidth: Int, letter: Char,
var hasBeenSelected: Boolean = false) extends Polygon {
private val (baseColor, selectedColor) = (Color.yellow, Color.magenta)
 
def setSelected(): Unit = hasBeenSelected = true
 
def draw(g: Graphics2D): Unit = {
val fm: FontMetrics = g.getFontMetrics
val (asc, dec) = (fm.getAscent, fm.getDescent)
 
def drawCenteredString(g: Graphics2D, s: String): Unit = {
val x: Int = bounds.x + (bounds.width - fm.stringWidth(s)) / 2
val y: Int = bounds.y + (asc + (bounds.height - (asc + dec)) / 2)
g.drawString(s, x, y)
}
 
g.setColor(if (hasBeenSelected) selectedColor else baseColor)
g.fillPolygon(this)
g.setColor(Color.black)
g.drawPolygon(this)
g.setColor(if (hasBeenSelected) Color.black else Color.red)
drawCenteredString(g, letter.toString)
}
 
for (i <- 0 until 6)
addPoint((x + halfWidth * cos(i * Pi / 3)).toInt, (y + halfWidth * sin(i * Pi / 3)).toInt)
 
getBounds
}
 
addKeyListener(new KeyAdapter() {
override def keyPressed(e: KeyEvent): Unit = {
val key = e.getKeyChar.toUpper
comb.find(_.letter == key).foreach(_.setSelected())
repaint()
}
})
 
addMouseListener(new MouseAdapter() {
override def mousePressed(e: MouseEvent): Unit = {
val mousePos: Point = e.getPoint
 
comb.find(h => h.contains(mousePos)).foreach(_.setSelected())
repaint()
}
})
 
setBackground(Color.white)
setPreferredSize(new Dimension(600, 500))
setFocusable(true)
requestFocus()
}
 
new JFrame("Honeycombs") {
add(new HoneycombsPanel(), BorderLayout.CENTER)
pack()
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
setLocationRelativeTo(null)
setResizable(false)
setVisible(true)
}
 
}</syntaxhighlight>
 
=={{header|Sidef}}==
{{trans|Perl}}
[[File:Honeycombs_sidef.png|250px|thumb|right]]
<langsyntaxhighlight lang="ruby">require('Tk')
 
class Honeycombs(
Number size = 36,
Array letters = @('A' .. 'Z' -> ).shuffle.first(20)),
) {
 
define tk = %sS<Tk>
has changed = Hash()
 
Line 2,445 ⟶ 4,001:
 
method comb(canvas, fromx, fromy, size, count) {
for x,y in (fromx ..^ (3*count*size - 1, 3*size)) {
for y in RangeNum(fromy ..^ (7.5fromx, 3*count* size - 1, 2 3* altitude(size))) {~X
RangeNum(fromy, var id7.5*size =- canvas.createPolygon1, 2*altitude(size))
) {
self.polygon_coordinates(x, y, size),
var '-outline'id => 'black',canvas.createPolygon(
self.polygon_coordinates(x, y, '-fill' => 'yellow'size),
'-widthoutline' => 2'black',
'-fill' ) => 'yellow',
var letter '-width' => letters.shift2,
var letter_id = canvas.createText(x, y, )
var '-fill'letter => 'red',letters.shift
var letter_id = canvas.createText(x, y,
'-text' => letter,
'-fontfill' => "{sans} #{size * 0.9}"'red',
) '-text' => letter,
canvas.MainWindow.bind( 'all-font', letter=> "{sans} #{size * 0.lc9}",
self.change(canvas, id, letter_id))
[idcanvas.MainWindow.bind('all', letter_id]letter.each { |b|lc,
canvas self.bindchange(bcanvas, '<Button-1>'id, letter_id))
[id, letter_id].each { |b|
self.change(canvas, id, letter_id))
}canvas.bind(b, '<Button-1>',
self.change(canvas, id, letter_id))
}
}
Line 2,470 ⟶ 4,027:
 
method display(title) {
fork {
var mw = %s'MainWindow'.new('-title' => title)
var canvas = mw.Canvas('-width' => 8*size,
Line 2,484 ⟶ 4,041:
mw.bind('<Alt-q>', { btn.invoke })
tk.MainLoop()
}.fork
}
}
 
Honeycombs().display(title: 'Honeycombs')</langsyntaxhighlight>
 
=={{header|Tcl}}==
{{libheader|Tk}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
package require Tk
 
Line 2,578 ⟶ 4,135:
tkwait window .c
puts "overall list of characters: $chosen"
exit</langsyntaxhighlight>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|DOME}}
{{libheader|Wren-polygon}}
Unlike the Kotlin entry, the 20 capital letters are now chosen at random from the available 26.
 
The following script uses a font called ''memory.ttf''. If this is not present in your DOME distribution, it can be downloaded from [https://github.com/domeengine/dome/raw/main/examples/fonts/memory.ttf here] and should be placed in the same directory as the script itself.
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color
import "dome" for Window, Process
import "math" for Math
import "font" for Font
import "input" for Mouse, Keyboard
import "random" for Random
import "./polygon" for Polygon
 
var Rand = Random.new()
 
class Hexagon is Polygon {
static baseColor { Color.yellow }
static selectedColor { Color.pink }
 
construct new(x, y, halfWidth, letter) {
_x = x
_y = y
_letter = letter
var vertices = List.filled(6, null)
for (i in 0..5) {
var vx = x + halfWidth * Math.cos(i * Num.pi / 3)
var vy = y + halfWidth * Math.sin(i * Num.pi / 3)
vertices[i] = [vx, vy]
}
super(vertices, "")
_selected = false
}
 
letter { _letter }
selected { _selected }
selected=(v) { _selected = v }
 
draw() {
var col = selected ? Hexagon.selectedColor : Hexagon.baseColor
drawfill(col)
super.draw(Color.black)
col = selected ? Color.black : Color.red
Canvas.print(_letter, _x - 8, _y - 8, col)
}
}
 
class Honeycombs {
construct new(width, height) {
Window.title = "Honeycombs"
Window.resize(width, height)
Canvas.resize(width, height)
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toList
Rand.shuffle(letters)
_letters = letters[0..19]
_x1 = 150
_y1 = 100
_x2 = 225
_y2 = 143
_w = 150
_h = 87
_hs = null
_comb = List.filled(20, null)
Font.load("memory", "memory.ttf", 48)
Font["memory"].antialias = true
Canvas.font = "memory"
}
 
drawHexagons() {
for (i in 0..._comb.count) {
var x
var y
if (i < 12) {
x = _x1 + (i % 3) * _w
y = _y1 + (i / 3).floor * _h
} else {
x = _x2 + (i % 2) * _w
y = _y2 + ((i - 12) / 2).floor * _h
}
_comb[i] = Hexagon.new(x, y, (_w / 3).floor, _letters[i])
_comb[i].draw()
}
}
 
allSelected() { _comb.all { |h| h.selected } }
 
init() {
drawHexagons()
}
 
update() {
_hs = null
if (Mouse.isButtonPressed("left")) {
for (h in _comb) {
if (h.contains(Mouse.position.x, Mouse.position.y)) {
_hs = h
break
}
}
} else if (Keyboard.allPressed.count > 0) {
for (h in _comb) {
if (Keyboard.isKeyDown(h.letter)) {
_hs = h
break
}
}
}
}
 
draw(alpha) {
if (_hs) {
_hs.selected = true
_hs.draw()
if (allSelected()) Process.exit(0)
}
}
}
 
var Game = Honeycombs.new(600, 500)</syntaxhighlight>
 
=={{header|XPL0}}==
[[File:HoneyXPL0.gif|right]]
<langsyntaxhighlight XPL0lang="xpl0">include c:\cxpl\stdlib; \(color definitions, etc.)
 
proc DrawHexagon(X0, Y0, Side, Color); \Draw a filled hexagon centered at X0,Y0
Line 2,623 ⟶ 4,301:
until Counter >= Cols*Rows;
SetVid($03); \restore normal text display
]</langsyntaxhighlight>
 
{{omit from|ACL2}}
Line 2,632 ⟶ 4,310:
{{omit from|Lotus 123 Macro Scripting}}
{{omit from|MIRC Scripting Language}}
{{omit from|TI-83 BASIC|Does not have a color display.}}
{{omit from|UNIX Shell}}
9,476

edits