Refactor parity bits game
- Changed parity indicators to display the count of black cells instead of "odd" or "even". - Made yellow highlights translucent to allow visibility of underlying black cells. - Added a "Random Start" option to initialize the grid with a random subset of black cells.
This commit is contained in:
parent
6813e73b97
commit
5c407b8b7f
1 changed files with 68 additions and 10 deletions
|
|
@ -27,6 +27,8 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
showColParity: boolean;
|
||||
rowParities: boolean[];
|
||||
colParities: boolean[];
|
||||
rowCounts: number[];
|
||||
colCounts: number[];
|
||||
}>({
|
||||
isAnimating: false,
|
||||
currentRow: -1,
|
||||
|
|
@ -34,7 +36,9 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
showRowParity: false,
|
||||
showColParity: false,
|
||||
rowParities: [],
|
||||
colParities: []
|
||||
colParities: [],
|
||||
rowCounts: [],
|
||||
colCounts: []
|
||||
});
|
||||
|
||||
// Reset game when grid size changes
|
||||
|
|
@ -113,17 +117,23 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
// Calculate all parities first
|
||||
const rowParities: boolean[] = [];
|
||||
const colParities: boolean[] = [];
|
||||
const rowCounts: number[] = [];
|
||||
const colCounts: number[] = [];
|
||||
|
||||
for (let i = 0; i < gridSize; i++) {
|
||||
const rowBits = parityGrid[i].slice(0, gridSize);
|
||||
const rowCount = rowBits.filter(bit => bit).length;
|
||||
const expectedParity = calculateParity(rowBits);
|
||||
rowParities[i] = expectedParity !== parityGrid[i][gridSize];
|
||||
rowCounts[i] = rowCount;
|
||||
}
|
||||
|
||||
for (let j = 0; j < gridSize; j++) {
|
||||
const colBits = parityGrid.slice(0, gridSize).map(row => row[j]);
|
||||
const colCount = colBits.filter(bit => bit).length;
|
||||
const expectedParity = calculateParity(colBits);
|
||||
colParities[j] = expectedParity !== parityGrid[gridSize][j];
|
||||
colCounts[j] = colCount;
|
||||
}
|
||||
|
||||
setAnimationState({
|
||||
|
|
@ -133,7 +143,9 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
showRowParity: false,
|
||||
showColParity: false,
|
||||
rowParities,
|
||||
colParities
|
||||
colParities,
|
||||
rowCounts,
|
||||
colCounts
|
||||
});
|
||||
|
||||
// Animate through rows
|
||||
|
|
@ -171,13 +183,45 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
showRowParity: false,
|
||||
showColParity: false,
|
||||
rowParities: [],
|
||||
colParities: []
|
||||
colParities: [],
|
||||
rowCounts: [],
|
||||
colCounts: []
|
||||
});
|
||||
|
||||
setPhase('detect');
|
||||
};
|
||||
|
||||
// Reset the game
|
||||
// Random start - fill random cells
|
||||
const randomStart = () => {
|
||||
if (phase !== 'setup') return;
|
||||
|
||||
const newGrid = Array(gridSize).fill(null).map(() => Array(gridSize).fill(false));
|
||||
|
||||
// Fill about 30-50% of cells randomly
|
||||
const fillPercentage = 0.3 + Math.random() * 0.2; // 30-50%
|
||||
const totalCells = gridSize * gridSize;
|
||||
const cellsToFill = Math.floor(totalCells * fillPercentage);
|
||||
|
||||
const positions: {row: number, col: number}[] = [];
|
||||
for (let i = 0; i < gridSize; i++) {
|
||||
for (let j = 0; j < gridSize; j++) {
|
||||
positions.push({row: i, col: j});
|
||||
}
|
||||
}
|
||||
|
||||
// Shuffle and take first cellsToFill positions
|
||||
for (let i = positions.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[positions[i], positions[j]] = [positions[j], positions[i]];
|
||||
}
|
||||
|
||||
for (let i = 0; i < cellsToFill; i++) {
|
||||
const {row, col} = positions[i];
|
||||
newGrid[row][col] = true;
|
||||
}
|
||||
|
||||
setGrid(newGrid);
|
||||
};
|
||||
const resetGame = () => {
|
||||
setGrid(Array(gridSize).fill(null).map(() => Array(gridSize).fill(false)));
|
||||
setParityBitsAdded(false);
|
||||
|
|
@ -192,7 +236,9 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
showRowParity: false,
|
||||
showColParity: false,
|
||||
rowParities: [],
|
||||
colParities: []
|
||||
colParities: [],
|
||||
rowCounts: [],
|
||||
colCounts: []
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -222,7 +268,7 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
${currentGrid[row]?.[col] ? 'bg-foreground' : 'bg-background'}
|
||||
${isParityCell ? 'border-primary' : 'border-foreground'}
|
||||
${isError ? 'ring-4 ring-green-500 bg-green-500/20' : ''}
|
||||
${shouldHighlightForAnimation ? 'ring-4 ring-yellow-400 bg-yellow-400/30' : ''}
|
||||
${shouldHighlightForAnimation ? 'ring-2 ring-yellow-400 bg-yellow-400/15' : ''}
|
||||
${phase === 'setup' && !isParityCell ? 'hover:bg-accent cursor-pointer' : ''}
|
||||
${phase === 'parity' ? 'hover:bg-accent cursor-pointer' : ''}
|
||||
`}
|
||||
|
|
@ -242,12 +288,13 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
<div className="flex flex-col gap-1">
|
||||
{Array(gridSize).fill(null).map((_, row) => {
|
||||
const hasOddParity = animationState.rowParities[row];
|
||||
const count = animationState.rowCounts[row];
|
||||
const showLabel = row === animationState.currentRow;
|
||||
return (
|
||||
<div key={`row-${row}`} className="w-12 h-12 flex items-center justify-center">
|
||||
{showLabel && (
|
||||
<span className={`text-xs font-medium ${hasOddParity ? 'text-red-500' : 'text-foreground'}`}>
|
||||
{hasOddParity ? 'odd' : 'even'}
|
||||
{count}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -260,10 +307,11 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
<div className="flex flex-col gap-1">
|
||||
{Array(gridSize).fill(null).map((_, row) => {
|
||||
const hasOddParity = animationState.rowParities[row];
|
||||
const count = animationState.rowCounts[row];
|
||||
return (
|
||||
<div key={`row-${row}`} className="w-12 h-12 flex items-center justify-center">
|
||||
<span className={`text-xs font-medium ${hasOddParity ? 'text-red-500' : 'text-foreground'}`}>
|
||||
{hasOddParity ? 'odd' : 'even'}
|
||||
{count}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -278,12 +326,13 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
<div className="flex gap-1">
|
||||
{Array(gridSize).fill(null).map((_, col) => {
|
||||
const hasOddParity = animationState.colParities[col];
|
||||
const count = animationState.colCounts[col];
|
||||
const showLabel = col === animationState.currentCol;
|
||||
return (
|
||||
<div key={`col-${col}`} className="w-12 h-6 flex items-center justify-center">
|
||||
{showLabel && (
|
||||
<span className={`text-xs font-medium ${hasOddParity ? 'text-red-500' : 'text-foreground'}`}>
|
||||
{hasOddParity ? 'odd' : 'even'}
|
||||
{count}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -296,10 +345,11 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
<div className="flex gap-1">
|
||||
{Array(gridSize).fill(null).map((_, col) => {
|
||||
const hasOddParity = animationState.colParities[col];
|
||||
const count = animationState.colCounts[col];
|
||||
return (
|
||||
<div key={`col-${col}`} className="w-12 h-6 flex items-center justify-center">
|
||||
<span className={`text-xs font-medium ${hasOddParity ? 'text-red-500' : 'text-foreground'}`}>
|
||||
{hasOddParity ? 'odd' : 'even'}
|
||||
{count}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -358,6 +408,14 @@ const ParityBitsGame = ({ showSocialShare = true }: ParityBitsGameProps) => {
|
|||
Add Parity Bits
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={randomStart}
|
||||
disabled={phase !== 'setup'}
|
||||
variant="outline"
|
||||
>
|
||||
Random Start
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={identifyFlip}
|
||||
disabled={phase !== 'flip' || animationState.isAnimating}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue