diff --git a/src/components/GoldCoinGame.tsx b/src/components/GoldCoinGame.tsx index 3650542..f2dd211 100644 --- a/src/components/GoldCoinGame.tsx +++ b/src/components/GoldCoinGame.tsx @@ -3,11 +3,11 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/com import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Badge } from '@/components/ui/badge'; -import { ArrowLeft, ArrowRight, Crown, Circle } from 'lucide-react'; +import { Crown, Circle, RotateCcw, BookOpen, Trophy } from 'lucide-react'; import SocialShare from '@/components/SocialShare'; type Player = 0 | 1; -type CellState = 'empty' | 'penny' | 'gold' | 'gold-prev'; +type CellState = 'empty' | 'penny' | 'gold'; interface GameState { track: CellState[]; @@ -20,7 +20,7 @@ interface GameState { const GoldCoinGame: React.FC = () => { const [gameState, setGameState] = useState({ - track: ['empty', 'penny', 'empty', 'penny', 'empty', 'penny', 'empty', 'gold', 'empty', 'empty', 'empty'], + track: Array(15).fill('empty'), currentPlayer: 0, winner: null, gameStarted: false, @@ -34,9 +34,31 @@ const GoldCoinGame: React.FC = () => { const playerNames = ['Player 1', 'Player 2']; const playerColors = ['#3b82f6', '#ef4444']; + const generateRandomBoard = (): CellState[] => { + const track = Array(15).fill('empty') as CellState[]; + + // Always place the gold coin at position 7-14 (random) + const goldPosition = Math.floor(Math.random() * 8) + 7; + track[goldPosition] = 'gold'; + + // Place 3-5 pennies randomly in positions 0-6 + const numPennies = Math.floor(Math.random() * 3) + 3; // 3-5 pennies + const availablePositions = Array.from({length: 7}, (_, i) => i); // positions 0-6 + + for (let i = 0; i < numPennies; i++) { + if (availablePositions.length > 0) { + const randomIndex = Math.floor(Math.random() * availablePositions.length); + const position = availablePositions.splice(randomIndex, 1)[0]; + track[position] = 'penny'; + } + } + + return track; + }; + const initializeGame = () => { setGameState({ - track: ['empty', 'penny', 'empty', 'penny', 'empty', 'penny', 'empty', 'gold', 'empty', 'empty', 'empty'], + track: generateRandomBoard(), currentPlayer: 0, winner: null, gameStarted: true, @@ -47,7 +69,7 @@ const GoldCoinGame: React.FC = () => { const resetGame = () => { setGameState({ - track: ['empty', 'penny', 'empty', 'penny', 'empty', 'penny', 'empty', 'gold', 'empty', 'empty', 'empty'], + track: Array(15).fill('empty'), currentPlayer: 0, winner: null, gameStarted: false, @@ -60,6 +82,7 @@ const GoldCoinGame: React.FC = () => { const canMoveCoin = (fromIndex: number, toIndex: number): boolean => { if (fromIndex <= toIndex) return false; // Can only move left if (toIndex < 0) return false; // Can't move off the track + if (gameState.track[toIndex] !== 'empty') return false; // Can't move to a position with a coin // Check if there are any coins in the way for (let i = toIndex + 1; i < fromIndex; i++) { @@ -81,13 +104,32 @@ const GoldCoinGame: React.FC = () => { return gameState.track[index] !== 'empty'; }; + const getValidMovePositions = (fromIndex: number): number[] => { + const validPositions: number[] = []; + for (let i = 0; i < fromIndex; i++) { + if (canMoveCoin(fromIndex, i)) { + validPositions.push(i); + } + } + return validPositions; + }; + const handleCellClick = (index: number) => { - if (gameState.winner !== null) return; + if (gameState.winner !== null || !gameState.gameStarted) return; const cellState = gameState.track[index]; // If a coin is selected, try to move it if (gameState.selectedCoin !== null) { + // If clicking on the same coin, deselect it + if (gameState.selectedCoin === index) { + setGameState(prev => ({ + ...prev, + selectedCoin: null + })); + return; + } + if (canMoveCoin(gameState.selectedCoin, index)) { const newTrack = [...gameState.track]; newTrack[index] = newTrack[gameState.selectedCoin]; @@ -115,15 +157,15 @@ const GoldCoinGame: React.FC = () => { } }; - const handleTakeCoin = (index: number) => { - if (gameState.winner !== null) return; - if (!canTakeCoin(index)) return; + const handleTakeCoin = () => { + if (gameState.winner !== null || !gameState.gameStarted || gameState.selectedCoin === null) return; + if (!canTakeCoin(gameState.selectedCoin)) return; - const cellState = gameState.track[index]; + const cellState = gameState.track[gameState.selectedCoin]; const newTrack = [...gameState.track]; - newTrack[index] = 'empty'; + newTrack[gameState.selectedCoin] = 'empty'; - const moveDescription = `Player ${gameState.currentPlayer + 1} took ${cellState === 'gold' ? 'gold coin' : 'penny'} from position ${index + 1}`; + const moveDescription = `Player ${gameState.currentPlayer + 1} took ${cellState === 'gold' ? 'gold coin' : 'penny'} from position ${gameState.selectedCoin + 1}`; // Check if this is a winning move const isWinningMove = cellState === 'gold'; @@ -144,106 +186,98 @@ const GoldCoinGame: React.FC = () => { const renderCell = (cellState: CellState, index: number) => { const isSelected = gameState.selectedCoin === index; - const canTake = canTakeCoin(index); - const isClickable = cellState !== 'empty' || gameState.selectedCoin !== null; + const validPositions = gameState.selectedCoin !== null ? getValidMovePositions(gameState.selectedCoin) : []; + const isValidMoveTarget = validPositions.includes(index); + const isClickable = gameState.gameStarted && (cellState !== 'empty' || gameState.selectedCoin !== null); return (
handleCellClick(index)} > {cellState === 'gold' && (
- +
)} {cellState === 'penny' && (
- +
)} - {cellState === 'gold-prev' && ( -
- -
- )} -
+
{index + 1}
); }; - const renderTakeButton = (index: number) => { - const canTake = canTakeCoin(index); - const cellState = gameState.track[index]; - - if (!canTake || cellState === 'empty') return null; - - return ( - - ); + const getLeftmostCoin = (): { index: number; type: string } | null => { + for (let i = 0; i < gameState.track.length; i++) { + if (gameState.track[i] !== 'empty') { + return { index: i, type: gameState.track[i] }; + } + } + return null; }; + const leftmostCoin = getLeftmostCoin(); + const canTakeSelectedCoin = gameState.selectedCoin !== null && canTakeCoin(gameState.selectedCoin); + return ( -
- - - - +
+ + + + The Gold Coin Game + - - A two-player strategy game. Move coins to the left or take the leftmost coin. + + A strategic two-player game where you move coins to the left or take the leftmost coin. The player who takes the gold coin wins! - + {/* Game Controls */} -
+
{!gameState.gameStarted ? ( - ) : ( - )} -
{/* Game Status */} {gameState.gameStarted && ( -
-
- Current Player: +
+
+ Current Player: {playerNames[gameState.currentPlayer]}
{gameState.selectedCoin !== null && ( -
+
Selected coin at position {gameState.selectedCoin + 1}. Click a position to move it.
)} @@ -251,35 +285,59 @@ const GoldCoinGame: React.FC = () => { )} {/* Game Board */} -
+
-
- {gameState.track.map((cellState, index) => ( -
- {renderCell(cellState, index)} - {renderTakeButton(index)} -
- ))} +
+
+ {gameState.track.map((cellState, index) => ( +
+ {renderCell(cellState, index)} +
+ ))} +
{/* Instructions */} -
- {gameState.selectedCoin !== null ? ( -

Click a position to move the selected coin, or click "Take" to collect a coin

- ) : ( -

Click on a coin to select it, then click a position to move it left, or click "Take" to collect the leftmost coin

- )} +
+
+

+ {!gameState.gameStarted ? ( + "Click 'Start Game' to begin with a randomized board" + ) : gameState.selectedCoin !== null ? ( + canTakeSelectedCoin ? ( + "Use the take button below to remove this coin" + ) : ( + "Click a highlighted position to move the selected coin" + ) + ) : ( + "Click on a coin to select it, then click a position to move it left, or take the leftmost coin" + )} +

+
+ + {/* Take Coin Button */} + {canTakeSelectedCoin && ( +
+ +
+ )}
{/* Move History */} {gameState.moveHistory.length > 0 && ( -
-

Move History

-
+
+

Move History

+
{gameState.moveHistory.map((move, index) => ( -
+
{move}
))} @@ -291,42 +349,46 @@ const GoldCoinGame: React.FC = () => { {/* Rules Dialog */} - + - The Gold Coin Game Rules + + + The Gold Coin Game Rules + -
+
-

Objective

-

Be the first player to acquire the gold coin and win the game!

+

Objective

+

Be the first player to acquire the gold coin and win the game!

-

Setup

-

The game starts with coins placed on a track. The gold coin is positioned farthest to the right.

+

Setup

+

The game starts with coins placed on a 15-position track. The gold coin is positioned farthest to the right.

-

On Your Turn

-

You have two options:

-
    +

    On Your Turn

    +

    You have two options:

    +
    1. Move a coin: Move any coin to the left by one or more spaces. A coin cannot jump over another coin.
    2. Take a coin: Take the leftmost coin on the track into your possession.
-

Winning

-

The player who successfully takes the gold coin is declared the winner!

+

Winning

+

The player who successfully takes the gold coin is declared the winner!

-

Strategy Tips

-
    +

    Strategy Tips

    +
    • Try to control the position of the gold coin
    • Use pennies to block your opponent's moves
    • Plan several moves ahead
    • Don't always take the first available coin
    • +
    • Consider the spacing between coins carefully
@@ -335,21 +397,24 @@ const GoldCoinGame: React.FC = () => { {/* Game Over Dialog */} - + - Game Over! + + + Game Over! + -
-
- - +
+
+ + {playerNames[gameState.winner!]} wins!
-

+

Congratulations! {playerNames[gameState.winner!]} successfully acquired the gold coin.

-