Open In App

Pig Game Design using JavaScript

Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will be explaining the steps and various logic required in making of the famous Pig Game, which is a virtual dice game. 

About Game: In this game, User Interface (UI) contains user/player that can do three things, they are as follows:

There will be two players in this game. At the start of the game Player 1 will be the CurrentPlayer and Player 2 will be the in-active one.

  1. Roll the dice: The current player has to roll the dice and then a random number will be generated. If current player gets any number other than 1 on the dice then that number will be added to the current score (initially the current score will be 0) and then the new score will be displayed under Current Score section.  Note: If the current player gets 1 on the dice then the players will be switched i.e. the current player will become in-active and vice-versa.
  2. Hold: If the current player clicks on HOLD, then the Current Score will be added to the Total Score. When the active player clicks the Hold button then the total score is evaluated. If the Total Score >= 100 then the current player wins else the players are switched.
  3. Reset: All the scores are set to 0 and Player 1 is set as the starting player (current player).

Making of Game: Being a game rendered by the web browser, it is built by the help of HTML, CSS (for the Front-end) and JavaScript (for the Back-end). The main logic of the game lies in the JS file whereas the appearance and the User Interface is rendered by HTML and CSS. In this project, there are basically four types of files:

  • HTML File (index.html)
  • CSS File (style.css)
  • JavaScript File (script.js file)
  • Images (dice.png file)

We will analyze all these files and thus make you understand their work/contribution in this game. So, first let’s start with index.html file:

HTML File: Index.html file is the file that makes the web browsers understand and thus interprets what type of document we are making. It stands for Hyper Text Markup Language, our web browsers read this file and understand its component via the V8 Engine (which parses the code in a language so that the browser can understand it). Below is the HTML code for this game:

HTML




<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content=
        "width=device-width, initial-scale=1.0" />
 
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="style.css" />
    <title>Pig Game Design using JavaScript</title>
</head>
 
<body>
    <div class="container">
        <section class="player player--0 player--active">
            <div class="tscore">
                <h2 class="name" id="name--0">
                    Total Score<br>
                    <span class="pl">Player 1</span>
                </h2>
                <p class="score" id="score--0">43</p>
            </div>
 
            <div class="current">
                <p class="current-label">Current Score</p>
 
                <p class="current-score" id="current--0">0</p>
 
            </div>
        </section>
 
        <section class="player player--1">
            <div class="tscore">
                <h2 class="name" id="name--1">
                    Total Score<br>
                    <span class="pl">Player 2</span>
                </h2>
                <p class="score" id="score--1">24</p>
            </div>
 
            <div class="current">
                <p class="current-label">Current Score</p>
 
                <p class="current-score" id="current--1">0</p>
 
            </div>
        </section>
 
        <img src="dice-5.png"
            alt="Playing dice" class="dice" />
        <button class="btn btn--new">Start Game</button>
        <button class="btn btn--roll">Roll dice</button>
        <button class="btn btn--hold">Hold</button>
    </div>
    <script src="gfg.js"></script>
</body>
 
</html>


In the above code, we have used various classes (for eg: btn btn–roll, rte), these will be used for the styling purpose in the CSS file, and will discuss them under the CSS files.

CSS File: In order to format and style the markup created by HTML, we need Cascading Style Sheets so that the markup (code) looks way better. Below is the CSS code for the game is given below. Before diving in the code, just have a quick look at which classes and ids are for what purpose:

  1. For overall HTML page and elements: * will affect the every element and tag in the markup. We have used 2 more tags to provide some particular styling which are html and body tag’s styling.
  2. Layout elements: Defined main tag & player class styling there. We have defined position attribute for main tag and set its property to relative.
  3. Self Made Classes: General styling needed to make the page more appealing.
  4. Absolute Positioned Classes: I have set the position attribute of btn and other classes and set its value to absolute as we have to make sure that the buttons and other elements are always at the right place in the page. Absolute position will make the arrangement of that particular element according to the element which is positioned relative (in this case, it is the main tag).

CSS




* {
    margin: 0;
    padding: 0;
}
 
body {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}
 
.container {
    position: relative;
    width: 80%;
    height: 90%;
    background-color: lightgreen;
    overflow: hidden;
    display: flex;
}
 
.player {
    flex: 50%;
    padding: 150px;
    display: flex;
    flex-direction: column;
    align-items: center;
    transition: all 0.75s;
}
 
