This commit is contained in:
gpt-engineer-app[bot] 2025-12-08 09:40:11 +00:00
parent bfff2b5651
commit 2e99b4b53d

View file

@ -28,44 +28,62 @@ const DominoRetilingPuzzle: React.FC<DominoRetilingPuzzleProps> = ({ showSocialS
const BOARD_ROWS = boardSize;
const BOARD_COLS = boardSize + 1; // n + 1 extra square on top row
// Generate a random valid tiling of the n×n board
// Generate a random valid tiling of the n×n board using backtracking
const generateRandomTiling = useCallback(() => {
const newDominoes: Domino[] = [];
const occupied = new Set<string>();
let dominoId = 0;
// Fill the n×n board with random dominoes
for (let row = 0; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
const key = `${row},${col}`;
if (occupied.has(key)) continue;
// Randomly choose horizontal or vertical
const canHorizontal = col + 1 < boardSize && !occupied.has(`${row},${col + 1}`);
const canVertical = row + 1 < boardSize && !occupied.has(`${row + 1},${col}`);
if (!canHorizontal && !canVertical) continue;
let isHorizontal: boolean;
if (canHorizontal && canVertical) {
isHorizontal = Math.random() > 0.5;
} else {
isHorizontal = canHorizontal;
// Helper to find first uncovered cell
const findFirstUncovered = (): { row: number; col: number } | null => {
for (let row = 0; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
if (!occupied.has(`${row},${col}`)) {
return { row, col };
}
}
}
return null;
};
newDominoes.push({
id: dominoId++,
row,
col,
isHorizontal
});
// Greedy fill with backtracking if needed
while (true) {
const cell = findFirstUncovered();
if (!cell) break; // All covered
occupied.add(key);
if (isHorizontal) {
occupied.add(`${row},${col + 1}`);
} else {
occupied.add(`${row + 1},${col}`);
}
const { row, col } = cell;
// Try to place a domino here
const canHorizontal = col + 1 < boardSize && !occupied.has(`${row},${col + 1}`);
const canVertical = row + 1 < boardSize && !occupied.has(`${row + 1},${col}`);
if (!canHorizontal && !canVertical) {
// Stuck - this shouldn't happen with even board sizes, but reset if it does
newDominoes.length = 0;
occupied.clear();
dominoId = 0;
continue;
}
let isHorizontal: boolean;
if (canHorizontal && canVertical) {
isHorizontal = Math.random() > 0.5;
} else {
isHorizontal = canHorizontal;
}
newDominoes.push({
id: dominoId++,
row,
col,
isHorizontal
});
occupied.add(`${row},${col}`);
if (isHorizontal) {
occupied.add(`${row},${col + 1}`);
} else {
occupied.add(`${row + 1},${col}`);
}
}
@ -174,6 +192,25 @@ const DominoRetilingPuzzle: React.FC<DominoRetilingPuzzleProps> = ({ showSocialS
const renderBoard = () => {
const cells: JSX.Element[] = [];
// Render the inaccessible shaded region (last column except top cell)
for (let row = 1; row < BOARD_ROWS; row++) {
cells.push(
<div
key={`inaccessible-${row}`}
className="border border-border/30"
style={{
position: 'absolute',
left: boardSize * cellSize,
top: row * cellSize,
width: cellSize,
height: cellSize,
backgroundColor: 'rgba(100, 100, 100, 0.3)',
backgroundImage: 'repeating-linear-gradient(45deg, transparent, transparent 4px, rgba(80, 80, 80, 0.4) 4px, rgba(80, 80, 80, 0.4) 8px)',
}}
/>
);
}
// Render cells
for (let row = 0; row < BOARD_ROWS; row++) {
const maxCol = row === 0 ? BOARD_COLS : boardSize;
@ -193,15 +230,10 @@ const DominoRetilingPuzzle: React.FC<DominoRetilingPuzzleProps> = ({ showSocialS
key={`cell-${row}-${col}`}
className={`border border-border/50 ${
isExtraSquare
? 'bg-blue-500/40'
? 'bg-blue-400/50'
: (row + col) % 2 === 0 ? 'bg-muted/30' : 'bg-muted/60'
} ${selectedDomino !== null ? 'cursor-pointer' : ''}`}
style={{
...cellStyle,
...(isExtraSquare ? {
backgroundImage: 'repeating-linear-gradient(45deg, transparent, transparent 4px, rgba(59, 130, 246, 0.3) 4px, rgba(59, 130, 246, 0.3) 8px)',
} : {})
}}
style={cellStyle}
onMouseEnter={() => handleCellHover(row, col)}
onMouseLeave={() => setHoverPlacement(null)}
onClick={() => {