Files
vim-sudoku/src/useGame.ts
T
pastilhas 4236f53ef8 feat: add configurable removedCells option and comprehensive documentation
- Add removedCells to GameOptions for custom puzzle sizes
- removedCells overrides difficulty default when provided
- Maintain backward compatibility with all defaults
- Complete IMPLEMENTATION.md with Iteration 16 and summary
- Completely rewrite README.md with comprehensive documentation:
  - Complete API reference (GameOptions, GameManager, CursorManager, ScoreManager)
  - Game states and state machine flow
  - Full VIM controls reference (movement, editing, hints, game control)
  - Cell state rules and visual feedback
  - Detailed scoring formula with examples
  - Game-over conditions (time and hint limits)
  - Hint system priority and penalties
  - Configuration examples for different play styles
  - Platform hook integration guide
- Mark implementation as COMPLETE and PRODUCTION READY
2025-10-22 21:58:59 +01:00

78 lines
2.3 KiB
TypeScript

import { useState, useEffect } from 'react';
import type { GameManager, GameOptions } from './types';
import { useBoard } from './useBoard/useBoard';
import { useGameStatus } from './useGameStatus';
import { useCursor } from './useCursor';
import { useCursorRender } from './useCursor/useCursorRender';
import { useScore } from './useScore';
export function useGame(options: GameOptions = {}, platformHook?: unknown): GameManager {
const { difficulty = 'easy', timeLimit = 600, removedCells } = options;
const board = useBoard();
const { containerRef, renderBoard, generateBoard, boardRendered } = board;
const gameStatusManager = useGameStatus();
const { gameStatus } = gameStatusManager;
const [keyLog, setKeyLog] = useState<{ key: string; timestamp: number }[]>([]);
const [hintsUsedRef] = useState({ current: 0 });
const cursor = useCursor(gameStatusManager, containerRef, board, () => {
hintsUsedRef.current++;
});
const cursorPosition = cursor.position();
const cursorMode = cursor.mode();
const scoreManager = useScore({ board, gameStatusManager, keyLog, cursorMode, difficulty, hintsUsed: hintsUsedRef.current, timeLimit });
useCursorRender(containerRef, cursorPosition, cursorMode, gameStatus, boardRendered);
useEffect(() => {
if (gameStatus !== 'started') return;
function handleKeyDown(e: KeyboardEvent) {
setKeyLog(prev => [...prev, { key: e.key, timestamp: Date.now() }]);
}
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [gameStatus]);
useEffect(() => {
if (gameStatus === 'started') {
setKeyLog([]);
}
}, [gameStatus]);
useEffect(() => {
renderBoard();
}, []);
useEffect(() => {
if (gameStatus === 'started') {
generateBoard(difficulty, removedCells);
renderBoard();
} else if (gameStatus === 'waiting') {
renderBoard();
}
}, [gameStatus, difficulty, removedCells]);
const gameManager: GameManager = {
containerRef,
renderBoard,
...gameStatusManager,
cursor,
scoreManager,
keyLog,
clearKeyLog: () => setKeyLog([]),
getKeyLog: () => [...keyLog],
};
if (typeof platformHook === 'function') {
platformHook(gameManager);
}
return gameManager;
}