why I have Maximum call stack size exceeded - javascript

I'm making a gem-puzzle. When I just use html and js I generate elements dynamically and put onclick on each one and when I click on it, everything works well, but when I connected the webpack it doesn't work. I rewrite the function showTable with createElement instead concatenation. And now I have an error Maximum call stack size exceeded at moveThisTile. I don't understand why? How can I fixed that? Please, help me to make this code work. There is my full code https://codepen.io/tomas777/pen/abZjZav?editors=1111
function startNewGame() {
let arrayOfNumbers = new Array();
let arrayHasNumberBeenUsed;
let randomNumber = 0;
let count = 0;
moves = 0;
rows = document.getElementById("rows").value;
columns = document.getElementById("columns").value;
textMoves.innerHTML = moves;
arrayForBoard = new Array(rows);
for (let i = 0; i < rows; i++){
arrayForBoard[i] = new Array(columns);
}
arrayHasNumberBeenUsed = new Array( rows * columns );
for (let i = 0; i < rows * columns; i++){
arrayHasNumberBeenUsed[i] = 0;
}
for (let i = 0; i < rows * columns; i++){
randomNumber = Math.floor(Math.random()*rows * columns);
if (arrayHasNumberBeenUsed[randomNumber] == 0) {
arrayHasNumberBeenUsed[randomNumber] = 1;
arrayOfNumbers.push(randomNumber);
}else
{
i--;
}
}
count = 0;
for (let i = 0; i < rows; i++){
for (let j = 0; j < columns; j++){
arrayForBoard[i][j] = arrayOfNumbers[count];
count++;
}
}
showTable();
}
function showTable() {
let tbody = document.createElement("tbody");
document.querySelector('#table').appendChild(tbody);
for (let i = 0; i < rows; i++) {
let tr = document.createElement('tr');
for (let j = 0; j < columns; j++) {
let cell = document.createElement('td');
if (arrayForBoard[i][j] == 0) {
cell.className = 'blank';
} else {
cell.className = 'tile';
cell.onclick = moveThisTile(i, j);
cell.innerHTML =arrayForBoard[i][j];
}
tr.appendChild(cell);
}
tbody.appendChild(tr);
}
};
function moveThisTile(tableRow, tableColumn) {
if (checkIfMoveable(tableRow, tableColumn, "up") ||
checkIfMoveable(tableRow, tableColumn, "down") ||
checkIfMoveable(tableRow, tableColumn, "left") ||
checkIfMoveable(tableRow, tableColumn, "right") ) {
incrementMoves();
} else {
alert("ERROR: Cannot move tile!\nTile must be next to a blank space.");
}
if (checkIfWinner()) {
alert("Congratulations! You solved the puzzle in " + moves + " moves.");
startNewGame();
}
}
function checkIfMoveable(rowCoordinate, columnCoordinate, direction) {
let rowOffset = 0;
let columnOffset = 0;
if (direction == "up"){rowOffset = -1;}
else if (direction == "down"){rowOffset = 1;}
else if (direction == "left"){columnOffset = -1;}
else if (direction == "right"){columnOffset = 1;}
if (rowCoordinate + rowOffset >= 0 && columnCoordinate + columnOffset >= 0 &&
rowCoordinate + rowOffset < rows && columnCoordinate + columnOffset < columns
){
if ( arrayForBoard[rowCoordinate + rowOffset][columnCoordinate + columnOffset] == 0){
arrayForBoard[rowCoordinate + rowOffset][columnCoordinate + columnOffset] = arrayForBoard[rowCoordinate][columnCoordinate];
arrayForBoard[rowCoordinate][columnCoordinate] = 0;
showTable();
return true;
}
}
return false;
}
function checkIfWinner(){
let count = 1;
for (let i = 0; i < rows; i++){
for (let j = 0; j < columns; j++){
if (arrayForBoard[i][j] != count){
if ( !(count === rows * columns && arrayForBoard[i][j] === 0 )){
return false;
}
}
count++;
}
}
return true;
}

