Code keeps looping into max call stack error - javascript

I am trying to make tic tac toe on a website using javascript. That worked and now I'm trying to make a bot that, then you have 2 area's in a row. It needs to block you. But everytime it does block me, it won't do anything else afterwards, because it keeps looping into the error.
The t-numbers are the tile names, 0 means unoccupied,1 means for player 1, and 2 for player 2.
The t-numbers with a 1 behind it are just the tiles but they mustn't interfere with the functions (they are t-numbers too).
How do I fix this?
function tbot(){
while (turn == "player 2") {
if (t41 == 0 &&
(t01 == 1 && t81 == 1) ||
(t11 == 1 && t71 == 1) ||
(t21 == 1 && t61 == 1) ||
(t31 == 1 && t51 == 1)
) {t4()}
else {
var tiles = ['0', '1', '2', '3', '4', '5', '6', '7', '8'];
var tile = tiles[Math.floor(Math.random()*tiles.length)];
if (tile == '0' && t01 == 0) {t0()}
else if (tile == '1' && t11 == 0) {t1()}
else if (tile == '2' && t21 == 0) {t2()}
else if (tile == '3' && t31 == 0) {t3()}
else if (tile == '4' && t41 == 0) {t4()}
else if (tile == '5' && t51 == 0) {t5()}
else if (tile == '6' && t61 == 0) {t6()}
else if (tile == '7' && t71 == 0) {t7()}
else if (tile == '8' && t81 == 0) {t8()}
}
}
}
function update() {
if (t01 == 1 &&
((t11 == 1 && t21 == 1)||(t31 == 1 && t61 == 1))
||t41 == 1 &&
((t31 == 1 && t51 == 1)||(t11 == 1 && t71 == 1)||
(t01 == 1 && t81 == 1)||(t21 == 1 && t61 == 1))
||t81 == 1 &&
((t61 == 1 && t71 == 1)||(t21 == 1 && t51 == 1))
) {
twin = 1;
document.getElementById('turnshow').innerHTML = "Player 1 is the winner!";
document.getElementById('treset').style.backgroundColor = '#888';
} else if (t01 == 2 &&
((t11 == 2 && t21 == 2)||(t31 == 2 && t61 == 2))
||t41 == 2 &&
((t31 == 2 && t51 == 2)||(t11 == 2 && t71 == 2)||
(t01 == 2 && t81 == 2)||(t21 == 2 && t61 == 2))
||t81 == 2 &&
((t61 == 2 && t71 == 2)||(t21 == 2 && t51 == 2))
) {
twin = 1;
document.getElementById('turnshow').innerHTML = "Player 2 is the winner!";
document.getElementById('treset').style.backgroundColor = '#888';
} else {
if (bot == 1) {tbot();}
document.getElementById('turnshow').innerHTML = "It is " + turn + "'s turn!";
}
}
function t4() {
if (t41 == 0 && twin == 0) {
if (turn == "player 1") {
document.getElementById('t4').style.backgroundColor = p1;
turn = "player 2";
t41 = 1;
} else {
document.getElementById('t4').style.backgroundColor = p2;
turn = "player 1";
t41 = 2;
}
}
update();
}

The program never exit the while loop because condition (turn == "player 2") is always true.
If you're expecting t4() to change turn then I guess it doesn't do the job right. Check for (t41 == 0 && twin == 0), turn will never change if this condition is never been true.

I found what i did wrong. When I was checking if there are two area's selected in a row my code was:
if (t41 == 0 &&
(t01 == 1 && t81 == 1) ||
(t11 == 1 && t71 == 1) ||
(t21 == 1 && t61 == 1) ||
(t31 == 1 && t51 == 1)
)
But what that did: t41 and t01 and t81 or t11 and t71 or etc.
I just needed to add "()" around the options :/
if (t41 == 0 &&
((t01 == 1 && t81 == 1) ||
(t11 == 1 && t71 == 1) ||
(t21 == 1 && t61 == 1) ||
(t31 == 1 && t51 == 1))
)

Related

Why won't the text show up with this code?

