Files
nd-wfc/demos/sudoku_demo_renderer.cpp
2025-08-26 14:00:00 +09:00

189 lines
6.0 KiB
C++

#include "console_renderer.h"
#include "sudoku/sudoku.h"
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
/**
* Sudoku Demo with Real-time Console Rendering
*
* This demo shows how to use the SudokuRenderer to display and animate
* a Sudoku puzzle being solved in real-time without adding new lines.
*/
void demonstrateSudokuRendering() {
std::cout << "=== SUDOKU CONSOLE RENDERING DEMO ===" << std::endl;
std::cout << "This demo will show a Sudoku puzzle and simulate solving it." << std::endl;
std::cout << "Press Enter to continue..." << std::endl;
std::cin.get();
// Clear screen for clean demo
ConsoleRenderer::clearScreen();
// Create a sample Sudoku puzzle
std::string puzzle = "530070000600195000098000060800060003400803001700020006060000280000419005000080079";
Sudoku sudoku(puzzle);
// Create renderer
SudokuRenderer renderer(sudoku);
// Allocate space first (this is crucial!)
std::cout << "Allocating console space..." << std::endl;
ConsoleRenderer::sleep(1000);
renderer.allocateSpace();
// Initial render
std::cout << "Rendering initial puzzle..." << std::endl;
ConsoleRenderer::sleep(500);
renderer.render();
// Wait a moment
ConsoleRenderer::sleep(2000);
// Simulate solving some cells with animation
std::vector<std::tuple<int, int, uint8_t>> moves = {
{0, 2, 1}, {0, 5, 8}, {0, 7, 4}, {0, 8, 2},
{1, 0, 2}, {1, 3, 4}, {1, 6, 7}, {1, 8, 3},
{2, 2, 7}, {2, 4, 3}, {2, 5, 2}, {2, 7, 6},
{3, 1, 9}, {3, 3, 5}, {3, 6, 2}, {3, 8, 7},
{4, 0, 5}, {4, 2, 6}, {4, 6, 9}, {4, 8, 8}
};
renderer.showSolvingProgress("Starting to solve...");
ConsoleRenderer::sleep(1000);
for (size_t i = 0; i < moves.size(); ++i) {
auto [row, col, value] = moves[i];
// Update status
std::string status = "Solving step " + std::to_string(i + 1) + " of " + std::to_string(moves.size());
renderer.showSolvingProgress(status);
// Set the value
sudoku.set(row, col, value);
// Animate the change
renderer.animateCell(row, col, value, 200);
// Small delay between moves
ConsoleRenderer::sleep(300);
}
// Final render
renderer.showSolvingProgress("Partial solution completed!");
ConsoleRenderer::sleep(2000);
// Show final state
if (sudoku.isSolved()) {
renderer.showSolvingProgress("PUZZLE SOLVED!");
} else {
renderer.showSolvingProgress("Partial solution (demo complete)");
}
ConsoleRenderer::sleep(2000);
}
void demonstrateRealTimeUpdates() {
std::cout << "\n=== REAL-TIME UPDATE DEMO ===" << std::endl;
std::cout << "This shows how to update the puzzle without adding lines." << std::endl;
std::cout << "Press Enter to continue..." << std::endl;
std::cin.get();
ConsoleRenderer::clearScreen();
// Create empty sudoku
Sudoku sudoku;
SudokuRenderer renderer(sudoku);
// Allocate and render
renderer.allocateSpace();
renderer.render();
ConsoleRenderer::sleep(1000);
// Add numbers one by one
std::vector<std::tuple<int, int, uint8_t>> sequence = {
{0, 0, 5}, {0, 1, 3}, {0, 4, 7},
{1, 0, 6}, {1, 3, 1}, {1, 4, 9}, {1, 5, 5},
{2, 1, 9}, {2, 2, 8}, {2, 7, 6},
{3, 0, 8}, {3, 4, 6}, {3, 8, 3},
{4, 0, 4}, {4, 3, 8}, {4, 5, 3}, {4, 8, 1}
};
for (const auto& [row, col, value] : sequence) {
renderer.showSolvingProgress("Adding number " + std::to_string(value) +
" at (" + std::to_string(row + 1) + "," + std::to_string(col + 1) + ")");
sudoku.set(row, col, value);
renderer.renderWithHighlight(row, col);
ConsoleRenderer::sleep(800);
renderer.render();
ConsoleRenderer::sleep(200);
}
renderer.showSolvingProgress("Real-time update demo complete!");
ConsoleRenderer::sleep(2000);
}
void showAPIUsage() {
std::cout << "\n=== API USAGE EXAMPLE ===" << std::endl;
std::cout << "Here's how to use the SudokuRenderer API:" << std::endl;
std::cout << std::endl;
std::cout << "// 1. Create a Sudoku puzzle" << std::endl;
std::cout << "Sudoku sudoku(\"530070000600195000...\");" << std::endl;
std::cout << std::endl;
std::cout << "// 2. Create renderer" << std::endl;
std::cout << "SudokuRenderer renderer(sudoku);" << std::endl;
std::cout << std::endl;
std::cout << "// 3. IMPORTANT: Allocate space first!" << std::endl;
std::cout << "renderer.allocateSpace();" << std::endl;
std::cout << std::endl;
std::cout << "// 4. Render initial state" << std::endl;
std::cout << "renderer.render();" << std::endl;
std::cout << std::endl;
std::cout << "// 5. Update puzzle and re-render" << std::endl;
std::cout << "sudoku.set(0, 0, 5);" << std::endl;
std::cout << "renderer.render(); // Updates in place!" << std::endl;
std::cout << std::endl;
std::cout << "// 6. Optional: Use animations" << std::endl;
std::cout << "renderer.animateCell(row, col, value);" << std::endl;
std::cout << "renderer.showSolvingProgress(\"Status\");" << std::endl;
std::cout << std::endl;
std::cout << "Press Enter to continue..." << std::endl;
std::cin.get();
}
int main() {
try {
// Hide cursor for cleaner display
ConsoleRenderer::hideCursor();
// Run demonstrations
showAPIUsage();
demonstrateSudokuRendering();
demonstrateRealTimeUpdates();
// Show cursor again
ConsoleRenderer::showCursor();
std::cout << "\n=== DEMO COMPLETE ===" << std::endl;
std::cout << "The SudokuRenderer provides a clean API for real-time puzzle rendering!" << std::endl;
} catch (const std::exception& e) {
ConsoleRenderer::showCursor();
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}