Related

the new table at gem-puzzle is not replaced in place of the old one

I'm making a tag game. When I just use html and js, I generate elements dynamically and click on each one, the selected cell is moved to an empty space, everything works fine, but when I connected webpack, it stopped working (due to the fact that moveThisTile was called inside the line ). I rewrote the showTable function using createElement instead of concatenation. And now, when pressed, it draws another table with tags - the old table is not rubbed with a new one, but simply added to the end, with the changed position of the pressed button. I do not understand why. How can I fix this? Please help me to get this code to work. Here is my complete code https://codepen.io/tom7777/pen/abZjZav
And here is what it was originally (to see how it should work) https://codepen.io/tom7777/pen/abZjmZp
function startNewGame() {
let arrayOfNumbers = new Array();
let arrayHasNumberBeenUsed;
let randomNumber = 0;
let count = 0;
moves = 0;
rows = document.getElementById("rows").value;
columns = document.getElementById("columns").value;
textMoves.innerHTML = moves;
arrayForBoard = new Array(rows);
for (let i = 0; i < rows; i++){
arrayForBoard[i] = new Array(columns);
}
arrayHasNumberBeenUsed = new Array( rows * columns );
for (let i = 0; i < rows * columns; i++){
arrayHasNumberBeenUsed[i] = 0;
}
for (let i = 0; i < rows * columns; i++){
randomNumber = Math.floor(Math.random()*rows * columns);
if (arrayHasNumberBeenUsed[randomNumber] == 0) {
arrayHasNumberBeenUsed[randomNumber] = 1;
arrayOfNumbers.push(randomNumber);
}else
{
i--;
}
}
count = 0;
for (let i = 0; i < rows; i++){
for (let j = 0; j < columns; j++){
arrayForBoard[i][j] = arrayOfNumbers[count];
count++;
}
}
showTable();
}
function showTable() {
let tbody = document.createElement("tbody");
document.querySelector('#table').appendChild(tbody);
for (let i = 0; i < rows; i++) {
let tr = document.createElement('tr');
for (let j = 0; j < columns; j++) {
let cell = document.createElement('td');
if (arrayForBoard[i][j] == 0) {
cell.className = 'blank';
} else {
cell.className = 'tile';
cell.onclick = moveThisTile(i, j);
cell.innerHTML =arrayForBoard[i][j];
}
tr.appendChild(cell);
}
tbody.appendChild(tr);
}
};
function moveThisTile(tableRow, tableColumn) {
if (checkIfMoveable(tableRow, tableColumn, "up") ||
checkIfMoveable(tableRow, tableColumn, "down") ||
checkIfMoveable(tableRow, tableColumn, "left") ||
checkIfMoveable(tableRow, tableColumn, "right") ) {
incrementMoves();
} else {
alert("ERROR: Cannot move tile!\nTile must be next to a blank space.");
}
if (checkIfWinner()) {
alert("Congratulations! You solved the puzzle in " + moves + " moves.");
startNewGame();
}
}
function checkIfMoveable(rowCoordinate, columnCoordinate, direction) {
let rowOffset = 0;
let columnOffset = 0;
if (direction == "up"){rowOffset = -1;}
else if (direction == "down"){rowOffset = 1;}
else if (direction == "left"){columnOffset = -1;}
else if (direction == "right"){columnOffset = 1;}
if (rowCoordinate + rowOffset >= 0 && columnCoordinate + columnOffset >= 0 &&
rowCoordinate + rowOffset < rows && columnCoordinate + columnOffset < columns
){
if ( arrayForBoard[rowCoordinate + rowOffset][columnCoordinate + columnOffset] == 0){
arrayForBoard[rowCoordinate + rowOffset][columnCoordinate + columnOffset] = arrayForBoard[rowCoordinate][columnCoordinate];
arrayForBoard[rowCoordinate][columnCoordinate] = 0;
showTable();
return true;
}
}
return false;
}
function checkIfWinner(){
let count = 1;
for (let i = 0; i < rows; i++){
for (let j = 0; j < columns; j++){
if (arrayForBoard[i][j] != count){
if ( !(count === rows * columns && arrayForBoard[i][j] === 0 )){
return false;
}
}
count++;
}
}
return true;
}

