Refine Bulgarian Solitaire columns

Adjusted column width in Bulgarian Solitaire to be just wider than block width. Implemented sorting of columns by height (tallest to left) after simulation starts. Added visual feedback: highlighting top boxes red, animating their movement to form the last column, and then visually displaying the sorting process.
This commit is contained in:
gpt-engineer-app[bot] 2025-08-21 11:20:19 +00:00
parent cb484c418e
commit 8944a5e485

View file

@ -21,6 +21,8 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
const [draggedBox, setDraggedBox] = useState<number | null>(null);
const [step, setStep] = useState(0);
const [isComplete, setIsComplete] = useState(false);
const [highlightedBoxes, setHighlightedBoxes] = useState<Set<number>>(new Set());
const [isAnimating, setIsAnimating] = useState(false);
const totalBoxes = (n * (n + 1)) / 2;
@ -115,6 +117,18 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
stepCount++;
setStep(stepCount);
// Highlight top boxes that will be moved
const topBoxes = new Set<number>();
currentColumns.forEach(col => {
if (col.length > 0) {
topBoxes.add(col[col.length - 1]);
}
});
setHighlightedBoxes(topBoxes);
setIsAnimating(true);
await sleep(800); // Show highlighting
// Create new pile from non-empty columns
const newPile: number[] = [];
const updatedColumns = currentColumns.map(col => {
@ -136,7 +150,21 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
break;
}
currentColumns = updatedColumns;
// Clear highlighting and animation
setHighlightedBoxes(new Set());
setIsAnimating(false);
// Sort columns by height (tallest to left)
const columnData = updatedColumns.map((col, index) => ({ col, originalIndex: index }))
.filter(item => item.col.length > 0)
.sort((a, b) => b.col.length - a.col.length);
const sortedColumns = Array.from({ length: updatedColumns.length }, () => []);
columnData.forEach((item, index) => {
sortedColumns[index] = item.col;
});
currentColumns = sortedColumns;
setColumns(currentColumns);
// Update box positions
@ -149,7 +177,7 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
return box;
}));
await sleep(1000); // Wait 1 second between steps
await sleep(1200); // Wait to see the sorted result
}
setIsComplete(isTriangularConfiguration(currentColumns));
@ -172,6 +200,8 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
setStep(0);
setIsComplete(false);
setIsPlaying(false);
setHighlightedBoxes(new Set());
setIsAnimating(false);
};
const containerBoxes = boxes.filter(box => box.columnIndex === null);
@ -233,22 +263,26 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
)}
</div>
<div className="grid grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-2 max-w-4xl mx-auto">
<div className="flex justify-center gap-1 flex-wrap max-w-2xl mx-auto">
{columns.map((column, index) => (
<div
key={index}
onDragOver={handleDragOver}
onDrop={(e) => handleDrop(e, index)}
className="border border-muted-foreground rounded-lg min-h-[100px] p-2 bg-background/50 flex flex-col-reverse gap-1"
className="border border-muted-foreground rounded-lg min-h-[100px] w-12 p-1 bg-background/50 flex flex-col-reverse gap-1 transition-all duration-500"
>
<div className="text-xs text-center text-muted-foreground mb-2">
<div className="text-xs text-center text-muted-foreground mb-1 transform rotate-0">
{index + 1}
</div>
{column.map((boxId, boxIndex) => (
<div
key={boxId}
onDoubleClick={() => handleDoubleClick(boxId)}
className="w-6 h-6 bg-primary rounded cursor-pointer hover:bg-primary/80 transition-colors flex items-center justify-center text-primary-foreground text-xs font-medium mx-auto"
className={`w-8 h-8 rounded cursor-pointer transition-all duration-300 flex items-center justify-center text-xs font-medium mx-auto ${
highlightedBoxes.has(boxId)
? 'bg-red-500 text-white shadow-lg scale-110'
: 'bg-primary text-primary-foreground hover:bg-primary/80'
} ${isAnimating && highlightedBoxes.has(boxId) ? 'animate-pulse' : ''}`}
title="Double-click to return to container"
>
{boxId + 1}