Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 8527

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 60k
Author
Asked: November 28, 20242024-11-28T01:59:08+00:00 2024-11-28T01:59:08+00:00

JavaScript tic tac toe – intermediate level – t24

  • 60k

Hi there👋🏽.

Intro

Translating a data structure(DS) to a visual component is an essential skill for a developer, especially as a JS dev, as you may find yourself dabbling in the frontend from time to time, which is what we going to do in this tutorial.

this is a build from the previous tut JavaScript tic tac toe – beginner level – t24 where we built a working console logged tic tac toe, you can find the code on git.

Image description

Intermediate

Translating a DS into a visual component is part of the intermediate, However the true intermediate comes from handling two environments, as now we are wrapping a node/native app for the browser, which is very exciting actually.

Node vs Browser

Node and the browser are completely two separate distinct environments that JS can run in, Node js(the site) words it way better “Unlike the browser where JavaScript is sandboxed for your safety, node. js has full access to the system like any other native application”

let's get crackin

before we do anything we need a way to detect or tell whether our code is running in the browser or node, for example the browser does not have the readline module while node has no document(DOM), so we need a way to run specific code for a specific env;

   let inNode = true;  // on top  if (typeof process !== 'undefined') {   // any code specific to node should be in this block and will not run in the browser   // as process is not defined in the browser but node only   // since readline is in node we need to move it's require here    }else{    // browser specific code is controlled by this else      // inNode being false   inNode = false;  }     
Enter fullscreen mode Exit fullscreen mode

moving node specific code

// move the readline emitter and require here // first declare readline on top, as it will hold our readline module on load let readline;   // will remain undefined in the browser let inNode = true;  if (typeof process !== 'undefined') {  readline = require("readline");    readline.emitKeypressEvents(process.stdin);  process.stdin.setRawMode(true);  process.stdin.on('keypress', (str, key) => {    if (key.ctrl && key.name === 'c') {      process.exit();    } else {        if(turn){          if(combo.row){              combo.col = key.name              turn = false              game.move(combo)           }else{             combo.row = key.name           }        }else{            console.log("wait your turn")        }      }  });  }else{    inNode = false;  }    
Enter fullscreen mode Exit fullscreen mode

as simple as that now we can run browser and node specific code in one file.

Browser side

here is a simple html file:

 <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>Document</title>     <style>         *{             box-sizing: border-box;          }          body{             padding: 0;             margin: 0;             font-family: sans-serif;             height: 100vh;             display: flex;             justify-content: center;             align-items: center;          }          .app{              display: flex;             flex-wrap: wrap;          }         .reset{             width: 0px;             height: 0px;             border: 1px solid black;          }          .img{           /* width: 100px;           height: 100px; */           object-fit: cover;          }     </style> </head> <body>        <div class="app">         </div>        <script src="tic.js"></script> </body> </html>    
Enter fullscreen mode Exit fullscreen mode

I won't be explaining the css, as I assume it's very easy as this also is an intermediate tut

Out goal here is translate our board :

const board = [[" ", " " , " "],                 [" ", " " , " "],                 [" ", " " , " "],   ]      
Enter fullscreen mode Exit fullscreen mode

to a visual board in the browser, so I had two options: to use elements or the canvas, I picked elements, as the canvas is kinda complex but way faster, speed won't be a problem for us thou since our board is small. Maybe in the advanced level we will have a side by side, elements and canvas.

first things first we need to update the updateBoard function to not console.log in the browser

updateBoard: function(){       if(inNode){         console.log("   ")         board.forEach((arr, i)=> {               console.log(arr.toString().replace(/,/g, "|"))           })     }else{      }   }   
Enter fullscreen mode Exit fullscreen mode

the following is browser code block, everything we do from about now, will be in this block