tic-tac-toe: different output while using 1d-array over 2d- array

I am trying to build tic-tac-toe AI using min max algorithm. I was referring to this post from geekforgeeks for writing my code. But strangely when I'm using 1D array instead of 2D array by modifying the code as given below, I'm not getting the right output from findBestMove function. It is supposed to return index as 4, but it always returns 2. what am I doing wrong?
function Move(x,y){
this.row = x,
this.col = y;
};
const player = 'o', opponent = 'x';
const isMovesLeft = (board) => {
for (let i = 0; i<3; i++)
for (let j = 0; j<3; j++)
if (board[i][j]=='_')
return true;
return false;
}
const isMovesLeft2 = (board) => {
for (let i = 0; i<9; i++)
if (board[i]=='_')
return true;
return false;
}
const evaluate = (b) =>{
for (let row = 0; row<3; row++)
{
if (b[row][0]==b[row][1] &&
b[row][1]==b[row][2])
{
if (b[row][0]==player)
return +10;
else if (b[row][0]==opponent)
return -10;
}
}
for (let col = 0; col<3; col++)
{
if (b[0][col]==b[1][col] &&
b[1][col]==b[2][col])
{
if (b[0][col]==player)
return +10;
else if (b[0][col]==opponent)
return -10;
}
}
if (b[0][0]==b[1][1] && b[1][1]==b[2][2])
{
if (b[0][0]==player)
return +10;
else if (b[0][0]==opponent)
return -10;
}
if (b[0][2]==b[1][1] && b[1][1]==b[2][0])
{
if (b[0][2]==player)
return +10;
else if (b[0][2]==opponent)
return -10;
}
return 0;
}
const evaluate2 = (b) =>{
for (let row = 0; row<3; row++)
{
if (b[row]==b[row+1] &&
b[row+1]==b[row+2])
{
if (b[row]==player)
return +10;
else if (b[row]==opponent)
return -10;
}
}
for (let col = 0; col<3; col++)
{
if (b[col]==b[col+3] &&
b[col+3]==b[col+6])
{
if (b[col]==player)
return +10;
else if (b[col]==opponent)
return -10;
}
}
if (b[0]==b[4] && b[4]==b[8])
{
if (b[0]==player)
return +10;
else if (b[0]==opponent)
return -10;
}
if (b[2]==b[4] && b[4]==b[6])
{
if (b[2]==player)
return +10;
else if (b[2]==opponent)
return -10;
}
return 0;
}
const minimax = (board , depth, isMax) => {
let score = evaluate(board);
if (score == 10)
return score;
if (score == -10)
return score;
if (isMovesLeft(board)==false)
return 0;
if (isMax)
{
let best = -1000;
for (let i = 0; i<3; i++)
{
for (let j = 0; j<3; j++)
{
if (board[i][j]=='_')
{
board[i][j] = player;
best = Math.max( best,
minimax(board, depth+1, !isMax) );
board[i][j] = '_';
}
}
}
return best;
}
else
{
let best = 1000;
// Traverse all cells
for (let i = 0; i<3; i++)
{
for (let j = 0; j<3; j++)
{
if (board[i][j]=='_')
{
board[i][j] = opponent;
best = Math.min(best,
minimax(board, depth+1, !isMax));
board[i][j] = '_';
}
}
}
return best;
}
}
const minimax2 = (board , depth, isMax) => {
let score = evaluate2(board);
if (score == 10)
return score;
if (score == -10)
return score;
if (isMovesLeft2(board)==false)
return 0;
if (isMax)
{
let best = -1000;
for (let i = 0; i<9; i++)
{
if (board[i]=='_')
{
board[i] = player;
best = Math.max( best,
minimax2(board, depth+1, !isMax) );
board[i] = '_';
}
}
return best;
}
else
{
let best = 1000;
for (let i = 0; i<9; i++)
{
if (board[i]=='_')
{
board[i] = opponent;
best = Math.min(best,
minimax2(board, depth+1, !isMax));
board[i] = '_';
}
}
return best;
}
}
const findBestMove = (board) =>{
let bestVal = -1000;
let bestMove = new Move(-1,-1);
for (let i = 0; i<3; i++)
{
for (let j = 0; j<3; j++)
{
if (board[i][j]=='_')
{
board[i][j] = player;
let moveVal = minimax(board, 0, false);
board[i][j] = '_';
if (moveVal > bestVal)
{
bestMove.row = i;
bestMove.col = j;
bestVal = moveVal;
}
}
}
}
return bestMove;
}
const findBestMove2 = (board) =>{
let bestVal = -1000;
let bestMove = -1;
for (let i = 0; i<9; i++)
{
if (board[i]=='_')
{
board[i] = player;
let moveVal = minimax2(board, 0, false);
board[i]= '_';
if (moveVal > bestVal)
{
bestMove = i
bestVal = moveVal;
}
}
}
return bestMove;
}
const test = () => {
const board = [['x','_','_'],
['_','_','_'],
['_','_','_']];
const board2 = ['x','_','_',
'_','_','_',
'_','_','_'];
console.log(findBestMove(board));
console.log(findBestMove2(board2));
}
test();
When the test() is executed first function call returns best move as (1,1) but second function returns 2. It should be 4 ideally.
In function evaluate2, you loop like this:
for (let row = 0; row<3; row++)
You should loop like this
for (let row = 0; row<9; row+=3)

