Add pause functionality to Bulgarian Solitaire

Update the "Playing..." button to "Pause". When clicked, the simulation will pause and the button text will change to "Continue", allowing the user to resume or reset the game.
This commit is contained in:
gpt-engineer-app[bot] 2025-08-22 10:09:13 +00:00
parent 64f864efed
commit a1945611ef

View file

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Slider } from '@/components/ui/slider'; import { Slider } from '@/components/ui/slider';
import SocialShare from '@/components/SocialShare'; import SocialShare from '@/components/SocialShare';
@ -18,6 +18,7 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
const [boxes, setBoxes] = useState<Box[]>([]); const [boxes, setBoxes] = useState<Box[]>([]);
const [columns, setColumns] = useState<number[][]>([]); const [columns, setColumns] = useState<number[][]>([]);
const [isPlaying, setIsPlaying] = useState(false); const [isPlaying, setIsPlaying] = useState(false);
const [isPaused, setIsPaused] = useState(false);
const [draggedBox, setDraggedBox] = useState<number | null>(null); const [draggedBox, setDraggedBox] = useState<number | null>(null);
const [step, setStep] = useState(0); const [step, setStep] = useState(0);
const [isComplete, setIsComplete] = useState(false); const [isComplete, setIsComplete] = useState(false);
@ -26,6 +27,8 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
const [lastUsedColumn, setLastUsedColumn] = useState<number | null>(null); const [lastUsedColumn, setLastUsedColumn] = useState<number | null>(null);
const [selectedBoxForMove, setSelectedBoxForMove] = useState<number | null>(null); const [selectedBoxForMove, setSelectedBoxForMove] = useState<number | null>(null);
const [showInstructions, setShowInstructions] = useState(false); const [showInstructions, setShowInstructions] = useState(false);
const pauseRef = useRef(false);
const totalBoxes = n; const totalBoxes = n;
@ -173,6 +176,22 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
const waitForUnpause = async () => {
while (pauseRef.current) {
await sleep(100);
}
};
const handlePause = () => {
pauseRef.current = true;
setIsPaused(true);
};
const handleResume = () => {
pauseRef.current = false;
setIsPaused(false);
};
const isTriangularConfiguration = (cols: number[][]) => { const isTriangularConfiguration = (cols: number[][]) => {
const nonEmptyCols = cols.filter(col => col.length > 0).sort((a, b) => a.length - b.length); const nonEmptyCols = cols.filter(col => col.length > 0).sort((a, b) => a.length - b.length);
@ -215,6 +234,7 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
setHighlightedBoxes(topBoxes); setHighlightedBoxes(topBoxes);
setIsAnimating(true); setIsAnimating(true);
await sleep(800); // Show highlighting await sleep(800); // Show highlighting
await waitForUnpause(); // Check for pause
// Create new pile from non-empty columns // Create new pile from non-empty columns
const newPile: number[] = []; const newPile: number[] = [];
@ -265,6 +285,7 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
})); }));
await sleep(1200); // Wait to see the sorted result await sleep(1200); // Wait to see the sorted result
await waitForUnpause(); // Check for pause again
} }
setIsComplete(isTriangularConfiguration(currentColumns)); setIsComplete(isTriangularConfiguration(currentColumns));
@ -278,6 +299,10 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
}; };
const reset = () => { const reset = () => {
pauseRef.current = false;
setIsPaused(false);
setIsPlaying(false);
const newBoxes: Box[] = []; const newBoxes: Box[] = [];
for (let i = 0; i < totalBoxes; i++) { for (let i = 0; i < totalBoxes; i++) {
newBoxes.push({ id: i, columnIndex: null }); newBoxes.push({ id: i, columnIndex: null });
@ -286,7 +311,6 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
setColumns(Array.from({ length: totalBoxes }, () => [])); setColumns(Array.from({ length: totalBoxes }, () => []));
setStep(0); setStep(0);
setIsComplete(false); setIsComplete(false);
setIsPlaying(false);
setHighlightedBoxes(new Set()); setHighlightedBoxes(new Set());
setIsAnimating(false); setIsAnimating(false);
}; };
@ -347,10 +371,10 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
disabled={isPlaying} disabled={isPlaying}
/> />
</div> </div>
<Button onClick={reset} variant="outline" disabled={isPlaying}> <Button onClick={reset} variant="outline" disabled={isPlaying && !isPaused}>
Reset Reset
</Button> </Button>
<Button onClick={randomStart} variant="default" disabled={isPlaying}> <Button onClick={randomStart} variant="default" disabled={isPlaying && !isPaused}>
Random Start Random Start
</Button> </Button>
</div> </div>
@ -428,12 +452,12 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
{/* Play Button */} {/* Play Button */}
<div className="flex justify-center"> <div className="flex justify-center">
<Button <Button
onClick={simulateBulgarianSolitaire} onClick={isPlaying ? (isPaused ? handleResume : handlePause) : simulateBulgarianSolitaire}
disabled={isPlaying || containerBoxes.length > 0} disabled={!isPlaying && containerBoxes.length > 0}
size="lg" size="lg"
className="px-12" className="px-12"
> >
{isPlaying ? 'Playing...' : 'Play'} {isPlaying ? (isPaused ? 'Continue' : 'Pause') : 'Play'}
</Button> </Button>
</div> </div>