Basic Sudoku Grid — Bokeh

A standard 9×9 Sudoku grid with proper visual hierarchy showing 3×3 box regions. Thick lines separate the nine boxes while thin lines divide individual cells. The clean black-and-white design is optimized for printing and solving puzzles.

Basic Sudoku Grid rendered with Bokeh

Python source (Bokeh)

""" anyplot.ai
sudoku-basic: Basic Sudoku Grid
Library: bokeh 3.9.1 | Python 3.13.14
Quality: 90/100 | Updated: 2026-06-25
"""

import io
import os
import sys
import time
from pathlib import Path


# Remove script directory from sys.path to avoid shadowing the bokeh package
sys.path = [p for p in sys.path if Path(p).resolve() != Path(__file__).resolve().parent]

from bokeh.io import output_file, save
from bokeh.models import ColumnDataSource, LabelSet
from bokeh.plotting import figure
from PIL import Image
from selenium import webdriver
from selenium.webdriver.chrome.options import Options


# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
BRAND_GREEN = "#009E73"

# Data - 9x9 Sudoku puzzle (0 = empty)
grid = [
    [0, 0, 0, 2, 6, 0, 7, 0, 1],
    [6, 8, 0, 0, 7, 0, 0, 9, 0],
    [1, 9, 0, 0, 0, 4, 5, 0, 0],
    [8, 2, 0, 1, 0, 0, 0, 4, 0],
    [0, 0, 4, 6, 0, 2, 9, 0, 0],
    [0, 5, 0, 0, 0, 3, 0, 2, 8],
    [0, 0, 9, 3, 0, 0, 0, 7, 4],
    [0, 4, 0, 0, 5, 0, 0, 3, 6],
    [7, 0, 3, 0, 1, 8, 0, 0, 0],
]

# Alternating 3x3 box fills — brand-green alpha tint for clear regional contrast
# Higher alpha in dark mode compensates for the lower ambient contrast
BOX_TINT_ALPHA = 0.10 if THEME == "light" else 0.20
box_rects = {"x": [], "y": [], "fill_color": [], "fill_alpha": []}
for box_row in range(3):
    for box_col in range(3):
        cx = box_col * 3 + 1.5
        cy = (2 - box_row) * 3 + 1.5
        if (box_row + box_col) % 2 == 0:
            color = BRAND_GREEN
            alpha = BOX_TINT_ALPHA
        else:
            color = PAGE_BG
            alpha = 1.0
        box_rects["x"].append(cx)
        box_rects["y"].append(cy)
        box_rects["fill_color"].append(color)
        box_rects["fill_alpha"].append(alpha)
box_source = ColumnDataSource(box_rects)

# Number labels — given clue numbers in brand green to visually distinguish
# pre-filled cells from empty solving space
number_rows = {"x": [], "y": [], "text": [], "text_color": []}
for row in range(9):
    for col in range(9):
        value = grid[row][col]
        if value != 0:
            number_rows["x"].append(col + 0.5)
            number_rows["y"].append(8 - row + 0.5)
            number_rows["text"].append(str(value))
            number_rows["text_color"].append(BRAND_GREEN)
numbers = ColumnDataSource(number_rows)

# Thin lines for individual cells
thin_rows = {"x0": [], "y0": [], "x1": [], "y1": []}
for i in range(10):
    thin_rows["x0"].extend([0, i])
    thin_rows["y0"].extend([i, 0])
    thin_rows["x1"].extend([9, i])
    thin_rows["y1"].extend([i, 9])
thin_lines = ColumnDataSource(thin_rows)

# Thick lines for 3x3 box boundaries
thick_rows = {"x0": [], "y0": [], "x1": [], "y1": []}
for i in range(0, 10, 3):
    thick_rows["x0"].extend([0, i])
    thick_rows["y0"].extend([i, 0])
    thick_rows["x1"].extend([9, i])
    thick_rows["y1"].extend([i, 9])
thick_lines = ColumnDataSource(thick_rows)

# Title — correct format with language token; 42 chars < 67 baseline, no scaling
title = "sudoku-basic · python · bokeh · anyplot.ai"
n = len(title)
ratio = 67 / n if n > 67 else 1.0
title_pt = f"{round(50 * ratio)}pt"

# Plot — 2400×2400 square canvas (canonical 1:1 for symmetric grid)
p = figure(
    width=2400,
    height=2400,
    x_range=(-0.25, 9.25),
    y_range=(-0.25, 9.25),
    title=title,
    tools="",
    toolbar_location=None,
    background_fill_color=PAGE_BG,
    border_fill_color=PAGE_BG,
    min_border_top=120,
    min_border_bottom=80,
    min_border_left=80,
    min_border_right=80,
)

# Draw alternating box tints first (underneath grid lines)
p.rect(
    x="x",
    y="y",
    width=3,
    height=3,
    fill_color="fill_color",
    fill_alpha="fill_alpha",
    line_color=None,
    source=box_source,
)

# Thin cell lines, then thick box boundaries on top
p.segment(x0="x0", y0="y0", x1="x1", y1="y1", source=thin_lines, line_width=3, line_color=INK)
p.segment(x0="x0", y0="y0", x1="x1", y1="y1", source=thick_lines, line_width=10, line_color=INK)

# Centered bold numbers — text_color per-glyph from source (brand green for given clues)
p.add_layout(
    LabelSet(
        x="x",
        y="y",
        text="text",
        source=numbers,
        text_font_size="50pt",
        text_font_style="bold",
        text_align="center",
        text_baseline="middle",
        text_color="text_color",
    )
)

# Style — hide all axis/grid chrome; center the title
p.title.text_font_size = title_pt
p.title.align = "center"
p.title.text_font_style = "bold"
p.title.text_color = INK
p.axis.visible = False
p.grid.visible = False
p.outline_line_color = None

# Save HTML artifact
output_file(f"plot-{THEME}.html", title=title)
save(p)

# Screenshot with headless Chrome — add 200px height buffer to absorb ~139px
# Chrome UI overhead; crop to exact canvas dims afterwards.
W, H = 2400, 2400
opts = Options()
for arg in (
    "--headless=new",
    "--no-sandbox",
    "--disable-dev-shm-usage",
    "--disable-gpu",
    f"--window-size={W},{H + 200}",
    "--hide-scrollbars",
    "--force-device-scale-factor=1",
):
    opts.add_argument(arg)
driver = webdriver.Chrome(options=opts)
driver.set_window_size(W, H + 200)
driver.get(f"file://{Path(f'plot-{THEME}.html').resolve()}")
time.sleep(3)
raw = driver.get_screenshot_as_png()
driver.quit()
img = Image.open(io.BytesIO(raw)).crop((0, 0, W, H))
img.save(f"plot-{THEME}.png")

Part of Basic Sudoku Grid on anyplot.ai.

Other implementations