What does var this.mtx[i][lead] do in javascript?

I was going through a reduced row echelon form code for javascript from this website: http://rosettacode.org/wiki/Reduced_row_echelon_form#JavaScript and I was trying to put it into simpler code so that I could understand what each instruction did. I then ran into: while (this.mtx[i][lead] == 0). I understand what the this.mtx[i] is but I don't know what [lead] in the context of being right after mtx[i] does. Your helps is greatly appreciated. Here is the code:
Matrix.prototype.toReducedRowEchelonForm = function() {
var lead = 0;
for (var r = 0; r < this.rows(); r++) {
if (this.columns() <= lead) {
return;
}
var i = r;
while (this.mtx[i][lead] == 0) {
i++;
if (this.rows() == i) {
i = r;
lead++;
if (this.columns() == lead) {
return;
}
}
}
var tmp = this.mtx[i];
this.mtx[i] = this.mtx[r];
this.mtx[r] = tmp;
var val = this.mtx[r][lead];
for (var j = 0; j < this.columns(); j++) {
this.mtx[r][j] /= val;
}
for (var i = 0; i < this.rows(); i++) {
if (i == r) continue;
val = this.mtx[i][lead];
for (var j = 0; j < this.columns(); j++) {
this.mtx[i][j] -= val * this.mtx[r][j];
}
}
lead++;
}
return this;
}

How to reduce time of execution for javascript code

