1
\$\begingroup\$

I need help with a question my teacher wants us to do by tomorrow. I would love for you to try to help me out with this.

The following functions must be implemented:

  1. A function that initializes all variables
  2. Variables that keep track of which player is currently playing, and which player is next
  3. Variables that keep count of X's and O's played

var currentPlayer = prompt("Who is The Current Player X=1 O=2");



var grid=new Array(3);
grid[0]=new Array(3);
grid[1]=new Array(3);
grid[2]=new Array(3);


for (var i=0; i<=2; i++) {
  for (var j=0; j<=2; j++) {
    grid[i][j]=0;
  }
}

// Checks If Grid Is Already Clicked
function clickCell(x,y) {
  if (grid[x][y]>0) {
    alert("Dont Try To Cheat Bud!!!!!");
  } 


// Clicking Of Boxes
  else {
    if (currentPlayer==1) {
      document.getElementById("cell_"+x+"_"+y).style.color="#3F88C5";
      document.getElementById("cell_"+x+"_"+y).innerHTML="X";
      grid[x][y]=1;
      currentPlayer=2;
    } else {
       document.getElementById("cell_"+x+"_"+y).style.color="#E2C290";
       document.getElementById("cell_"+x+"_"+y).innerHTML="O";
      grid[x][y]=2;
      currentPlayer=1;
    }
  }
}

// Reset Game

function reset() {
for (var i=0; i<=2; i++) {
  for (var j=0; j<=2; j++) {
    grid[i][j]=0;
    document.getElementById("cell_"+i+"_"+j).innerHTML="&nbsp;";
  }
}
 currentPlayer=1;
}
h1 {
    text-align: center;
    font-family: 'Indie Flower', cursive;
  font-size: 53px;
}
div {
  text-align: center;
  margin: 0px auto;
    text-align: center;
  margin: auto;
}
body {
    background-color: #02c39a;
}

.cell {
  width:80px;
  height:80px;
  border: 5px solid #000000;
  background: #FFFFFF;
  font-size: 46pt;
  font-family: arial;
  font-weight: bold;
  text-align: center;
  margin: auto;

}

fieldset {
  text-align: center;
  margin: auto;
}

.cell:hover {
  background: #C2DBFC;
  text-align: center;
}
<html>
<head>
    <meta charset="utf-8" />
    <title>Tic-Tac-Toe</title>
    <link rel="stylesheet" type="text/css" href="tictoe.css">
    <link href='https://fonts.googleapis.com/css?family=Indie+Flower' rel='stylesheet' type='text/css'>
    <script type="text/javascript" src="tictoe.js"></script>
</head>
<body>

<h1>Tic Tac Toe</h1>



<fieldset>
<p>Please Reload The Page To Choose Player Who Goes First Again</p>

<div>
<Table>
  <tr>
    <td id="cell_0_0" class="cell" onClick="JavaScript: clickCell(0,0);">&nbsp;</td>
    <td id="cell_0_1" class="cell" onClick="JavaScript: clickCell(0,1);">&nbsp;</td>
    <td id="cell_0_2" class="cell" onClick="JavaScript: clickCell(0,2);">&nbsp;</td>
  </tr>
    <tr>
    <td id="cell_1_0" class="cell" onClick="JavaScript: clickCell(1,0);">&nbsp;</td>
    <td id="cell_1_1" class="cell" onClick="JavaScript: clickCell(1,1);">&nbsp;</td>
    <td id="cell_1_2" class="cell" onClick="JavaScript: clickCell(1,2);">&nbsp;</td>
  </tr>
    <tr>
    <td id="cell_2_0" class="cell" onClick="JavaScript: clickCell(2,0);">&nbsp;</td>
    <td id="cell_2_1" class="cell" onClick="JavaScript: clickCell(2,1);">&nbsp;</td>
    <td id="cell_2_2" class="cell" onClick="JavaScript: clickCell(2,2);">&nbsp;</td>
  </tr>
  </table>
  </div>
<input type=button onClick="Javascript: reset();" value="Reset">
  <br/><br/>

</body>
</html>

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

You should not use "magic numbers". Define a constant representing the size of the grid:

var GRID_SIZE = 3;

Generally new Array() can be shorted to [] (an empty literal array). Also it's not really necessary to give a length when initializing arrays, because JavaScript has dynamic arrays. Thus

var grid=new Array(3);
grid[0]=new Array(3);
grid[1]=new Array(3);
grid[2]=new Array(3);

can be shorted to

var grid = [];
grid[0] = [];
grid[1] = [];
grid[2] = [];

or by using a literal array even to

var grid = [ [], [], [] ];

This however skips the use if the GRID_SIZE constant. So you could instead integrate this with the loops filling the grid:

var grid = [];
for (var i = 0; i < GRID_SIZE; i++) {
  grid[i] = [];
  for (var j = 0; j < GRID_SIZE; j++) {
    grid[i][j] = 0;
  }
}

Your HTML table is unnecessary complex.

You don't need to encode the coordinates of the cells in the ID. You can get the coordinates (or find a cell based on coordinates) using the DOM (more about that later).

You don't need to give every single the same class. Instead give the table a class or identifier (e.g. tic-tac-toe) and style the cells using a descendant selector:

.tic-tac-toe td {
   /* ... */
}

Event handlers shouldn't be assigned using HTML attributes. And if you do, then you don't need to use javascript: in them. javascript: is only used in attributes that normally don't contain JavaScript, such as href, however you shouldn't be using that either. Event handlers should only be assigned using addEventListener.

Finally the non-breaking spaces are also unnecessary. To make sure that the empty cells are displayed use the CSS empty-cells: show.

This leaves us with:

<table class="tic-tac-toe" id="tic-tac-toe-1">
  <tr>
    <td></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <td></td>
    <td></td>
  </tr>
</table>

When assigning the event handler it is not not necessary to assign each cell it's own handler. Instead assign the handler to a common parent element - in this case the table. The event object will contain a reference to the actually clicked element:

var table = document.getElementById("tic-tac-toe-1");
table.addEventListener("click", tableClick);

function tableClick(event) {
    var element = event.target;
    if (element && element.tagName === "TD") {
       var y = element.cellIndex;
       var x = element.parent.rowIndex;

       clickCell(element, x, y);
    }
}

Since you already have a reference to the clicked cell, you don't need to look for it in clickCell.

function clickCell(cell, x, y) {
  if (grid[x][y] > 0) {
    alert("Dont Try To Cheat Bud!!!!!");
  } else {
    if (currentPlayer == 1) {
      cell.className = "x";
      cell.innerHTML = "X";
      grid[x][y]=1;
      currentPlayer=2;
    } else {
      cell.className = "o";
      cell.innerHTML = "O";
      grid[x][y]=2;
      currentPlayer=1;
    }
  }
}

Also you shouldn't assign the colors to the elements. Instead define the colors in the CSS with classes.

.x { color: #3F88C5; }
.o { color: #E2C290; }

If you ever need to get an element from the coordinates, then you can use the DOM properties rows and cells:

var cell = table.rows[y].cells[x];

Some quick last things:

  • Identifying the current player using the numbers 1 and 2 is not good (magic numbers again). Find an alternative. Also: What happens, if the user doesn't enter 1 or 2 at the beginning?

  • The reset function basically has the same loop as the initialization. You should re-write both so that you can re-use the loop instead of having it twice in your code.

  • The grid variable isn't necessary. All information in it can be get directly from the HTML table.

\$\endgroup\$
1
\$\begingroup\$

In order to fultill task 1 (function to initialize all variables), just pack your first lines of code inside of a function:

var currentPlayer, 
    grid, 
    i, 
    j;

function initVars() {
  currentPlayer =  = prompt("Who is The Current Player X=1 O=2");
  grid = new Array(3);
  grid[0]=new Array(3);
  grid[1]=new Array(3);
  grid[2]=new Array(3);

  for (i=0; i<=2; i++) {
    for (j=0; j<=2; j++) {
      grid[i][j]=0;
    }
  }
}

initVars();


// Checks If Grid Is Already Clicked
function clickCell(x,y) {
... rest of Code ...
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.