diff --git a/04week/mastermind.js b/04week/mastermind.js index 60e5cfa18..369f2999a 100644 --- a/04week/mastermind.js +++ b/04week/mastermind.js @@ -2,6 +2,7 @@ const assert = require('assert'); const readline = require('readline'); +const colors = require('colors'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout @@ -10,13 +11,26 @@ const rl = readline.createInterface({ let board = []; let solution = ''; let letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; +let youHaveWon = false; +// create function to reset game after win/loss: +let reset = () => { + // set board, solution, and win state boolean to their initial values: + board = []; + solution = ''; + youHaveWon = false; + // generate a new solution: + generateSolution(); +} + +// print function to add items to 'board' array in order to display previous guesses, as well as generate turn count for loss detection: function printBoard() { for (let i = 0; i < board.length; i++) { console.log(board[i]); } } +// generate random solution based on the letters array: function generateSolution() { for (let i = 0; i < 4; i++) { const randomIndex = getRandomInt(0, letters.length); @@ -24,24 +38,114 @@ function generateSolution() { } } +// define getRandomInt function for use in the generateSolution function: function getRandomInt(min, max) { - return Math.floor(Math.random() * (max - min)) + min; + return Math.floor( Math.random() * (max - min) ) + min; } -function generateHint() { - // your code here +// generate hint by displaying both the number of correctly guessed letter locations, as well as the number of correctly guessed letters are not in the right order: +function generateHint( guess ) { + // split guess and solution strings into discrete arrays: + let solutionArray = solution.split(''); + let guessArray = guess.split(''); + + // define variables to store numbers to use in the hint: + let correctLetterLocations = 0; + let correctLetters = 0; + + // iterate through the solution array and check if each character of the guess matches the solution at the same position; if so add one to correctLetterLocations: + for( let i = 0; i < solutionArray.length; i++ ) { + if( solutionArray[i] == guessArray[i] ) { + correctLetterLocations++; + solutionArray[i] = null; + } + } + + // iterate through arrays again to check for guess characters which match but aren't in the correct position: + for( let i = 0; i < solutionArray.length; i++ ) { + // define a variable to store the index number in the solution of each character in the guess array: + let targetIndex = solutionArray.indexOf( guessArray[i] ); + // if the solution array index of the character at guessArray[i] is > -1 then the character must exist somewhere within the solution array; add one to correctLetters: + if( targetIndex > -1 ) { + correctLetters++; + solutionArray[targetIndex] = null; + } + } + return `${correctLetterLocations}-${correctLetters}`; + //return colors.red(correctLetterLocations) + '-' + colors.white(correctLetters) ; } -function mastermind(guess) { - solution = 'abcd'; // Comment this out to generate a random solution - // your code here +// made isValid function to check if the guessed letters are valid; wrote it this way so it still works if the letters array is changed: +let isValid = ( guess ) => { + // define variable to store a count (4 valid letters in a guess results in validCount of 4): + let validCount = 0; + // iterate through the characters in guess: + for( let character of guess ) { + // iterate through each letter in the letters array: + for( let letter of letters) { + // if each character of the guess matches a letter within the array, add 1 to validCount: + if( character == letter ) { + validCount++; + } + } + } + // if validCount is 4, the guess is valid: + if( validCount == 4 ) return true; + else return false; } +// create function to check if player is out of turns. i put this in its own function to simplify code later on: +let outOfTurns = () => { + // if board array length is 10 then display loss message and reset the board: + if( board.length == 10 ) { + console.log( colors.bold.bgRed(`You ran out of turns! The solution was ${solution}.`) ); + console.log( colors.blue('Try again?') ); + reset(); + } + // or else log how many turns have been taken and keep playing: + else console.log(`Guess again. You've made ${board.length} turn(s) out of 10.`); +} + +let mastermind = ( guess ) => { + // solution reassignment for troubleshooting use (leave commented for normal gameplay): + // solution = 'abcd'; + + // make guess lowercase to avoid errors caused by unexpected capitalization: + guess = guess.toLowerCase(); + + // if guess length is not exactly 4 characters, or if the guess is not valid per the isValid function, log try again message: + if( guess.length != 4 || !isValid(guess) ) { + console.log( colors.red('Try again and guess four valid letters!') ); + } + // or else if the guess is equal to the solution, set youHaveWon boolean to true: + else if( guess == solution ) { + youHaveWon = true; + return 'You guessed it!'; + } + // or else push the guess and the generated hint to the board array: + else { + let hint = generateHint( guess ); + board.push( `${guess} ${hint}` ); + } +} function getPrompt() { + // log message to explain what to do; wrote it like this so it still works if the letters array is modified: + console.log( colors.bold(`--- Pick four letters between ${letters[0]} and ${letters[letters.length-1]}! ---`) ); + // begin prompt: rl.question('guess: ', (guess) => { + // run the user's guess through the mastermind function: mastermind(guess); + // print the board which displays all guesses and hints: printBoard(); + // if youHaveWon variable is true (see line 121), log win message and reset: + if( youHaveWon ) { + console.log( colors.bold.green(`You guessed it in ${board.length + 1} turn(s)! The answer was ${solution}`) ); + console.log( colors.bold.blue('Play again?') ); + reset(); + } + // or else run the outOfTurns function (see line 98) to check for loss state or if the game should continue: + else outOfTurns(); getPrompt(); }); } @@ -49,7 +153,7 @@ function getPrompt() { // Tests if (typeof describe === 'function') { - solution = 'abcd'; + // solution = 'abcd'; describe('#mastermind()', () => { it('should register a guess and generate hints', () => { mastermind('aabb'); @@ -62,10 +166,10 @@ if (typeof describe === 'function') { describe('#generateHint()', () => { it('should generate hints', () => { - assert.equal(generateHint('abdc'), '2-2'); + assert.strictEqual(generateHint('abdc'), '2-2'); }); it('should generate hints if solution has duplicates', () => { - assert.equal(generateHint('aabb'), '1-1'); + assert.strictEqual(generateHint('aabb'), '1-1'); }); }); diff --git a/package-lock.json b/package-lock.json index bd07c0e56..71548816c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -553,9 +553,9 @@ } }, "colors": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", - "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" }, "colors-tmpl": { "version": "0.1.1", @@ -563,6 +563,13 @@ "integrity": "sha1-F+n5rYBceS/6OsagSctzJ9llt/4=", "requires": { "colors": "~0.6.2" + }, + "dependencies": { + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + } } }, "combined-stream": { @@ -1728,15 +1735,14 @@ "version": "github:kevincolten/htmllint-cli#5901ac1f6cd612f484f40c7f4f7515f22a2ba52d", "from": "github:kevincolten/htmllint-cli", "requires": { - "bluebird": "^3.4.7", - "chalk": "^1.1.3", + "bluebird": "^3.5.1", + "chalk": "^2.3.0", "cjson": "^0.5.0", "glob": "^7.1.1", - "htmllint": "^0.6.0", - "liftoff": "^2.3.0", - "promise": "^7.1.1", - "semver": "^5.3.0", - "yargs": "^6.6.0" + "htmllint": "^0.7.0", + "liftoff": "^2.5.0", + "semver": "^5.4.1", + "yargs": "^10.0.3" }, "dependencies": { "ansi-styles": { diff --git a/package.json b/package.json index aff08712c..57080b13d 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ }, "homepage": "https://github.com/AustinCodingAcademy/javascript-workbook#readme", "dependencies": { + "colors": "^1.3.3", "eslint": "^3.19.0", "functional-javascript-workshop": "^1.0.6", "htmllint-cli": "github:kevincolten/htmllint-cli",