{"id":9252,"date":"2022-10-21T16:16:53","date_gmt":"2022-10-21T15:16:53","guid":{"rendered":"https:\/\/stevepedwards.today\/DebianAdmin\/?p=9252"},"modified":"2023-10-28T20:08:27","modified_gmt":"2023-10-28T19:08:27","slug":"js-refactoring-the-guess-number-game-code","status":"publish","type":"post","link":"https:\/\/stevepedwards.today\/DebianAdmin\/js-refactoring-the-guess-number-game-code\/","title":{"rendered":"JS: Refactoring the Guess Number Game Code"},"content":{"rendered":"<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_9252\" class=\"pvc_stats all  \" data-element-id=\"9252\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/stevepedwards.today\/DebianAdmin\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p>To work toward the DRY principle (Don't Repeat Yourself), the code in the previous learning Post comprised 2 almost equal blocks for two differnet conditions - one guess too high, the other too low.<\/p>\n<p>A ternary operator can be used to replace those code blocks so massively decrease the code quantity, while doing the same job. This is called code <em>refactoring<\/em>.<\/p>\n<p>The original similar blocks are:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">} else if (guess &gt; secretNumber) {\r\n    if (score &gt; 1) {\r\n      document.querySelector('.message').textContent = <span style=\"color: #ff0000;\">'Too high';<\/span>\r\n      document.querySelector('.message').style.color = 'red';\r\n      score--;\r\n      document.querySelector('.score').textContent = score;\r\n    } else {\r\n      document.querySelector('.message').textContent = 'You lost the game!';\r\n      document.querySelector('.score').textContent = 0;\r\n    }\r\n\r\n    \/\/ Guess too low\r\n  } else if (guess &lt; secretNumber) {\r\n    if (score &gt; 1) {\r\n      document.querySelector('.message').textContent = <span style=\"color: #ff0000;\">'Too low';<\/span>\r\n      document.querySelector('.message').style.color = 'yellow';\r\n      score--;\r\n      document.querySelector('.score').textContent = score;\r\n    } else {\r\n      document.querySelector('.message').textContent = 'You lost the game!';\r\n      document.querySelector('.score').textContent = 0;\r\n    }\r\n  }<\/pre>\n<p>The key logic for replacement are :<\/p>\n<p><span style=\"color: #ff0000;\">if (guess &gt; secretNumber)<\/span> and<span style=\"color: #ff0000;\"> if (guess &lt; secretNumber)<\/span><\/p>\n<p>with the main block differences being the screen messages \"too high\" and \"too low\"<\/p>\n<p>The logic that differentiates these \"if\" blocks asks if the guess is either higher or lower than the secret number to be guessed, which can be replaced by the logic that the guessed number is just \"different from\" or not equal to the secret number to be guessed.<\/p>\n<p>This original method can be replaced with an \"else if\" block placed above the prior two blocks and only ONE code block segment placed in it::<\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">else if (guess !== secretNumber) {\u00a0\r\n      if (score &gt; 1) {\r\n            document.querySelector('.message').textContent = \r\n            guess &gt; secretNumber ? 'Too high!' : 'Too low!'\r\n            score--;\r\n            document.querySelector('.score').textContent = score;\r\n          } else {\r\n            document.querySelector('.message').textContent = 'You lost the game!';\r\n            document.querySelector('.score').textContent = 0;\r\n          }\r\n      }<\/pre>\n<p>The ternary operator can be placed so:<\/p>\n<\/div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">'use strict';\r\n\r\n\/\/ -----------------------------GAME------------------------------\r\n\r\n\/\/ -----------------pre Play Again button code\r\n\r\nlet secretNumber = Math.trunc(Math.random() * 20 + 1);\r\n\/\/ state variable - part of the state of the code - not in the DOM\r\nlet score = 20;\r\nlet highscore = 0;\r\n\r\ndocument.querySelector('.check').addEventListener('click', function () {\r\n  const guess = Number(document.querySelector('.guess').value);\r\n\r\n  \/\/ When no input\r\n  if (!guess) {\r\n    document.querySelector('.message').textContent =\r\n      'No Number Entered! Try Again!';\r\n\r\n    \/\/ When player wins\r\n  } else if (guess === secretNumber) {\r\n    document.querySelector('.message').textContent = 'Correct Number! You Win!';\r\n    document.querySelector('.number').textContent = secretNumber;\r\n\r\n    \/\/ change bg on win\r\n    document.querySelector('body').style.backgroundColor = '#60b347';\r\n    \/\/ change text width\r\n    document.querySelector('.number').style.width = '30rem';\r\n\r\n    if (score &gt; highscore) {\r\n      highscore = score;\r\n      document.querySelector('.highscore').textContent = highscore;\r\n    }\r\n\r\n    \/\/ when guess is different from secret number:\r\n      } else if (guess !== secretNumber) {\r\n      if (score &gt; 1) {\r\n        <span style=\"color: #ff0000;\">document.querySelector('.message').textContent =\r\n          guess &gt; secretNumber ? 'Too high!' : 'Too low!';<\/span>\r\n        score--;\r\n        document.querySelector('.score').textContent = score;\r\n      } else {\r\n        document.querySelector('.message').textContent = 'You lost the game!';\r\n        document.querySelector('.score').textContent = 0;\r\n      }\r\n     }\r\n});\r\n\/\/ \"Again\" reset button - really simple method of reloading from server i window.location.reload() so cache is released - so whole page! Would incur traffic and lose highscore value. Now do long version...\r\ndocument.querySelector('.again').addEventListener('click', function () {\r\n  console.log(document.querySelector('.again').value);\r\n  \/\/ window.location.reload()\r\n  score = 20;\r\n  secretNumber = Math.trunc(Math.random() * 20 + 1);\r\n  document.querySelector('.message').textContent = 'Start guessing...';\r\n  document.querySelector('.score').textContent = '20';\r\n  document.querySelector('.number').textContent = '?';\r\n  document.querySelector('.guess').value = '';\r\n  document.querySelector('body').style.backgroundColor = '#222';\r\n  document.querySelector('.number').style.width = '15rem';\r\n});\r\n<\/pre>\n<p>A next refactoring step would be to replace all the duplicate code line with functions where possible. If a code block is highlighted in VS Code it shows in all the other places the same text exists, so the example of code lines for the (\".message\") class HTML lines shows 5 code lines the same that could be replaced with functions:<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-9259\" src=\"https:\/\/stevepedwards.today\/DebianAdmin\/wp-content\/uploads\/2022\/10\/MesgRpt.png\" alt=\"\" width=\"697\" height=\"973\" \/><\/p>\n<p>The function for this code that creates a generic displayMessage function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\/\/ document.querySelector('.message').textContent = <span style=\"color: #ff0000;\">'Correct Number! You Win!'<\/span>;\r\n   const displayMessage = function (<span style=\"color: #ff0000;\">message<\/span>) {\r\n     document.querySelector('.message').textContent = message;<\/pre>\n<p>Once that function is created, the original code can be commented out, copied from then\/or deleted, then the function can be used in all the other places with the original text of that code entered as it's message argument.<\/p>\n<p>It's definition needs to be placed outside the main game container code with the other declared variables. The complete replacement code:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">'use strict';\r\n\r\n\/\/ -----------------------------GAME------------------------------\r\n\r\n\/\/ -----------------pre Play Again button code\r\n\r\nlet secretNumber = Math.trunc(Math.random() * 20 + 1);\r\n\/\/ state variable - part of the state of the code - not in the DOM\r\nlet score = 20;\r\nlet highscore = 0;\r\nconst displayMessage = function (message) {\r\n  document.querySelector('.message').textContent = message;\r\n};\r\n\r\n\/\/ Main game container {} start\r\ndocument.querySelector('.check').addEventListener('click', function () {\r\n  const guess = Number(document.querySelector('.guess').value);\r\n\r\n  \/\/ When no input\r\n  if (!guess) {\r\n    \/\/ document.querySelector('.message').textContent =\r\n    \/\/   'No Number Entered! Try Again!';\r\n    \/\/ const displayMessage = function (message) {\r\n    \/\/   document.querySelector('.message').textContent = message;\r\n    \/\/ };\r\n    displayMessage('No Number Entered!');\r\n\r\n    \/\/ When player wins\r\n  } else if (guess === secretNumber) {\r\n    displayMessage('Correct Number! You Win!');\r\n\r\n    document.querySelector('.number').textContent = secretNumber;\r\n\r\n    \/\/ change bg on win\r\n    document.querySelector('body').style.backgroundColor = '#60b347';\r\n    \/\/ change text width\r\n    document.querySelector('.number').style.width = '30rem';\r\n\r\n    if (score &gt; highscore) {\r\n      highscore = score;\r\n      document.querySelector('.highscore').textContent = highscore;\r\n    }\r\n\r\n    \/\/ when guess is different from secret number:\r\n  } else if (guess !== secretNumber) {\r\n    if (score &gt; 1) {\r\n      \/\/ guess &gt; secretNumber ? 'Too high!' : 'Too low!';\r\n      \/\/ document.querySelector('.message').textContent = guess &gt; secretNumber ? 'Too high!' : 'Too low!'\r\n      displayMessage(guess &gt; secretNumber ? 'Too high!' : 'Too low!');\r\n      score--;\r\n      document.querySelector('.score').textContent = score;\r\n    } else {\r\n      \/\/ document.querySelector('.message').textContent = 'You lost the game!';\r\n      displayMessage('You lost the game!!');\r\n      document.querySelector('.score').textContent = 0;\r\n    }\r\n  }\r\n});\r\n\/\/ \"Again\" reset button - really simple method of reloading from server i window.location.reload() so cache is released - so whole page! Would incur traffic and lose highscore value. Now do long version...\r\ndocument.querySelector('.again').addEventListener('click', function () {\r\n  console.log(document.querySelector('.again').value);\r\n  \/\/ window.location.reload()\r\n  score = 20;\r\n  secretNumber = Math.trunc(Math.random() * 20 + 1);\r\n  \/\/ document.querySelector('.message').textContent = 'Start guessing...';\r\n  displayMessage('Start guessing...');\r\n  document.querySelector('.score').textContent = '20';\r\n  document.querySelector('.number').textContent = '?';\r\n  document.querySelector('.guess').value = '';\r\n  document.querySelector('body').style.backgroundColor = '#222';\r\n  document.querySelector('.number').style.width = '15rem';\r\n});\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>The same can even be done with the ternary operator :<\/p>\n<div>\n<div><span style=\"color: #00ff00;\">\/\/ guess &gt; secretNumber ? 'Too high!' : 'Too low!';<\/span><\/div>\n<div>\n<div>\n<div><span style=\"color: #339966;\">\/\/ document.querySelector('.message').textContent = guess &gt; secretNumber ? 'Too high!' : 'Too low!'<\/span><\/div>\n<\/div>\n<\/div>\n<div>\n<div>\n<div><span style=\"color: #ff0000;\">displayMessage(guess &gt; secretNumber ? 'Too high!' : 'Too low!')<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-9257\" src=\"https:\/\/stevepedwards.today\/DebianAdmin\/wp-content\/uploads\/2022\/10\/GameWon.png\" alt=\"\" width=\"1921\" height=\"1033\" \/><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_9252\" class=\"pvc_stats all  \" data-element-id=\"9252\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/stevepedwards.today\/DebianAdmin\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p>To work toward the DRY principle (Don't Repeat Yourself), the code in the previous learning Post comprised 2 almost equal blocks for two differnet conditions - one guess too high, the other too low. A ternary operator can be used to replace those code blocks so massively decrease the code quantity, while doing the same <a href=\"https:\/\/stevepedwards.today\/DebianAdmin\/js-refactoring-the-guess-number-game-code\/\" class=\"more-link\">...<span class=\"screen-reader-text\">\u00a0 JS: Refactoring the Guess Number Game Code<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-9252","post","type-post","status-publish","format-standard","hentry","category-post"],"a3_pvc":{"activated":true,"total_views":3,"today_views":0},"_links":{"self":[{"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/posts\/9252","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/comments?post=9252"}],"version-history":[{"count":14,"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/posts\/9252\/revisions"}],"predecessor-version":[{"id":9957,"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/posts\/9252\/revisions\/9957"}],"wp:attachment":[{"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/media?parent=9252"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/categories?post=9252"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/stevepedwards.today\/DebianAdmin\/wp-json\/wp\/v2\/tags?post=9252"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}