Know how to use global variables to change the "state" of your program.
Be familiar with the concept and practice of "refactoring"
Introduction
We can use global state to expand the functionality of our apps. For games, we can use global state to keep track of game modes to treat inputs differently depending on the game mode.
Global State for App Modes
The following code outputs a different default quote depending on whether the app mode is green or blue. Note that we get the same output until we command the program to change modes. To change app modes, we can use the special input words greenmode and bluemode. Note that the initially-assigned value of mode is the default app mode.
var mode ='green';varmain=function (input) {if (input =='greenmode') { mode ='green'; } elseif (input =='bluemode') { mode ='blue'; }var myOutputValue ='A fool sees not the same tree that a wise man sees. -William Blake';if (mode =='blue') { myOutputValue ='The sea, once it casts its spell, holds one in its net of wonder forever. -Jacques Cousteau'; }return myOutputValue;};
App Mode to Accept and Store User Name
In addition to keeping score, we may also want to persist data such as user name to personalise our app. In the following example, we persist user name when in a "waiting for user name" app mode. At the beginning of the game, the first input is saved as the user name. After that first input, the program changes the game mode to "dice game", and subsequent inputs are considered inputs to the dice game. Throughout the game, the app can refer to the userName variable to personalise output for the current user.
var currentGameMode ='waiting for user name';var bankRoll =10;var userName ='';varrollDice=function () {var randomDecimal =Math.random() *6;var randomInteger =Math.floor(randomDecimal);var diceNumber = randomInteger +1;return diceNumber;};varmain=function (input) {var myOutputValue ='';if (currentGameMode =='waiting for user name') {// if the game mode is user name... set the name as the input userName = input;// now that we have the name, switch the mode currentGameMode ='dice game'; myOutputValue ='Hello '+ userName; } elseif (currentGameMode =='dice game') {// if the game mode is dice game... define userGuess as the inputvar userGuess = input;// dice game logicvar randomDiceRoll =rollDice(); myOutputValue = userName +' you lost! you guessed: '+ input +'. you rolled: '+ randomDiceRoll +'. current bank roll: '+ bankRoll;if (userGuess == randomDiceRoll) { bankRoll = bankRoll +1; myOutputValue = userName +' you won! you guessed: '+ input +'. you rolled: '+ randomDiceRoll +'. your current bank roll: '+ bankRoll; } }return myOutputValue;};
Refactoring Code
As our programs become larger and more complicated we want to be able to "refactor" our programs to be more concise, understandable, and testable. We can use functions as subroutines and use parameters and return values to help us control the flow of data in our program. The following example is a refactored version of the code from the previous section, where we extract the dice game logic and put it into a new function playDiceGame. This is desirable because it makes it easier to skim the logic of our app by reading the main function. It also makes it easier to test logic in isolation, for example by running functions independently in the browser console.
var currentGameMode ='waiting for user name';var bankRoll =10;var userName ='';varrollDice=function () {var randomDecimal =Math.random() *6;var randomInteger =Math.floor(randomDecimal);var diceNumber = randomInteger +1;return diceNumber;};varplayDiceGame=function (userName, userGuess) {var message ='';// dice game logicvar randomDiceRoll =rollDice(); message = userName +' you lost! you guessed: '+ userGuess +'. you rolled: '+ randomDiceRoll +'. current bank roll: '+ bankRoll;if (userGuess == randomDiceRoll) { bankRoll = bankRoll +1; message = userName +' you won! you guessed: '+ userGuess +'. you rolled: '+ randomDiceRoll +'. your current bank roll: '+ bankRoll; }return message;};varmain=function (input) {var myOutputValue ='';if (currentGameMode =='waiting for user name') {// set the name userName = input;// now that we have the name, switch the mode currentGameMode ='dice game'; myOutputValue ='Hello '+ userName; } elseif (currentGameMode =='dice game') { myOutputValue =playDiceGame(userName, input); }return myOutputValue;};
Exercises
Follow Along
Duplicate the Blue / Green app above.
Red Mode
Add a Red mode to the game. A reference solution can be found here.