.name {
    position: relative;
    font-weight: bold;
    font-size: 38px;
    text-align: center;
}
 
.pl {
    font-size: 24px;
}
 
.tscore {
    background-color: #fff;
    border-radius: 9px;
    width: 65%;
    padding: 2rem;
    text-align: center;
    transition: all 0.75s;
}
 
.score {
    font-size: 38px;
    font-weight: bold;
    margin-bottom: auto;
    padding-top: 10px;
}
 
.player--active {
    background-color: green;
}
 
.player--active .current {
    opacity: 1;
}
 
.current {
    margin-top: 10rem;
    background-color: #fff;
    border-radius: 9px;
    width: 65%;
    padding: 2rem;
    text-align: center;
    transition: all 0.75s;
}
 
.current-label {
    text-transform: uppercase;
    margin-bottom: 1rem;
    font-size: 1.7rem;
    color: #ddd;
}
 
.current-score {
    font-size: 3.5rem;
}
 
.btn {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    color: rgb(7, 124, 69);
    border: none;
    font-size: 30px;
    cursor: pointer;
    font-weight: bold;
    background-color: rgba(255, 255, 255, 0.6);
    backdrop-filter: blur(10px);
    padding: 10px 30px;
    border-radius: 10px;
}
 
.btn--new {
    top: 4rem;
}
 
.btn--roll {
    top: 39.3rem;
}
 
.btn--hold {
    top: 46.1rem;
}
 
.dice {
    position: absolute;
    left: 50%;
    top: 24rem;
    transform: translateX(-50%);
}
 
.player--winner {
    background-color: #003612;
}
 
.player--winner .name {
    font-weight: 700;
    color: #c7365f;
}
 
.hidden {
    display: none;
}


In the HTML code, we have provided names of various classes. In this file, we have provided their different functionalities. The CSS file plays an important role in making a webpage or a game look good (only in the case of web browsers).

Till now, we have made the UI of the game perfectly, now comes the trickier part. So let’s dive into the Game Logic…

JavaScript File: There are some JavaScript variables, we can use two type of variables i.e. let and constant. One can modify the variables declared with let, while the variables declared with constant can’t be changed. In the JavaScript file, we are basically doing the DOM Manipulations (everything in JavaScript is a type of Object, so we term the UI as the Document Object Model). So document.querySelector() is a way of selecting elements from the DOM. 

In order to understand the work-flow of the logic, we have to first understand the concept of Event Listeners. Event Listeners are the functions that performs an action based on certain events. They wait for the specific event to happen. We have a total of 03 event listeners for this game:  btnRoll, btnHold, btnNew.  We will understand functionalities of all these event listeners:

Note: Before heading to the event handlers section, we must declare some variables in the file so that we can use them later in our game logic.

Javascript




'use strict';
 
// Selecting elements
const player0El = document.querySelector('.player--0');
const player1El = document.querySelector('.player--1');
const score0El = document.querySelector('#score--0');
const score1El = document.getElementById('score--1');
const current0El = document.getElementById('current--0');
const current1El = document.getElementById('current--1');
 
const diceEl = document.querySelector('.dice');
const btnNew = document.querySelector('.btn--new');
const btnRoll = document.querySelector('.btn--roll');
const btnHold = document.querySelector('.btn--hold');
 
let scores, currentScore, activePlayer, playing;


At the very beginning of the JavaScript File, there is a line ‘use strict’. The purpose of “use strict” is to indicate that the code should be executed in “strict mode”.  All modern browsers support “use strict” except Internet Explorer 9 and lower. 

Now lets start to see the code for each of the 3 event handlers.

1. btnRoll Event Handler:

Javascript




// Rolling dice functionality
btnRoll.addEventListener('click', function () {
  if (playing) {
   
    // 1. Generating a random dice roll
    const dice = Math.trunc(Math.random() * 6) + 1;
 
    // 2. Display dice
    diceEl.classList.remove('hidden');
    diceEl.src = `dice-${dice}.png`;
 
    // 3. Check for rolled 1
    if (dice !== 1) {
     
      // Add dice to current score
      currentScore += dice;
      document.getElementById(
        `current--${activePlayer}`
      ).textContent = currentScore;
    } else {
     
      // Switch to next player
      switchPlayer();
    }
  }
});


