feat: implement hint system (Shift+H) with scoring penalties
- Add getHint() method to BoardManager with two-tier priority: 1. Find incorrect user-entered cells → flash red 2. Find empty cells → show correct digit green temporarily - Add Shift+H key handler in useCursor (normal mode only) - Visual feedback: - Red flash (hint-flash-error): incorrect cells, 1s duration, red bg + border - Green flash (hint-flash-correct): correct digit shown, 1s duration, green bg + border - Distinct from invalid-move (no background, 500ms) - Score penalties based on difficulty: - Easy: 25 points per hint - Medium: 50 points per hint - Hard: 100 points per hint - Track hints used in scoreboard display - Correct digit appears temporarily (1s) then disappears (player still does the work) - Update example app to show hints counter and Shift+H instruction
This commit is contained in:
@@ -2,6 +2,7 @@ import { useRef, useState } from 'react';
|
||||
import { SudokuGenerator } from './SudokuGenerator';
|
||||
import { SudokuRenderer } from './SudokuRenderer';
|
||||
import type { Difficulty } from './SudokuGenerator';
|
||||
import type { HintResult } from './types';
|
||||
|
||||
export function useBoard() {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
@@ -54,6 +55,47 @@ export function useBoard() {
|
||||
renderBoard();
|
||||
}
|
||||
|
||||
function getHint(): HintResult {
|
||||
const board = boardRef.current;
|
||||
const solution = solutionRef.current;
|
||||
const initialBoard = initialBoardRef.current;
|
||||
|
||||
if (!board || !solution) return null;
|
||||
|
||||
const incorrectCells: Array<{ row: number; col: number }> = [];
|
||||
const emptyCells: Array<{ row: number; col: number }> = [];
|
||||
|
||||
for (let i = 0; i < 81; i++) {
|
||||
const row = Math.floor(i / 9);
|
||||
const col = i % 9;
|
||||
const currentValue = board[i];
|
||||
const correctValue = solution[i];
|
||||
const initialValue = initialBoard[i];
|
||||
|
||||
if (currentValue !== '.' && initialValue === '.' && currentValue !== correctValue) {
|
||||
incorrectCells.push({ row, col });
|
||||
}
|
||||
|
||||
if (currentValue === '.') {
|
||||
emptyCells.push({ row, col });
|
||||
}
|
||||
}
|
||||
|
||||
if (incorrectCells.length > 0) {
|
||||
const randomCell = incorrectCells[Math.floor(Math.random() * incorrectCells.length)];
|
||||
return { ...randomCell, type: 'error' };
|
||||
}
|
||||
|
||||
if (emptyCells.length > 0) {
|
||||
const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
|
||||
const index = randomCell.row * 9 + randomCell.col;
|
||||
const correctValue = solution[index];
|
||||
return { ...randomCell, type: 'correct', value: correctValue };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
containerRef,
|
||||
boardRef,
|
||||
@@ -61,5 +103,6 @@ export function useBoard() {
|
||||
generateBoard,
|
||||
renderBoard,
|
||||
setCell,
|
||||
getHint,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user