This is all of the code for an app I've been making for class thats meant to tell you what game to buy depending on the genre, length, and amount of players but I cant figure out why it wont display the text.
It may be obvious whats wrong but this class is my first time coding except so ill miss some obvious things
var Genre = getText("genreSelector");
var Length = getNumber("lengthSelector");
var Mode = getText("modeSelector");
onEvent("genreSelector", "change", function( ) {
updateScreen();
});
onEvent("modeSelector", "change", function( ) {
updateScreen();
});
onEvent("lengthSelector", "change", function( ) {
updateScreen();
});
function updateScreen() {
if (Genre == "RPG" && Mode == "Multiplayer" && Length == 80 || Length == 70 || Length == 60 || Length == 50) {
setText("selectedGameText", "Baldur's Gate");
}
if (Genre == "RPG" && Mode == "Multiplayer" && Length == 40 || Length == 30) {
setText("selectedGameText", "Diablo");
}
if(Genre == "RPG" && Mode == "Multiplayer" && Length == 20 || Length == 10) {
setText("selectedGameText", "Child of light");
}
if (Genre == "RPG" && Mode == "Singleplayer" && Length == 80 || Length == 70 || Length == 60 || Length == 50) {
setText("selectedGameText", "Final Fantasy");
}
if (Genre == "RPG" && Mode == "Singleplayer" && Length == 30 || Length == 20 || Length == 10) {
setText("selectedGameText", "NieR");
}
if (Genre == "Sci-Fi" && Mode == "Multiplayer" && Length == 80 || Length == 70 || Length == 60 || Length == 50) {
setText("selectedGameText", "Astroneer");
}
if (Genre == "Sci-Fi" && Mode == "Multiplayer" && Length == 40 || Length == 30 || Length == 20) {
setText("selectedGameText", "Destiny 2");
}
if (Genre == "Sci-fi" && Mode == "Multiplayer" && Length == 10) {
setText("selectedGameText", "Halo");
}
if (Genre == "Sci-Fi" && Mode == "Singleplayer" && Length == 80 || Length == 70 || Length == 60) {
setText("selectedGameText", "Mass Effect Legendary Edition");
}
if (Genre == "Sci-Fi" && Mode == "Singleplayer" && Length == 40 || Length == 30 ) {
setText("selectedGameText", "Xcom");
}
if (Genre == "Sci-Fi" && Mode == "Singleplayer" && Length == 20 || Length == 10) {
setText("selectedGameText", "Deadspace");
}
}

Comparing numbers with JavaScript