Below is my code which is taking time in the for loop to extract data from one object and filling another object. Is there any way to reduce the time of execution? I have tried a while loop but it is not helping that much. Kindly help
function SetGridWithData(result) {
if (!result) {
return;
}
CtrlBillableItem_SearhedBillableItems = result
var boxOfJson = [];
var j = 100;
if (result.length >= 100) {
if (PagingLastRecNum == 0) {
btnPrevious.style.display = 'none';
for (var i = 0; i < j; i++) {
boxOfJson.push(result[i]);
}
} else {
btnPrevious.style.display = 'inline';
var intializer = (j * PagingLastRecNum) + PagingLastRecNum;
var limiter = intializer + 99;
for (var i = intializer; i < limiter; i++) {
boxOfJson.push(result[i]);
}
}
} else {
btnPrevious.style.display = 'none';
btnNext.style.display = 'none';
for (var i = 0; i < result.length; i++) {
boxOfJson.push(result[i]);
}
}
}
I am trying to implement paging which is done, but 100 data per page first it will check page no 0 if it is then loop one and if other than 0 than else case.
You could try caching result.length at the beginning of your function (following the if check at the beginning)..
function SetGridWithData(result) {
if (!result) { return; }
var resultLength = result.length;
CtrlBillableItem_SearhedBillableItems = result
var boxOfJson = [];
var j = 100;
if (resultLength >= 100) {
if (PagingLastRecNum == 0) {
btnPrevious.style.display = 'none';
for (var i = 0; i < j; i++) {
boxOfJson.push(result[i]);
}
}
else {
btnPrevious.style.display = 'inline';
var intializer = (j * PagingLastRecNum) + PagingLastRecNum;
var limiter = intializer + 99;
for (var i = intializer; i < limiter; i++) {
boxOfJson.push(result[i]);
}
}
}
else {
btnPrevious.style.display = 'none';
btnNext.style.display = 'none';
for (var i = 0; i < resultLength; i++) {
boxOfJson.push(result[i]);
}
}
}

can any one tell me whats the wrong with code

function MoveAddToCartAccordingly()
{
var elems = document.getElementsByClassName('box-collateral box-related');
var av = document.getElementsByClassName('availability in-stock');
var sp = document.getElementsByClassName('product-options');
var ac = document.getElementsByClassName('add-to-cart');
var first = document.getElementsByClassName('item first');
var second = document.getElementsByClassName('item');
for(var k = 0; k < sp.length; k++){
if (getComputedStyle(sp[k]).visibility == "visible")
{
for (var i = 0; i < elems.length; i++) {
if (getComputedStyle(elems[i]).visibility == 'visible') {
for (var j = 0; j < av.length; j++) {
av[j].style.visibility = 'visible';
av[j].id = "someID";
elems[i].appendChild(av[j]);
}
}
else
{
for (var s = 0; s < av.length; s++) {
av[s].style.visibility = 'hidden';
}
for (var l = 0; l < ac.length; l++) {
ac[l].style.marginTop = "-500px";
ac[l].style.marginLeft = "-20px";
}
}
}
}
return;
}
for (var p = 0; p < elems.length; p++) {
if (getComputedStyle(elems[p]).visibility == 'visible') {
for (var q = 0; q < av.length; q++) {
av[q].style.visibility = 'visible';
av[q].id = "someID";
elems[p].appendChild(av[q]);
}
if(elems[p].style.marginTop == "-610px")
{
elems[p].style.marginTop = "-640px";
}
for(var r = 0; r < first.length; r++)
{
if(getComputedStyle(first[r]).visiblity == 'visible'){
for(var m = 0; m < ac.length; m++)
{
if(ac[m].style.marginTop == "-120px")
{
ac[m].style.marginTop ="-140px";
}
}
}
else if(getComputedStyle(first[r]).visiblity == 'visible' && getComputedStyle(second[r]).visiblity == 'visible' )
{
for(var n = 0; n < ac.length; n++)
{
if(ac[n].style.marginTop == "-120px")
{
ac[n].style.marginTop ="-140px";
}
}
}
}
}
}
}
window.onload = MoveAddToCartAccordingly;
can any one whats the wrong with code here actually i am checking if div product option is visible then again i am checking if div with class "box-colatral box-related" if visible if it is not then i am hidding other tag p with class Availability-in-stock and moving add-to- cart div to top position but that one is not working
You have a return statement in your first for loop. I imagine that you are always going to bail on the function call after the first iteration of that loop.

Categories

Resources