Author Topic: Honeycombs _ Rosetta Code  (Read 4508 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Honeycombs _ Rosetta Code
« on: October 30, 2021, 02:33:20 pm »
ref:  http://rosettacode.org/wiki/Honeycombs

Here is updated translation and overhaul I made today:
Code: QB64: [Select]
  1. _Title "Honeycombs - Rosetta Code" ' b+ 2021-10-30 trans from
  2. ' Honeycomb Rosetta.txt for JB v2 2018-11-24 B+ finish Rosetta Challenge
  3. ' 2021-10-30 complete overhaul except for grid drawing numbers and names.
  4.  
  5. ' ===================== Try alternate Cols and Rows for HoneyComb ===============================
  6.  
  7. Const Cols = 5, Rows = 4, LMax = Cols * Rows ' hex grid  <<<<<<<<<<<<<<  as Rosetta Requires
  8. 'Const Cols = 4, Rows = 5, LMax = Cols * Rows ' hex grid <<<<<<<<<<<<<< reverse
  9. 'Const Cols = 6, Rows = 5, LMax = Cols * Rows ' hex grid <<<<<<<<<<<<<< More than just Letters
  10. 'Const Cols = 13, Rows = 2, LMax = Cols * Rows ' hex grid do exactly whole alphabet!
  11.  
  12.  
  13. ' global   SELECTED$ ' all caps for globals
  14. Const Pi3 = _Pi / 3, Sqr3 = Sqr(3), Side = 30 '           constants for Hexagon making
  15. Const Xoff = 100 - 1.5 * Side, Yoff = 100 - Side * Sqr3 ' center grid with offsets on screen
  16. Const XMax = 2 * Xoff + Cols * 1.5 * Side + 1.5 * Side '  screen display size needed
  17. Const YMax = 2 * Yoff + (Rows + 2) * Side * Sqr3
  18.  
  19. Dim Shared L$(LMax), LX(LMax), LY(LMax), LSELECTED(LMax), Selected$ ' save letter and hex center positions by index
  20.  
  21. Randomize Timer ' get new grid when we start
  22. For i = 1 To LMax ' get letters array loaded
  23.     L$(i) = Chr$(64 + i)
  24. For i = LMax To 2 Step -1 ' shuffle letters Fisher - Yates
  25.     Swap L$(i), L$(Int(Rnd * i) + 1)
  26.  
  27. Screen _NewImage(XMax, YMax, 32) 'graphics custom size RGBA colors
  28. _Delay .25 ' get screen loaded before trying to move
  29. _ScreenMove _Middle ' center  screen
  30.  
  31. f& = _LoadFont("Consolab.ttf", 40) ' >>>>>>>>>>>> from Windows 10 Fonts
  32. Color , _RGB32(200, 200, 220): Cls ' draw grid before selections
  33. For y = 1 To Rows ' initialize screen with grid
  34.     For x = 1 To Cols
  35.         n = n + 1 ' index hex buttons
  36.         If x Mod 2 = 0 Then yoff2 = .5 * Side * Sqr3 Else yoff2 = 0 ' is this column lower than first column?
  37.         cx = x * 1.5 * Side + Xoff: cy = y * Side * Sqr3 + Yoff + yoff2 ' calc hex key centers
  38.         LX(n) = cx: LY(n) = cy ' save hex key center positions
  39.         drawHex n, 0 ' draw key
  40.     Next
  41.  
  42. While _KeyDown(27) = 0 ' allow user to select letters by key or mouse
  43.     k$ = InKey$
  44.     If Len(k$) Then
  45.         For i = 1 To LMax 'if so was it selected already? or select it.
  46.             If UCase$(k$) = L$(i) And LSELECTED(i) = 0 Then drawHex i, 1: Exit For
  47.         Next
  48.     End If
  49.     While _MouseInput: Wend ' polls mouse
  50.     mx = _MouseX: my = _MouseY: mb = _MouseButton(1)
  51.     If mb Then
  52.         For i = 1 To LMax ' is distance from click within radius of non-selected button?
  53.             If Sqr((mx - LX(i)) ^ 2 + (my - LY(i)) ^ 2) <= Side * .5 * Sqr3 And LSELECTED(i) = 0 Then drawHex i, 1
  54.         Next
  55.     End If
  56.  
  57. Sub drawHex (i, selectedTF)
  58.     If selectedTF = 0 Then
  59.         Color _RGB32(255, 0, 0), _RGB32(255, 255, 0)
  60.     Else
  61.         Color _RGB32(0, 0, 0), _RGB32(255, 0, 255)
  62.     End If
  63.     For a = 0 To 6
  64.         x1 = LX(i) + Side * Cos(a * Pi3): y1 = LY(i) + Side * Sin(a * Pi3)
  65.         If a > 0 Then Line (lastx, lasty)-(x1, y1), _RGB32(0, 0, 0)
  66.         lastx = x1: lasty = y1
  67.     Next
  68.     Paint (LX(i), LY(i)), _BackgroundColor, _RGB32(0, 0, 0)
  69.     _PrintString (LX(i) - 10, LY(i) - 13), L$(i)
  70.     If selectedTF Then ' show the order of selection
  71.         Color _RGB32(0, 0, 0), _RGB32(200, 200, 220)
  72.         LSELECTED(i) = 1
  73.         Selected$ = Selected$ + L$(i)
  74.         centerText 0, _Width, _Height - 60, Mid$(Selected$, 1, Int(LMax / 2))
  75.         If Len(Selected$) > 10 Then
  76.             centerText 0, _Width, _Height - 20, Mid$(Selected$, Int(LMax / 2) + 1) 'are we done yet? are all letters selected?
  77.             If Len(Selected$) = LMax Then Beep ' all have been selected
  78.         End If
  79.     End If
  80.  
  81. Sub centerText (x1, x2, midy, s$) ' ' if you want to center fit a string between two goal posts x1, and x2
  82.     _PrintString ((x1 + x2) / 2 - _PrintWidth(s$) / 2, midy - _FontHeight(_Font) / 2), s$
  83.  

Here's what it looked like in Just Basic 3 years ago:
Code: [Select]
'Honeycomb Rosetta.txt for JB v2 2018-11-24 B+ finish Rosetta Challenge

global XMAX, YMAX, PI3, SQR3, SIDE, LMAX, SELECTED$, ROWS, YOFF  ' all caps for globals
PI3 = acs(-1)/3 : SQR3 = sqr(3) : SIDE = 30                      ' constants for Hexagon making
cols = 5 : ROWS = 4 : LMAX = cols * ROWS                         ' hex grid size
dim L$(LMAX), LX(LMAX), LY(LMAX), LSELECTED(LMAX)                ' save letter and hex center positions by index
xoff = 100 - 1.5 * SIDE : YOFF = 100 - SIDE * SQR3               ' center grid with offsets
for i = 1 to LMAX : L$(i) = chr$(64 + i) : next                  ' get letters array loaded
for i = LMAX to 2 step -1                                        ' shuffle letters Fisher - Yates
    r = int(rnd(0) * i) + 1                                      ' random number up to i place
    t$ = L$(r) : L$(r) = L$(i) : L$(i) = t$                      ' swap
next
XMAX = 2*xoff + cols*1.5*SIDE + 1.5*SIDE                         'screen display size needed
YMAX = 2*YOFF + (ROWS + 2)*SIDE*SQR3
nomainwin                                                        ' Window prep before open
WindowWidth = XMAX + 8                                           ' size
WindowHeight = YMAX + 32
UpperLeftX = (DisplayWidth - XMAX) / 2                           ' top left corner, center window
UpperLeftY = (DisplayHeight - YMAX) / 2
open "Honeycomb - Rosetta Challenge" for graphics_nsb_nf as #gr  ' open with title
#gr "setfocus"                                                   ' catch keys and mouse
#gr "trapclose quit"                                             ' set exit code sub
#gr "when leftButtonUp lButtonUp"                                ' set mouse click up sub
#gr "when characterInput charIn"                                 ' set keppress sub
#gr "font consolus bold 20"                                      ' set font
#gr "down"                                                       ' pen ready to draw
for y = 1 to ROWS                                                ' initialize screen with grid
    for x = 1 to cols
        n = n + 1                                                ' index hex buttons
        if x mod 2 = 0 then yoff2 = .5*SIDE*SQR3 else yoff2 = 0  ' is this column lower than first column?
        cx = x*1.5*SIDE + xoff : cy = y*SIDE*SQR3 + YOFF + yoff2 ' calc hex key centers
        LX(n) = cx : LY(n) = cy                                  ' save hex key center positions
        call drawHex n, "green"                                  ' draw key
    next
next
#gr "flush"
wait
sub charIn H$, c$                                                'is c$, the key pressed, one of the letters in L$?
    for i = 1 to LMAX                                            'if so was it selected already? or select it.
        if upper$(c$) = L$(i) and LSELECTED(i) = 0 then call drawHex i, "blue" : #gr "flush" : exit sub
    next
end sub
sub lButtonUp H$, mx, my                                         ' mx, my are mouse button release locations
    for i = 1 to LMAX                                            ' is distance from click within radius of non-selected button?
        if sqr((mx-LX(i))^2+(my-LY(i))^2) <= SIDE*.5*SQR3 and LSELECTED(i) = 0 then call drawHex i, "blue" : #gr "flush" : exit sub
    next
end sub
sub drawHex i, c$
    #gr "size 1"
    #gr "backcolor ";c$                                          ' color location
    #gr "place ";LX(i) + .5;" ";LY(i);"; circlefilled ";SIDE * .5 * SQR3
    #gr "color black"                                            ' color letter and grid, thick line #10
    #gr "size 10"
    call Hex LX(i), LY(i)                                        ' draw hexagon cell
    call stext LX(i) - 10, LY(i) + 11, L$(i)                     ' draw letter
    if c$ = "blue" then                                          ' update Selection tracking and display
        LSELECTED(i) = 1
        SELECTED$ = SELECTED$ + L$(i)
        call stext 0, (ROWS + 2) * SIDE * SQR3 + YOFF, SELECTED$ 'are we done yet? are all letters selected?
        if len(SELECTED$) = LMAX then notice "All the keys have been used. Goodbye" : call quit "#gr"
    end if
end sub
sub Hex x0, y0                                                    ' draw hexagon around x0, y0 with 6 lines
    for i = 0 to 6
        x1 = x0 + SIDE * cos(i * PI3) : y1 = y0 + SIDE * sin(i * PI3)
        if i > 0 then #gr "line ";lastx;" ";lasty;" ";x1;" ";y1
        lastx = x1 : lasty = y1
    next
end sub
sub stext x, y, message$                                          ' note: y is the bottom edge not top
    #gr "place ";x;" ";y;";|";message$                            ' print message at x, y
end sub
sub quit H$                                                       ' close window ie click top right x box
    close #H$ : end
end sub

Just Basic has a very different way of doing screens and graphics.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: Honeycombs _ Rosetta Code
« Reply #1 on: October 30, 2021, 03:16:15 pm »
excellent bplus 😀

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Honeycombs _ Rosetta Code
« Reply #2 on: October 30, 2021, 04:20:30 pm »
Thanks @jack   Just Basic has no Paint and no Triangle Fill though Andy Amaya came up with good one.

What JB has is adjustable line thickness, so to fill the Hexagons I used Filled Circles and then I drew very thick lined Hexagons to look like Honeycomb. The lines covered all the over lapping parts of circles. :)

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Honeycombs _ Rosetta Code
« Reply #3 on: October 30, 2021, 05:50:05 pm »
That's cool.  Good coding, beeplus.  :)

I like to see code along with other translations for comparison.  Rosettacode is really a neat site.

- Dav

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Honeycombs _ Rosetta Code
« Reply #4 on: October 30, 2021, 06:05:06 pm »
You mentioned about JB having thick lines.  I wished QB64 had it built-in, but Fellippe wrote a really cool easy to use SUB for doing that which is worth mentioning: https://www.qb64.org/forum/index.php?topic=116.0

- Dav
« Last Edit: October 30, 2021, 07:54:15 pm by Dav »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Honeycombs _ Rosetta Code
« Reply #5 on: October 30, 2021, 08:42:21 pm »
Thanks @Dav, you must know I've debated thickening those lines. I didn't know you could size lines with Draw.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Honeycombs _ Rosetta Code
« Reply #6 on: October 31, 2021, 09:57:54 pm »
Well I looked into Fellippe's Thick Lines and needed a color parameter added to the sub so I tried a couple of my own Thick Line Subs. Drawing Rectangle Thick lines leaves gaps where the two lines meet. I tried to fix with filled circles at the end points but a circle with radius 1/2 thickness left knobs and subtracting 1 from radius still left gaps in places.
So I pulled out my thick line by filled circles like a ball point pen, OK no gaps or knobs at meeting point but sort of jagged at some angles still the best I think.

