Add range display to guessing game
Show the full range of numbers in the guessing game, and grey out invalid choices when the user is guessing.
This commit is contained in:
parent
a981f2ec87
commit
9e899131fd
1 changed files with 82 additions and 8 deletions
|
|
@ -34,6 +34,7 @@ const GuessingGame: React.FC<GuessingGameProps> = ({ showSocialShare = true }) =
|
||||||
const [userGuess, setUserGuess] = useState('');
|
const [userGuess, setUserGuess] = useState('');
|
||||||
const [guesses, setGuesses] = useState<number[]>([]);
|
const [guesses, setGuesses] = useState<number[]>([]);
|
||||||
const [feedback, setFeedback] = useState<string>('');
|
const [feedback, setFeedback] = useState<string>('');
|
||||||
|
const [validNumbers, setValidNumbers] = useState<Set<number>>(new Set());
|
||||||
|
|
||||||
// Computer asking mode
|
// Computer asking mode
|
||||||
const [possibleNumbers, setPossibleNumbers] = useState<number[]>([]);
|
const [possibleNumbers, setPossibleNumbers] = useState<number[]>([]);
|
||||||
|
|
@ -116,6 +117,44 @@ const GuessingGame: React.FC<GuessingGameProps> = ({ showSocialShare = true }) =
|
||||||
};
|
};
|
||||||
}, [possibleNumbers]);
|
}, [possibleNumbers]);
|
||||||
|
|
||||||
|
// Calculate valid numbers based on guesses and feedback
|
||||||
|
const updateValidNumbers = useCallback((guesses: number[], secretNumber: number | null) => {
|
||||||
|
if (guesses.length === 0 || !secretNumber) {
|
||||||
|
const allNumbers = new Set(Array.from({ length: maxRange }, (_, i) => i + 1));
|
||||||
|
setValidNumbers(allNumbers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const valid = new Set<number>();
|
||||||
|
for (let num = 1; num <= maxRange; num++) {
|
||||||
|
let isValid = true;
|
||||||
|
|
||||||
|
for (const guess of guesses) {
|
||||||
|
if (guess === secretNumber) break; // Game would be over
|
||||||
|
|
||||||
|
if (guess < secretNumber) {
|
||||||
|
// Guess was too low, so number must be higher than guess
|
||||||
|
if (num <= guess) {
|
||||||
|
isValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Guess was too high, so number must be lower than guess
|
||||||
|
if (num >= guess) {
|
||||||
|
isValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
valid.add(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setValidNumbers(valid);
|
||||||
|
}, [maxRange]);
|
||||||
|
|
||||||
// Start new game
|
// Start new game
|
||||||
const startGame = () => {
|
const startGame = () => {
|
||||||
if (gameMode === 'user-guesses') {
|
if (gameMode === 'user-guesses') {
|
||||||
|
|
@ -123,6 +162,8 @@ const GuessingGame: React.FC<GuessingGameProps> = ({ showSocialShare = true }) =
|
||||||
setSecretNumber(secret);
|
setSecretNumber(secret);
|
||||||
setGuesses([]);
|
setGuesses([]);
|
||||||
setFeedback('');
|
setFeedback('');
|
||||||
|
const allNumbers = new Set(Array.from({ length: maxRange }, (_, i) => i + 1));
|
||||||
|
setValidNumbers(allNumbers);
|
||||||
} else {
|
} else {
|
||||||
const numbers = Array.from({ length: maxRange }, (_, i) => i + 1);
|
const numbers = Array.from({ length: maxRange }, (_, i) => i + 1);
|
||||||
setPossibleNumbers(numbers);
|
setPossibleNumbers(numbers);
|
||||||
|
|
@ -160,9 +201,9 @@ const GuessingGame: React.FC<GuessingGameProps> = ({ showSocialShare = true }) =
|
||||||
setCurrentQuestion(question);
|
setCurrentQuestion(question);
|
||||||
}, [computerStrategy, possibleNumbers, generateRandomQuestion, generateLinearQuestion, generateBinaryQuestion]);
|
}, [computerStrategy, possibleNumbers, generateRandomQuestion, generateLinearQuestion, generateBinaryQuestion]);
|
||||||
|
|
||||||
// Handle user's guess
|
// Handle user's guess (both input and number click)
|
||||||
const handleGuess = () => {
|
const handleGuess = (guessValue?: number) => {
|
||||||
const guess = parseInt(userGuess);
|
const guess = guessValue || parseInt(userGuess);
|
||||||
if (isNaN(guess) || guess < 1 || guess > maxRange) {
|
if (isNaN(guess) || guess < 1 || guess > maxRange) {
|
||||||
setFeedback('Please enter a valid number within the range.');
|
setFeedback('Please enter a valid number within the range.');
|
||||||
return;
|
return;
|
||||||
|
|
@ -174,10 +215,14 @@ const GuessingGame: React.FC<GuessingGameProps> = ({ showSocialShare = true }) =
|
||||||
if (guess === secretNumber) {
|
if (guess === secretNumber) {
|
||||||
setGameState('won');
|
setGameState('won');
|
||||||
setFeedback(`Congratulations! You found the number in ${newGuesses.length} guesses!`);
|
setFeedback(`Congratulations! You found the number in ${newGuesses.length} guesses!`);
|
||||||
} else if (guess < secretNumber!) {
|
|
||||||
setFeedback('Too low! Try a higher number.');
|
|
||||||
} else {
|
} else {
|
||||||
setFeedback('Too high! Try a lower number.');
|
if (guess < secretNumber!) {
|
||||||
|
setFeedback('Too low! Try a higher number.');
|
||||||
|
} else {
|
||||||
|
setFeedback('Too high! Try a lower number.');
|
||||||
|
}
|
||||||
|
// Update valid numbers based on new feedback
|
||||||
|
updateValidNumbers(newGuesses, secretNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
setUserGuess('');
|
setUserGuess('');
|
||||||
|
|
@ -388,17 +433,46 @@ const GuessingGame: React.FC<GuessingGameProps> = ({ showSocialShare = true }) =
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Number Grid Display */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h4 className="font-semibold text-center">Click a number or type your guess:</h4>
|
||||||
|
<div className="grid grid-cols-8 sm:grid-cols-10 md:grid-cols-12 lg:grid-cols-16 gap-1 max-h-64 overflow-y-auto p-2 border rounded-lg">
|
||||||
|
{Array.from({ length: maxRange }, (_, i) => i + 1).map(num => {
|
||||||
|
const isValid = validNumbers.has(num);
|
||||||
|
const isGuessed = guesses.includes(num);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
key={num}
|
||||||
|
size="sm"
|
||||||
|
variant={isGuessed ? "default" : isValid ? "outline" : "ghost"}
|
||||||
|
className={`
|
||||||
|
h-8 p-1 text-xs
|
||||||
|
${!isValid && !isGuessed ? 'opacity-30 cursor-not-allowed text-muted-foreground' : ''}
|
||||||
|
${isGuessed ? 'bg-accent text-accent-foreground' : ''}
|
||||||
|
${isValid && !isGuessed ? 'hover:bg-accent/10' : ''}
|
||||||
|
`}
|
||||||
|
onClick={() => isValid && !isGuessed && handleGuess(num)}
|
||||||
|
disabled={!isValid || isGuessed}
|
||||||
|
>
|
||||||
|
{num}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="Enter your guess"
|
placeholder="Or type your guess"
|
||||||
value={userGuess}
|
value={userGuess}
|
||||||
onChange={(e) => setUserGuess(e.target.value)}
|
onChange={(e) => setUserGuess(e.target.value)}
|
||||||
onKeyDown={(e) => e.key === 'Enter' && handleGuess()}
|
onKeyDown={(e) => e.key === 'Enter' && handleGuess()}
|
||||||
min={1}
|
min={1}
|
||||||
max={maxRange}
|
max={maxRange}
|
||||||
/>
|
/>
|
||||||
<Button onClick={handleGuess} disabled={!userGuess}>
|
<Button onClick={() => handleGuess()} disabled={!userGuess}>
|
||||||
Guess
|
Guess
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue