Overview
Random puzzles generate unique, irregular piece shapes using a randomized approach. Unlike the regular patterns of rectangular or hexagonal puzzles, random puzzles create organic, unpredictable boundaries that make each puzzle truly one-of-a-kind.
Piece Count Variations
make_rand_pieces <- function (n) {
ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = n,
seed = 42
) +
scale_fill_viridis_c (option = "inferno" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = paste0 (n, " pieces" ))
}
print (make_rand_pieces (5 ) + make_rand_pieces (10 ) + make_rand_pieces (20 ))
# Generate piece count previews in a grid
counts <- c (5 , 10 , 20 )
items <- lapply (counts, function (n) {
generate_puzzle (type = "random" , grid = c (n), size = c (200 , 200 ), seed = 42 , fill_palette = "inferno" )
})
render_puzzle_grid (items, ncol = 3 , labels = paste (counts, "pieces" ))
Corner Variations
The n_corner parameter controls the complexity of each piece’s shape:
make_rand_corners <- function (nc, label) {
ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = 8 ,
n_corner = nc,
seed = 42
) +
scale_fill_viridis_c (option = "plasma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = label)
}
print (make_rand_corners (3 , "3 corners" ) + make_rand_corners (4 , "4 corners" ) +
make_rand_corners (6 , "6 corners" ) + make_rand_corners (8 , "8 corners" ))
# Generate corner variation previews in a grid
corners <- c (3 , 4 , 6 , 8 )
items <- lapply (corners, function (nc) {
generate_puzzle (type = "random" , grid = c (8 ), size = c (200 , 200 ), seed = 42 , n_corner = nc, fill_palette = "plasma" )
})
render_puzzle_grid (items, ncol = 4 , labels = paste (corners, "corners" ))
Color Palettes
make_rand_palette <- function (pal) {
ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = 10 ,
seed = 42
) +
scale_fill_viridis_c (option = pal, guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = pal)
}
print ((make_rand_palette ("viridis" ) + make_rand_palette ("magma" ) + make_rand_palette ("plasma" )) /
(make_rand_palette ("inferno" ) + make_rand_palette ("cividis" ) + make_rand_palette ("turbo" )))
# Generate all palette previews and combine into a grid
palettes <- c ("viridis" , "magma" , "plasma" , "inferno" , "cividis" , "turbo" )
items <- lapply (palettes, function (pal) {
generate_puzzle (type = "random" , grid = c (10 ), size = c (200 , 200 ), seed = 42 , fill_palette = pal)
})
render_puzzle_grid (items, ncol = 3 , labels = palettes)
Fill Direction
Control the spatial order of color assignment. This is distinct from palette_invert which reverses the dark↔︎light ends of the palette.
make_direction_plot <- function (dir) {
ggplot () +
geom_puzzle_random (
aes (fill = after_stat (fill_order)),
n_interior = 8 ,
fill_direction = dir,
seed = 42
) +
scale_fill_viridis_c (option = "viridis" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = paste0 ("fill_direction = \" " , dir, " \" " ))
}
print (make_direction_plot ("forward" ) + make_direction_plot ("reverse" ))
directions <- c ("forward" , "reverse" )
items <- lapply (directions, function (dir) {
generate_puzzle (type = "random" , grid = c (8 ), size = c (200 , 200 ), seed = 42 , fill_palette = "viridis" , fill_direction = dir)
})
render_puzzle_grid (items, ncol = 2 , labels = paste0 ("fill_direction = \" " , directions, " \" " ))
Offset (Separation)
make_rand_offset <- function (off) {
ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = 9 ,
offset = off, seed = 42
) +
scale_fill_viridis_c (option = "cividis" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = paste0 ("offset = " , off))
}
print (make_rand_offset (0 ) + make_rand_offset (5 ) + make_rand_offset (10 ) + make_rand_offset (20 ))
# Generate offset previews in a grid
offsets <- c (0 , 5 , 10 , 20 )
items <- lapply (offsets, function (off) {
generate_puzzle (type = "random" , grid = c (9 ), size = c (200 , 200 ), seed = 42 , offset = off, fill_palette = "cividis" )
})
render_puzzle_grid (items, ncol = 4 , labels = paste ("offset =" , offsets))
Seed Variations
Each seed creates a completely unique puzzle:
make_rand_seed <- function (s) {
ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = 8 ,
seed = s
) +
scale_fill_viridis_c (option = "turbo" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = paste0 ("seed = " , s))
}
print (make_rand_seed (1 ) + make_rand_seed (42 ) + make_rand_seed (123 ) + make_rand_seed (999 ))
# Generate seed variation previews in a grid
seeds <- c (1 , 42 , 123 , 999 )
items <- lapply (seeds, function (s) {
generate_puzzle (type = "random" , grid = c (8 ), size = c (200 , 200 ), seed = s, fill_palette = "turbo" )
})
render_puzzle_grid (items, ncol = 4 , labels = paste ("seed =" , seeds))
Random puzzles handle any aspect ratio - wide, square, or tall. See the Aspect Ratios Tutorial for examples comparing all puzzle types.
Fusion Groups
Merge pieces together using PILES notation:
# Standard
print (ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = 6 ,
seed = 42
) +
scale_fill_viridis_c (option = "magma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "Standard" ))
# Adjacent pieces fused
print (ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = 6 ,
seed = 42 ,
fusion_groups = "1-2-3,5-6"
) +
scale_fill_viridis_c (option = "magma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "Pieces fused" ))
# Standard
result_standard <- generate_puzzle (
type = "random" ,
grid = c (6 ),
size = c (200 , 200 ),
seed = 42 ,
fill_palette = "magma"
)
render_puzzle_preview (result_standard, title = "Standard" )
# Adjacent pieces fused
result_fused <- generate_puzzle (
type = "random" ,
grid = c (6 ),
size = c (200 , 200 ),
seed = 42 ,
fill_palette = "magma" ,
fusion_groups = "1-2-3,5-6"
)
render_puzzle_preview (result_fused, title = "Pieces fused" )
Large Random Puzzle
ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = 30 ,
width = 400 , height = 300 ,
seed = 456
) +
scale_fill_viridis_c (option = "turbo" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "30-Piece Random Puzzle" )
result <- generate_puzzle (
type = "random" ,
grid = c (30 ),
size = c (300 , 400 ),
seed = 456 ,
fill_palette = "turbo"
)
render_puzzle_preview (result, max_width = "600px" )
Parameters Reference
n_interior
integer
12
Number of interior points (influences piece count)
n_corner
integer
4
Corners per piece (3-8)
seed
integer
random
Random seed for reproducibility
offset
numeric
0 (mm)
Piece separation distance
tabsize
numeric
6 (%)
Tab size as percentage of edge length
jitter
numeric
2 (%)
Randomness in tab shape as percentage
min_tab_size
numeric
0 (mm)
Minimum tab size in millimeters
max_tab_size
numeric
auto (random) / Inf (others)
Maximum tab size in mm. Auto-calculated for random puzzles to prevent overlapping tabs
fusion_groups
string
NULL
PILES notation for fusing pieces
Corner Complexity Guide
3
Triangular
Simple, angular
4
Quadrilateral
Classic, balanced
5
Pentagonal
Natural, organic
6
Hexagonal
Honeycomb-like
7-8
Complex
Highly irregular
When to Use Random Puzzles
Random puzzles are perfect for:
Maximum uniqueness : No two puzzles alike
Artistic applications : Abstract, modern designs
Challenge modes : Irregular shapes are harder to assemble
Custom piece counts : Exact control over difficulty
Code Example
ggplot () +
geom_puzzle_random (
aes (fill = after_stat (piece_id)),
n_interior = 15 ,
width = 400 , height = 300 , # width=400mm, height=300mm
n_corner = 5 ,
seed = 42 , offset = 5
) +
scale_fill_viridis_c (option = "inferno" , guide = "none" ) +
coord_fixed () +
theme_puzzle ()
result <- generate_puzzle (
type = "random" ,
grid = c (15 ), # 15 pieces
size = c (300 , 400 ), # height=300mm, width=400mm
seed = 42 ,
n_corner = 5 , # Pentagonal pieces
offset = 5
)
render_puzzle_preview (result)
The API approach returns a result object that can be saved to SVG:
writeLines (result$ svg_content, "random_puzzle.svg" )