Published
Edited
Feb 25, 2019
Insert cell
Insert cell
Insert cell
Insert cell
Math.random()
Insert cell
Insert cell
// create function that generates random number within a user-inputted range

function randomInRange(min, max){
// Check how many parameters are inputted.
// If 1 instead of 2, recognize that the inputs is the max value and assign 0 as min.
if (max === undefined) {
max = min;
min = 0;
}
// generate the random number to be returned
// Use Math.random to generate random value from 0 to 1, and scale it to cover the range covered by max-min
// Shift it by + min so that output covers the part of the number line specified by the user inputs.
// Round to nearest integer
let rand = Math.round((Math.random())*(max-min)+min);
return rand;
}

Insert cell
// tester function that takes in min, max, and value to be tested

function randomTester(minTest, maxTest, valueTest)
{
// Check how many parameters are inputted.
// If 2 instead of 3, recognize that the inputs are the max value and the value to be tested. Assign 0 as min.
if (valueTest === undefined) {
valueTest = maxTest;
maxTest = minTest;
minTest = 0;
}
// Test if value being tested is within the specified range. If so, return true. Otherwise, return false.
if (valueTest <= maxTest && valueTest >= minTest) {
return true+": Randomly generated value "+valueTest+" is between "+minTest+" and "+maxTest;
}
else {
return false+": Randomly generated value "+valueTest+" is not between "+minTest+" and "+maxTest;
}
}

Insert cell
//run tester in the case where only 1 parameter is passed to the random generator
{
return randomTester(23, randomInRange(23));
}
Insert cell
//run tester in the case where both parameters are passed to the random generator
{
return randomTester(13, 234, randomInRange(13, 234));
}
Insert cell
Insert cell
// set input string to title-case by capitalizing the start of each word
// does not account for special conditions

function titleCase(text) {
let textlower = (text.slice()).toLowerCase(); //set input to all lower case in case it has unusual capitalization
let textCap = ""; //initialize string to hold output
// Loop through each letter in input string, capitalizing the letter if needed before adding it to output string
// Always capitalize first letter in the input string
// For other letters, capitalize only if it is preceeded by a space, which indicates start of a new word
for (let i = 0; i < text.length; i++) {
if (i === 0) {
textCap = textCap + textlower[i].toUpperCase();
} else if (textlower[i-1] === " ") {
textCap = textCap + textlower[i].toUpperCase();
} else {
textCap = textCap + textlower[i];
}
}
return textCap;
}

Insert cell
//test titleCase
titleCase("tHERE was a QuiCk bROWn fox!")
Insert cell
//formatter1: first input optional
function formatter1(title, N)
{
// check if user only passed the function one parameter
// if so, that parameter should be N, since first input is optional
// assumes the user passes a value that would make sense being used as N, ie an int
if (N === undefined) {
N = title;
title = "Some Book";
}
// return the desired output with title in title case
return "The number " + N + " bestseller today is: " + titleCase(title);
}
Insert cell
//test formatter1 when both parameters are filled
formatter1("lord of tHE rings", 1)
Insert cell
//test formatter1 when only 2nd parameter is filled
formatter1(10)
Insert cell
//formatter2: second input optional
function formatter2(title, N)
{
// check if user only passed the function one parameter
// If so, that parameter should be the title, since second input is optional. We put in a default value for N
// assumes the user passes a value that would make sense being used as title, ie a string
if (N === undefined) {
N = 1;
}
// return the desired output with the title in title case
return "The number " + N + " bestseller today is: " + titleCase(title);
}
Insert cell
//test formatter2 when user passes in both parameters
formatter2("lOrd of the rinGs", 2)
Insert cell
//test formatter2 when user passes in only 1st parameter
formatter2("the wandERIng earTH")
Insert cell
// formatter3: both inputs optional
function formatter3(title, N)
{
if (N === undefined) {
if (title === undefined) {
// if both title, N are undefined, then the user has passed the function zero parameters
// we use default values for both title and N
title = "Some Book";
N = 1;
} else if(!isNaN(title)) {
// if only N is undefined, the user has passed the function one parameter
// check whether that parameter is a number; if so assign that parameter input to N
// and use default name for book since user did not input one
N = title;
title = "Some Book";
} else {
// if user passed the function only one parameter but that parameter is not a number, then it's a title
// keep the parameter input as the title and use a default value for N
N = 1;
}
}
// return desired outpuut with appropriate title capitalization
return "The number " + N + " bestseller today is: " + titleCase(title);
}

