shikaku

package
v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2026 License: MIT Imports: 18 Imported by: 0

README

Shikaku

Divide the grid into rectangles so each contains exactly one number equal to its area.

Shikaku gameplay

How to Play

The grid contains numbered clues. Your goal is to partition the entire grid into non-overlapping rectangles where each rectangle contains exactly one clue and the clue's value equals the rectangle's area.

  1. Navigate to a numbered clue and press Enter or Space to select it.
  2. Press arrow keys to expand the rectangle in each direction.
  3. Press Shift+Arrow to shrink a side if you overshot.
  4. Press Enter or Space to confirm when the preview is green.
  5. Press Backspace to cancel a draft or delete a placed rectangle.

Controls

Navigation Mode
Key Action
Arrow keys / WASD / hjkl Move cursor
Enter / Space Select clue for expansion
Backspace Cancel preview or delete rectangle at cursor
Ctrl+R Reset puzzle
Ctrl+H Toggle full help
Escape Return to main menu
Expansion Mode (after selecting a clue)
Key Action
Arrow keys / WASD / hjkl Expand rectangle in that direction
Shift+Arrow / WASD / HJKL Shrink rectangle from that side
Enter / Space Confirm placement (green preview only)
Backspace Cancel, discard preview

Modes

Mode Grid Max Rect Description
Mini 5x5 5x5 5 Gentle introduction
Easy 7x7 7x7 8 Straightforward puzzles
Medium 8x8 8x8 12 Moderate challenge
Hard 10x10 10x10 15 Requires careful planning
Expert 12x12 12x12 20 Maximum challenge

Quick Start

puzzletea new shikaku mini-5x5
puzzletea new shikaku easy-7x7
puzzletea new shikaku hard-10x10

Documentation

Overview

Package shikaku implements the Shikaku rectangle-partition puzzle game.

Index

Constants

This section is empty.

Variables

View Source
var DefaultKeyMap = KeyMap{
	CursorKeyMap: game.DefaultCursorKeyMap,
	ShrinkUp: key.NewBinding(
		key.WithKeys("shift+up", "K", "W"),
		key.WithHelp("shift+↑", "Shrink up"),
	),
	ShrinkDown: key.NewBinding(
		key.WithKeys("shift+down", "J", "S"),
		key.WithHelp("shift+↓", "Shrink down"),
	),
	ShrinkLeft: key.NewBinding(
		key.WithKeys("shift+left", "H", "A"),
		key.WithHelp("shift+←", "Shrink left"),
	),
	ShrinkRight: key.NewBinding(
		key.WithKeys("shift+right", "L", "D"),
		key.WithHelp("shift+→", "Shrink right"),
	),
	Select: key.NewBinding(
		key.WithKeys("enter", "space"),
		key.WithHelp("enter/space", "Select/Confirm"),
	),
	Delete: key.NewBinding(
		key.WithKeys("backspace"),
		key.WithHelp("bkspc", "Cancel/Delete"),
	),
}
View Source
var Definition = puzzle.NewDefinition(puzzle.DefinitionSpec{
	Name:         "Shikaku",
	Description:  "Divide the grid into rectangles with set sizes.",
	Aliases:      []string{"rectangles"},
	Modes:        ModeDefinitions,
	DailyModeIDs: puzzle.SelectModeIDsByIndex(ModeDefinitions, 1, 2),
})
View Source
var HelpContent string
View Source
var ModeDefinitions = gameentry.BuildModeDefs(Modes)
View Source
var Modes = []game.Mode{
	NewMode("Mini 5x5", "5x5 grid, gentle introduction.", 5, 5, 5),
	NewMode("Easy 7x7", "7x7 grid, straightforward puzzles.", 7, 7, 8),
	NewMode("Medium 8x8", "8x8 grid, moderate challenge.", 8, 8, 12),
	NewMode("Hard 10x10", "10x10 grid, requires careful planning.", 10, 10, 15),
	NewMode("Expert 12x12", "12x12 grid, maximum challenge.", 12, 12, 20),
}
View Source
var PDFPrintAdapter = printAdapter{}

Functions

func New

func New(mode ShikakuMode, puzzle Puzzle) game.Gamer

New creates a new Shikaku game model.

Types

type Clue

type Clue struct {
	ID    int `json:"id"`
	X     int `json:"x"`
	Y     int `json:"y"`
	Value int `json:"value"` // required rectangle area
}

Clue represents a numbered cell in the grid.

type KeyMap

type KeyMap struct {
	game.CursorKeyMap
	ShrinkUp    key.Binding
	ShrinkDown  key.Binding
	ShrinkLeft  key.Binding
	ShrinkRight key.Binding
	Select      key.Binding
	Delete      key.Binding
}

type Model

type Model struct {
	// contains filtered or unexported fields
}

Model implements game.Gamer for Shikaku.

func ImportModel

func ImportModel(data []byte) (*Model, error)