How can I loop through an array of numbers and compare them to multiple sets of numbers. I am trying to program the game logic for a Tic Tac Toe project. When the players click a square the number of the square that was clicked is stored in p1Taken or p2Taken. I am trying to loop through those arrays and compare the numbers to the numbers for the squares needed to win. Only the first if statement works and I don’t think it’s bc of the number of squares but because there is 3 numbers in the array. Here is the code that I have so far:
const turnTaken = {
X: [],
O: []
}
var whosTurn = 'X';
let p1Taken = turnTaken.X;
let p2Taken = turnTaken.O;
const gameGrid = document.getElementsByClassName("grid");
const message = document.getElementById("message");
for(i=0, l=gameGrid.length; i < l; i++){
const boardNum = gameGrid[i].getAttribute("value");
gameGrid[i].addEventListener('click', function(e) {
if(whosTurn == 'X') {
message.innerHTML = "O's Turn";
player1Turn(e);
} else {
message.innerHTML = "X's Turn";
player2Turn(e);
}
});
}
function player1Turn(e){
const clickedValue = e.target.getAttribute("value");
const clicked = e.target;
const xIcon = document.createElement("IMG");
const srcX = "img/x-icon.png";
xIcon.setAttribute("src", srcX);
clicked.appendChild(xIcon);
p1Taken.push(clickedValue);
whosTurn = 'O';
player1CheckWin(p1Taken);
}
function player2Turn(e){
const clickedValue = e.target.getAttribute("value");
const clicked = e.target;
const oIcon = document.createElement("IMG");
const srcO = "img/o-icon.png";
oIcon.setAttribute("src", srcO);
clicked.appendChild(oIcon);
p2Taken.push(clickedValue);
whosTurn = 'X';
player2CheckWin(p2Taken);
}
function player1CheckWin(p1Taken){
for(var i=0; i < p1Taken.length; i++) {
if(p1Taken.length > 2) {
if(p1Taken[i] == 1 || p1Taken[i] == 2 || p1Taken[i] == 3) {
console.log("first");
message.innerHTML = "X Won!";
} else if(p1Taken[i] == 4 || p1Taken[i] == 5 || p1Taken[i] == 6) {
console.log("second");
message.innerHTML = "X Won!";
} else if(p1Taken[i] == 7 || p1Taken[i] == 8 || p1Taken[i] == 9) {
console.log("third");
message.innerHTML = "X Won!";
} else if(p1Taken[i] == 1 || p1Taken[i] == 4 || p1Taken[i] == 7) {
message.innerHTML = "X Won!";
} else if(p1Taken[i] == 2 || p1Taken[i] == 5 || p1Taken[i] == 8) {
message.innerHTML = "X Won!";
} else if(p1Taken[i] == 3 || p1Taken[i] == 6 || p1Taken[i] == 9) {
message.innerHTML = "X Won!";
} else if(p1Taken[i] == 1 || p1Taken[i] == 5 || p1Taken[i] == 9){
message.innerHTML = "X Won!";
} else if(p1Taken[i] == 3 || p1Taken[i] == 5 || p1Taken[i] == 7) {
message.innerHTML = "X Won!";
} else {
break;
}
} else {
break;
}
}
}
function player2CheckWin(p2Taken){
for(var j=0; j < p2Taken.length; j++) {
if(p2Taken.length > 2) {
if(p2Taken[j] == 1 || p2Taken[j] == 2 || p2Taken[j] == 3) {
message.innerHTML = "O Won!";
} else if(p2Taken[j] == 4 || p2Taken[j] == 5 || p2Taken[j] == 6) {
message.innerHTML = "O Won!";
} else if(p2Taken[j] == 7 || p2Taken[j] == 8 || p2Taken[j] == 9) {
message.innerHTML = "O Won!";
} else if(p2Taken[j] == 1 || p2Taken[j] == 4 || p2Taken[j] == 7) {
message.innerHTML = "O Won!";
} else if(p2Taken[j] == 2 || p2Taken[j] == 5 || p2Taken[j] == 8) {
message.innerHTML = "O Won!";
} else if(p2Taken[j] == 3 || p2Taken[j] == 6 || p2Taken[j] == 9) {
message.innerHTML = "O Won!";
} else if(p2Taken[j] == 1 || p2Taken[j] == 5 || p2Taken[j] == 9){
message.innerHTML = "O Won!";
} else if(p2Taken[j] == 3 || p2Taken[j] == 5 || p2Taken[j] == 7) {
message.innerHTML = "O Won!";
} else {
break;
}
} else {
break;
}
}
}
I'll just pick one of your predicates:
p1Taken[i] == 1 && 2 && 3
This is true iff all of the following are true:
p1Taken[i] is similar to 1 (after necessary casting)
2 is true (after necessary casting)
3 is true (after necessary casting)
So I know that the numbers 2 and 3 are truthy and thus casting to boolean will both be true. If you meant to compare p1Taken[i] to the 3 numbers you need to do 3 comparisons:
p1Taken[i] == 1 || p1Taken[i] == 2 || p1Taken[i] == 3
If the number always are integers you can use ranges:
p1Taken[i] >= 1 && p1Taken[i] <= 3
EDIT
The key to making something easy rather than hard is to have a though out data structure that supports the operations you want to do. I would imagine that a board with the indexes representing the positions would be just as easy to update and it will be easy to check if one won. Here is how I would have modelled it:
function getWinner(b) {
if (b[4] && (
b[3] == b[4] && b[4] == b[5] ||
b[0] == b[4] && b[4] == b[8] ||
b[2] == b[4] && b[4] == b[6] ||
b[1] == b[4] && b[4] == b[7])) {
return b[4];
}
if (b[0] && (
b[1] == b[0] && b[0] == b[2] ||
b[3] == b[0] && b[0] == b[6])) {
return b[0];
}
if (b[8] && (
b[6] == b[8] && b[8] == b[7] ||
b[2] == b[8] && b[8] == b[5])) {
return b[8];
}
return false;
}
// tests
const o = 'o';
const x = 'x';
const n = undefined;
const test1 = [
o, o, x,
x, o, x,
o, n, x
];
const test2 = [
o, x, x,
x, o, o,
o, n, x
];
const test3 = [
o, x, x,
o, o, o,
x, n, x
];
console.log(getWinner(test1)); // prints x
console.log(getWinner(test2)); // prints false
console.log(getWinner(test3)); // prints o
you need to correct your logic of comparison
change this
p1Taken[i] == 1 && 2 && 3
to
p1Taken[i] == 1 && p1Taken[i] == 2 && p1Taken[i] == 3
similarly for others
&& operator expects expressions to be compared, in your case you gave first expression as p1Taken[i] == 1 which is correct but second & third expression given were '2' & '3' which are truthy values
Now about your logic part, the above code still wont give correct result as you expecting same thing p1Taken[i] to be equal to multiple values at same time.
so just a hint, p1Taken keep it as array of taken tile nos & use condition as
p1Taken.includes(1) && p1Taken.includes(2) && p1Taken.includes(3)
TicTacToe game