Insert cell
//test formatter3 in the case where user passes in no inputs
formatter3()
Insert cell
//test formatter3 when the user only inputs a title
formatter3("The lord of the rings")
Insert cell
//test formatter3 when user only inputs book rank
formatter3(23)
Insert cell
Insert cell
// password validation function; parameter passed in is the user password attempt

function validator(pwd) {
// check if password is 8-14 char, inclusive; if not return false
if (pwd.length >= 8 && pwd.length <= 14) {
// if password is the right length, check to see it contains the necessary chars
// begin checking for this by initializing counters for each desired characteristics
// also, input the list of special characters that we must check against
let digitCount = 0;
let upperCount = 0;
let specialCount = 0;
let specialList = "!@#$%^&*()-_+="
// loop through each char in the password attempt inputted by the user
for (let i = 0; i < pwd.length; i++) {
if (!isNaN(pwd[i])) {
digitCount++; // increment count of included digits if the char is a digit
}
if (pwd[i] >= "A" && pwd[i] <= "Z") {
upperCount++; // increment count of capital letters if char is capitalized
// takes advantage of how Javascript orders chars by listing all caps before all lower case letters
}
if (specialList.indexOf(pwd[i]) > -1) {
specialCount++; // increment the special character counte if the char is one of the special characters
// the condition uses the fact that indexOf returns -1 if a value is not found in the target list
}
}
if (digitCount >= 2 && upperCount >= 1 && specialCount >= 1) {
return true; // if the right number of digits, caps, and special char are located, password is valid
}
else {
return false; // if not the right number of these elements are included, password is invalid
}
}
else {
return false; // if password is not the right length, it is invalid
}
}
Insert cell
Insert cell
Insert cell
{
// validate input from the text box above, which is saved in pwdInput
// if it's valid, reset total attempts counter to 3 and tell user s/he succeeded
if (validator(pwdInput)) {
attempts.value = 3;
return("Success! You've set your password.");
}
else {
// if attempt is unsuccessful and there are still attempts left,
// decrement attempts counter and ask user to try again
// tell user how many attempts are left and what the pwd requires are
if (attempts.value > 1) {
attempts.value--;
return "TRY AGAIN. You have " + attempts.value + " attempts left. \n Passwords must be 8-14 characters, with at least 2 numbers, 1 upper case, and one of !@#$%^&*()-_+="
}
else {
// if attempt is unsuccessful and there are no attempts left,
// restart the attempts counter and tell user s/he has tried too many times
attempts.value = 3; //reset attempts counter
return "Sorry, you've tried too many times. Quitting password setting mode."
}
}
}
Insert cell
// password attempt counter, declared as global variable courtesy of Dylan H's idea as per his Piazza post
attempts = html`<input type = range min = 0 max = 3 step = 1>`
Insert cell
Insert cell
// exponentiation function that takes in a user-specified base and an exponent

function exp(base, exponent) {
if (exponent === 0) {
return 1; // covers the fact that any number to the power of 0 is 1
}
else if (exponent === 1) {
return base; // any number to the power of 1 is itself; this is the stopping condition for the recursion
}
else {
if (exponent > 0) {
return base * exp(base, exponent - 1);
// if exponent is not 0, 1 but is positive, continue calculating the exponentiation by
// calling exp but with a decremented exponent
// this is equivalent to calculating, for example, b^3 = b*(b^2)
// hope recursively calling my own function counts as using at least one custom-defined function
}
else {
return 1/(exp(base, -exponent));
// if exponent is negative, continue calculating exponentiation by
// calculating the value of the same base but to the absolute value of that exponent, then taking reciprocal
}
}
}

Insert cell
//test exponentiation function
exp(5,4)
Insert cell
//test exponentiation function
exp(2,-3)
Insert cell
Insert cell
// find minimum assuming list passed in contains only numbers