This event handler is in action whenever the player clicks on Roll button (that is why we have used the click event there). Then there is a callback function which starts with an if-else block. As we have declared the variable playing = true, so the if block of this event handler will be true and thus the code of if block will be executed. Following are the steps ahead:

  1. Step1: After the player hits the roll dice button, this event handler produces a random number using the Math.trunc() function. We have used Math.trunc() function because this function returns the integer portion of the randomly generated function and have added a 1 to it because the random() function can generate any number starting from 0 to 1 but in our case, we only need numbers from 1 to 6. <br>Understanding the dice variable: The dice variable will store the random generated number. Say the Math.random() function generates number 0.02. According to the code, first 0.02 will be multiplied by 6. So variable dice will now have a value of 0.12. Then the Math.trunc() function will come into play and will make the dice variable 0. Now 1 will be added to the variable which will make the dice = 1 (That is what we need as a number for our dice)
  2. Step2: Now we have got the score for the dice, we have to display the dice corresponding to the number of dice. (In the CSS file, we have made a class named as hidden which will make the dice hidden initially at the start of the game) But as now we have a dice number to be displayed in the form of dice image, we have to remove the hidden class. This is achieved by the line diceE1.classList.remove(‘hidden’) and then the correct image of dice is rendered to the UI. 
  3. Step3. Now as per the game rules, we have to check the number on the dice. So, if the dice number is not 1 then current score is updated. If the dice number is 1, then switchPlayer() gets invoked. 

Javascript




const switchPlayer = function () {
  document.getElementById(`current--${activePlayer}`).textContent = 0;
  currentScore = 0;
  activePlayer = activePlayer === 0 ? 1 : 0;
  player0El.classList.toggle('player--active');
  player1El.classList.toggle('player--active');
};


According to the rules: “If the player rolls out a 1, then he losts all of his current score”. The same functionality is being achieved by this function.

activePlayer =  activePlayer === 0 ? 1 : 0 {This is a ternary operator in which we are saying that if the activeplayer is 0 then make it 1 and if it is make then turn it to 0.

2. btnHold Event Handler

Javascript




btnHold.addEventListener('click', function () {
  if (playing) {
   
    // 1. Add current score to active player's score
    scores[activePlayer] += currentScore;
    // scores[1] = scores[1] + currentScore
 
    document.getElementById(`score--${activePlayer}`)
      .textContent = scores[activePlayer];
 
    // 2. Check if player's score is >= 100
    if (scores[activePlayer] >= 100) {
     
      // Finish the game
      playing = false;
      diceEl.classList.add('hidden');
 
      document
        .querySelector(`.player--${activePlayer}`)
        .classList.add('player--winner');
      document
        .querySelector(`.player--${activePlayer}`)
        .classList.remove('player--active');
    } else {
     
      // Switch to the next player
      switchPlayer();
    }
  }
});


This event handler fires off whenever a player hits the HOLD button. Following are the steps involved in this handler:

  1. Step1: As soon as the player hits hold, the current score gets added to the overall score of that player.
  2. Step2: Evaluation of the overall scores is done after that step. If overall score is found to be greater than 100, then the game finishes and then the class of player-winner (which make the background-color: black and changes the color and font-weight) and removes the class of active-player.

3. btnNew Event Handler:

btnNew.addEventListener(‘click’,init): Whenever a new game is initialized, this event handler fires off. It only does initialize the Init() function. Init() kinds of reset the game to the start, that is it does the following things:

  • Makes the scores of both players 0.
  • Makes the Player 1 as the active/current player.
  • Hides the dice by the hidden class.
  • Removes the player–winner class from both players
  • Adds the player–active class to Player 1

Javascript




// Starting conditions
const init = function () {
  scores = [0, 0];
  currentScore = 0;
  activePlayer = 0;
  playing = true;
 
  score0El.textContent = 0;
  score1El.textContent = 0;
  current0El.textContent = 0;
  current1El.textContent = 0;
 
  diceEl.classList.add('hidden');
  player0El.classList.remove('player--winner');
  player1El.classList.remove('player--winner');
  player0El.classList.add('player--active');
  player1El.classList.remove('player--active');
};
init();


Note: init() function is initialized at the time of loading the game also. 

Output:

Reference of Diced Images:



Last Updated : 09 Sep, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads