Files
nd-wfc/demos

Console Rendering System for Puzzle Demos

This directory contains a comprehensive console rendering system designed for real-time puzzle visualization without adding new lines to the console. The system is perfect for showing solving animations and interactive demos.

Features

  • Real-time Updates: Render puzzle states without scrolling the console
  • Space Pre-allocation: Reserve console space before rendering to prevent layout issues
  • Animation Support: Smooth animations for solving steps and cell highlights
  • Cross-platform: Works on Linux, macOS, and Windows
  • Multiple Puzzle Types: Support for Sudoku and Nonogram puzzles

Quick Start

Basic Sudoku Rendering

#include "console_renderer.h"
#include "sudoku/sudoku.h"

int main() {
    // 1. Create a Sudoku puzzle
    std::string puzzle = "530070000600195000098000060800060003400803001700020006060000280000419005000080079";
    Sudoku sudoku(puzzle);
    
    // 2. Create renderer
    SudokuRenderer renderer(sudoku);
    
    // 3. IMPORTANT: Allocate space first!
    renderer.allocateSpace();
    
    // 4. Render initial state
    renderer.render();
    
    // 5. Update puzzle and re-render (updates in place!)
    sudoku.set(0, 0, 5);
    renderer.render();
    
    return 0;
}

Animation Example

// Animate a cell change with highlighting
renderer.animateCell(row, col, new_value, 200);  // 200ms delay

// Show solving progress
renderer.showSolvingProgress("Solving step 1 of 10");

// Highlight specific cells
renderer.renderWithHighlight(highlight_row, highlight_col);

API Reference

SudokuRenderer

The SudokuRenderer class provides a clean API for rendering Sudoku puzzles with real-time updates.

Constructor

SudokuRenderer(const Sudoku& sudoku)

Core Methods

void allocateSpace()                    // Reserve console space (call first!)
void render()                          // Render current puzzle state
void clear()                           // Clear allocated space

Animation Methods

void renderWithHighlight(int row, int col)              // Highlight specific cell
void showSolvingProgress(const std::string& status)     // Update status line
void animateCell(int row, int col, uint8_t value, int delay_ms = 100)  // Animate cell change

NonogramRenderer

The NonogramRenderer class handles Nonogram puzzle visualization with hints and solution grid.

Constructor

NonogramRenderer(const Nonogram& nonogram)

Core Methods

void allocateSpace()                    // Reserve console space
void render()                          // Render puzzle with hints
void clear()                           // Clear allocated space

Nonogram-specific Methods

void renderWithState(const std::vector<std::vector<int>>& state)  // Render with current solving state
void showSolvingProgress(const std::string& status)               // Update status

ConsoleRenderer (Base Class)

Provides low-level console control utilities.

Static Utilities

static void moveCursorUp(int lines)
static void moveCursorDown(int lines)
static void moveCursorToPosition(int row, int col)
static void clearLine()
static void clearScreen()
static void hideCursor()
static void showCursor()
static void sleep(int milliseconds)
static std::string repeatChar(char c, int count)
static std::string centerText(const std::string& text, int width)

DemoAnimator

Helper class for creating smooth demo animations.

static void typewriterEffect(const std::string& text, int delay_ms = 50)
static void fadeIn(const std::vector<std::string>& lines, int delay_ms = 100)
static void progressBar(const std::string& label, int current, int total, int width = 30)

Important Usage Notes

1. Always Allocate Space First

Critical: Call allocateSpace() before any rendering operations:

SudokuRenderer renderer(sudoku);
renderer.allocateSpace();  // This MUST be called first!
renderer.render();

This reserves the necessary console lines and prevents the display from being corrupted by new output.

2. Real-time Updates

After calling allocateSpace(), all subsequent render() calls will update the display in place:

renderer.allocateSpace();  // Once at the start
renderer.render();         // Initial display

// Update puzzle state
sudoku.set(0, 0, 5);
renderer.render();         // Updates in place - no new lines!

sudoku.set(1, 1, 3);
renderer.render();         // Updates in place again

3. Animation Best Practices

For smooth animations, use the provided animation methods:

// Good: Use built-in animation
renderer.animateCell(row, col, value, 200);

// Also good: Manual animation with proper timing
for (int i = 0; i < steps.size(); ++i) {
    renderer.showSolvingProgress("Step " + std::to_string(i + 1));
    // Update state
    renderer.render();
    ConsoleRenderer::sleep(300);
}

4. Error Handling

try {
    ConsoleRenderer::hideCursor();  // For cleaner display
    
    SudokuRenderer renderer(sudoku);
    renderer.allocateSpace();
    renderer.render();
    
    // ... your demo logic ...
    
    ConsoleRenderer::showCursor();  // Always restore cursor
} catch (const std::exception& e) {
    ConsoleRenderer::showCursor();  // Restore cursor on error
    std::cerr << "Error: " << e.what() << std::endl;
}

Building

Using CMake

cd /testbed/demos
mkdir build && cd build
cmake ..
make sudoku_demo_renderer
./sudoku_demo_renderer

Manual Compilation

cd /testbed/demos
g++ -std=c++17 -I. -I.. -pthread \
    sudoku_demo_renderer.cpp console_renderer.cpp sudoku/sudoku.cpp \
    -o sudoku_demo_renderer
./sudoku_demo_renderer

Demo Programs

sudoku_demo_renderer

A comprehensive demonstration showing:

  • Basic Sudoku rendering
  • Real-time puzzle updates
  • Solving animations
  • API usage examples
./sudoku_demo_renderer

test_renderer

Simple test program to verify the renderer functionality:

./test_renderer

Technical Details

Console Control

The system uses ANSI escape sequences for cursor control:

  • \033[nA - Move cursor up n lines
  • \033[nB - Move cursor down n lines
  • \033[2K - Clear current line
  • \033[?25l - Hide cursor
  • \033[?25h - Show cursor

Memory Efficiency

  • Sudoku puzzles use only 41 bytes of storage
  • Nonogram puzzles use bit-packed storage for solutions
  • Renderers don't store puzzle state - they reference existing objects

Cross-platform Support

The renderer works on:

  • Linux (tested)
  • macOS (ANSI escape sequences supported)
  • Windows (with ANSI support enabled)

Examples

See the demo programs for complete working examples:

  • sudoku_demo_renderer.cpp - Full-featured Sudoku demo
  • test_renderer.cpp - Basic functionality test

The console rendering system provides a powerful foundation for creating engaging puzzle demos and interactive solving visualizations!