function min(numberList) {
// initialize a var containing the lowest number encountered so far; start it at the first item in the array
let minNum = numberList[0];
// loop through each item in the remainder of the list, updating minNum if the number encountered
// in the list is lower than the current value of minNum
for(var i = 1; i < numberList.length; i++) {
if(numberList[i] < minNum){
minNum = numberList[i];
}
}
return minNum; // return the smallest item in the list
}
Insert cell
// test min
min([80,3,90,1,23,45,-23,-1])

Insert cell
//find maximum assuming list passed in contains only numbers

function max(numberList) {
// initialize a var containing the largest number encountered so far; start it at the first item in the array
let maxNum = numberList[0];
for(var i = 1; i < numberList.length; i++) {
// loop through each item in the remainder of the list, updating maxNum if the number encountered
// in the list is larger than the current value of maxNum
if(numberList[i] > maxNum){
maxNum = numberList[i];
}
}
return maxNum; // return the largest item in the list
}
Insert cell
// test max
max([80,3,92,1,23,45,81,-1])
Insert cell
Insert cell
Insert cell
{
// runs the game
return hangMan(gameGuess);
}
Insert cell
// function to process guesses

function hangMan(guess) {
// check guess passed in by the user if there are still guess attempts remaining on the guess counter
if(counter.value > 1) {
if(!guess) {
return "You didn't make a guess! Try again." //if empty input, prompt user to make actual guess
}
// if actual guess is inputted, convert to lower case since our word is in lower case
// update status of the game with our guess; status shows, for example, b--b--b--
guess = (guess[0]).toLowerCase();
updateGame(guess);
// after game status has been updated, check to see if user has guessed the full word
// if so, congratulate user after restarting counter, game state
if(state.value === dictionary) {
counter.value = 8;
state.value = "---------";
return dictionary + ": You got the word! Let's play again!";
}
else if (check(guess) > -1) {
// if guess checkers says guessed letter is part of the word,
// give player the updated game status and number guesses remaining
// counter not decremented for correct guesses
return state.value + ": Great guess! You still have " + counter.value + " guesses left.";
}
else {
// if wrong guess, decrement guess counter
// if that was user's last guess, reinitiate game by resetting game state and counter and tell user game over
// if there are guesses remaining, tell user the guess was wrong, the state of the game, guesses remaining
counter.value--;
if (counter.value === 0) {
counter.value = 8;
state.value = "---------";
return state.value + ": Nope, sorry! And you're out of turns. Let's start over";
}
else {
return state.value + ": Nope, sorry. " + counter.value + " guesses left.";
}
}
}
// if there are no turns remaining, restart the game by resetting counter, game state and informing user
counter.value = 8;
state.value = "---------";
return "Sorry, you're out of turns."
}
Insert cell
// checks if user's letter guess is in the target word
// returns -1 if guess is not in word

function check(guess) {
return dictionary.indexOf(guess.toLowerCase());
}
Insert cell
// updates game state given an input

function updateGame(guess) {
let checkResult = check(guess); // check if guess appears in target word
if (checkResult > -1 ) {
// if guess does appear in target word, start a new output string
// loop through each char of the target word; if char matches guess, copy that char into the new output string
// if the char does not match, keep the existing state of the game for that slot in the string
let newvalue = "";
for (let i = 0; i < dictionary.length; ++i) {
if (dictionary[i] === guess) {
newvalue += guess;
}
else {
newvalue += state.value[i];
}
}
state.value = newvalue; // update game state to the new value that incorporates the latest guess
}
}
Insert cell
//it's a small game...just one word to guess
dictionary = "bumblebee"
Insert cell
// Thanks to Dylan H for his idea on implementing global variables in Observable, as he posted in Piazza.
// "Global variable" tracking number of remaining guesses. Counter deducted for wrong guesses only.
counter = html`<input type = range min = 0 max = 8 step = 1>`
Insert cell
//"Global variable" tracking state of the game. Initialize with blanks for all the letters of "bumblebee"
state = html`<input value = "---------">`
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more