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:
parent
64f864efed
commit
a1945611ef
1 changed files with 31 additions and 7 deletions
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue