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>

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Feb 9, 2016 at 20:48
\$\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.

answered Feb 10, 2016 at 15:43
\$\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 ...
answered Feb 9, 2016 at 22:48
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.