JavaScript variable changes to outcome the line after it is defined - javascript
I am working on creating a computer bot that plays itself at chopsticks. I have invented a while loop to run until one of the computers wins. I store the computer's gameState in a variable that looks like [[1,1],[1,1]]. The first item in the list is player one, and his left hand and right hand values are at 1. The second player is the same way. However, the line after I define gameState, I console.log() the gameState variable and get the end result of the game, the line after I define it as [[1,1],[1,1]]. The problem with this is that during the while loop, I'm not able to get information about the moves that the computer is making. Help!
Here is my code:
function makeMove(s, player, m) { //source, player, move
//if it is player 2, flip it around
if (player == 2) {
var s = [s[1], s[0]];
}
var target;
var source;
//move 0 is when the left hand targets the opponent's right hand
//move 1 is when the right hand targets the opponent's left hand
//move 2 is when the left hand targets the opponent's left hand
//move 3 is when the right hand targets the opponent's right hand
//the state [[1,1],[1,1]] stores the values of each hand and each opponent
if (m == 0 || m == 3) {
target = [1, 0];
} else {
target = [1, 1];
}
if (m == 0 || m == 2) {
source = [0, 0];
} else {
source = [0, 1];
}
s[target[0]][target[1]] += s[source[0]][source[1]];
s[target[0]][target[1]] %= 5;
if (player == 2) {
s = [s[1], s[0]];
}
return s;
}
function playmatch() {
//the original state,
var gameState = [[1, 1], [1, 1]];
//right after I create the value, for some reason it changes to the end result when I log it the next line.
console.log(gameState);
var winner = -1;
while (winner == -1) {
var choice = [0,1,2,3];
var move = choice[Math.floor(Math.random() * choice.length)];
gameState = makeMove(gameState, 1, move);
var move = choice[Math.floor(Math.random() * choice.length)];
gameState = makeMove(gameState, 2, move);
if (gameState[0][0] == 0 && gameState[0][1] == 0) {
winner = 2;
}
if (gameState[1][0] == 0 && gameState[1][1] == 0) {
winner = 1;
}
console.log(gameState);
}
return winner;
}
playmatch();
And a link to the codepen pen: https://codepen.io/gmoyer/pen/EeepbE
The behavior of console.log is not standardized. As suggested by MDN, you should serialize your object.
Do this
console.log(JSON.parse(JSON.stringify(obj)));
instead of
console.log(obj);
to ensure that what is passed to console.log is a snapshot of the object at that moment in time rather than a reference to the object. I assume that console.log is not executing right when you call it and is given a reference to your array. Thus, your array changes, and later when console.log executes, it logs the changed array.
Related
Cinema Seating With Gaps
Given and Array **[0,0,0,1,0,0,1,0,0,0]** of occupied and unoccupied seats, where 1 indicated occupied and 0 indicated unoccupied, we have return the maximum maximum number of people who can be seated as long as there is a gap of **2 seats **between people. I trid a sliding window approac but it didnt worked ` // maxim seats question // [0,0,0,1,0,0,1,0,0,0] function cinSeating(array) { let seats = 0; for (let p1 = 0, p2 = 3; p1, p2 <= array.length; p1++, p2++) { if (array[p1] !== array[p2]) { seats++; } } return seats; } console.log(cinSeating([0, 0, 0, 1, 0, 0, 1, 0, 0, 0])); `
Try using dynamic programming to solve this problem. Basic approach: Parse through the array one by one recursively At every point, check if that seat can be filled in or not. At this point, you can take either one of the two options - YES or NO If YES - increment the total count and call the same function with the next index and incremented count If YES - call the same function with the next index and existing count Find out the max between the two calculations and return the answer Code will look something like this: function hasAPerson(array, index){ // Utility function to encapsulate all the checks while checking the next index for possible vacant seat if(index >= array.length){ return false; } else return array[index] === 1; } function cinSeating(array, existingNumber, leftIndex, index) { let newlyAdded = 0; if(index >= array.length){ return existingNumber; } if(array[index] === 1){ return cinSeating(array, existingNumber, index, index + 1); } let excludeCurrentSeat = currentValue = cinSeating(array, existingNumber, leftIndex, index + 1); let includeCurrentSeat = existingNumber; //Check if last leftIndex with 1 is beyond index-2 if(leftIndex < index-2){ let next = index+1; let nextToNext = next+1; //Check if next or next to next index has any 1 if(!hasAPerson(array, next) && !hasAPerson(array, nextToNext)){ includeCurrentSeat = cinSeating(array, existingNumber + 1, index, index+1); } } return Math.max(currentValue, includeCurrentSeat); } You can call the cinSeating function with the following arguments: input array existing number of people (seats already booked) - basically number of 1s in the array last left index that had 1. When we start we can pass -3 so that left check gets passed index to process console.log(cinSeating([0, 0, 0, 1, 0, 0, 1, 0, 0, 0], 2, -3, 0)); This is something that I wrote quickly to illustrate my approach. This code can definitely be optimised. Feel free to play around with it
Maze algorithm: which line of code specifies that when a ball hits a dead end, it will backtrack?
I am learning how to create a maze using Javascript. I went through the following code. Basically the logic is to randomly pick a square (I hard coded the value so I can better understand the pattern) and check if its neighbors have been visited or not. If so, just skip that neighbor and randomly choose an unvisited one and repeat the process by checking its neighbors again...I know that when the target hits a dead end, it will backtrack. But I didn't find any code that make the ball backtrack. Please see the image link here:1 [(3, 3) is a dead end. The for of loop checked that the left and the top were visited and the right and the bottom were out of bounds. My problem is that for(neighbor of neighbors){...} already looped through all four neighbors and the last iteration (in this case, checking the left square) was skipped because it was visited. But after the iteration, i immediately console log on the first line of the for of loop and surprisingly, the neighbors have changed from [[4, 3, "down"], [2, 3, "up"], [3, 4, "right"], [3, 2, "left"]] to [[3, 3, "down"],[1, 3, "up"],[2, 4, "right"],[2, 2, "left"]]. But wasn't the last iteration skipped with the continue key word and the iteration was supposed to end? Why I still got another four neighbors to loop through? Is this where the ball backtracks? Thank you very much for your time! Much appreciated! Here is the code: const width = innerWidth; const height = innerHeight; const cellsHorizontal = 4; // columns const cellsVertical = 4; // rows const unitLengthX = width / cellsHorizontal; const unitLengthY = height / cellsVertical; const stepThroughCell = (row, column) => { // If I have visited the cell at [row, column], then return if (grid[row][column]) { return; } // Mark this cell as being visited grid[row][column] = true; // Specify neighbors const neighbors = [ [row + 1, column, "down"], [row - 1, column, "up"], [row, column + 1, "right"], [row, column - 1, "left"], ]; // For each neighbor... for (neighbor of neighbors) { console.log(neighbors, row, column); // why we got another four neighbors after the last iteration was skipped? const [nextRow, nextColumn, direction] = neighbor; // see if that neighbor goes to a cell that doesn't exist if ( nextRow < 0 || nextRow >= cellsVertical || nextColumn < 0 || nextColumn >= cellsHorizontal ) { continue; } // If we have visited that neighbor, continue to next neighbor if (grid[nextRow][nextColumn]) { continue; // the last iteration was skipped when the target hits a dead end, so the iteration was supposed to end? But the first line in the for of loop shows that there are another four neighbors, why? } // Remove a wall from either horizontals or verticals if (direction === "left") { verticals[row][column - 1] = true; } else if (direction === "right") { verticals[row][column] = true; } else if (direction === "up") { horizontals[row - 1][column] = true; } else if (direction === "down") { horizontals[row][column] = true; } // Visited that next cell stepThroughCell(nextRow, nextColumn); } }; stepThroughCell(1, 1);
This is a recursive algorithm, actually you calling "stepThroughCell" inside if itself and continue/return on success/failure , so suppose you get dead end in some situation , the algorithm will continue from the last check point which "stepThroughCell" is called for another neighbor.
Grouping Numbers JS algorithm
I was trying to solve a problem: Problem: Given an array of Positive repetitive numbers. Output should give an array with odds sorted on the right and evens on the left (no particular order) Input : [4,1,2,3,4] Output: [4,2,3,1] Solve it In-place and without using extra space and O(N) runtime. Code: /* * Algorithm is simple, have two pointers one on the left and another on the right. * Note: We are sorting all evens on the left and odds on the right * If you see even on left, move on else swap. */ function groupNumbers(intArr) { if(intArr.length == 0 || intArr.length == 1){ return intArr; } for(let i=0, j =intArr.length-1; i<intArr.length; i++){ if(j>=i){ //elements should not overlap let start = intArr[i]; let end = intArr[j]; if(start%2 == 0){ //Even i++; } else { [start, end] = [end, start]; //swap } if(end%2 == 1){ j--; } else { [start, end] = [end, start]; //swap } } //if-ends }//for-ends return intArr; } I'm not sure where I'm going wrong. I'm missing something. I'm getting the same sorted array as output. Condition: **SOLVE it INPLACE and without using extra space ** (Preferably in ONE iteration)
I'm not sure where I'm going wrong. I'm missing something. I'm getting the same sorted array as output. several things: let start = intArr[i]; let end = intArr[j]; ... [start, end] = [end, start]; this does indeed swap the values in the variables start and end, but not the indices in the Array. Then you have two i++ in the same loop that increment the left pointer. if(start%2 == 0){ //Even i++; } else { [start, end] = [end, start]; //swap } here you swap the items when the left pointer points to an odd value, but there's no check that the right pointer also points to an even value. you might as well just swap two odd values here. Same for the right pointer. const isEven = v => (v&1) === 0; const isOdd = v => (v&1) === 1; function groupNumbers(arr){ var left = 0, right = arr.length-1; while(left < right){ //move the left pointer to find the next odd value on the left while(left < right && isEven(arr[left])) ++left; //move the right pointer to find the next even value on the right while(left < right && isOdd(arr[right])) --right; //checking that the two pointer didn't pass each other if(left < right) { console.log("swapping %i and %i", arr[left], arr[right]); //at this point I know for sure that I have an odd value at the left pointer //and an even value at the right pointer //swap the items var tmp = arr[left]; arr[left] = arr[right]; arr[right] = tmp; } } return arr; } [ [1,2,3,4], [1,2,3,4,5,6,7,8,9,0], [1,3,5,7], [2,4,1,3], [5,4,3,2,1], ].forEach(sequence => { console.log("\ninput: " + sequence); console.log("output: " + groupNumbers(sequence)); }); .as-console-wrapper{top:0;max-height:100%!important} as suggested by #JaredSmith, the same thing just using a sort-function :) function sortEvenLeftOddRight(a,b){ return (a&1) - (b&1); //return (a&1) - (b&1) || a-b; //to additionally sort by value } [ [1,2,3,4], [1,2,3,4,5,6,7,8,9,0], [1,3,5,7], [2,4,1,3], [5,4,3,2,1], ].forEach(sequence => { console.log("\ninput: " + sequence); sequence.sort(sortEvenLeftOddRight); console.log("output: " + sequence); }); .as-console-wrapper{top:0;max-height:100%!important}
A very concise method to solve this would be to use reduce: const out = arr.reduce((p, c) => { // if the value is divisible by 2 add it // to the start of the array, otherwise push it to the end c % 2 === 0 ? p.unshift(c) : p.push(c) return p; }, []); OUT [4,2,4,1,3] DEMO
What is wrong with this code? Am I going about this the right way?
Okay, so I'm fairly new to programming. I've been learning to code for quite sometime now, but I hadn't really MADE anything. That considered, I'm attempting to make my first project using JavaScript and make a snake game. Unfortunately, I've ran into multiple problems, which obviously is something that comes hand in hand with programming, but I am new and I'm stuck. Can someone help me figure out if I'm coding this in an efficient way. Also, I have a more specific issue. I've added basic movement functionality to the head of my snake, but I can't figure out how to get the rest of it's parts to follow. If someone could explain to me how to do this, that would be incredible. I've worked about two weeks now to try and figure it out and I'm just stumped. I'm using Raphael's JavaScript Library to generate the graphics on an SVG canvas. /* Libraries in use: 1. Rapheal 2. jQuery */ // This variable is set to an array so that we can add multiple snakeParts to our PrimarySnake. var snakeParts = [], // This variable uses Raphael to generate a canvas. snakeCanvas = Raphael(10, 10, 400, 400), // This generates a rectangle that fills the canvas. snakeCanvasBg = snakeCanvas.rect(0,0,400,400), // This variable is set to an array so that we can use each and every direction that is pressed. direction = [], // This variable is set to an array so that we can use the turn coordinates of our first snake part. turnCoords = []; // Generates and returns a random number between 0 and 400. This function is used to help generate the goal of our snake at a random location on the canvas. function getRandNum () { var rand = Math.round(Math.random()*400); // This while loop ensures that our snakeGoal never exceeds the coordinates x = 390 or y = 390. If it did, it's parts would be cut from the canvas. while (rand > 395) { rand = Math.round(Math.random()*400); } // This while loop ensures that our rand variabe will always be divisible by 10, which is used to make sure our snakeGoal and snakePart elements are always rendered in coordinates divisible by 10. while (rand % 10 !== 0) { var randString = rand.toString(), // This variable stores the whole length of our randString variable. randStringLength = randString.length, // This variable stores the last number of our rand as a string character. subtractionChar = randString.charAt(randStringLength - 1), // This variable stores the last number of our rand as a integer. subtractionInt = parseInt(subtractionChar), // Finally, this line subtracts the last number of our rand from the entirety and then sets that value equal to rand, ensuring that rand is always divisible by 10. rand = rand - subtractionInt; } return rand; } // This function is called any time a button is pressed. The jQuery which method allows our code to compare if the key pressed is equal to the keyCode of a designated key. $(document).keydown( function (pressedDirection) { if (pressedDirection.which === 37) { direction.push("left"); } else if (pressedDirection.which === 38) { direction.push("up"); } else if (pressedDirection.which === 39) { direction.push("right"); } else if (pressedDirection.which === 40) { direction.push("down"); } else if (pressedDirection.which === 32) { direction.push("stop"); } if (pressedDirection.which === 37 || pressedDirection.which === 38 || pressedDirection.which === 39 || pressedDirection.which === 40 || pressedDirection.which === 32) { console.log(direction[direction.length - 1]); PrimarySnake.addTurnCoords(); PrimarySnake.movePeice(); } // This prevents our screen from scrolling when an arrow key is pressedDirection.preventDefault(); } ); function Snake () { // This method generates a new peice to the Snake. this.addPart = function () { console.log(snakeParts.length); snakeParts[snakeParts.length] = snakeCanvas.rect(0,0,10,10); snakeParts[snakeParts.length - 1].attr("fill", "blue"); snakeParts[snakeParts.length - 1].attr("stroke-width", ".25"); } // This method provides the movement functionality of our Snake. this.moveDirection = function () { for (value in snakeParts) { var currentCoord = [snakeParts[value].attr("x"), snakeParts[value].attr("y")]; // This if-else statement moves the snakePart at the -value- index up, down, left, or right according to the last direction pressed. if (direction[direction.length - 1] === "up") { snakeParts[value].attr("y", currentCoord[1] - 10); } else if (direction[direction.length - 1] === "down") { snakeParts[value].attr("y", currentCoord[1] + 10); } else if (direction[direction.length - 1] === "left") { snakeParts[value].attr("x", currentCoord[0] - 10); } else if (direction[direction.length - 1] === "right") { snakeParts[value].attr("x", currentCoord[0] + 10); } } } this.moveInterval; // This function makes our moveDirection move our snakePeice every 50 milliseconds. this.movePeice = function () { var moveDirection = this.moveDirection; // clearInterval is used to eliminate any interval previously running, ensuring that our peices only move one direction at a time. clearInterval(this.moveInterval); this.moveInterval = setInterval(function(){moveDirection()}, 50); } // This function adds an array of coordinates to the turnCoords array. this.addTurnCoords = function () { turnCoords.push([snakeParts[0].attr("x"), snakeParts[0].attr("y")]); } } // This generates a new instance of our Snake class. var PrimarySnake = new Snake(); // This generates a new part on the canvas. PrimarySnake.addPart(); // This fills our snakeCanvasBg with a grey color, giving us a grey background. snakeCanvasBg.attr("fill", "#CDCDCD");
Well, your code seems nice, or at least "efficient" as you are calling it. To make the parts of your snake follow its head, you must iterate through its parts and assign each (n+1) piece the coordinates from (n). To do so, start with the last piece and iterate up to the first one, which movement is defined by the user, like in: this.moveDirection = function () { // Move every piece except the head. for (var i = snakeParts.length - 1; i > 0; i--) { snakeParts[i].attr("x", snakeParts[i-1].attr("x")); snakeParts[i].attr("y", snakeParts[i-1].attr("y")); } // Now move the head. if (direction[direction.length - 1] === "up") { snakeParts[value].attr("y", currentCoord[1] - 10); } else if (direction[direction.length - 1] === "down") { snakeParts[value].attr("y", currentCoord[1] + 10); } else if (direction[direction.length - 1] === "left") { snakeParts[value].attr("x", currentCoord[0] - 10); } else if (direction[direction.length - 1] === "right") { snakeParts[value].attr("x", currentCoord[0] + 10); } } That code may need a bit of work but that's the idea. Hope it helps!
Stopping a function, Arrays, and Integer Check
So I made code for creating 5 ships in a battleship game. I succesfully made some code that layed out all the players ships. It had no bugs. I had the player write out the cords for where he wanted to position his ship. It would then write in the ship position to the corresponding part in a two dimensional array which was the game map.. Of course the cords had to be integers or it would crash and burn. So I then made something to check if the coordinate was a integer before doing anything else. If it wasn't it would restart the function making so that the rest of the function wouldn't run. If you write in the numbers correctly there are no problems. The problem is that if you don't write in a number the function does restart but the function or some part of it must still be running because a ship gets written to the array for no reason. The cords haven't even been specified for it so I have no clue how this can be possible. Here is the code I made for checking if its an integer and restarting the function. userYTest = parseInt(prompt("Horizontal Coordinate position for the first unit of a ship")); userXTest = parseInt(prompt("Vertical Coordinate position for the first unit of a ship")); if(userXTest % 1 === 0 && userYTest % 1 === 0) { userY = userYTest-1; userX = userXTest-1; direction = prompt("Now choose the direction you want the rest of your ship to face. You may use the words left, right up, or down.").toLowerCase(); } else{ window.alert("You must enter a number between one and ten for the two coordinates."); ship(); //ship is the name of the function } Here is all the code. //These are all the different game boards you need to keep track of. Two possible values in each position 1 or 0 var user = [[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]]; var cpu = [[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]]; var userGuessed = [[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]]; var userHit = [[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]]; var cpuGuessed = [[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]]; var cpuHit = [[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]]; var clearBoard = [[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]]; // These are just used to set left the game board. // I counted 10 by 10 - it should be 10 by 10 var userY = 0; var userX = 0; var cpuX = 0; var cpuY = 0; var cpuDir = 0; var cpuWork = false; var direction = ""; var isThere = false; var i=0; var userXTest; var userYTest; // In battleship, there is 1x5 length ship, 1x4 length ship, 2 1x3 length ship, and 1x2 length ship. down now it checks how many units are covered to see if you have all the ships. Later we need to add so they ships are the down shape //User will add their ships here one by one. If you can think of a better have a go at it! for(i=0;i<4;i++){ if (i===0){ window.alert("We will be placing your 1 by 5 length ship. Take note that you are playing on a 10 by 10 board."); ship(); } if (i===1){ window.alert("We will be placing your 1 by 4 length ship. Take note that you are playing on a 10 by 10 board."); ship(); } if (i===2){ window.alert("We will be placing your two 1 by 3 length ships. Take note that you are playing on a 10 by 10 board."); ship(); ship(); } if (i===3){ window.alert("We will be placing your 1 by 2 length ship. Take note that you are playing on a 10 by 10 board."); ship(); } function ship(){ userYTest = parseInt(prompt("Horizontal Coordinate position for the first unit of a ship")); userXTest = parseInt(prompt("Vertical Coordinate position for the first unit of a ship")); if(userXTest % 1 === 0 && userYTest % 1 === 0) { userY = userYTest-1; userX = userXTest-1; direction = prompt("Now choose the direction you want the rest of your ship to face. You may use the words left, right up, or down.").toLowerCase(); } else{ window.alert("You must enter a number between one and ten for the two coordinates."); ship(); } //Making sure the ship will fit and nothing is already there! if ((userY+4-i)>9 && direction=== "down"){ window.alert("You are too close to the down edge of the board to do that. Restarting..."); ship(); } else if ((userY-4-i)<0 && direction=== "up"){ window.alert("You are too close to the up edge of the board to do that. Restarting..."); ship(); } else if ((userX+4-i)>9 && direction=== "right"){ window.alert("You are too close to the bottom edge of the board to do that. Restarting..."); ship(); } else if ((userX-4-i)<0 && direction=== "left"){ window.alert("You are too close to the top edge of the board to do that. Restarting..."); ship(); } else if (user[userY][userX] === 1) { window.alert("Coordinate already used. Please try again"); ship(); } else if (user[userY][userX] === null || user[userY][userX] === ""){ window.alert("That coordinate isn't on the board. Restarting..."); ship(); } else if(direction ==="left" || direction ==="right" || direction ==="up" || direction ==="down") { for(var a=1; a<5-i; a++){ if(direction=== "down"){ if(user[userY+a][userX] === 1){ window.alert("Can't place your ship in that direction, another ship is in your way."); isThere=true; } } if(direction=== "up"){ if(user[userY-a][userX] === 1){ window.alert("Can't place your ship in that direction, another ship is in your way."); isThere=true; } } if(direction=== "right"){ if(user[userY][userX+a] === 1 ){ window.alert("Can't place your ship in that direction, another ship is in your way."); isThere=true; } } if(direction=== "left"){ if(user[userY][userX-a] === 1){ window.alert("Can't place your ship in that direction, another ship is in your way."); isThere=true; } } if(isThere===true){ isThere = false; ship(); return false; } else{ user[userY][userX] = 1; } } } else{ window.alert("Sorry but you didn't type in the direction you wanted your ship to go correctly. Restarting..."); ship(); } // Building Ship 1x5 for(var b=1; b<5-i; b++){ if (direction==="left"){ user[userY][userX-b] =1; } else if (direction==="right"){ user[userY][userX+b] =1; } else if (direction==="up"){ user[userY-b][userX] =1; } else if (direction==="down"){ user[userY+b][userX] =1; } } } } console.log(user);
First, understand that calling a function within itself does not stop running the original function. Try this (jsfiddle) to see how it works: var i = 0; function askDogsName() { var dogsName = prompt("What is the dog's name?"); if (dogsName != "Rover") { askDogsName(); } i++; document.body.innerHTML += "i = " + i + "; dog's name: " + dogsName + '<br />'; } askDogsName(); After the new recursion of the function has completed, the original one simply carries on where it left off; it does not 'restart'. So this is not a good way of responding to user input that is not valid, especially because you are using global variables. Each recursion of the function can alter those variables in a way that can become difficult to predict, before returning control to its 'parent' (the recursion of the function that called it). What you can do instead is to use return values to check whether the correct input has been given or not: function ship() { var c; while (!c) { c = getValidCoords(); } x = c[0]; y = c[1]; // then make the ship at x, y } function getValidCoords() { y = parseInt(prompt("Horizontal Coordinate position for the first unit of a ship")); x = parseInt(prompt("Vertical Coordinate position for the first unit of a ship")); // conduct various tests on x and y if (testsFail) { return false; } return [x, y]; }
You can't recurse when its wrong. Try something like this: var done; while (!done) { if(userXTest % 1 === 0 && userYTest % 1 === 0) { userY = userYTest-1; userX = userXTest-1; direction = prompt("Now choose the direction you want the rest of your ship to face. You may use the words left, right up, or down.").toLowerCase(); ... All the other tests that are after the else part ... else { // if its a good answer done = true; } } else{ window.alert("You must enter a number between one and ten for the two coordinates."); } } You will want some way they can say they want to quit too.