Need solution for if statement logic

I need help on a condition logic using if statement as following:
Variables A and B contain 3 properties which is level1, level2 and level3.
level1 and level2 can be 0 or more and level3 is null or numeric.
Variables A and B can be null.
Currently I have this condition:
if (A.level1 == 0 and B.level1 == 0) {
code here
} else if (A.level2 == 0 and B.level2 == 0) {
code here
} else if (A.level3 != null and B.level3 != null) {
code here
}
The problem is that this code doesn't handle the Variables A and B can be null part. The code should handle that part like this:
When A is null, B will still go through the same condition but without A and vice versa.
However, if A and B is null then the condition will be false at once.
I have problem in how to implement the Variables A and B can be null part in my condition, any advice?
Add the A and B isNull check in your condition:
if (A == null && B == null) {
return;
} else if ((A == null || A.level1 == 0) && (B == null || B.level1 == 0)) {
// code here
} else if ((A == null || A.level2 == 0) && (B == null || B.level2 == 0)) {
// code here
} else if ((A == null || A.level3 != null) && (B == null || B.level3 != null)) {
// code here
}
Explanation,
Take A for example in this else if ((A == null || A.level1 == 0) && (B == null || B.level1 == 0)) statement:
By putting the A == null || in (A == null || A.level1 == 0) && (B == null || B.level1 == 0), if A is null, then this A.level1 == 0 check will be ignored, thus the check will be equivalent with else if (B == null || B.level1 == 0).
Since the first if already check A == null && B == null, the else if below won't have A and B both null. Therefore now else if ((A == null || A.level1 == 0) && (B == null || B.level1 == 0)) will be equivalent to else if (B.level1 == 0).
p.s. Here we are taking advantage of the || characteristic, that is if the first condition is fulfilled, the second condition will be ignored.
Seems like this is what you're looking for:
// Both A and B are null
if(A == null && B == null){
// do something
}
// Only A is null
else if(A == null){
if(B.level1 == 0){
// do something
}
else if(B.level2 == 0){
// do something
}
else if(B.level3 != null){
// do something
}
}
// Only B is null
else if(B == null){
if(A.level1 == 0){
// do something
}
else if(A.level2 == 0){
// do something
}
else if(A.level3 != null){
// do something
}
}
// Neither A or B are null
else{
if(A.level1 == 0 && B.level1 == 0){
// do something
}
else if(A.level2 == 0 && B.level1 == 0){
// do something
}
else if(A.level3 != null && B.level3 != null){
// do something
}
}
I suggest to check for falsy values of A or B first and then check the properties.
var A = null,
B = null;
if (!A && !B) {
console.log('A or B is null');
} else if (A.level1 === 0 && B.level1 === 0) {
console.log(1);
} else if (A.level2 === 0 && B.level2 === 0) {
console.log(2);
} else if (A.level3 != null && B.level3 != null) {
console.log(3);
}
Handle A and B separately,
if(!A){
if(A.level1 === 0 && A.level2 ===0){
}
else if(A.level1 === 0){
}
else if(A.level1 > 0){
}
if(A.level2 === 0){
}
else if(A.level2 > 0){
}
if(A.level3 === null){
}
else if (typeof (A.level3) === "number"){
}
}
same for B here...

