From 4f27765251f504431cf26c88676747aab64fbb20 Mon Sep 17 00:00:00 2001 From: Neeldhara Misra Date: Tue, 22 Jul 2025 03:44:16 +0530 Subject: [PATCH] Add The Gold Coin Game - a strategic two-player game where players move coins to acquire the gold coin --- src/App.tsx | 2 + src/components/GamesGallery.tsx | 8 + src/components/GoldCoinGame.tsx | 368 ++++++++++++++++++++++++++++ src/components/InteractiveIndex.tsx | 9 + src/pages/GoldCoinGamePage.tsx | 12 + 5 files changed, 399 insertions(+) create mode 100644 src/components/GoldCoinGame.tsx create mode 100644 src/pages/GoldCoinGamePage.tsx diff --git a/src/App.tsx b/src/App.tsx index 60f17e7..0339c8c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -31,6 +31,7 @@ import NorthcottsGamePage from "./pages/NorthcottsGamePage"; import KnightsPuzzlePage from "./pages/KnightsPuzzlePage"; import NimGamePage from "./pages/NimGamePage"; import AssistedNimGamePage from "./pages/AssistedNimGamePage"; +import GoldCoinGamePage from "./pages/GoldCoinGamePage"; import Foundations from "./pages/theme-pages/discrete-math/Foundations"; import Proofs from "./pages/theme-pages/discrete-math/Proofs"; import Counting from "./pages/theme-pages/discrete-math/Counting"; @@ -88,6 +89,7 @@ const App = () => ( } /> } /> } /> + } /> {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */} } /> diff --git a/src/components/GamesGallery.tsx b/src/components/GamesGallery.tsx index 2aae6df..83d68d2 100644 --- a/src/components/GamesGallery.tsx +++ b/src/components/GamesGallery.tsx @@ -8,6 +8,7 @@ import GameOfSim from '@/components/GameOfSim'; import NorthcottsGame from '@/components/NorthcottsGame'; import NimGame from '@/components/NimGame'; import AssistedNimGame from '@/components/AssistedNimGame'; +import GoldCoinGame from '@/components/GoldCoinGame'; interface Game { id: string; @@ -18,6 +19,13 @@ interface Game { } const games: Game[] = [ + { + id: 'gold-coin', + title: 'The Gold Coin Game', + description: '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!', + tags: ['strategy', 'two-player', 'logic', 'game-theory', 'movement', 'coins'], + component: GoldCoinGame + }, { id: 'assisted-nim', title: 'Assisted Game of Nim', diff --git a/src/components/GoldCoinGame.tsx b/src/components/GoldCoinGame.tsx new file mode 100644 index 0000000..3650542 --- /dev/null +++ b/src/components/GoldCoinGame.tsx @@ -0,0 +1,368 @@ +import React, { useState } from 'react'; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; +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 SocialShare from '@/components/SocialShare'; + +type Player = 0 | 1; +type CellState = 'empty' | 'penny' | 'gold' | 'gold-prev'; + +interface GameState { + track: CellState[]; + currentPlayer: Player; + winner: Player | null; + gameStarted: boolean; + selectedCoin: number | null; + moveHistory: string[]; +} + +const GoldCoinGame: React.FC = () => { + const [gameState, setGameState] = useState({ + track: ['empty', 'penny', 'empty', 'penny', 'empty', 'penny', 'empty', 'gold', 'empty', 'empty', 'empty'], + currentPlayer: 0, + winner: null, + gameStarted: false, + selectedCoin: null, + moveHistory: [] + }); + + const [showRules, setShowRules] = useState(false); + const [showGameOver, setShowGameOver] = useState(false); + + const playerNames = ['Player 1', 'Player 2']; + const playerColors = ['#3b82f6', '#ef4444']; + + const initializeGame = () => { + setGameState({ + track: ['empty', 'penny', 'empty', 'penny', 'empty', 'penny', 'empty', 'gold', 'empty', 'empty', 'empty'], + currentPlayer: 0, + winner: null, + gameStarted: true, + selectedCoin: null, + moveHistory: [] + }); + }; + + const resetGame = () => { + setGameState({ + track: ['empty', 'penny', 'empty', 'penny', 'empty', 'penny', 'empty', 'gold', 'empty', 'empty', 'empty'], + currentPlayer: 0, + winner: null, + gameStarted: false, + selectedCoin: null, + moveHistory: [] + }); + setShowGameOver(false); + }; + + 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 + + // Check if there are any coins in the way + for (let i = toIndex + 1; i < fromIndex; i++) { + if (gameState.track[i] !== 'empty') { + return false; + } + } + + return true; + }; + + const canTakeCoin = (index: number): boolean => { + // Can only take the leftmost coin + for (let i = 0; i < index; i++) { + if (gameState.track[i] !== 'empty') { + return false; + } + } + return gameState.track[index] !== 'empty'; + }; + + const handleCellClick = (index: number) => { + if (gameState.winner !== null) return; + + const cellState = gameState.track[index]; + + // If a coin is selected, try to move it + if (gameState.selectedCoin !== null) { + if (canMoveCoin(gameState.selectedCoin, index)) { + const newTrack = [...gameState.track]; + newTrack[index] = newTrack[gameState.selectedCoin]; + newTrack[gameState.selectedCoin] = 'empty'; + + const moveDescription = `Player ${gameState.currentPlayer + 1} moved ${newTrack[index] === 'gold' ? 'gold coin' : 'penny'} from position ${gameState.selectedCoin + 1} to position ${index + 1}`; + + setGameState(prev => ({ + ...prev, + track: newTrack, + currentPlayer: ((prev.currentPlayer + 1) % 2) as Player, + selectedCoin: null, + moveHistory: [...prev.moveHistory, moveDescription] + })); + } + return; + } + + // Select a coin if it's not empty + if (cellState !== 'empty') { + setGameState(prev => ({ + ...prev, + selectedCoin: index + })); + } + }; + + const handleTakeCoin = (index: number) => { + if (gameState.winner !== null) return; + if (!canTakeCoin(index)) return; + + const cellState = gameState.track[index]; + const newTrack = [...gameState.track]; + newTrack[index] = 'empty'; + + const moveDescription = `Player ${gameState.currentPlayer + 1} took ${cellState === 'gold' ? 'gold coin' : 'penny'} from position ${index + 1}`; + + // Check if this is a winning move + const isWinningMove = cellState === 'gold'; + + setGameState(prev => ({ + ...prev, + track: newTrack, + currentPlayer: isWinningMove ? prev.currentPlayer : ((prev.currentPlayer + 1) % 2) as Player, + winner: isWinningMove ? prev.currentPlayer : null, + selectedCoin: null, + moveHistory: [...prev.moveHistory, moveDescription] + })); + + if (isWinningMove) { + setShowGameOver(true); + } + }; + + const renderCell = (cellState: CellState, index: number) => { + const isSelected = gameState.selectedCoin === index; + const canTake = canTakeCoin(index); + const isClickable = 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 ( + + ); + }; + + return ( +
+ + + + + The Gold Coin Game + + + A two-player strategy game. 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: + + {playerNames[gameState.currentPlayer]} + +
+ {gameState.selectedCoin !== null && ( +
+ Selected coin at position {gameState.selectedCoin + 1}. Click a position to move it. +
+ )} +
+ )} + + {/* Game Board */} +
+
+
+ {gameState.track.map((cellState, index) => ( +
+ {renderCell(cellState, index)} + {renderTakeButton(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

+ )} +
+
+ + {/* Move History */} + {gameState.moveHistory.length > 0 && ( +
+

Move History

+
+ {gameState.moveHistory.map((move, index) => ( +
+ {move} +
+ ))} +
+
+ )} +
+
+ + {/* Rules Dialog */} + + + + The Gold Coin Game Rules + +
+
+

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.

+
+ +
+

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. +
  3. Take a coin: Take the leftmost coin on the track into your possession.
  4. +
+
+ +
+

Winning

+

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

+
+ +
+

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
  • +
+
+
+
+
+ + {/* Game Over Dialog */} + + + + Game Over! + +
+
+ + + {playerNames[gameState.winner!]} wins! + +
+

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

+ +
+
+
+ + +
+ ); +}; + +export default GoldCoinGame; \ No newline at end of file diff --git a/src/components/InteractiveIndex.tsx b/src/components/InteractiveIndex.tsx index d3e38da..97325bb 100644 --- a/src/components/InteractiveIndex.tsx +++ b/src/components/InteractiveIndex.tsx @@ -91,6 +91,15 @@ const allInteractives: Interactive[] = [ theme: 'Puzzles', dateAdded: '2024-07-21' }, + { + id: 'gold-coin', + title: 'The Gold Coin Game', + description: '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!', + tags: ['strategy', 'two-player', 'logic', 'game-theory', 'movement', 'coins'], + path: '/games/gold-coin', + theme: 'Games', + dateAdded: '2024-12-19' + }, { id: 'assisted-nim', title: 'Assisted Game of Nim', diff --git a/src/pages/GoldCoinGamePage.tsx b/src/pages/GoldCoinGamePage.tsx new file mode 100644 index 0000000..d838ae9 --- /dev/null +++ b/src/pages/GoldCoinGamePage.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import GoldCoinGame from '@/components/GoldCoinGame'; + +const GoldCoinGamePage = () => { + return ( +
+ +
+ ); +}; + +export default GoldCoinGamePage; \ No newline at end of file