if (!inNode) {     // will run in the browser only   }    
Enter fullscreen mode Exit fullscreen mode

I suggest using VScode live server plugin to run this, using tools like Parcel will cause problems, as they transpile the code, I assume, you can try thou.

let w = 0; // declare on top    if (!inNode) {      let app = document.querySelector(".app")       w = Math.floor(300/board.length - 2);      // w is the width of each cell     // our app div is 300 x 300 px, we are dividing by     // board len(rows) so each cell will take up equal space     // basically creating a grid with equal spaces     // the minus 2 accounts for border line in each cell /**  * @type {HTMLDivElement}  */    const len = board.length     for(let i = 0; i < len; i++){     for(let j = 0; j < len; j++){        // create cell will return a div       app.appendChild(createCell(w, i, j))        // we are passing i and j so each cell is aware of it's position(coordinates)        // which correspond to coordinates on the board     }    }   }   
Enter fullscreen mode Exit fullscreen mode

the createcell function

let cells = {} // declare on top, ...  if (!inNode) {         function createCell(w, col, row){              // closure function,             // to make sure we receive the correct state onclick           function keepContext(){              let state = {               col,                row,                w             }              let d = document.createElement("div");             d.style = `background: lightgray;`             d.classList.add("reset")             // stretching the empty div width and height             d.style.paddingBottom = `${w}px`             d.style.paddingRight = `${w}px`             d.onclick = () => processClick(state)             // cache of the created cells(elements), so we              // use the elements in the updateBoard func to             cells[`${row}-${col}`] = d             return d          }        return keepContext()      }    ...  }   
Enter fullscreen mode Exit fullscreen mode

all we need now is the processClick function

if (!inNode) {    function processClick(state){          const img = document.createElement("img")          img.src = "./img/X.png"  // an Image with x, you can use any you like, I drew it with excalidraw, make the background transparent          img.height = state.w          img.width = state.w          // magic happens here:          if(board[state.row][state.col] === " " && turn){          // if the user clicks on empty cell and it's not computer playing          // append an image on the click row and col          cells[`${state.row}-${state.col}`].appendChild(img)          // also update the board(remember the coords correspond)          // so the computer knows we played and can see updated possible moves          board[state.row][state.col] = "X"          // update possible moves          game.update();          setTimeout(() => {           game.computer()       }, 300);         }      }   ... }  
Enter fullscreen mode Exit fullscreen mode

all we need to do now, is update the visual board from the state of the array board, so they are in sync,

in the else of updateBoard

else{       // console.log("updating viz board")       board.forEach((arr, i)=> {            arr.forEach((val, j)=> {               if(val === "O"){                   // checking if there's no O image in the current cel                 if(!cells[`${i}-${j}`].firstChild){                    const img = document.createElement("img")                   img.src = "./img/O.png"                   img.height = w                   img.width = w                   cells[`${i}-${j}`].appendChild(img)                   // adding O's in the visual board                 }              }            })       })       }   
Enter fullscreen mode Exit fullscreen mode

remember X's are added onclick,

The only thing left now, is to sync the visual board with the states of winning and draw, meaning the player and computer cannot add O or X when the game is over,

it's a bit messy, but it works, in the advanced level, I will consider refactoring

 ...  update : function(){     this.isgameOver();      if(gameOver){       this.updateBoard()       console.log(`Game over ${winner} won!`)         if(inNode){           process.exit();         }else{           turn = false         }       }      this.updateBoard();     m = this.possibleMoves();     if(m.length === 0){       gameOver = true;       console.log("Game over by draw")       if(inNode){         process.exit();       }else{         turn = false       }     }    }  ...  
Enter fullscreen mode Exit fullscreen mode

With that we are done with the intermediate level, as the levels increase the explanation does the opposite, if you get stuck use the repo**** as a reference

Conclusion

I will try to make this series as consistent as possible, More interesting projects coming, including a mini compiler👌🧙‍♂️, yes I am going all out, teaching is the best way to learn too,.

if you would like to support me, you can buy me a coffee below, I will highly appreciate it❤❤, you certainly don't have to if you can't.

Buy Me A Coffee

with that cheers till next time, Happy Hacking!!

javascriptprogrammingtutorialwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 2k
  • Popular
  • Answers
  • Author

    ES6 - A beginners guide - Template Literals

    • 0 Answers
  • Author

    Understanding Higher Order Functions in JavaScript.

    • 0 Answers
  • Author

    Build a custom video chat app with Daily and Vue.js

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.