Let's Make Dice Wars: Part 1

Creating a project is not easy, but it is essential to demonstrate your worth as a developer. Mainly for grins, I'll start a simple project, and keep adding to it. 

We'll create "dice wars", a pretty simple game. We'll start simple, but we'll embellish it until it looks really darn good. The rules for "dice wars" are available here.  I am best with JavaScript, so we'll start there. Please note that you need to have SOME fundamental knowledge of JavaScript to follow along at a normal speed. This is NOT a JavaScript tutorial, though it can be treated as a project sample. 

You will learn in this segment:
  • Very simple Bootstrap
  • Very simple DOM manipulation with jQuery
  • How to use the random number generator
  • How to write a message to JavaScript console with console.log
  • How to write JavaScript function, and how to call it from elsewhere
  • How to click a button and make it run a function

Initial Planning

For the first step, we will ONLY create a simple form just to prove rolling the dice works. We can expand the functionalities like scorekeeping later, or variable number of dice, or variable rules, but those all come later. For now, we'll just work on "push button, roll 3 dice". And yes, I am doing the 3-dice version. 

For simplicity, let us start with basic HTML and Bootstrap (which includes jQuery) for layout and something a bit better than "plain" HTML. We will create the logic for the rules and scorekeeping. Later, we will create a better UI, but calling the same logic. But one thing at a time. If you don't know Bootstrap and jQuery, you can still follow along by studying the code with references from getbootstrap.com and jQuery.com but it'll take you a bit longer. 

Starting With the UI

Here's the HTML, complete with the Bootstrap starter code. There is a title, there is a button, and there is an area where we can stick the roll results in. There's not much of a style, just a plain Bootstrap look. We can change that later. We'll also add the JavaScript for the dice roll and the button code to call such die roll and push the results into the roll results after this. 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
    <title>Dice Wars</title>
</head>

<body>
    <!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
    <div class="container-fluid bg-light py-2">
        <div class="container">
            <h1>Dice Wars</h1>
        </div>
    </div>
    <div class="container-fluid bg-light py-2">
        <P><button id="btnRollDice" type="button" class="btn btn-primary">Roll 3 dice</button></P>
        <P>
            <B>Roll Results</B>
        </P>
        <P id="rollResults" class="d-md-flex p-2 bg-secondary">
        </P>
    </div>
</body>
</html>
The result should look something like this:

Upon pushing the "roll 3 dice" button, the results of the dice rolls would show up in the gray bar under "Roll Results". Most of the verbiage is the setup of the Bootstrap which we will use later. 

One thing to note: you can see I gave some HTML elements "id", while some get "class", and others get both. This is intentional. The items that need to be named for access later each gets a unique ID, and I tend to give the ID similar to the element's purpose. As for "class", Bootstrap uses class to add specific styles to the element. See Bootstrap reference for details. 

Rolling the Dice

Now, let us write some dice rolling code, then we'll write the button code and the result writing code. Let us review the logic of dice throwing:

Dice throwing is basically generating a random number from between 1 and 6, inclusive (1-6).  

Let's make it very simple:

function rollDice() {
    return /* some randomly generated number */
}

But we don't know what code to put in return just yet. It's not Math.random(), because it just returns a decimal number between 0 and 1, like 0.1384652  or something like that. 

We need to multiply the random() by 6, take the Math.floor() of it (to round down), then add 1. Why? B ecause if we multiply the number by 6, we get something between 0.xxxx and 5.xxxx, so if we take floor() of that, we get 0-5. So we add 1 and we get 1-6.  Thus, the rollDice() now looks like this:

function rollDice() {
    return Math.floor(Math.random()*6)+1
}

However, we will write this a little differently, so we can see some debug messages if things go wrong. Console.log prints something to the browser JavaScript console. This can be very useful when debugging JavaScript. We'll check the output in the console a little further down. For now, just note that it outputs the dice roll onto the console. 

function rollDice() { 
  var tnum;
  tnum = Math.floor(Math.random()*6)+1;
  console.log(tnum);
  return tnum
}

