Honeycomb Grid¶
By the end of this lab you'll be able to:
- Write a
hexagon(x, y, size)function and call it from nested loops - Understand the offset row pattern for tiling hexagons
- See why hexagons tile the plane perfectly while squares leave gaps
Dozens of filled hexagons tile the canvas in alternating yellow and orange — a perfect honeycomb just like a beehive.
Welcome to the Honeycomb!
Hexagons are special: they tile the plane perfectly with no gaps or overlaps.
In this lab you'll discover how to place them using a neat offset-row trick.
Let's code it together!
How the Tiling Works¶
Each hexagon is drawn by a function. The key to tiling is offset rows: - Odd rows shift right by half a hexagon width - The vertical spacing between rows is the hexagon's height × 0.75
The hexagon height is size * 2 (vertex-to-vertex) and width is size * sqrt(3) (flat-to-flat, approximately size * 1.732).
Sample Code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
What Do You Think Will Happen?
A hexagon has 6 sides. The exterior angle at each corner is 360 / 6 = 60°.
After drawing all 6 sides, how many total degrees has Monty turned?
Make your guess — then click Run to find out!
Try It Now¶
6 × 60° = 360° — a full rotation, just like every regular polygon. Were you right?
How It Works¶
The hexagon() function uses setheading(30) so each hexagon starts at a 30° angle, producing a pointy-top hexagon. Resetting the heading at the start of every call is essential — you never know what angle Monty is at when the function is called.
The offset formula col_w / 2 if row % 2 == 1 else 0 shifts odd rows right by half the hex width, staggering them so each hexagon nestles into the gap between two hexagons in the row above.
Explanation Table¶
| Line | What it does |
|---|---|
def hexagon(x, y, size, color) |
Reusable function: draws one hexagon at position (x,y) |
monty.setheading(30) |
Start at 30° to draw a pointy-top hexagon — critical for correct tiling |
monty.left(60) |
Exterior angle of a hexagon (360/6) |
h = size * 2 |
Height of a pointy-top hexagon (vertex to vertex) |
col_w = size * math.sqrt(3) |
Width of a pointy-top hexagon (flat edge to flat edge) |
offset = col_w / 2 if row % 2 == 1 else 0 |
Odd rows shift right by half the hex width |
y = 150 - row * h * 0.75 |
Rows overlap by 25% of height so hexagons interlock |
Learning Check¶
Spot the Bug!
The program below draws hexagons but they don't tile — there are gaps and overlaps!
The row offset formula is wrong. Fix it so odd rows shift by exactly size pixels.
Change col_w to col_w / 2 in the offset line — the shift should be half the hex width, not the full width.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
How the Math WorksThe Offset:¶
Hexagons cannot sit directly on top of each other in a standard grid. By using if r % 2 == 1: x += w / 2, we shift every odd row slightly to the right so it nests perfectly inside the valleys of the even row.Vertical Distance: The vertical step size (size * 1.5) ensures that rows overlap perfectly without crashing into each other or leaving spaces.
Alternative Package Options¶
If you are building a specific type of application, specialized libraries can save you from writing the grid math manually:
For Games & Simulation¶
Use the Red Blob Games Hex Grid Guide coordinate logic, or use the hexy library to manage neighbor tracking and axial coordinates easily.For Data Visualization: Use matplotlib.pyplot.hexbin() to quickly turn data coordinates into a beautiful hexagonal heatmap layout.For GIS & Maps: Look into h3-pandas or geohexgrid to map geographic coordinates directly onto a global honeycomb grid.
Experiments¶
-
Change the colors. Use
['royalblue', 'navy']for a blue honeycomb. You'll know it worked when the colors change but the tiling stays perfect. -
Make the hexagons bigger. Change
size = 30tosize = 45and reduce the row/col ranges. You'll know it worked when fewer, larger hexagons tile the canvas. -
Remove the fill. Delete the
begin_fill()andend_fill()lines from the function. You'll know it worked when the honeycomb shows only outlines. -
Color by row only. Change
colors[(row + col) % 2]tocolors[row % 2]. All cells in a row become the same color. You'll know it worked when horizontal bands of alternating color appear.
Incredible Work!
You built a full tiling engine with a function, nested loops, and offset-row geometry!
Bees figured out this pattern millions of years ago — and now you know the math behind it.
Up next: City Skyline — composing a scene from reusable building functions.