well, i'm trying to do a snake game using basic imports, but at some time, i got stuck, because of a javascript assignment.
i assigned the value the oldSnake as the value of the snake before its changes.
but as i get into the forEach, the value already assigned changes and i don't know why.
Before getting into the forEach
After getting into the forEach
i searched about it, and didn't get anywhere, Does someone know what's happening?
import { snake } from "/snake.js";
let lastDirection = {y: 1, x:0};
export function updateGame(direction){
let oldSnake = snake;
if (!(direction.y == 0 && direction.x == 0)){
if((lastDirection.y == 1 && direction.y == -1 || lastDirection.y == -1 && direction.y == 1)
||(lastDirection.x == 1 && direction.x == -1 || lastDirection.x == -1 && direction.x == 1)){
direction = lastDirection;
}
snake.forEach((snakeSlice, index)=>{
lastDirection = direction;
if (index === 0){
snakeSlice.ypos+= direction.y;
snakeSlice.xpos+= direction.x;
}
else{
snakeSlice.ypos = oldSnake[index-1].ypos;
snakeSlice.xpos = oldSnake[index-1].xpos;
}
});
}
}
Related
I am building an application similar to minesweeper where a user will click a square on a grid and the app will tell the user how many of the surrounding squares contain an 'X'. I have my code working when I only check up, down, left, and right. My code is beginning to get very long since there are quite a few edge cases to account for. I am going to begin checking diagonals for 'X's and I want to come up with a shorter way to check these cases.
Can anyone help me develop a for loop or other short hand way to write this code. Here is what I have so far for a 8x8 grid.
Here is my sandbox: https://codesandbox.io/s/6y6wzo001w
showNumber= () => {
let Xcounter = 0;
console.log(this.props.keys)
console.log(this.props.reduxState.reducer.board[this.props.keys])
if(this.props.keys% 8 ===0){
if(this.props.reduxState.reducer.board[this.props.keys +1] === 'X'){
Xcounter++
}
}
if(this.props.keys% 8 ===7){
if(this.props.reduxState.reducer.board[this.props.keys -1] === 'X'){
Xcounter++
}
}
if(this.props.keys/8 <1){
if(this.props.reduxState.reducer.board[this.props.keys +8] === 'X'){
Xcounter++
}
}
if(this.props.keys/8 >=7){
if(this.props.reduxState.reducer.board[this.props.keys -8] === 'X'){
Xcounter++
}
}
if(this.props.keys % 8 !== 0 && this.props.keys % 8 !== 7){
if(this.props.reduxState.reducer.board[this.props.keys +1] === 'X'){
Xcounter++
}
if(this.props.reduxState.reducer.board[this.props.keys -1]=== 'X'){
Xcounter++
}
}
if(Math.floor(this.props.keys)/8 > 0 && Math.floor(this.props.keys)/ 8 < 7){
if(this.props.reduxState.reducer.board[this.props.keys +8] === 'X'){
Xcounter++
}
if(this.props.reduxState.reducer.board[this.props.keys -8]=== 'X'){
Xcounter++
}
}
if(this.props.id === 'X'){
this.setState({...this.state, clicked: true, counter: 'X'})
return this.state.counter;
}
this.setState({...this.state, clicked: true, counter: Xcounter})
return this.state.counter;
}
Assuming you have an array this.props.reduxState.reducer.boardof length 64 with 'X's or non-'X's, one could simply loop through the x and y directions like so:
let Xcounter = 0;
//save the board for shorter and more readable code
let board = this.props.reduxState.reducer.board;
//the current index we've clicked on
let c = this.props.keys;
//we're going to check if we're at the edge of the board.
//I'll explain these later.
let minX = c%8 == 0 ? 0 : -1;
let maxX = c%8 == 7 ? 0: 1;
let minY = (c-minX)/8 == 0 ? 0 : -1;
let maxY = (c-minY)/8 == 7 ? 0 : 1;
for( let x = minX; x <= maxX; ++x ){
for( let minY = -1; y <= maxY; ++y ){
if( board[c+x+8*y)] == 'X' ){ Xcounter++; }
}
}
//we also checked the square itself, but we didn't want to
if( board[c] == 'X' ){ Xcounter--; }
This assumes the indeces of the board are from right to left, and then top to bottom, not the other way around (i.e. board[7] is the top-right corner, not the bottom-left one).
As far as what this actually does; essentially, we look whether or not we're at the edge of a board, and find the relative x- and y-coordinates we have to check. To visualize:
Here minX=0, because going to the left of the current clicked square c would throw us off the board. maxX=1 though, because we can check to the right of the clicked square. Similarly, we check the y-coordinates.
Assuming that your checks are already correct, let's work with what you already have.
Try to rewrite what you actually have with more condensed style to get an overview as a first step and introduce a board side constant as a second:
showNumber = () => {
const BOARD_SIDE = 8;
let Xcounter = 0;
let keys = this.props.keys;
let board = this.props.reduxState.reducer.board;
console.log(keys);
console.log(board[this.props.keys]);
for (let edge = BOARD_SIDE; edge < BOARD_SIDE * BOARD_SIDE; edge += BOARD_SIDE) {
if (keys % edge === 0 && board[keys + 1] === "X") Xcounter++;
if (keys % edge === (edge - 1) && board[keys - 1] === "X") Xcounter++;
if (keys / edge < 1 && board[keys + edge] === "X") Xcounter++;
if (keys / edge >= (edge - 1) && board[keys - edge] === "X") Xcounter++;
if (keys % edge !== 0 && keys % edge !== (edge - 1)) {
if (board[keys + 1] === "X") Xcounter++;
if (board[keys - 1] === "X") Xcounter++;
}
if (Math.floor(keys) / edge > 0 && Math.floor(keys) / edge < (edge - 1)) {
if (board[keys + edge] === "X") Xcounter++;
if (board[keys - edge] === "X") Xcounter++;
}
}
if (this.props.id === "X") {
this.setState({ ...this.state, clicked: true, counter: "X" });
return this.state.counter;
}
this.setState({ ...this.state, clicked: true, counter: Xcounter });
return this.state.counter;
};
I'm trying to write the minimax algorithm in Javascript for a tic-tac-toe game project. It's a person vs computer game. I want to find the best move for the computer but I keep getting the following error on the Chrome console: Uncaught RangeError: Maximum call stack size exceeded.
I've tried to solve the problem many different ways but it has become hard for me to debug.
If anyone could help it would be appreciated, thanks in advance.
Here is my sample code:
let board_index = ["X", 1, 2, 3, "O", 5, 6, "X", 8]; // original board with the somes indexies played
let ai = "X";
let hu = "O";
// filter the available boxes in the board
function emptySpot(board) {
return board.filter(st => st != "O" && st != "X");
}
// winning combinations using the board indexies
function evaluate(board, player) {
if (
(board[0] == player && board[1] == player && board[2] == player) ||
(board[3] == player && board[4] == player && board[5] == player) ||
(board[6] == player && board[7] == player && board[8] == player) ||
(board[0] == player && board[3] == player && board[6] == player) ||
(board[1] == player && board[4] == player && board[7] == player) ||
(board[2] == player && board[5] == player && board[8] == player) ||
(board[0] == player && board[4] == player && board[8] == player) ||
(board[2] == player && board[4] == player && board[6] == player)
)
{
if(player == ai) {
return 10;
}
else
if(player == hu) {
return -10;
}
return 0;
}
}
// minimax algorithm
function minimax(board, depth, isMax) {
// available spots in board
let avail = emptySpot(board);
// evaluate score on board
let score = evaluate(board);
// check and return a value for terminal states such as win, lose, and tie
if(score == 10 || score == -10) {
return score;
}
else if(avail == []) {
return 0;
}
if(isMax) {
let bestScore = -1000;
for(let i = 0; i < avail.length; i++) {
let index = avail[i];
// make move
avail[i] = ai;
// call minimax recursively and choose the maximum value
bestScore = minimax(board, depth+1, !isMax);
// undo the move
avail[i] = index;
}
return bestScore;
}
else {
let bestScore = 1000;
for(let i = 0; i < avail.length; i++) {
let index = avail[i];
// make move
avail[i] = hu;
// call minimax recursively and choose the minimum value
bestScore = minimax(board, depth+1, !isMax);
// undo the move
avail[i] = index;
}
return bestScore;
}
}
// finding the best possible move and return it
function findBestMove(board) {
let bestVal = -1000;
let bestMove = -1;
let avail = emptySpot(board);
for(let i = 0; i < avail.length; i++) {
// save index
let index = avail[i];
// compute the evalutation for this move
let moveVal = minimax(board, 0, false);
// undo move
avail[i] = index;
if(moveVal > bestVal){
bestVal = moveVal;
bestMove = avail[i];
}
}
console.log(bestVal);
console.log(bestMove);
}
let bestSpot = findBestMove(board_index);
I am having trouble getting my script to function the way I want it to. What I want it to do is take 3 values, evaluate them against several arguments then pass a value into a specific cell based on the evaluation. So far I have this;
function myFunction() {
var f = SpreadsheetApp.getActiveSheet().getRange("B$8");
var l = SpreadsheetApp.getActiveSheet().getRange("B$14");
var m = SpreadsheetApp.getActiveSheet().getRange("B$20");
if(f >= 1 && l >= 1 && m >= 1) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('0');
} else if (f >= 2) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('0');
} else if (f == 1 && l == 0 && m == 0) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('1');
} else if (f == 0 && l >=1 && m >= 1) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('2');
} else if (f == 0 && l+m <= 4) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('3');
} else if (f == 0 && l == 0 && m <=4) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('4');
} else if (f == 0 && i == 0 && m == 0) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('5');
} else {
SpreadsheetApp.getUi().alert('There has been an error, please rate manually');
}
}
No matter what values I have in cells B8, B14 or B20 I get the error message.
I would also like it to be able to function in multiple columns, while rows stay the same (hense the '$' in ranges). Though I am not certain I am doing this correctly.
If anyone could take a look through my code and explain what I am doing wrong and help me understand how to fix it that would be greatly appreciated.
In the lines getting data, you need to add .getValue() like this:
SpreadsheetApp.getActiveSheet().getRange("B$8").getValue()
You have a typo in:
else if (f == 0 && i == 0 && m == 0)
I believe the i should be l.
Also, check your logic for the value '3'. Like it is you will never get to '4' or '5'.
This error kept troubling me for about 2 hours now... I'm making an idle game where you can have your own city and I'm making a building system right now, the problem is the game crashes whenever I delete from array (I have build queue which holds buildings to be built and then removes them) building from build queue. I tried .shift .pop .push .indexOf(0) === 0 and [0] === "" and .splice(1,1) it just comes up with like .splice is not a function or .pop is not a function for all of them.
Nothing worked. Please HELP!
if (buildValue === 100 && buildQueue.indexOf("house") === 0){
populationmax++;
// here i need a command that will remove first element from array called buildQueue.
buildValue = 0;
}
Removing From Array
if (buildValue === 100 && buildQueue.indexOf("house") === 0){
populationmax++;
buildQueue.splice(0, 1); //removes first element
buildValue = 0;
}
JS Snippet
x = [1, 2, 3];
alert(x); //1,2,3
x.splice(0, 1);
alert(x); //2,3
Adding To/Creating Array
First, you don't need to put a blank string inside the buildQueue array, this might actually cause problems later, just do this:
buildQueue = [];
Second, you are trying to add strings to your array as if it were a string, using +=. Doing this however, is turning your array into a string, which is why you're getting the warning about `.splice()' you need to add strings to your array like this:
buildQueue.push(someString);
This way buildQueue will remain an array of strings.
var buildValue = 0,
buildQueue = [""],
buildSpeed = 1/200;
if (buildQueue[0]){
buildValue += buildSpeed;
}
if (buildValue >= 100){
buildValue = 100;
}
if (buildValue === 100 && buildQueue.indexOf("house") === 0){
populationmax++;
buildValue = 0;
}
if (buildValue === 100 && buildQueue.indexOf("big house") === 0){
populationmax+=4;
buildValue = 0;
}
if (buildValue === 100 && buildQueue.indexOf("gold storage") === 0){
goldmax++;
buildValue = 0;
}
if (buildValue === 100 && buildQueue.indexOf("food storage") === 0){
foodmax++;
buildValue = 0;
}
if (buildValue === 100 && buildQueue.indexOf("wood storage") === 0){
woodmax++;
buildValue = 0;
}
if (buildValue === 100 && buildQueue.indexOf("stone storage") === 0){
stonemax++;
buildValue = 0;
}
if (buildValue === 100 && buildQueue.indexOf("iron storage") === 0){
ironmax++;
buildValue = 0;
}
buildSpeed = 0.2;
That is all i have to do with build. Also if you buy a building it will just add to array. eg gold storage will add buildQueue += "gold store"; And the spaces between lines inside ifs are supposed to have command that deletes the [0] element.
Help me please, I'm trying to make a rule for the little game and there is the problem.
I'm creating winning combination and say if the cell && cell+1 && cell+2 == to 'X' then you win, but when between two "X"s presents "o" it also says that "X" wins. Why? Please see my code and the game example on link a the bottom.
this.rezult = function(){
this.arr2.forEach(function(arr, i, innerArr){
arr.forEach(function(val, j){
var wincomb = innerArr[i][j] && innerArr[i][j+1] && innerArr[i][j+2];
var wincomb2 = innerArr[i][j] && innerArr[i+1][j] && innerArr[i+2][j];
var wincomb3 = innerArr[i][j] && innerArr[i+1][j+1] && innerArr[i+2][j+2];
console.log(wincomb == "X" && innerArr[i][j] !== "o");
// console.log(innerArr);
// THE RULE
if(wincomb == "X"){
alert(' X wins!');
}
});
});
};
Link to JSFiddle
In JavaScript, the && operator has interesting behavior with non-boolean values.
If the left-side of && is "truthy", the result is the right-side.
If the left-side of && is "falsey", the result is the left-side.
All non-empty strings are "truthy".
So, consider these examples:
("A" && "B" && "C") === "C"
("" && "B" && "C") === ""
(0 && "B" && "C") === 0
("X" && "X" && "O") === "O"
("O" && "O" && "X") === "X"
By the looks of it, you're trying to check if all 3 values are equal. You shouldn't use && for that, you should use === for that.
At the risk of doing your homework for you ;) here's a good way to do this:
function areTheSame(a,b,c) {
return a === b && b === c;
}
var down = areTheSame(innerArr[i][j], innerArr[i][j+1], innerArr[i][j+2]);
var across = areTheSame(innerArr[i][j], innerArr[i+1][j], innerArr[i+2][j]);
var diagonal = areTheSame(innerArr[i][j], innerArr[i+1][j+1], innerArr[i+2][j+2]);
if (down || across || diagonal) {
var winner = innerArr[i][j];
alert( winner + " wins!");
}