Button Logic

Now that we have a rollDice() function, we need to program the button, that will a) roll the dice 3 times, and b) display the results in rollResults. 

Let's write a function funcBtnRollDice()   (note: we already named the button btnRollDice, so we don't really want to call this btnRollDice as well). The actual name is not that important, just make sure it is obvious what it does. Don't name them a or b or something dumb. Name it after what it does.  Note here, I also did the console log output, the same way I did in rollDice earlier. 

function funcBtnRoll3Dice() {
  //roll 3 dice
  var dice1, dice2, dice3, tstr;
  dice1 = rollDice();
  dice2 = rollDice();
  dice3 = rollDice();
  // stick results into rollResults paragraph
  tstr = "You rolled " + dice1 + ", " + dice2 + ", and " + dice3;
  $("#rollResults").html(tstr);
  console.log(tstr)
}

(BONUS: Can you write an even MORE generic version of this, so we can implement variant games later? Let's say... make the number of dice a parameter, instead of fixed? We'll deal with this in the next installment, as we're getting a bit long already. )

This function and the rollDice function will be included just after the <BODY> tag, after the two prerequisite scripts, inside another <SCRIPT></SCRIPT> tag pair.  

Now we have to add the "click event listener" to make the button run the funcBtnRoll3Dice(). This is unique to jQuery, in that you need to make sure the document is loaded before you can add the click event handler. This section of code goes just before the </BODY> closing tag.   

<script>
    $(document).ready(function() {
        $("#btnRollDice").click(function() {
            funcBtnRoll3Dice();
        });
    });
</script>

With this, the button will now work. Basically it says "for the element with id of "btnRollDice", if you click on it, call JavaScript function funcBtnRoll3Dice()". And if you do press the button, you'll see the result of your 3 dice rolls in the dark gray area (yes, we'll fix that later too). 

Now if you go into Chrome Inspect (ctrl-shift-I or F12) (or the equivalent in Firefox, Edge, etc.) you can see the JavaScript console and the debug messages we chose to log to it:

Note that we called rollDice 3 times, thus 3 separate numbers. Then finally funcBtnRoll3Dice() displays the "You rolled..." message. Now you know how to add "hidden" output that can be very useful for you to find bugs down the road. 

Conclusion

We have the beginnings of a game. In the next part, we will make it into a complete game. It would not be a very exciting game, but it would be a game. But remember... baby steps. We will keep adding functions to this game, improve the user interface, and so on and so forth, but we have to start somewhere. 

Here is the complete HTML and JavaScript in a single file. You can find it in the archive as DiceWars1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
    <title>Dice Wars</title>
</head>
<body>
    <!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
    <script>
        function rollDice() {
            console.log("Dice rolled")
            return Math.floor(Math.random() * 6) + 1
        }
        // meant to be called by BtnRollDice
        function funcBtnRoll3Dice() {
            //roll 3 dice
            var dice1, dice2, dice3, tstr;
            dice1 = rollDice();
            dice2 = rollDice();
            dice3 = rollDice();
            // stick results into rollResults paragraph
            tstr = "You rolled " + dice1 + ", " + dice2 + ", and " + dice3;
            $("#rollResults").html(tstr);
            console.log(tstr)
                //return tstr
        }
    </script>
    <div class="container-fluid bg-light py-2">
        <div class="container">
            <h1>Dice Wars</h1>
        </div>
    </div>
    <div class="container-fluid bg-light py-2">
        <P><button id="btnRollDice" type="button" class="btn btn-primary">Roll 3 dice</button></P>
        <P>
            <B>Roll Results</B>
        </P>
        <P id="rollResults" class="d-md-flex p-2 bg-secondary">
        </P>
    </div>
    <script>
        $(document).ready(function() {
            $("#btnRollDice").click(function() {
                funcBtnRoll3Dice();
            });
        });
    </script>
</body>
</html>

Comments

Popular posts from this blog

Yet another take on recursion

How to Solve a Problem, with Examples

Problem Solving for Programmers: a Neglected Topic?