Solidify knowledge of HTML, CSS and React by using it to build a standalone React app
How to deploy a React app to the internet
Introduction
High Card is a turn-based game between 2 or more players where each player draws a card and the player with the highest card wins that round. The overall winner is the player that has won the most rounds when the deck runs out of cards. We will implement High Card with React.
Starter Code
Clone starter code
Fork and clone Rocket's High Card repo (Rocket-themed Create React App) and understand the following starter code before creating High Card. Run npm i to install default packages our app needs to run, and run npm start to start our app and see it in our browser.
For Windows:
If your React Application does not reflect saved changes in the browser please refer back to this section to enable a refresh cycle.
Understand starter code
Notice a file utils.js (short for "utilities") in the src folder that contains helper functions for creating and shuffling a card deck. This is the same code we use in Coding Basics.
utils.js
// Get a random index ranging from 0 (inclusive) to max (exclusive).constgetRandomIndex= (max) =>Math.floor(Math.random() * max);// Shuffle an array of cardsconstshuffleCards= (cards) => {// Loop over the card deck array oncefor (let currentIndex =0; currentIndex <cards.length; currentIndex +=1) {// Select a random index in the deckconstrandomIndex=getRandomIndex(cards.length);// Select the card that corresponds to randomIndexconstrandomCard= cards[randomIndex];// Select the card that corresponds to currentIndexconstcurrentCard= cards[currentIndex];// Swap positions of randomCard and currentCard in the deck cards[currentIndex] = randomCard; cards[randomIndex] = currentCard; }// Return the shuffled deckreturn cards;};constmakeDeck= () => {// Initialise an empty deck arrayconstnewDeck= [];// Initialise an array of the 4 suits in our deck. We will loop over this array.constsuits= ["Hearts","Diamonds","Clubs","Spades"];// Loop over the suits arrayfor (let suitIndex =0; suitIndex <suits.length; suitIndex +=1) {// Store the current suit in a variableconstcurrentSuit= suits[suitIndex];// Loop from 1 to 13 to create all cards for a given suit// Notice rankCounter starts at 1 and not 0, and ends at 13 and not 12.// This is an example of a loop without an array.for (let rankCounter =1; rankCounter <=13; rankCounter +=1) {// By default, card name and card rank are the same as rankCounterlet cardName =`${rankCounter}`;let cardRank = rankCounter;// If rank is 1, 11, 12, or 13, set cardName to the ace or face card's nameif (cardName ==="1") { cardName ="Ace";// Ace has higher rank than all other cards cardRank =14; } elseif (cardName ==="11") { cardName ="Jack"; } elseif (cardName ==="12") { cardName ="Queen"; } elseif (cardName ==="13") { cardName ="King"; }// Create a new card with the current name, suit, and rankconstcard= { name: cardName, suit: currentSuit, rank: cardRank, };// Add the new card to the decknewDeck.push(card); } }// Return the completed card deckreturn newDeck;};// Export functionality to create a shuffled 52-card deckexportconstmakeShuffledDeck= () =>shuffleCards(makeDeck());
Understand App.js's logic to deal 2 cards at a time from the card deck. Understand what each line of code does before moving on, and ask your section if not sure.
App.js
import React from"react";import"./App.css";import { makeShuffledDeck } from"./utils.js";classAppextendsReact.Component {constructor(props) {// Always call super with props in constructor to initialise parent classsuper(props);this.state = {// Set default value of card deck to new shuffled deck cardDeck:makeShuffledDeck(),// currCards holds the cards from the current round currCards: [], }; }dealCards= () => {// this.state.cardDeck.pop() modifies this.state.cardDeck arrayconstnewCurrCards= [this.state.cardDeck.pop(),this.state.cardDeck.pop()];this.setState({ currCards: newCurrCards, }); };render() {// You can write JavaScript here, just don't try and set your state!// You can access your current components state here, as indicated belowconstcurrCardElems=this.state.currCards.map(({ name, suit }) => (// Give each list element a unique key <divkey={`${name}${suit}`}> {name} of {suit} </div> ));return ( <divclassName="App"> <headerclassName="App-header"> <h3>High Card 🚀</h3> {currCardElems} <br /> <buttononClick={this.dealCards}>Deal</button> </header> </div> ); }}exportdefault App;
Base
Complete High Card with the following features.
Determine who has won each round (Player 1 or Player 2)
Keep score during each game (how many rounds has each player won)
Declare a winner at the end of each game when the deck has run out of cards, and give the players the option to restart the game.
Comfortable
Add nice-to-have features.
Style the app to clarify what each UI component is for. Clarify which card belongs to which player. Consider using React Bootstrap or MUI components as default styles.
Create a re-usable PlayingCard component to render cards nicely. This component can use playing card images or create a custom playing card UI.
More Comfortable
If you have time and want to practise more.
Allow players to keep track of scores across games, not just across rounds within a single game.
Submission
Submit a pull request to the main branch of Rocket's High Card repo and share your PR link in your section Slack channel.
If you would like to deploy your app to the internet, follow Create React App GitHub Pages deployment instructions here.