I have the 3 versions, 2 commented out that you can try. I also had to change size of font because letter background was drawing over the blacklines:

Code: QB64: [Select]
  1. _Title "Honeycombs thic lines - Rosetta Code" ' b+ 2021-10-30 trans from
  2. ' Honeycomb Rosetta.txt for JB v2 2018-11-24 B+ finish Rosetta Challenge
  3. ' 2021-10-30 complete overhaul except for grid drawing numbers and names.
  4. ' 2021-10-31 thicken lines a little, fix font for thicker lines.
  5.  
  6. ' ===================== Try alternate Cols and Rows for HoneyComb ===============================
  7.  
  8. Const Cols = 5, Rows = 4, LMax = Cols * Rows ' hex grid  <<<<<<<<<<<<<<  as Rosetta Requires
  9. 'Const Cols = 4, Rows = 5, LMax = Cols * Rows ' hex grid <<<<<<<<<<<<<< reverse
  10. 'Const Cols = 6, Rows = 5, LMax = Cols * Rows ' hex grid <<<<<<<<<<<<<< More than just Letters
  11. 'Const Cols = 13, Rows = 2, LMax = Cols * Rows ' hex grid do exactly whole alphabet!
  12.  
  13.  
  14. ' global   SELECTED$ ' all caps for globals
  15. Const Pi3 = _Pi / 3, Sqr3 = Sqr(3), Side = 30 '           constants for Hexagon making
  16. Const Xoff = 100 - 1.5 * Side, Yoff = 100 - Side * Sqr3 ' center grid with offsets on screen
  17. Const XMax = 2 * Xoff + Cols * 1.5 * Side + 1.5 * Side '  screen display size needed
  18. Const YMax = 2 * Yoff + (Rows + 2) * Side * Sqr3
  19.  
  20. Dim Shared L$(LMax), LX(LMax), LY(LMax), LSELECTED(LMax), Selected$ ' save letter and hex center positions by index
  21.  
  22. Randomize Timer ' get new grid when we start
  23. For i = 1 To LMax ' get letters array loaded
  24.     L$(i) = Chr$(64 + i)
  25. For i = LMax To 2 Step -1 ' shuffle letters Fisher - Yates
  26.     Swap L$(i), L$(Int(Rnd * i) + 1)
  27.  
  28. Screen _NewImage(XMax, YMax, 32) 'graphics custom size RGBA colors
  29. _Delay .25 ' get screen loaded before trying to move
  30. _ScreenMove _Middle ' center  screen
  31.  
  32. f& = _LoadFont("Consolab.ttf", 36) ' >>>>>>>>>>>> from Windows 10 Fonts
  33. Color , _RGB32(200, 200, 220): Cls ' draw grid before selections
  34. For y = 1 To Rows ' initialize screen with grid
  35.     For x = 1 To Cols
  36.         n = n + 1 ' index hex buttons
  37.         If x Mod 2 = 0 Then yoff2 = .5 * Side * Sqr3 Else yoff2 = 0 ' is this column lower than first column?
  38.         cx = x * 1.5 * Side + Xoff: cy = y * Side * Sqr3 + Yoff + yoff2 ' calc hex key centers
  39.         LX(n) = cx: LY(n) = cy ' save hex key center positions
  40.         drawHex n, 0 ' draw key
  41.     Next
  42.  
  43. While _KeyDown(27) = 0 ' allow user to select letters by key or mouse
  44.     k$ = InKey$
  45.     If Len(k$) Then
  46.         For i = 1 To LMax 'if so was it selected already? or select it.
  47.             If UCase$(k$) = L$(i) And LSELECTED(i) = 0 Then drawHex i, 1: Exit For
  48.         Next
  49.     End If
  50.     While _MouseInput: Wend ' polls mouse
  51.     mx = _MouseX: my = _MouseY: mb = _MouseButton(1)
  52.     If mb Then
  53.         For i = 1 To LMax ' is distance from click within radius of non-selected button?
  54.             If Sqr((mx - LX(i)) ^ 2 + (my - LY(i)) ^ 2) <= Side * .5 * Sqr3 And LSELECTED(i) = 0 Then drawHex i, 1
  55.         Next
  56.     End If
  57.  
  58. Sub drawHex (i, selectedTF)
  59.     If selectedTF = 0 Then
  60.         Color _RGB32(255, 0, 0), _RGB32(255, 255, 0)
  61.     Else
  62.         Color _RGB32(0, 0, 0), _RGB32(255, 0, 255)
  63.     End If
  64.     For a = 0 To 6
  65.         x1 = LX(i) + Side * Cos(a * Pi3): y1 = LY(i) + Side * Sin(a * Pi3)
  66.  
  67.         ' =============================== Different versions of Thick Lines ======================
  68.         'If a > 0 Then Line (lastx, lasty)-(x1, y1), _RGB32(0, 0, 0) ' original no thick lines
  69.  
  70.         'If a > 0 Then thic lastx, lasty, x1, y1, 2, _RGB32(0, 0, 0) ' these rectangle thick lines
  71.         ' leave gaps where they meet at angles rounded with circles they leave knobs, r-1 they
  72.         ' still leave gaps!
  73.  
  74.         'Best
  75.         If a > 0 Then thic2 lastx, lasty, x1, y1, 2, _RGB32(0, 0, 0)
  76.         ' these thick lines are draw with filled circles like ball point pen
  77.         '=========================================================================================
  78.  
  79.         lastx = x1: lasty = y1
  80.     Next
  81.     Paint (LX(i), LY(i)), _BackgroundColor, _RGB32(0, 0, 0)
  82.     _PrintString (LX(i) - 9, LY(i) - 11), L$(i)
  83.     If selectedTF Then ' show the order of selection
  84.         Color _RGB32(0, 0, 0), _RGB32(200, 200, 220)
  85.         LSELECTED(i) = 1
  86.         Selected$ = Selected$ + L$(i)
  87.         centerText 0, _Width, _Height - 60, Mid$(Selected$, 1, Int(LMax / 2))
  88.         If Len(Selected$) > 10 Then
  89.             centerText 0, _Width, _Height - 20, Mid$(Selected$, Int(LMax / 2) + 1)
  90.             If Len(Selected$) = LMax Then Beep ' all have been selected
  91.         End If
  92.     End If
  93.  
  94. Sub centerText (x1, x2, midy, s$) ' ' if you want to center fit a string between two goal posts x1, and x2
  95.     _PrintString ((x1 + x2) / 2 - _PrintWidth(s$) / 2, midy - _FontHeight(_Font) / 2), s$
  96.  
  97. 'update 2020-01-24 to include PD2 inside the sub
  98. Sub thic (x1, y1, x2, y2, thick, K As _Unsigned Long)
  99.     Dim PD2 As Double, t2 As Single, a As Single, x3 As Single, y3 As Single, x4 As Single, y4 As Single
  100.     Dim x5 As Single, y5 As Single, x6 As Single, y6 As Single
  101.     PD2 = 1.570796326794897
  102.     t2 = thick / 2
  103.     If t2 < 1 Then t2 = 1
  104.     a = _Atan2(y2 - y1, x2 - x1)
  105.     x3 = x1 + t2 * Cos(a + PD2)
  106.     y3 = y1 + t2 * Sin(a + PD2)
  107.     x4 = x1 + t2 * Cos(a - PD2)
  108.     y4 = y1 + t2 * Sin(a - PD2)
  109.     x5 = x2 + t2 * Cos(a + PD2)
  110.     y5 = y2 + t2 * Sin(a + PD2)
  111.     x6 = x2 + t2 * Cos(a - PD2)
  112.     y6 = y2 + t2 * Sin(a - PD2)
  113.     ftri x6, y6, x4, y4, x3, y3, K
  114.     ftri x3, y3, x5, y5, x6, y6, K
  115.     fcirc x1, y1, t2 - 1, _RGB32(0, 0, 0) ' close gaps where two lines meet
  116.     fcirc x2, y2, t2 - 1, _RGB32(0, 0, 0)
  117.  
  118. '2019-12-16 fix by Steve saves some time with STATIC and saves and restores last dest
  119. Sub ftri (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
  120.     Dim D As Long
  121.     Static a&
  122.     D = _Dest
  123.     If a& = 0 Then a& = _NewImage(1, 1, 32)
  124.     _Dest a&
  125.     _DontBlend a& '  '<<<< new 2019-12-16 fix
  126.     PSet (0, 0), K
  127.     _Blend a& '<<<< new 2019-12-16 fix
  128.     _Dest D
  129.     _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
  130.  
  131. Sub fcirc (CX As Long, CY As Long, R As Long, C As _Unsigned Long)
  132.     Dim Radius As Long, RadiusError As Long
  133.     Dim X As Long, Y As Long
  134.     Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
  135.     If Radius = 0 Then PSet (CX, CY), C: Exit Sub
  136.     Line (CX - X, CY)-(CX + X, CY), C, BF
  137.     While X > Y
  138.         RadiusError = RadiusError + Y * 2 + 1
  139.         If RadiusError >= 0 Then
  140.             If X <> Y + 1 Then
  141.                 Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  142.                 Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  143.             End If
  144.             X = X - 1
  145.             RadiusError = RadiusError - X * 2
  146.         End If
  147.         Y = Y + 1
  148.         Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  149.         Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  150.     Wend
  151.  
  152. 'this version needs fcirc and is pretty inefficient but once and a while it comes in handy
  153. Sub thic2 (x1, y1, x2, y2, rThick, K As _Unsigned Long)
  154.     'x1, y1 is one endpoint of line
  155.     'x2, y2 is the other endpoint of the line
  156.     'rThick is the radius of the tiny circles that will be drawn
  157.     '   from one end point to the other to create the thick line
  158.     'Yes, the line will then extend beyond the endpoints with circular ends.
  159.     rThick = Int(rThick / 2): stepx = x2 - x1: stepy = y2 - y1
  160.     length = Int((stepx ^ 2 + stepy ^ 2) ^ .5)
  161.     If length Then
  162.         dx = stepx / length: dy = stepy / length
  163.         For i = 0 To length
  164.             fcirc x1 + dx * i, y1 + dy * i, rThick, K
  165.         Next
  166.     Else
  167.         fcirc x1, y1, rThick, K
  168.     End If
  169.  
  170.  
  171.