Create an Example Solution for a Rock Paper Scissors Game #323#333
Conversation
|
@suryaprakash0010 is attempting to deploy a commit to the Suman Kunwar's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull Request Overview
Adds a complete Rock-Paper-Scissors example demonstrating DOM manipulation, event handling, animations, and score tracking.
- New example app with HTML UI, responsive CSS, and JavaScript game logic
- Includes round history, keyboard shortcuts, and reset functionality
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| examples/Rock-Paper-Scissors/index.html | Game markup, controls, and containers for scores, results, and history |
| examples/Rock-Paper-Scissors/styles.css | Visual design, animations, responsiveness |
| examples/Rock-Paper-Scissors/script.js | Core game class, event wiring, scoring, history, and rendering |
| examples/Rock-Paper-Scissors/README.md | Documentation for features, concepts, and usage |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| // Initialize the game when DOM is loaded | ||
| document.addEventListener('DOMContentLoaded', () => { | ||
| const game = new RockPaperScissorsGame(); | ||
|
|
||
| // Add keyboard support for accessibility | ||
| document.addEventListener('keydown', (e) => { | ||
| if (e.key.toLowerCase() === 'r') { | ||
| game.playRound('rock'); | ||
| } else if (e.key.toLowerCase() === 'p') { | ||
| game.playRound('paper'); | ||
| } else if (e.key.toLowerCase() === 's') { | ||
| game.playRound('scissors'); | ||
| } | ||
| }); | ||
|
|
||
| // Add sound effects (optional) | ||
| const playSound = (type) => { | ||
| // You can add sound files in the same directory and uncomment this | ||
| // const audio = new Audio(`${type}.mp3`); | ||
| // audio.volume = 0.3; | ||
| // audio.play().catch(e => console.log('Audio play failed:', e)); | ||
| }; | ||
|
|
||
| // Export for potential testing | ||
| if (typeof module !== 'undefined' && module.exports) { | ||
| module.exports = RockPaperScissorsGame; | ||
| } | ||
| }); |
There was a problem hiding this comment.
module.exports is placed inside the DOMContentLoaded handler, so it never runs in a Node/test environment where the DOM is not present. Move the export outside the event listener to make the class importable in tests: place if (typeof module !== 'undefined' && module.exports) { module.exports = RockPaperScissorsGame; } right after the class definition; keep DOM initialization inside the listener.
| <h3 id="playerChoiceText">Make your move!</h3> | ||
| </div> | ||
|
|
||
| <div class="result-display" id="gameResult"> |
There was a problem hiding this comment.
The result area updates dynamically but lacks an ARIA live region, so screen readers may not announce round outcomes. Add role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" to the container to announce result changes: <div class=\"result-display\" id=\"gameResult\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">.
| <div class="result-display" id="gameResult"> | |
| <div class="result-display" id="gameResult" role="status" aria-live="polite" aria-atomic="true"> |
| <button class="choice-btn rock" id="rockBtn" data-choice="rock"> | ||
| <span class="emoji">🪨</span> | ||
| <span class="label">Rock</span> | ||
| </button> | ||
| <button class="choice-btn paper" id="paperBtn" data-choice="paper"> | ||
| <span class="emoji">📄</span> | ||
| <span class="label">Paper</span> | ||
| </button> | ||
| <button class="choice-btn scissors" id="scissorsBtn" data-choice="scissors"> | ||
| <span class="emoji">✂️</span> | ||
| <span class="label">Scissors</span> | ||
| </button> | ||
| </div> | ||
|
|
||
| <button class="reset-btn" id="resetBtn"> |
There was a problem hiding this comment.
Buttons default to type="submit" in some contexts; explicitly set type=\"button\" to avoid unintended form submissions and add discoverability for shortcuts with aria-keyshortcuts on choice buttons. Example: <button type=\"button\" class=\"choice-btn rock\" id=\"rockBtn\" data-choice=\"rock\" aria-keyshortcuts=\"R\">...; apply similarly for Paper (P), Scissors (S), and the Reset button.
| <button class="choice-btn rock" id="rockBtn" data-choice="rock"> | |
| <span class="emoji">🪨</span> | |
| <span class="label">Rock</span> | |
| </button> | |
| <button class="choice-btn paper" id="paperBtn" data-choice="paper"> | |
| <span class="emoji">📄</span> | |
| <span class="label">Paper</span> | |
| </button> | |
| <button class="choice-btn scissors" id="scissorsBtn" data-choice="scissors"> | |
| <span class="emoji">✂️</span> | |
| <span class="label">Scissors</span> | |
| </button> | |
| </div> | |
| <button class="reset-btn" id="resetBtn"> | |
| <button type="button" class="choice-btn rock" id="rockBtn" data-choice="rock" aria-keyshortcuts="R"> | |
| <span class="emoji">🪨</span> | |
| <span class="label">Rock</span> | |
| </button> | |
| <button type="button" class="choice-btn paper" id="paperBtn" data-choice="paper" aria-keyshortcuts="P"> | |
| <span class="emoji">📄</span> | |
| <span class="label">Paper</span> | |
| </button> | |
| <button type="button" class="choice-btn scissors" id="scissorsBtn" data-choice="scissors" aria-keyshortcuts="S"> | |
| <span class="emoji">✂️</span> | |
| <span class="label">Scissors</span> | |
| </button> | |
| </div> | |
| <button type="button" class="reset-btn" id="resetBtn" aria-keyshortcuts="X"> |
| .game-container { | ||
| background: rgba(255, 255, 255, 0.95); | ||
| backdrop-filter: blur(20px); | ||
| border-radius: 20px; | ||
| padding: 2rem; | ||
| box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); | ||
| max-width: 600px; | ||
| width: 100%; | ||
| border: 1px solid rgba(255, 255, 255, 0.2); |
There was a problem hiding this comment.
Safari requires the -webkit-backdrop-filter prefix; add it alongside backdrop-filter for broader support: -webkit-backdrop-filter: blur(20px);.
| this.rockBtn.classList.remove('selected'); | ||
| this.paperBtn.classList.remove('selected'); | ||
| this.scissorsBtn.classList.remove('selected'); | ||
|
|
||
| const playerBtn = document.querySelector(`[data-choice="${playerChoice}"]`); | ||
| if (playerBtn) { | ||
| playerBtn.classList.add('selected'); | ||
| } |
There was a problem hiding this comment.
Avoid hard-coding individual button references; remove the selected class generically to simplify maintenance: document.querySelectorAll('.choice-btn.selected').forEach(el => el.classList.remove('selected')); then add the class to the chosen button.
| result: result | ||
| }; | ||
|
|
||
| this.gameHistory.unshift(historyItem); |
There was a problem hiding this comment.
gameHistory grows unbounded even though only the last 10 entries are displayed. Cap the array to 10 entries after unshifting to avoid unnecessary memory growth: this.gameHistory.unshift(historyItem); if (this.gameHistory.length > 10) this.gameHistory.length = 10;.
| this.gameHistory.unshift(historyItem); | |
| this.gameHistory.unshift(historyItem); | |
| if (this.gameHistory.length > 10) this.gameHistory.length = 10; |
| /* Animations */ | ||
| @keyframes shake { | ||
| 0%, 100% { | ||
| transform: translateX(0); | ||
| } | ||
| 10%, 30%, 50%, 70%, 90% { | ||
| transform: translateX(-5px); | ||
| } | ||
| 20%, 40%, 60%, 80% { | ||
| transform: translateX(5px); | ||
| } | ||
| } | ||
|
|
||
| .shake { | ||
| animation: shake 0.5s ease-in-out; | ||
| } |
There was a problem hiding this comment.
Respect users' reduced motion preferences by disabling or minimizing animations. Add a prefers-reduced-motion query (e.g., @media (prefers-reduced-motion: reduce) { .choice-btn.selected, .shake { animation: none !important; } .score { transition: none !important; } }).
|
|
||
| **CSS Concepts:** | ||
| - **Responsive Design** - Mobile-first approach with media queries | ||
| - **CSS Grid & Flexbox** - Layout management |
There was a problem hiding this comment.
The styles use Flexbox but not CSS Grid; update this bullet to avoid confusion (e.g., change to 'Flexbox' only) or add a Grid example to align with the claim.
| - **CSS Grid & Flexbox** - Layout management | |
| - **Flexbox** - Layout management |
|
@suryaprakash0010 Great job. When you have time can you look into above suggestions? |

Rock-Paper-Scissors Game Example (#323)
Description
Added a complete Rock-Paper-Scissors game example in the
examples/folder demonstrating DOM manipulation, event handling, animations, and game logic with score tracking.Features
Files Added
index.html— Game UI structure with buttons and score displaystyles.css— Responsive, animated design for better UXscript.js— Core game logic with event handling, animations, and scoringREADME.md— Game overview and setup instructionsConcepts Demonstrated
DOM Manipulation • Event Handling • Conditional Logic • Randomization • State Management • Animations • Responsive Design
**Ready for review! **