ImportModel reconstructs a Model from saved JSON data.

func (Model) GetDebugInfo

func (m Model) GetDebugInfo() string

func (Model) GetFullHelp

func (m Model) GetFullHelp() [][]key.Binding

func (Model) GetSave

func (m Model) GetSave() ([]byte, error)

func (Model) Init

func (m Model) Init() tea.Cmd

func (Model) IsSolved

func (m Model) IsSolved() bool

func (Model) Reset

func (m Model) Reset() game.Gamer

func (Model) SetTitle

func (m Model) SetTitle(t string) game.Gamer

func (Model) Update

func (m Model) Update(msg tea.Msg) (game.Gamer, tea.Cmd)

func (Model) View

func (m Model) View() string

type Puzzle

type Puzzle struct {
	Width, Height int
	Clues         []Clue
	Rectangles    []Rectangle // player-placed
	// contains filtered or unexported fields
}

Puzzle holds the full state of a Shikaku game.

func GeneratePuzzle

func GeneratePuzzle(width, height, maxRectSize int) (Puzzle, error)

GeneratePuzzle creates a Shikaku puzzle with random RNG.

func GeneratePuzzleSeeded

func GeneratePuzzleSeeded(width, height, maxRectSize int, rng *rand.Rand) (Puzzle, error)

GeneratePuzzleSeeded creates a Shikaku puzzle with a deterministic RNG.

func (*Puzzle) CandidateRectanglesForClue added in v1.7.0

func (p *Puzzle) CandidateRectanglesForClue(clueID int) []Rectangle

CandidateRectanglesForClue returns every legal rectangle for the clue.

func (*Puzzle) CellOwner

func (p *Puzzle) CellOwner(x, y int) int

CellOwner returns the clue ID of the rectangle covering (x, y), or -1.

func (*Puzzle) CluesInRect

func (p *Puzzle) CluesInRect(r Rectangle) []*Clue

CluesInRect returns all clues contained within the given rectangle bounds.

func (*Puzzle) FindClueAt

func (p *Puzzle) FindClueAt(x, y int) *Clue

FindClueAt returns the clue at position (x, y), or nil.

func (*Puzzle) FindClueByID

func (p *Puzzle) FindClueByID(id int) *Clue

FindClueByID returns the clue with the given ID, or nil.

func (*Puzzle) FindRectangleForClue

func (p *Puzzle) FindRectangleForClue(clueID int) *Rectangle

FindRectangleForClue returns the rectangle placed for the given clue ID, or nil.

func (*Puzzle) IsSolved

func (p *Puzzle) IsSolved() bool

IsSolved reports whether the puzzle is complete: every cell is covered exactly once and each rectangle contains exactly one clue whose value equals the rectangle's area.

func (*Puzzle) Overlaps

func (p *Puzzle) Overlaps(rect Rectangle, excludeClueID int) bool

Overlaps reports whether the given rectangle overlaps any existing rectangle, optionally excluding the rectangle belonging to excludeClueID.

func (*Puzzle) RemoveRectangle

func (p *Puzzle) RemoveRectangle(clueID int)

RemoveRectangle removes the rectangle for the given clue ID.

func (*Puzzle) SetRectangle

func (p *Puzzle) SetRectangle(rect Rectangle)

SetRectangle places or replaces the rectangle for a clue.

func (*Puzzle) ValidRectangleForClue added in v1.7.0

func (p *Puzzle) ValidRectangleForClue(rect Rectangle, clueID int) bool

ValidRectangleForClue reports whether rect is a legal placement for clueID.

type Rectangle

type Rectangle struct {
	ClueID int `json:"clue_id"`
	X      int `json:"x"` // top-left
	Y      int `json:"y"`
	W      int `json:"w"` // dimensions
	H      int `json:"h"`
}

Rectangle represents a player-placed rectangle covering grid cells.

func (Rectangle) Area

func (r Rectangle) Area() int

Area returns the area of the rectangle.

func (Rectangle) Contains

func (r Rectangle) Contains(cx, cy int) bool

Contains reports whether the rectangle covers the cell at (cx, cy).

type Save

type Save struct {
	Width      int         `json:"width"`
	Height     int         `json:"height"`
	Clues      []Clue      `json:"clues"`
	Rectangles []Rectangle `json:"rectangles"`
	ModeTitle  string      `json:"mode_title"`
}

Save represents the serialized state of a Shikaku game.

type ShikakuMode

type ShikakuMode struct {
	game.BaseMode
	Width       int
	Height      int
	MaxRectSize int
}

func NewMode

func NewMode(title, description string, width, height, maxRectSize int) ShikakuMode

func (ShikakuMode) Spawn

func (s ShikakuMode) Spawn() (game.Gamer, error)

func (ShikakuMode) SpawnSeeded

func (s ShikakuMode) SpawnSeeded(rng *rand.Rand) (game.Gamer, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL