1
\$\begingroup\$

I had previously submitted a tic tac toe code. I followed some of the changes suggested. This is my new code.

var playerSym;
var computerSym;
var turnCount = 0;
var playerWin = 0;
var compWin = 0;
var whoseTurn;
var grid = [];
var winFlag = false;
var playerScore = 0;
var compScore = 0;
var winningLine;
var emptyBoxes = [0, 1, 2, 3, 4, 5, 6, 7, 8];
function initialiseGrid() {
 var k = 0;
 for (var i = 0; i < 9; i++) {
 grid[i] = document.getElementById(k);
 k++;
 }
}
function enterPlayerChoice(eventSrc) {
 document.getElementById("easy").disabled = true;
 document.getElementById("difficult").disabled = true;
 if (!(document.getElementById("x").checked || document.getElementById("o").checked)) {
 alert("Choose Your Symbol");
 return;
 }
 var target = eventSrc.target;
 if (target.innerText !== "")
 return;
 turnCount++;
 var txtNode = document.createTextNode(playerSym);
 target.appendChild(txtNode);
 updateEmptyBox(Number(target.id));
 whoseTurn = "Player";
 if (turnCount > 3) {
 if (checkWin())
 return;
 }
 if (isDraw(turnCount, winFlag)) {
 gameReset();
 return;
 } else
 computersTurn();
}
function computersTurn() {
 whoseTurn = "Computer";
 if (document.getElementById("easy").checked)
 playEasy();
 else
 playHard();
}
function isDraw(turnCount, winFlag) {
 if (turnCount > 8 && !winFlag) {
 return confirm("It's A Draw");
 }
 return false;
}
function getRandomNum(min, max) {
 return Math.floor(Math.random() * (max - min + 1)) + min;
}
function playEasy() {
 turnCount++;
 var boxNum;
 boxNum = emptyBoxes[getRandomNum(0, emptyBoxes.length - 1)];
 insertCompChoice(boxNum);
 updateEmptyBox(boxNum);
 if (turnCount > 3) {
 if (checkWin())
 return;
 }
 if (isDraw(turnCount, winFlag))
 gameReset();
}
function insertCompChoice(boxNum) {
 var txtNode = document.createTextNode(computerSym);
 document.getElementById(boxNum).appendChild(txtNode);
}
function updateEmptyBox(boxNum) {
 var boxIndex = emptyBoxes.indexOf(boxNum);
 emptyBoxes.splice(boxIndex, 1);
 //alert(emptyBoxes);
}
function returnEmptyBoxes(possibleBoxes) {
 var empty = [];
 var i = 0;
 while (i < possibleBoxes.length) {
 if (emptyBoxes.indexOf(possibleBoxes[i]) !== -1)
 empty.push(possibleBoxes[i]);
 i++;
 }
 return empty;
}
function checkRowOrColumnOrDiagonal(cell1, cell2, cell3, symbol) {
 if (cell1.innerText == symbol && cell2.innerText == symbol) {
 if (cell3.innerText == symbol) {
 winningLine = [cell1.id, cell2.id, cell3.id];
 winFlag = true;
 } else {
 if (document.getElementById(cell3.id).innerText === "")
 return Number(cell3.id);
 }
 } else if (cell1.innerText == symbol && cell3.innerText == symbol) {
 if (cell2.innerText == symbol) {
 winFlag = true;
 } else {
 if (document.getElementById(cell2.id).innerText === "")
 return Number(cell2.id);
 }
 } else if (cell3.innerText == symbol && cell2.innerText == symbol) {
 if (cell1.innerText == symbol) {
 winFlag = true;
 } else {
 if (document.getElementById(cell1.id).innerText === "")
 return Number(cell1.id);
 }
 }
 return null;
}
function checkForWin() {
 //diagonal left to right
 if (checkRowOrColumnOrDiagonal(grid[0], grid[4], grid[8], computerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[0], grid[4], grid[8], computerSym);
 //diagonal right to left
 else if (checkRowOrColumnOrDiagonal(grid[2], grid[4], grid[6], computerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[2], grid[4], grid[6], computerSym);
 //first row
 else if (checkRowOrColumnOrDiagonal(grid[0], grid[1], grid[2], computerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[0], grid[1], grid[2], computerSym);
 //second row
 else if (checkRowOrColumnOrDiagonal(grid[3], grid[4], grid[5], computerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[3], grid[4], grid[5], computerSym);
 //third Row
 else if (checkRowOrColumnOrDiagonal(grid[6], grid[7], grid[8], computerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[6], grid[7], grid[8], computerSym);
 //first coloumn
 else if (checkRowOrColumnOrDiagonal(grid[0], grid[3], grid[6], computerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[0], grid[3], grid[6], computerSym);
 //second column
 else if (checkRowOrColumnOrDiagonal(grid[1], grid[4], grid[7], computerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[1], grid[4], grid[7], computerSym);
 //third column
 else if (checkRowOrColumnOrDiagonal(grid[2], grid[5], grid[8], computerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[2], grid[5], grid[8], computerSym);
 return -1;
}
function blockOppWin() {
 //diagonal left to right
 if (checkRowOrColumnOrDiagonal(grid[0], grid[4], grid[8], playerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[0], grid[4], grid[8], playerSym);
 //diagonal right to left
 else if (checkRowOrColumnOrDiagonal(grid[2], grid[4], grid[6], playerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[2], grid[4], grid[6], playerSym);
 //first row
 else if (checkRowOrColumnOrDiagonal(grid[0], grid[1], grid[2], playerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[0], grid[1], grid[2], playerSym);
 //second row
 else if (checkRowOrColumnOrDiagonal(grid[3], grid[4], grid[5], playerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[3], grid[4], grid[5], playerSym);
 //third Row
 else if (checkRowOrColumnOrDiagonal(grid[6], grid[7], grid[8], playerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[6], grid[7], grid[8], playerSym);
 //first coloumn
 else if (checkRowOrColumnOrDiagonal(grid[0], grid[3], grid[6], playerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[0], grid[3], grid[6], playerSym);
 //second column
 else if (checkRowOrColumnOrDiagonal(grid[1], grid[4], grid[7], playerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[1], grid[4], grid[7], playerSym);
 //third column
 else if (checkRowOrColumnOrDiagonal(grid[2], grid[5], grid[8], playerSym) !== null)
 return checkRowOrColumnOrDiagonal(grid[2], grid[5], grid[8], playerSym);
 return -1;
}
function isDiagonalFork(cell1, cell2, cell3) {
 if (cell1.innerText !== "" && cell2.innerText !== "" && cell3.innerText !== "") {
 if (cell1.innerText == cell2.innerText) {
 return [2, 6, 0, 8];
 } else if (cell2.innerText == cell3.innerText) {
 return [2, 6, 0, 8];
 } else if (cell1.innerText == cell3.innerText) {
 return [1, 3, 5, 7];
 }
 }
 return false;
}
function isArrowHeadFork(left, topOrBottom, right) {
 if (topOrBottom.innerText === "")
 return false;
 else if (left.innerText == topOrBottom.innerText) {
 return [Number(topOrBottom.id) - 1, Number(left.id) + 3, Number(left.id) - 3];
 } else if (topOrBottom.innerText == right.innerText) {
 return [Number(topOrBottom.id) - 1, Number(right.id) + 3, Number(right.id) - 3];
 }
}
function blockOppFork() {
 var possibleBlockMoves = [];
 var suggestedMove;
 if (isDiagonalFork(grid[2], grid[4], grid[6]) || isDiagonalFork(grid[0], grid[4], grid[8])) {
 if (isDiagonalFork(grid[0], grid[4], grid[8]))
 possibleBlockMoves = isDiagonalFork(grid[0], grid[4], grid[8]);
 else if (isDiagonalFork(grid[2], grid[4], grid[6]))
 possibleBlockMoves = isDiagonalFork(grid[2], grid[4], grid[6]);
 possibleBlockMoves = returnEmptyBoxes(possibleBlockMoves);
 if (possibleBlockMoves.length > 0) {
 suggestedMove = possibleBlockMoves[getRandomNum(0, possibleBlockMoves.length - 1)];
 return suggestedMove;
 }
 }
 if (isArrowHeadFork(grid[3], grid[7], grid[5])) {
 possibleBlockMoves = isArrowHeadFork(grid[3], grid[7], grid[5]);
 possibleBlockMoves = returnEmptyBoxes(possibleBlockMoves);
 suggestedMove = possibleBlockMoves[getRandomNum(0, possibleBlockMoves.length - 1)];
 if (possibleBlockMoves.length > 0) {
 suggestedMove = possibleBlockMoves[getRandomNum(0, possibleBlockMoves.length - 1)];
 return suggestedMove;
 }
 }
 if (isArrowHeadFork(grid[3], grid[1], grid[5])) {
 possibleBlockMoves = isArrowHeadFork(grid[3], grid[1], grid[5]);
 possibleBlockMoves = returnEmptyBoxes(possibleBlockMoves);
 suggestedMove = possibleBlockMoves[getRandomNum(0, possibleBlockMoves.length - 1)];
 if (possibleBlockMoves.length > 0) {
 suggestedMove = possibleBlockMoves[getRandomNum(0, possibleBlockMoves.length - 1)];
 return suggestedMove;
 }
 }
 return -1;
}
function oppCorner() {
 if (!(grid[0].innerText !== "" && grid[4].innerText !== "" && grid[8].innerText !== "")) {
 if (grid[0].innerText !== "")
 return Number(grid[8].id);
 else if (grid[8].innerText !== "")
 return Number(grid[0].id);
 }
 if (!(grid[2].innerText !== "" && grid[4].innerText !== "" && grid[6].innerText !== "")) {
 if (grid[2].innerText !== "")
 return Number(grid[6].id);
 else if (grid[6].innerText !== "")
 return Number(grid[2].id);
 }
 return -1;
}
function takeCorner() {
 var corners = [0, 2, 6, 8];
 var possibilities = returnEmptyBoxes(corners);
 if (possibilities.length > 0) {
 var suggestedMove = possibilities[getRandomNum(0, possibilities.length - 1)];
 return suggestedMove;
 }
 return -1;
}
function playHard() {
 /*
 //////////////////////
 The first two turns decide the game.
 First Turn:
 Take corner or center.
 Second Turn:
 If Center is empty take it.
 If not, take a corner.
 From third turn onwards,
 1) play for win
 2) block opp win
 3) block fork
 a) diagonal Fork
 b) arrowhead Fork
 4) play center if open
 6) play Opp corner
 7) play corner
 8) play sidecenter.
 //////////////////////
 */
 turnCount++;
 var boxNum;
 if ((turnCount == 1)) {
 boxNum = 2 * getRandomNum(0, 4);
 insertCompChoice(boxNum);
 updateEmptyBox(boxNum);
 } else if (turnCount == 2) {
 if (emptyBoxes.indexOf(4) !== -1)
 boxNum = 4;
 else {
 var cornersAndCenter = [0, 2, 4, 6, 8];
 var possibilities = returnEmptyBoxes(cornersAndCenter);
 boxNum = possibilities[getRandomNum(0, possibilities.length - 1)];
 }
 insertCompChoice(boxNum);
 updateEmptyBox(boxNum);
 } else if (turnCount > 2) {
 if (checkForWin() !== -1) {
 boxNum = checkForWin();
 insertCompChoice(boxNum);
 checkWin();
 updateEmptyBox(boxNum);
 } else if (blockOppWin() !== -1) {
 boxNum = blockOppWin();
 insertCompChoice(boxNum);
 updateEmptyBox(boxNum);
 } else if (blockOppFork() !== -1) {
 boxNum = blockOppFork();
 insertCompChoice(boxNum);
 updateEmptyBox(boxNum);
 } else if (emptyBoxes.indexOf(4) !== -1) {
 insertCompChoice(4);
 updateEmptyBox(boxNum);
 } else if (oppCorner() !== -1) {
 boxNum = oppCorner();
 insertCompChoice(boxNum);
 updateEmptyBox(boxNum);
 } else if (takeCorner() !== -1) {
 boxNum = takeCorner();
 insertCompChoice(boxNum);
 updateEmptyBox(boxNum);
 } else {
 var sideCenters = [1, 3, 5, 7];
 var possibilities = returnEmptyBoxes(sideCenters);
 boxNum = possibilities[getRandomNum(0, possibilities.length - 1)];
 insertCompChoice(boxNum);
 updateEmptyBox(boxNum);
 }
 }
 if (isDraw(turnCount, winFlag))
 gameReset();
}
function checkWin() {
 var symToCompare;
 if (whoseTurn == "Player")
 symToCompare = playerSym;
 else if (whoseTurn == "Computer")
 symToCompare = computerSym;
 checkRowOrColumnOrDiagonal(grid[0], grid[1], grid[2], symToCompare);
 checkRowOrColumnOrDiagonal(grid[3], grid[4], grid[5], symToCompare);
 checkRowOrColumnOrDiagonal(grid[6], grid[7], grid[8], symToCompare);
 checkRowOrColumnOrDiagonal(grid[0], grid[3], grid[6], symToCompare);
 checkRowOrColumnOrDiagonal(grid[1], grid[4], grid[7], symToCompare);
 checkRowOrColumnOrDiagonal(grid[2], grid[5], grid[8], symToCompare);
 checkRowOrColumnOrDiagonal(grid[0], grid[4], grid[8], symToCompare);
 checkRowOrColumnOrDiagonal(grid[2], grid[4], grid[6], symToCompare);
 if (winFlag) {
 addOrRemoveCSS(winningLine);
 //alert(winningLine);
 if (whoseTurn == "Player")
 playerScore++;
 else
 compScore++;
 updateScore();
 if (confirm(whoseTurn + " wins. Play Again??"))
 gameReset();
 return true;
 }
 return false;
}
/*/////////////////////////////////////////////////////////
Check 
/////////////////////////////////////////////////////////*/
function addOrRemoveCSS(line) {
 var i = 0;
 while (i < 3) {
 //alert(typeof line[i]);
 var cell = $("#"+line[i]);
 cell.toggleClass("winningCSS");
 i++;
 }
}
function updateScore() {
 $("#playerScores").empty();
 $("#compScores").empty();
 var textNodePlayer = document.createTextNode(playerScore);
 var textNodeComp = document.createTextNode(compScore);
 document.getElementById("playerScores").appendChild(textNodePlayer);
 document.getElementById("compScores").appendChild(textNodeComp);
}
function gameReset() {
 var cells = document.getElementsByClassName("box");
 var i = 0;
 while (i < cells.length) {
 cells[i++].innerText = "";
 }
 document.getElementById("easy").disabled = false;
 document.getElementById("difficult").disabled = false;
 turnCount = 0;
 whoseTurn = "";
 winFlag = false;
 emptyBoxes = [0, 1, 2, 3, 4, 5, 6, 7, 8];
 addOrRemoveCSS(winningLine);
 winningLine=[];
}
window.addEventListener("load", initialiseGrid);
document.getElementById("symChange").addEventListener("click", function() {
 if (!turnCount) {
 document.getElementById("o").disabled = false;
 document.getElementById("x").disabled = false;
 } else {
 alert("You cannot change Your Symbol during a game");
 }
});
document.getElementById("easy").addEventListener("click", function() {
 document.getElementById("easy").disabled = true;
 document.getElementById("difficult").disabled = true;
});
document.getElementById("difficult").addEventListener("click", function() {
 document.getElementById("easy").disabled = true;
 document.getElementById("difficult").disabled = true;
});
document.getElementById("x").addEventListener("click", function() {
 playerSym = "X";
 computerSym = "O";
 document.getElementById("o").disabled = true;
 document.getElementById("x").disabled = true;
});
document.getElementById("o").addEventListener("click", function() {
 playerSym = "O";
 computerSym = "X";
 document.getElementById("o").disabled = true;
 document.getElementById("x").disabled = true;
});
document.getElementById("resetBoard").addEventListener("click", gameReset);
document.getElementById("scoreReset").addEventListener("click", function() {
 playerScore = 0;
 compScore = 0;
 updateScore();
});
document.getElementById("0").addEventListener("click", enterPlayerChoice);
document.getElementById("1").addEventListener("click", enterPlayerChoice);
document.getElementById("2").addEventListener("click", enterPlayerChoice);
document.getElementById("3").addEventListener("click", enterPlayerChoice);
document.getElementById("4").addEventListener("click", enterPlayerChoice);
document.getElementById("5").addEventListener("click", enterPlayerChoice);
document.getElementById("6").addEventListener("click", enterPlayerChoice);
document.getElementById("7").addEventListener("click", enterPlayerChoice);
document.getElementById("8").addEventListener("click", enterPlayerChoice);

Are there any changes that I can do ??

asked May 31, 2016 at 6:36
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

First start by thinking of the board as squares with x and y coordinates. like so

0,0 | 0,1 | 0,2
----|-----|----
1,0 | 1,1 | 1,2
----|-----|----
2,0 | 2,1 | 2,2

If you think about the board this way, you can potentially scale the board to any size, make use of patterns, etc, etc. By laying out the board this way you can already see what constitutes a win regardless of board size.

There's vertical win if all Y's are the same There's a horizontal win if all X's are the same There's a diagonal-down win if X and Y are the same for each box There's a diagonal-up win if X and Y make the sum of the board minus 1.

With this in mind, I would encourage getting out of hard-coding the potential win scenarios like you have with checkForWin().

You may have to refactor your code a little bit to make it simple, scalable and to support any size board. Here's where I'd start.

  1. Keep your players in an array so you can bounce from player to player easily by using the modulus of positions played to the index of the player in the array.

e.g.

var players = [
 { name: 'Player 1', symbol: 'X', positions_played: [] },
 { name: 'Player 2', symbol: 'O', positions_played: [] }
];

where positions_played for each player could contain an array of positions played for just that player using the X and Y coordinates as described above.

positions_played: [
 [0,0],
 [0,1],
 [0,2]
]

As an example, this array above represents a win because all the X's are the same.

That's for starters. I know that's a bit of a departure from what you have, but following that approach would dramatically simplify your code and make it pretty robust.

answered Jun 2, 2016 at 20:17
\$\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.