X's Replaces O's

i'm making the tic tac toe game and im trying to fix a bug that i have now.
When i play the game and i click on the O's it changes to X how can i fix this?
I thought it would be something like: If (turn == 0 && ('td') == "") {
But that doesn't work
var newGame = function () {
$('td').one('click', function (event) {
if (turn == 0) {
$(this).text(human);
boardCheck();
checkWin();
turn == 1;
compMove();
boardCheck();
checkWin();
}
});
};
// VARIABLES
var human = 'x'; // turn = 0
var computer = 'o'; // turn = 1
var compMove;
var turn = 0; // toggles btw 0 and 1 for switching turns
var boardCheck; // function to check value in each cell
var a1; // value within each cell
var a2;
var a3;
var b1;
var b2;
var b3;
var c1;
var c2;
var c3;
var checkWin; // function that checks the board for winning combo
var xWin = false; // true if X wins
var oWin = false; // true if O wins
var winAlert; // function that declares winner and restarts game
var newGame;
var clearBoard;
// PLACES AN X OR O IN THE BOX WHEN CLICKED. TOGGLES.
var newGame = function () {
$('td').one('click', function (event) {
if (turn == 0) {
$(this).text(human);
boardCheck();
checkWin();
turn == 1;
compMove();
boardCheck();
checkWin();
}
});
};
// INITIALIZES GAME - keep after var newGame
$(document).ready(function () {
newGame();
});
// COMP MOVE AI DETECTS IF THERE ARE TWO IN A ROW NEXT TO AN EMPTY CELL AND PLACES MOVE THERE
var compMove = function () {
if (a1 == "" && ((a3 == "x" && a2 == "x") || (c3 == "x" && b2 == "x") || (c1 == "x" && b1 == "x"))) {
$('#a1').text("o");
turn = 0;
} else {
if (a2 == "" && ((a1 == "x" && a3 == "x") || (c2 == "x" && b2 == "x"))) {
$('#a2').text("o");
turn = 0;
}
else{
if (a3 == "" && ((a1 == "x" && a2 == "x") || (c1 == "x" && b2 == "x") || (c3 == "x" && b3 == "x"))) {
$('#a3').text("o");
turn = 0;
}
else{
if (c3 == "" && ((c1 == "x" && c2 == "x") || (a1 == "x" && b2 == "x") || (a3 == "x" && b3 == "x"))) {
$('#c3').text("o");
turn = 0;
}
else{
if (c1 == "" && ((c3 == "x" && c2 == "x") || (a3 == "x" && b2 == "x") || (a1 == "x" && b1 == "x"))) {
$('#c1').text("o");
turn = 0;
}
else{
if (c2 == "" && ((c3 == "x" && c1 == "x") || (a2 == "x" && b2 == "x"))) {
$('#c2').text("o");
turn = 0;
}
else{
if (b1 == "" && ((b3 == "x" && b2 == "x") || (a1 == "x" && c1 == "x"))) {
$('#b1').text("o");
turn = 0;
}
else{
if (b3 == "" && ((a3 == "x" && c3 == "x") || (b2 == "x" && b1 == "x"))) {
$('#b3').text("o");
turn = 0;
}
else{
if (b2 == "" && ((a3 == "x" && c1 == "x") || (c3 == "x" && a1 == "x") || (b3 == "x" && b1 == "x") || (c2 == "x" && a2 == "x"))) {
$('#b2').text("o");
turn = 0;
}
else{ // IF NO OPP TO BLOCK A WIN, THEN PLAY IN ONE OF THESE SQUARES
if (b2 == "") {
$('#b2').text("o");
turn = 0;
}
else{
if (a1 == "") {
$('#a1').text("o");
turn = 0;
}
else{
if (c3 == "") {
$('#c3').text("o");
turn = 0;
}
else {
if (c2 == "") {
$('#c2').text("o");
turn = 0;
}
else{
if (b1 == "") {
$('#b1').text("o");
turn = 0;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
};
// CREATES A FUNCTION TO DETECT WHAT IS IN EACH BOX AFTER EACH MOVE
boardCheck = function () {
a1 = $('#a1').html();
a2 = $('#a2').html();
a3 = $('#a3').html();
b1 = $('#b1').html();
b2 = $('#b2').html();
b3 = $('#b3').html();
c1 = $('#c1').html();
c2 = $('#c2').html();
c3 = $('#c3').html();
};
// CREATES A FUNCTION TO DETECT A WIN OR A TIE
checkWin = function () { // CHECKS IF X WON
if ((a1 == a2 && a1 == a3 && (a1 == "x")) || //first row
(b1 == b2 && b1 == b3 && (b1 == "x")) || //second row
(c1 == c2 && c1 == c3 && (c1 == "x")) || //third row
(a1 == b1 && a1 == c1 && (a1 == "x")) || //first column
(a2 == b2 && a2 == c2 && (a2 == "x")) || //second column
(a3 == b3 && a3 == c3 && (a3 == "x")) || //third column
(a1 == b2 && a1 == c3 && (a1 == "x")) || //diagonal 1
(a3 == b2 && a3 == c1 && (a3 == "x")) //diagonal 2
) {
xWin = true;
winAlert();
} else { // CHECKS IF O WON
if ((a1 == a2 && a1 == a3 && (a1 == "o")) || //first row
(b1 == b2 && b1 == b3 && (b1 == "o")) || //second row
(c1 == c2 && c1 == c3 && (c1 == "o")) || //third row
(a1 == b1 && a1 == c1 && (a1 == "o")) || //first column
(a2 == b2 && a2 == c2 && (a2 == "o")) || //second column
(a3 == b3 && a3 == c3 && (a3 == "o")) || //third column
(a1 == b2 && a1 == c3 && (a1 == "o")) || //diagonal 1
(a3 == b2 && a3 == c1 && (a3 == "o")) //diagonal 2
) {
oWin = true;
winAlert();
} else { // CHECKS FOR TIE GAME IF ALL CELLS ARE FILLED
if (((a1 == "x") || (a1 == "o")) && ((b1 == "x") || (b1 == "o")) && ((c1 == "x") || (c1 == "o")) && ((a2 == "x") || (a2 == "o")) && ((b2 == "x") || (b2 == "o")) && ((c2 == "x") || (c2 == "o")) && ((a3 == "x") || (a3 == "o")) && ((b3 == "x") || (b3 == "o")) && ((c3 == "x") || (c3 == "o"))) {
alert("It's a tie!");
clearBoard();
}
}
}
};
// DECLARES WHO WON
var winAlert = function () {
if (xWin == true) {
alert("You won!");
clearBoard(); // THIS DOESN'T WORK
} else {
if (oWin == true) {
alert("Sorry, you lose!");
clearBoard(); // THIS DOESN'T WORK
}
}
};
// NEWGAME BUTTON CLEARS THE BOARD, RESTARTS GAME, AND RESETS THE WINS
var clearBoard = $('#restart').click(function (event) {
a1 = $('#a1').text("");
b1 = $('#b1').text("");
c1 = $('#c1').text("");
a2 = $('#a2').text("");
b2 = $('#b2').text("");
c2 = $('#c2').text("");
a3 = $('#a3').text("");
b3 = $('#b3').text("");
c3 = $('#c3').text("");
xWin = false;
oWin = false;
newGame();
window.location.reload(true); // WITHOUT THIS, THERE'S A BUG WHICH PLACES MULTIPLE 0'S ON ALL GAMES AFTER THE FIRST
});
// STILL NEED TO FIX:
// * Alert for tie game or xWin appears twice
// * X's can replace O's
// * Missed opportunities for O to win
// * Almost never let's human win
// * Clean up logic for compMove'
if (turn == 0 && $(this).text() == "") {

Javascript syntax

How do you say if (A == 0) OR (B == 0)?
Just to be snarky:
if (A === 0 || B === 0)
if (A == 0 || B == 0)
or
if ((A == 0) || (B == 0))
Check out Control Structures and Operators on Wikibooks
if ( A == 0 || B == 0 ) {
}
depends if you mean exclusive or inclusive OR :)
Inclusive OR:
if(A == 0 || B == 0)
{
}
Exclusive OR:
if(A == 0 && B != 0 || A != 0 && B == 0)
{
}

Categories

Resources