How to solve this multiple nested for loop - javascript

EDIT: Big edit from ealier
I have achieved: the ultimate for-loop HELL.
What it does: scans an image and finds a 40 by 40 pixel square that has every pixel within it approximately the same color.
The problem: The code doesn't work as intended. Unsure why, but all my attempts to debug are in vain.
jimp.read('jeffrey.png')
.then(image => {
console.log(jimp.intToRGBA(image.getPixelColor(0,0)))
console.log(image.bitmap.width)
console.log(image.bitmap.height)
var breakAll = false;
var FINALX;
var FINALY;
var doneCounter = 0;
//40 by 40 pixels needed for qr code. Thisis barcode, so make it 40 by 80 or smthn, figure out that x thing.
for(var x = 0; x < image.bitmap.width; x++) {
var breakThis = false;
console.log(x + " is x")
if(breakAll == true) {
break;
}
var verticalStart = 0;
for(var y1 = verticalStart; y1 < image.bitmap.height; y1++) {
if(breakAll == true) {
break;
}
var tempStandardR = jimp.intToRGBA(image.getPixelColor(x,y1)).r;
var tempStandardG = jimp.intToRGBA(image.getPixelColor(x,y1)).g;
var tempStandardB = jimp.intToRGBA(image.getPixelColor(x,y1)).b;
var verticalCounter = 0;
for(var y2 = y1; y2 < image.bitmap.height; y2++) {
if(breakAll == true) {
break;
}
if(verticalCounter >= 40) {
//Then do X stuff
//horizcountertim
for(var y3 = y1; y3 < y1 + 40; y3++) {
if(breakAll == true) {
break;
}
breakThis = false;
var horizontalCounter = 0;
var tempStandardR3 = jimp.intToRGBA(image.getPixelColor(x,y3)).r;
var tempStandardG3 = jimp.intToRGBA(image.getPixelColor(x,y3)).g;
var tempStandardB3 = jimp.intToRGBA(image.getPixelColor(x,y3)).b;
for(var x2 = x; x2 < x + 41; x2++) {
if(breakAll == true) {
break;
}
console.log(doneCounter)
if(doneCounter >= 40) {
//SUCESS!!!!!!
//THE SPOT HAS BEEN FOUND AT (x minus 40, y minus 40).
//insert other image in this image at above coordinates. Wow I highly doubt this works.
console.log('SUCESS!!!!!!!!!')
FINALX = x2-40;
FINALY = y3-40;
breakAll = true;
break;
}
if(breakAll == true) {
break;
}
var tempStandardR4 = jimp.intToRGBA(image.getPixelColor(x2,y3)).r;
var tempStandardG4 = jimp.intToRGBA(image.getPixelColor(x2,y3)).g;
var tempStandardB4 = jimp.intToRGBA(image.getPixelColor(x2,y3)).b;
if((((tempStandardR3 - tempStandardR4) <= 20) && ((tempStandardR3 - tempStandardR4) >= -20)) && (((tempStandardG3 - tempStandardG4) <= 20) && ((tempStandardG3 - tempStandardG4) >= -20)) && (((tempStandardB3 - tempStandardB4) <= 20) && ((tempStandardB3 - tempStandardB4) >= -20))) {
horizontalCounter++;
if(horizontalCounter == 40) {
horizontalCounter = 0;
doneCounter++;
break;
}
// if((x2 - x >= 39) && (y3 - y1) >= 39) {
if(breakAll == true) {
break;
}
}
else {
horizontalCounter = 0;
verticalCounter = 0;
doneCounter = 0;
console.log('donecounter reset')
verticalStart = y3;
//y2 = y3;
breakThis = true;
break;
}
}
if(breakAll == true) {
break;
}
if(breakThis = true) {
break;
}
}
if(breakThis = true) {
breakThis = false;
break;
}
}
if(breakAll == true) {
break;
}
var tempStandardR2 = jimp.intToRGBA(image.getPixelColor(x,y2)).r;
var tempStandardG2 = jimp.intToRGBA(image.getPixelColor(x,y2)).g;
var tempStandardB2 = jimp.intToRGBA(image.getPixelColor(x,y2)).b;
if((((tempStandardR - tempStandardR2) <= 20) && ((tempStandardR - tempStandardR2) >= -20)) && (((tempStandardG - tempStandardG2) <= 20) && ((tempStandardG - tempStandardG2) >= -20)) && (((tempStandardB - tempStandardB2) <= 20) && ((tempStandardB - tempStandardB2) >= -20))) {
verticalCounter++;
}
else {
verticalCounter = 0;
verticalStart = y2;
console.log('lvl1 reset')
doneCounter = 0;
break;
}
}
}
}
console.log(' done');
console.log(FINALX + " = x")
console.log(FINALY + " = y")
})
.catch(err => {
console.log(err);
})
Each of the tempStandards are the RGB value for that individual pixel.
All of the for loops are to get a 40 by 40 open grid.
The issue I do see is a problem, but am baffled as to why, is doneCounter, that is supposed to ++ every time a horizontal counter has reached 40 and thus finished its horizontal check of one row of the 40 by 40 grid.
The issue when console logging doneCounter is, it console logs the same value twice, which makes no sense since its within the same for loop that has an if else statement that either adds to donecounter or resets it to 0.
EDIT: I scrapped the above code to try and remake it entirely to see if that would let it work, still failed though and not a clue as to why: Below is the updated attempt:
jimp.read('jeffrey.png')
.then(image => {
console.log(jimp.intToRGBA(image.getPixelColor(0,0)))
console.log(image.bitmap.width)
console.log(image.bitmap.height)
var breakAll = false;
var FINALX;
var FINALY;
var doneCounter = 0;
var veritcalCounter = 0;
var verticalStart = 0;
var horizontalCounter = 0;
var breakAll = false;
var breakThis = false;
//40 by 40 pixels needed for qr code. Thisis barcode, so make it 40 by 80 or smthn, figure out that x thing.
for(var x = 0; x < image.bitmap.width; x++) {
console.log(x)
verticalCounter = 0;
for(var y = 0; y < image.bitmap.height; y++) {
var tempStandardR = jimp.intToRGBA(image.getPixelColor(x,verticalStart)).r;
var tempStandardG = jimp.intToRGBA(image.getPixelColor(x,verticalStart)).g;
var tempStandardB = jimp.intToRGBA(image.getPixelColor(x,verticalStart)).b;
var tempStandardR2 = jimp.intToRGBA(image.getPixelColor(x,y)).r;
var tempStandardG2 = jimp.intToRGBA(image.getPixelColor(x,y)).g;
var tempStandardB2 = jimp.intToRGBA(image.getPixelColor(x,y)).b;
if((((tempStandardR - tempStandardR2) <= 20) && ((tempStandardR - tempStandardR2) >= -20)) && (((tempStandardG - tempStandardG2) <= 20) && ((tempStandardG - tempStandardG2) >= -20)) && (((tempStandardB - tempStandardB2) <= 20) && ((tempStandardB - tempStandardB2) >= -20))) {
verticalCounter++;
if(verticalCounter == 40) {
verticalCounter = 0;
for(var y1 = y-40; y1 < y; y1++) {
horizontalCounter = 0;
for(var x1 = x; x1 < x+41; x1++) {
var tempStandardR3 = jimp.intToRGBA(image.getPixelColor(x,y1)).r;
var tempStandardG3 = jimp.intToRGBA(image.getPixelColor(x,y1)).g;
var tempStandardB3 = jimp.intToRGBA(image.getPixelColor(x1,y1)).b;
var tempStandardR4 = jimp.intToRGBA(image.getPixelColor(x1,y1)).r;
var tempStandardG4 = jimp.intToRGBA(image.getPixelColor(x1,y1)).g;
var tempStandardB4 = jimp.intToRGBA(image.getPixelColor(x1,y1)).b;
if((((tempStandardR3 - tempStandardR4) <= 20) && ((tempStandardR3 - tempStandardR4) >= -20)) && (((tempStandardG3 - tempStandardG4) <= 20) && ((tempStandardG3 - tempStandardG4) >= -20)) && (((tempStandardB3 - tempStandardB4) <= 20) && ((tempStandardB3 - tempStandardB4) >= -20))) {
if(x1 == x+40) {
doneCounter++;
if(doneCounter == 39) {
//SUCESS!!!!!!
//THE SPOT HAS BEEN FOUND AT (x minus 40, y minus 40).
//insert other image in this image at above coordinates. Wow I highly doubt this works.
console.log('SUCESS!!!!!!!!!')
FINALX = x;
FINALY = y1-40;
breakAll = true;
break;
}
break;
}
}
else {
verticalCounter = 0;
horizontalCounter = 0;
doneCounter = 0;
y = y1;
breakThis = true;
break;
}
if(breakAll == true) {
break;
}
}
if(breakThis == true) {
breakThis = false;
break;
}
if(breakAll == true) {
break;
}
}
if(breakAll == true) {
break;
}
}
if(breakAll == true) {
break;
}
}
else {
verticalCounter = 0;
verticalStart = 0;
}
if(breakAll == true) {
break;
}
}
if(breakAll == true) {
break;
}
}
console.log(' done');
console.log(FINALX + " = x")
console.log(FINALY + " = y")
})
.catch(err => {
console.log(err);
})

Related

an if statement returns true, but the condition won't trigger

I have an if statement in my code as you can see below. When I check in console log when those two elements collide with each other, the if statement becomes true, but it won't stop my interval function. I wonder what would have caused it to not work as it should?
var animationTimer = setInterval(bladAnimation, 30);
document.onkeydown = function(event) {
if (event.keyCode == 37) {
// <--
fx = -15;
fy = 0;
froskAnimation()
}
if (event.keyCode == 38) {
// opp
fy = -15;
fx = 0;
froskAnimation()
}
if (event.keyCode == 39) {
// -->
fx = 15;
fy = 0;
froskAnimation()
}
if (event.keyCode == 40) {
// ned
fy = 15;
fx = 0;
froskAnimation()
}
}
function froskAnimation() {
Xfrosk = fx + Xfrosk;
Yfrosk = fy + Yfrosk;
if ((Yfrosk + 70 > maxY) || (Yfrosk < minY)) {
Yfrosk = Yfrosk - fy;
}
if ((Xfrosk + 70 > maxX) || (Xfrosk < minX)) {
Xfrosk = Xfrosk - fx;
}
frosk.style.left = Xfrosk + "px";
frosk.style.top = Yfrosk + "px";
console.log(Xfrosk)
}
function bladAnimation() {
Yblad = by + Yblad;
if ((Yblad + 70 > maxY) || (Yblad < minY)) {
by = by * -1;
}
blad.style.top = Yblad + "px";
}
if (blad.x < frosk.x + frosk.width && blad.x + blad.width > frosk.x
&& blad.y < frosk.y + frosk.height && blad.y + blad.height > frosk.y) {
clearInterval(animationTimer);
}
full code here: https://codepen.io/ctrlvi/pen/jXbJYG
That condition is executed only once, when your javascript is loaded. At that point the condition is probably false. You should move it at the end of bladAnimation (I suppose what you're trying to do is stop the self-moving block when it hits the other one).
function bladAnimation() {
Yblad = by + Yblad;
if ((Yblad + 70 > maxY) || (Yblad < minY)) {
by = by * -1;
}
blad.style.top = Yblad + "px";
if (blad.x < frosk.x + frosk.width && blad.x + blad.width > frosk.x
&& blad.y < frosk.y + frosk.height && blad.y + blad.height > frosk.y) {
clearInterval(animationTimer);
}
}

Prevent collisions with new paths

I'm building a program that runs through an matrix (nxn) avoiding collisions with certain obstacles. I'm having trouble implementing a generic algorithm that works for all possible collision situations, the ultimate goal is to go through all the points of the matrix.
The algorithm I built is looping and can not complete the matrix.
Note: The red square can move in any direction (horizontal, vertical and diagonal movements), but only one cell(square) at a time.
var WALL = 0;
var started = false;
var gridSize = 20;
class Agent {
constructor(x, y, charge, cap, distance) {
this.x = x;
this.y = y;
this.charge = charge;
this.cap = cap;
this.distance = distance;
}
}
$(function() {
var $grid = $("#search_grid");
var opts = {
gridSize: 20
};
var grid = new GraphSearch($grid, opts);
//Initializes the agent
$("#btnInit").click(function() {
if (!started) {
var agent = new Agent(0, 0, 100, 50, 0);
agent.initialize();
started = true;
}
});
});
//Initializes the matrix
function GraphSearch($graph, options) {
this.$graph = $graph;
this.opts = options;
this.initialize();
}
//Initializes the matrix
GraphSearch.prototype.initialize = function() {
this.grid = [];
$graph = this.$graph;
$graph.empty();
var cellWidth = ($graph.width() / this.opts.gridSize) - 2,
cellHeight = ($graph.height() / this.opts.gridSize) - 2,
lineHeight = (this.opts.gridSize >= 30 ? "9.px" : ($graph.height() / this.opts.gridSize) - 10 + "px"),
fontSize = (this.opts.gridSize >= 30 ? "10px" : "20px");
$cellTemplate = $("<span />").addClass("grid_item").width(cellWidth).height(cellHeight).css("line-height", lineHeight).css("font-size", fontSize);
for (var x = 0; x < this.opts.gridSize; x++) {
var $row = $("<div class='row' />");
for (var y = 0; y < this.opts.gridSize; y++) {
var id = "cell_" + x + "_" + y,
$cell = $cellTemplate.clone();
$cell.attr("id", id).attr("x", x).attr("y", y);
$row.append($cell);
var isWall = addWall(x, y, this.opts.gridSize);
if (isWall === 1) {
$cell.addClass("wall");
} else {
$cell.addClass('weight1');
}
}
$graph.append($row);
//Fix for stackoverflow snippet
if ($(window).width() < 700) {
$("#search_grid").css("width", "320px");
$("#main").css("width", "38%");
} else {
$("#search_grid").css("width", "300px");
$("#main").css("width", "20%");
}
}
};
//Where will be wall in the matrix
addWall = function(x, y, size) {
var limitPointLeftUp = [2, 3];
var limitPointRightUp = [2, size - 4];
var limitPointLeftDown = [size - 4, 2];
var limitPointRightDown = [size - 4, size - 4];
if ((x == 2 && y == 2) || (x == 2 && y == size - 3)) {
return 1;
}
if ((x == size - 3 && y == 2) || (x == size - 3 && y == size - 3)) {
return 1;
}
if (x >= 2 && (y == 3 && x >= limitPointLeftUp[0] && x <= limitPointLeftDown[0] + 1)) {
return 1;
}
if (x >= 2 && (y == size - 4 && x >= limitPointRightUp[0] && x <= limitPointRightDown[0] + 1)) {
return 1;
}
if ((x == 1 && y == 5) || (x == 9 && y == 17) || (x == 6 && y == 0) || (x == 9 && y == 7) || (x == 15 && y == 0) || (x == 15 && y == 2) || (x == 18 && y == 15)) {
return 1;
}
}
//Initializes the agent
Agent.prototype.initialize = function() {
var agent = this;
var lastDir = "right";
var tryTo = "";
var trying = false;
var right = true;
var up = false;
var down = false;
var left = false;
var timerId = 0;
//Simulates agent movement [Here is my problem]
timerId = setInterval(function() {
RemoveAgent();
var cell = $("#search_grid .row .grid_item[x=" + agent.x + "][y=" + agent.y + "]");
cell.css("background-color", "#e2e2e2");
cell.addClass("agent");
//start direction: right
if (right) {
lastDir = "right";
if (tryTo == "down" && trying) {
if (EmptySqm(agent.x + 1, agent.y)) {
trying = false;
right = false;
down = true;
agent.x++;
}
} else if (tryTo == "up" && trying) {
if (EmptySqm(agent.x - 1, agent.y)) {
trying = false;
right = false;
up = true;
agent.x--;
}
}
if (right) {
//check if is valid sqm
if (ValidSqm(agent.x, agent.y + 1)) {
//go right if empty
if (EmptySqm(agent.x, agent.y + 1)) {
agent.y++;
} else {
right = false;
//check up sqm
if (EmptySqm(agent.x - 1, agent.y)) {
up = true;
trying = true;
}
//check down
else if (EmptySqm(agent.x + 1, agent.y)) {
down = true;
trying = true;
}
}
} else {
agent.x++;
right = false;
left = true;
}
}
//left direction
} else if (left) {
lastDir = "left";
if (tryTo == "down" && trying) {
if (EmptySqm(agent.x + 1, agent.y)) {
trying = false;
left = false;
down = true;
agent.x++;
}
} else if (tryTo == "up" && trying) {
if (EmptySqm(agent.x - 1, agent.y)) {
trying = false;
left = false;
up = true;
agent.x--;
}
}
if (left) {
if (ValidSqm(agent.x, agent.y - 1)) {
if (EmptySqm(agent.x, agent.y - 1)) {
agent.y--;
} else {
left = false;
if (EmptySqm(agent.x + 1, agent.y)) {
down = true;
trying = true;
} else if (EmptySqm(agent.x - 1, agent.y)) {
up = true;
trying = true;
}
}
} else {
agent.x++;
right = true;
left = false;
}
}
//up direction
} else if (up) {
tryTo = "down";
if (lastDir == "left") {
if (EmptySqm(agent.x, agent.y - 1)) {
up = false;
left = true;
agent.y--;
}
} else if (lastDir == "right") {
if (EmptySqm(agent.x, agent.y + 1)) {
up = false;
right = true;
agent.y++;
}
}
if (up) {
if (ValidSqm(agent.x - 1, agent.y)) {
if (EmptySqm(agent.x - 1, agent.y)) {
agent.x--;
} else {
up = false;
//check left sqm
if (EmptySqm(agent.x, agent.y - 1)) {
left = true;
agent.y--;
}
//check right sqm
else if (EmptySqm(agent.x, agent.y + 1)) {
right = true;
agent.y++;
}
//check down sqm
else if (EmptySqm(agent.x + 1, agent.y)) {
down = true;
agent.x++;
}
}
} else {
agent.x++;
up = false;
down = true;
}
}
//down direction
} else if (down) {
tryTo = "up";
if (lastDir == "left") {
if (EmptySqm(agent.x, agent.y - 1)) {
down = false;
left = true;
agent.y--;
}
} else if (lastDir == "right") {
if (EmptySqm(agent.x, agent.y + 1)) {
down = false;
right = true;
agent.y++;
}
}
if (down) {
if (ValidSqm(agent.x + 1, agent.y)) {
if (EmptySqm(agent.x + 1, agent.y)) {
agent.x++;
} else {
down = false;
//check left sqm
if (EmptySqm(agent.x, agent.y - 1)) {
left = true;
agent.y--;
}
//check right sqm
else if (EmptySqm(agent.x, agent.y + 1)) {
right = true;
agent.y++;
}
//check up sqm
else if (EmptySqm(agent.x - 1, agent.y)) {
up = true;
agent.x--;
}
}
} else {
agent.x--;
up = true;
down = false;
}
}
}
}, 100);
var stopInterval = function() {
clearInterval(timerId);
};
};
EmptySqm = function(x, y) {
var bNotWall = !$("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]").hasClass("wall");
return bNotWall;
}
RemoveAgent = function() {
$("#search_grid .row .grid_item").removeClass("agent");
}
ValidSqm = function(x, y) {
return ((x >= 0 && x < gridSize) && (y >= 0 && y < gridSize));
}
html,
body {
height: 100%;
margin: 0;
}
.buttons {
float: right;
position: relative;
right: 10px;
top: 10px;
}
.buttons a {
text-decoration: none;
}
#content {
margin: 0 auto;
width: 98%;
text-align: center;
}
#controls {
text-align: center;
margin-bottom: 25px;
padding: 5px;
}
#search_grid {
width: 320px;
height: 300px;
position: relative;
}
#main {
margin: auto;
width: 20%;
}
.grid_item {
display: block;
border: 1px solid #bbb;
float: left;
line-height: 12px;
font-size: 10px;
}
.grid_item.wall {
background-color: #000000;
}
.grid_item.weight1 {
background-color: #ffffff;
}
.agent {
text-align: center;
color: grey;
font-size: 20px;
background-color: red !important;
color: blue;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="content">
<input type="button" id="btnInit" value="Start" /><br><br>
<div id="main">
<div id="search_grid">Loading...</div>
</div>
</div>
<div id="footer"></div>
</body>
I solved my problem with the help of the a* algorithm, more specifically this implementation, the deviation of the obstacles is done with the move method, which returns the path to a certain cell
path = grid.move(currentCell, endCell);
var agentSpeed = 10;
var WALL = 0;
var started = false;
var gridSize = 20;
var x = 0;
var y = 0;
var runsSameLine = false;
class Agent {
constructor(x, y, charge, cap, distance) {
this.x = x;
this.y = y;
this.charge = charge;
this.cap = cap;
this.distance = distance;
}
}
$(function() {
var $grid = $("#search_grid");
var opts = {
gridSize: gridSize
};
var grid = new GraphSearch($grid, opts, astar.search);
//Initializes the agent
$("#btnInit").click(function() {
if (!started) {
var agent = new Agent(0, 0, 100, 50, 0);
agent.initialize();
started = true;
}
});
});
//Initializes the matrix
function GraphSearch($graph, options, implementation) {
this.$graph = $graph;
this.search = implementation;
this.opts = options;
this.initialize();
}
var grid;
GraphSearch.prototype.move = function($start, $end) {
var end = this.nodeFromElement($end);
if ($end.hasClass("wall")) {
return;
}
var start = this.nodeFromElement($start);
var path = this.search(this.graph.nodes, start, end, true);
if (!path || path.length == 0) {
//this.animateNoPath();
} else {
return path;
}
};
GraphSearch.prototype.nodeFromElement = function($cell) {
return this.graph.nodes[parseInt($cell.attr("x"))][parseInt($cell.attr("y"))];
};
//Initializes the matrix
GraphSearch.prototype.initialize = function() {
this.grid = [];
var self = this,
nodes = [],
$graph = this.$graph;
$graph.empty();
var cellWidth = ($graph.width() / this.opts.gridSize) - 2,
cellHeight = ($graph.height() / this.opts.gridSize) - 2,
lineHeight = (this.opts.gridSize >= 30 ? "9.px" : ($graph.height() / this.opts.gridSize) - 10 + "px"),
fontSize = (this.opts.gridSize >= 30 ? "10px" : "20px");
$cellTemplate = $("<span />").addClass("grid_item").width(cellWidth).height(cellHeight).css("line-height", lineHeight).css("font-size", fontSize);
for (var x = 0; x < this.opts.gridSize; x++) {
var $row = $("<div class='row' />");
nodeRow = [],
gridRow = [];
for (var y = 0; y < this.opts.gridSize; y++) {
var id = "cell_" + x + "_" + y,
$cell = $cellTemplate.clone();
$cell.attr("id", id).attr("x", x).attr("y", y);
$row.append($cell);
gridRow.push($cell);
var isWall = addWall(x, y, this.opts.gridSize);
if (isWall === 1) {
$cell.addClass("wall");
nodeRow.push(1);
} else {
$cell.addClass('weight1');
nodeRow.push(0);
}
}
$graph.append($row);
this.grid.push(gridRow);
nodes.push(nodeRow);
//Fix for stackoverflow snippet
if ($(window).width() < 700) {
$("#search_grid").css("width", "320px");
$("#main").css("width", "38%");
} else {
$("#search_grid").css("width", "300px");
$("#main").css("width", "20%");
}
}
this.graph = new Graph(nodes);
this.$cells = $graph.find(".grid_item");
grid = this;
};
//Where will be wall in the matrix
addWall = function(x, y, size) {
var limitPointLeftUp = [2, 3];
var limitPointRightUp = [2, size - 4];
var limitPointLeftDown = [size - 4, 2];
var limitPointRightDown = [size - 4, size - 4];
if ((x == 2 && y == 2) || (x == 2 && y == size - 3)) {
return 1;
}
if ((x == size - 3 && y == 2) || (x == size - 3 && y == size - 3)) {
return 1;
}
if (x >= 2 && (y == 3 && x >= limitPointLeftUp[0] && x <= limitPointLeftDown[0] + 1)) {
return 1;
}
if (x >= 2 && (y == size - 4 && x >= limitPointRightUp[0] && x <= limitPointRightDown[0] + 1)) {
return 1;
}
if ((x == 1 && y == 5) || (x == 9 && y == 17) || (x == 6 && y == 0) || (x == 9 && y == 7) || (x == 15 && y == 0) || (x == 15 && y == 2) || (x == 18 && y == 15)) {
return 1;
}
}
//Initializes the agent
Agent.prototype.initialize = function() {
var agent = this;
var goToLeft = false;
var goToRight = true;
var rightLimit = gridSize - 1;
var leftLimit = 0;
var lastPos = 0;
var path = [];
var completedPath = true;
timerId = setInterval(function() {
agent.x = x;
agent.y = y;
currentCell = $("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]");
currentCell.css("background-color", "#e2e2e2");
if (agent.x == gridSize - 1 && agent.y == 0) {
stopInterval(timerId);
return false;
}
if (goToRight && y == rightLimit) {
if (runsSameLine) {
goToLeft = true;
goToRight = false;
runsSameLine = false;
} else {
if (FreeCell((x + 1), y)) {
endCell = $("#search_grid .row .grid_item[x=" + (x + 1) + "][y=" + y + "]");
x++;
goToLeft = true;
goToRight = false;
} else {
endCell = FindNextFreeCell(x, y, "limDir");
goToLeft = true;
goToRight = false;
}
}
} else if (goToLeft && y == leftLimit) {
if (runsSameLine) {
goToLeft = false;
goToRight = true;
runsSameLine = false;
} else {
if (FreeCell((x + 1), y)) {
endCell = $("#search_grid .row .grid_item[x=" + (x + 1) + "][y=" + y + "]");
x++;
goToLeft = false;
goToRight = true;
} else {
endCell = FindNextFreeCell(x, y, "limEsq");
goToLeft = false;
goToRight = true;
}
}
} else if (goToRight) {
if (FreeCell(x, (y + 1))) {
endCell = $("#search_grid .row .grid_item[x=" + x + "][y=" + (y + 1) + "]");
y++;
} else {
endCell = FindNextFreeCell(x, y, "dir");
}
} else if (goToLeft) {
if (FreeCell(x, (y - 1))) {
endCell = $("#search_grid .row .grid_item[x=" + x + "][y=" + (y - 1) + "]");
y--;
} else {
endCell = FindNextFreeCell(x, y, "esq");
}
}
if (completedPath) {
path = grid.move(currentCell, endCell);
}
if (path) {
if (lastPos == path.length - 1) {
completedPath = true;
}
if (path.length > 1 && lastPos < path.length && lastPos != path.length - 1) {
x = path[lastPos].x;
y = path[lastPos].y;
lastPos++;
completedPath = false;
} else if (completedPath) {
x = path[lastPos].x;
y = path[lastPos].y;
lastPos = 0;
}
}
grid.$cells.removeClass("agent");
$("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]").addClass("agent");
}, agentSpeed);
var stopInterval = function() {
clearInterval(timerId);
};
};
FindNextFreeCell = function(x, y, dir) {
if (dir == "limDir") {
if (x != gridSize) {
for (var y = y; y >= 0; y--) {
if (FreeCell((x + 1), y)) {
return getCell((x + 1), y);
}
}
}
} else if (dir == "limEsq") {
if (x != gridSize) {
for (var y = y; y <= gridSize; y++) {
if (FreeCell((x + 1), y)) {
return getCell((x + 1), y);
}
}
}
} else if (dir == "dir") {
for (var y = y; y < gridSize - 1; y++) {
if (FreeCell(x, (y + 1))) {
return getCell(x, (y + 1));
}
}
for (var x = x; x <= gridSize - 1; x++) {
if (FreeCell((x + 1), y)) {
runsSameLine = true;
return getCell((x + 1), y);
}
}
} else if (dir == "esq") {
for (var y = y; y > 0; y--) {
if (FreeCell(x, (y - 1))) {
return getCell(x, (y - 1));
}
}
for (var x = x; x <= gridSize - 1; x++) {
if (FreeCell((x + 1), y)) {
runsSameLine = true;
return getCell((x + 1), y);
}
}
}
}
EmptySqm = function(x, y) {
var bNotWall = !$("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]").hasClass("wall");
return bNotWall;
}
getCell = function(x, y) {
return $("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]");
}
FreeCell = function(x, y) {
var bNaoTemParede = !$("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]").hasClass("wall");
var bNaoTemLixeira = !$("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]").hasClass("lixeira");
var bNaoTemRecarga = !$("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]").hasClass("pontoRecarga");
return bNaoTemParede && bNaoTemLixeira && bNaoTemRecarga;
}
ValidSqm = function(x, y) {
return ((x >= 0 && x < gridSize) && (y >= 0 && y < gridSize));
}
// javascript-astar
// http://github.com/bgrins/javascript-astar
// Freely distributable under the MIT License.
// Implements the astar search algorithm in javascript using a binary heap.
var astar = {
init: function(grid) {
for (var x = 0, xl = grid.length; x < xl; x++) {
for (var y = 0, yl = grid[x].length; y < yl; y++) {
var node = grid[x][y];
node.f = 0;
node.g = 0;
node.h = 0;
node.cost = node.type;
node.visited = false;
node.closed = false;
node.parent = null;
}
}
},
heap: function() {
return new BinaryHeap(function(node) {
return node.f;
});
},
search: function(grid, start, end, diagonal, heuristic) {
astar.init(grid);
heuristic = heuristic || astar.manhattan;
diagonal = !!diagonal;
var openHeap = astar.heap();
openHeap.push(start);
while (openHeap.size() > 0) {
// Grab the lowest f(x) to process next. Heap keeps this sorted for us.
var currentNode = openHeap.pop();
// End case -- result has been found, return the traced path.
if (currentNode === end) {
var curr = currentNode;
var ret = [];
while (curr.parent) {
ret.push(curr);
curr = curr.parent;
}
return ret.reverse();
}
// Normal case -- move currentNode from open to closed, process each of its neighbors.
currentNode.closed = true;
// Find all neighbors for the current node. Optionally find diagonal neighbors as well (false by default).
var neighbors = astar.neighbors(grid, currentNode, diagonal);
for (var i = 0, il = neighbors.length; i < il; i++) {
var neighbor = neighbors[i];
if (neighbor.closed || neighbor.isWall() || $("#search_grid .row .grid_item[x=" + neighbor.x + "][y=" + neighbor.y + "]").hasClass("pontoRecarga") || $("#search_grid .row .grid_item[x=" + neighbor.x + "][y=" + neighbor.y + "]").hasClass("lixeira")) {
// Not a valid node to process, skip to next neighbor.
continue;
}
// The g score is the shortest distance from start to current node.
// We need to check if the path we have arrived at this neighbor is the shortest one we have seen yet.
var gScore = currentNode.g + neighbor.cost;
var beenVisited = neighbor.visited;
if (!beenVisited || gScore < neighbor.g) {
// Found an optimal (so far) path to this node. Take score for node to see how good it is.
neighbor.visited = true;
neighbor.parent = currentNode;
neighbor.h = neighbor.h || heuristic(neighbor.pos, end.pos);
neighbor.g = gScore;
neighbor.f = neighbor.g + neighbor.h;
if (!beenVisited) {
// Pushing to heap will put it in proper place based on the 'f' value.
openHeap.push(neighbor);
} else {
// Already seen the node, but since it has been rescored we need to reorder it in the heap
openHeap.rescoreElement(neighbor);
}
}
}
}
// No result was found - empty array signifies failure to find path.
return [];
},
manhattan: function(pos0, pos1) {
// See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
var d1 = Math.abs(pos1.x - pos0.x);
var d2 = Math.abs(pos1.y - pos0.y);
return d1 + d2;
},
neighbors: function(grid, node, diagonals) {
var ret = [];
var x = node.x;
var y = node.y;
// West
if (grid[x - 1] && grid[x - 1][y]) {
ret.push(grid[x - 1][y]);
}
// East
if (grid[x + 1] && grid[x + 1][y]) {
ret.push(grid[x + 1][y]);
}
// South
if (grid[x] && grid[x][y - 1]) {
ret.push(grid[x][y - 1]);
}
// North
if (grid[x] && grid[x][y + 1]) {
ret.push(grid[x][y + 1]);
}
if (diagonals) {
// Southwest
if (grid[x - 1] && grid[x - 1][y - 1]) {
ret.push(grid[x - 1][y - 1]);
}
// Southeast
if (grid[x + 1] && grid[x + 1][y - 1]) {
ret.push(grid[x + 1][y - 1]);
}
// Northwest
if (grid[x - 1] && grid[x - 1][y + 1]) {
ret.push(grid[x - 1][y + 1]);
}
// Northeast
if (grid[x + 1] && grid[x + 1][y + 1]) {
ret.push(grid[x + 1][y + 1]);
}
}
return ret;
}
};
// javascript-astar
// http://github.com/bgrins/javascript-astar
// Freely distributable under the MIT License.
// Includes Binary Heap (with modifications) from Marijn Haverbeke.
// http://eloquentjavascript.net/appendix2.html
var GraphNodeType = {
OPEN: 0,
WALL: 1
};
// Creates a Graph class used in the astar search algorithm.
function Graph(grid) {
var nodes = [];
for (var x = 0; x < grid.length; x++) {
nodes[x] = [];
for (var y = 0, row = grid[x]; y < row.length; y++) {
nodes[x][y] = new GraphNode(x, y, row[y]);
}
}
this.input = grid;
this.nodes = nodes;
}
Graph.prototype.toString = function() {
var graphString = "\n";
var nodes = this.nodes;
var rowDebug, row, y, l;
for (var x = 0, len = nodes.length; x < len; x++) {
rowDebug = "";
row = nodes[x];
for (y = 0, l = row.length; y < l; y++) {
rowDebug += row[y].type + " ";
}
graphString = graphString + rowDebug + "\n";
}
return graphString;
};
function GraphNode(x, y, type) {
this.data = {};
this.x = x;
this.y = y;
this.pos = {
x: x,
y: y
};
this.type = type;
}
GraphNode.prototype.toString = function() {
return "[" + this.x + " " + this.y + "]";
};
GraphNode.prototype.isWall = function() {
return this.type === GraphNodeType.WALL;
};
function BinaryHeap(scoreFunction) {
this.content = [];
this.scoreFunction = scoreFunction;
}
BinaryHeap.prototype = {
push: function(element) {
// Add the new element to the end of the array.
this.content.push(element);
// Allow it to sink down.
this.sinkDown(this.content.length - 1);
},
pop: function() {
// Store the first element so we can return it later.
var result = this.content[0];
// Get the element at the end of the array.
var end = this.content.pop();
// If there are any elements left, put the end element at the
// start, and let it bubble up.
if (this.content.length > 0) {
this.content[0] = end;
this.bubbleUp(0);
}
return result;
},
remove: function(node) {
var i = this.content.indexOf(node);
// When it is found, the process seen in 'pop' is repeated
// to fill up the hole.
var end = this.content.pop();
if (i !== this.content.length - 1) {
this.content[i] = end;
if (this.scoreFunction(end) < this.scoreFunction(node)) {
this.sinkDown(i);
} else {
this.bubbleUp(i);
}
}
},
size: function() {
return this.content.length;
},
rescoreElement: function(node) {
this.sinkDown(this.content.indexOf(node));
},
sinkDown: function(n) {
// Fetch the element that has to be sunk.
var element = this.content[n];
// When at 0, an element can not sink any further.
while (n > 0) {
// Compute the parent element's index, and fetch it.
var parentN = ((n + 1) >> 1) - 1,
parent = this.content[parentN];
// Swap the elements if the parent is greater.
if (this.scoreFunction(element) < this.scoreFunction(parent)) {
this.content[parentN] = element;
this.content[n] = parent;
// Update 'n' to continue at the new position.
n = parentN;
}
// Found a parent that is less, no need to sink any further.
else {
break;
}
}
},
bubbleUp: function(n) {
// Look up the target element and its score.
var length = this.content.length,
element = this.content[n],
elemScore = this.scoreFunction(element);
while (true) {
// Compute the indices of the child elements.
var child2N = (n + 1) << 1,
child1N = child2N - 1;
// This is used to store the new position of the element,
// if any.
var swap = null;
var child1Score;
// If the first child exists (is inside the array)...
if (child1N < length) {
// Look it up and compute its score.
var child1 = this.content[child1N];
child1Score = this.scoreFunction(child1);
// If the score is less than our element's, we need to swap.
if (child1Score < elemScore) {
swap = child1N;
}
}
// Do the same checks for the other child.
if (child2N < length) {
var child2 = this.content[child2N],
child2Score = this.scoreFunction(child2);
if (child2Score < (swap === null ? elemScore : child1Score)) {
swap = child2N;
}
}
// If the element needs to be moved, swap it, and continue.
if (swap !== null) {
this.content[n] = this.content[swap];
this.content[swap] = element;
n = swap;
}
// Otherwise, we are done.
else {
break;
}
}
}
};
html,
body {
height: 100%;
margin: 0;
}
.buttons {
float: right;
position: relative;
right: 10px;
top: 10px;
}
.buttons a {
text-decoration: none;
}
#content {
margin: 0 auto;
width: 98%;
text-align: center;
}
#controls {
text-align: center;
margin-bottom: 25px;
padding: 5px;
}
#search_grid {
width: 300px;
height: 300px;
position: relative;
}
#main {
margin: auto;
width: 20%;
}
.grid_item {
display: block;
border: 1px solid #bbb;
float: left;
line-height: 12px;
font-size: 10px;
}
.grid_item.wall {
background-color: #000000;
}
.grid_item.weight1 {
background-color: #ffffff;
}
.agent {
text-align: center;
color: grey;
font-size: 20px;
background-color: red !important;
color: blue;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="content">
<input type="button" id="btnInit" value="Start" /><br><br>
<div id="main">
<div id="search_grid">Loading...</div>
</div>
</div>
<div id="footer"></div>
</body>

Control ball speed in pong

I have this code below, and I'm having a hard time solving this one.
On dotime function, i have the ball speed:
/* HERE */
function dotime() {
move1();
if (myform != null) {
myform.text3.value = display1();
myform.score.value = "" + score;
}
/* ---Ball Speed--- */
if (!oops_flag) timerID = setTimeout("dotime()", 190);
/* ---trying to make ball speed faster--- */
if (score == 1) {
timerID = setTimeout("dotime()", 100 - 30);
}
timerRunning = true;
}
I tried to make the ball move faster but when i do the second "if", the ball just flying too fast.
Thanks in advance,
fufle.
full code:
var crlf = "\r\n";
var x = 0;
var y = 0;
var dx = 1;
var dy = 1;
var s = "";
var u = 0;
var oops_flag = false;
var score = 0;
function move1() {
x += dx;
if (x > 61) {
x -= 2 * Math.abs(dx);
if (dx > 0) dx = -dx;
}
if (x < 0) {
x += 2 * Math.abs(dx);
if (dx < 0) dx = -dx;
}
y += dy;
if (y > 24) {
y -= 2 * Math.abs(dy);
if (dy > 0) dy = -dy;
if (Math.abs(x - 2 * u - 1) > 2) {
oops_flag = true;
} else {
score += 1;
}
}
if (y < 0) {
y += 2 * Math.abs(dy);
if (dy < 0) dy = -dy;
}
}
function display1() {
var s1 = ""
var i, j;
if (oops_flag) return " Unlucky, Play again?"
for (j = 0; j < 25; j++) {
for (i = 0; i < 62; i++) {
/* BALL */
if (j == y && i == x) s1 += "🔴";
else s1 += " ";
}
s1 += crlf;
}
/* DEFENDER */
var s2 = "";
for (i = 0; i < 31; i++) {
if (u == i) s2 += "â–„â–„â–„â–„â–„";
else s2 += " ";
}
return (s1 + s2);
}
var timerID = null;
var timerRunning = false;
var myform;
function stopclock() {
if (timerRunning) clearTimeout(timerID);
timerRunning = false;
}
function startclock(form) {
myform = form;
oops_flag = false;
score = 0;
if (navigator.userAgent.indexOf("Mac") > 2) crlf = "\n";
stopclock();
dotime();
// var id= setInterval(frameElement,10000);
}
/* HERE */
function dotime() {
move1();
if (myform != null) {
myform.text3.value = display1();
myform.score.value = "" + score;
}
if (!oops_flag) timerID = setTimeout("dotime()", 100);
if (score == 1) {
timerID = setTimeout("dotime()", 100 - 30);
}
timerRunning = true;
}
Looks like you have two timers running so you need to make it so only one will run.
if (!oops_flag) {
var speed = 100;
if (score===1) speed = 70;
timerID = setTimeout(dotime, speed);
}
or with a ternary operator
if (!oops_flag) {
var speed = (score===1) ? 70 : 100;
timerID = setTimeout(dotime, speed);
}

Generating a random grid of connected paths

I am trying to generate a random grid of connected paths. The image below shows how far I've managed to get it:
The rules that the grid needs to adhere to are the following:
all the paths must connect to each other in some way but there can be dead ends
there can be no blocks that have no connections (i.e. can't be reached)
the blocks on the edge must have paths that point inward, not outward.
As you can see in my image, my code isn't quite right, but I can't find the error.
Here is a fiddle with the code: jsfiddle.net/thatOneGuy/jz5sfr00/1
But I think my mistake is in this function:
function linkAll() {
for (var x = 0; x < 9; x++) {
for (y = 0; y < 9; y++) {
//link up to each other
var count = 0;
if ((x > 0) && (y > 0)) {
if (hz[x - 1][y].right) {
hz[x][y].left = 1;
} else count++;
if (hz[x][y - 1].bottom) {
hz[x][y].top = 1;
} else count++;
}
if ((x < 9) && (y < 9)) {
if (hz[x + 1][y].left) {
hz[x][y].right = 1;
} else count++;
if (hz[x][y + 1].top) {
hz[x][y].bottom = 1;
} else count++;
}
if (count == 4) {
var newPath = getDirection(getRandomInt(0, 3));
if (newPath == 'top') {
hz[x][y - 1].bottom = 1
hz[x][y].top = 1;
} else if (newPath == 'left') {
hz[x - 1][y].right = 1;
hz[x][y].left = 1;
} else if (newPath == 'bottom') {
hz[x][y + 1].top = 1;
hz[x][y].bottom = 1;
} else if (newPath == 'right') {
hz[x + 1][y].left = 1;
hz[x][y].right = 1;
}
}
} //end for (y)
} //end for (x)
}
UPDATE:
I realised that I confused the x and y values of the array. They should have been swopped.
So I added a linkEdges() function so that the edge blocks all link together:
function linkEdges(){
for(var x = 0; x < 10; x++){
for(var y = 0; y < 10; y++){
if((x==0) && (y > 0) && (y < 9)){
if(hz[0][y-1].right){
//console.log(x + ' ' + y + ' y-1 = 1');
//console.log('Inside (y-1) ');
//console.log(hz[x][y]);
if (hz[0][y].left != null)
{
hz[0][y].left = 1;
}
}
}
if ((y==0) && (x > 0)){
if(hz[x-1][0].bottom){
if(hz[x][0].top != null)
hz[x][0].top = 1;
}
}
if ((y==9) && (x < 9) && (x > 0)){
if(hz[x+1][9].top){
if(hz[x][9].bottom != null)
hz[x][9].bottom = 1;
}
}
if ((x==9) && (y < 9)){
if(hz[9][y+1].left){
if(hz[9][y].right != null)
hz[9][y].right = 1;
}
}
} //end for(y)
}//end for(x)
}
I also updated the linkAll() function:
function linkAll(){
for(var x=0; x < 9; x++){
for(var y=0; y < 9; y++){
//link up to each other
var count = 0;
if((x > 0) && (y > 0)){
if(hz[x-1][y].bottom){
hz[x][y].top = 1;
}
else count++;
if(hz[x][y-1].right){
hz[x][y].left = 1;
}
else count++;
}
if((x < 9) && (y < 9)){
if(hz[x+1][y].top){
hz[x][y].bottom = 1;
}
else count++;
if(hz[x][y+1].left){
hz[x][y].right = 1;
}
else count++;
}
if(count == 4){
//console.log('x: ' + x + ' y: '+y);
var newPath = getDirection(getRandomInt(0, 3));
//console.log(newPath);
if(newPath == 'top'){
hz[x][y-1].right = 1
hz[x][y].left = 1;
}
else if(newPath == 'left'){
hz[x-1][y].bottom = 1;
hz[x][y].top = 1;
}
else if(newPath == 'bottom'){
hz[x][y+1].left = 1;
hz[x][y].right = 1;
}
else if(newPath == 'right'){
hz[x+1][y].top = 1;
hz[x][y].bottom = 1;
}
}
}//end for (y)
}//end for (x)
}
My grid now looks like this:
I just don't know how to connect those last few edges. I think it has something to do with my linkEdges() function.

javascript array problem

i have written a snake program using javascript..
the problem is that the snake does not grow more than 2 blocks size....
<html>
<head>
<script type="text/javascript">
var matrix, body, dir, key, lastx, lasty, start, applex, appley, eat, hal;
function node(x, y) {
this.x = x;
this.y = y;
}
function draw() {
var str;
for (var i = 0; i < body.length; i++) {
matrix[body[i].x * 50 + body[i].y].bgColor = "black";
}
}
function halt() {
hal = 1 - hal;
if (hal == 0) automove();
}
function check_status() {
if (start == 1 && hal == 0) {
var ch;
if (eat == 1) {
do {
ch = 0;
applex = Math.round(49 * Math.random());
appley = Math.round(49 * Math.random());
for (var i = 0; i < body.length; i++)
if (body[i].x == applex && body[i].x == appley) ch = 1;
} while (ch == 1);
matrix[applex * 50 + appley].bgColor = "blue";
eat = 0;
}
lastx = body[body.length - 1].x;
lasty = body[body.length - 1].y;
for (var i = 1; i < body.length; i++) {
body[i].x = body[i - 1].x;
body[i].y = body[i - 1].y;
}
if (dir == 1)--body[0].x;
else if (dir == -1)++body[0].x;
else if (dir == 2)--body[0].y;
else if (dir == -2)++body[0].y;
if (body[0].x == -1 || body[0].x == 50 || body[0].y == 50 || body[0].y == -1) {
alert("GAME OVER!!");
start = 0;
}
for (var i = 1; i < body.length; i++) {
if (body[0].x == body[i].x && body[0].y == body[i].y) {
alert("GAME OVER!!");
start = 0;
i = 10000;
}
}
if (body[0].x == applex && appley == body[0].y) {
eat = 1;
body[body.length] = new node(lastx, lasty);
}
matrix[lastx * 50 + lasty].bgColor = "white";
draw();
}
}
function automove() {
if (start == 1 && hal == 0) {
if (key != -dir) dir = key;
check_status();
window.setTimeout("automove()", 200);
}
}
function init() {
start = 1;
var x = document.getElementById("mine");
var str = "<table id='tab' align='center' height='500px' cellSpacing='0' cellPadding='0' width='500px' border='4' >";
for (var i = 0; i < 50; i++) {
str += "<tr>";
for (var j = 0; j < 50; j++)
str += "<td></td>";
str += "</tr>";
}
str += "</table>";
x.innerHTML = str;
matrix = document.getElementsByTagName("td");
body = new Array();
body[0] = new node(0, 0);
draw();
dir = key = -1;
eat = 1;
v = 0;
hal = 0;
automove();
}
function keypress(e) {
if ((e.keyCode == 38) || ((e.which) && (e.which == 38))) //up
key = 1;
else if ((e.keyCode == 40) || ((e.which) && (e.which == 40))) //down
key = -1;
else if ((e.keyCode == 37) || ((e.which) && (e.which == 37))) //left
key = 2;
else if ((e.keyCode == 39) || ((e.which) && (e.which == 39))) //right
key = -2;
check_status();
}
</script>
</head>
<body onkeydown=keypress(event)>
<br/>
<input type="button" onClick="init()" value="play">
<input type="button" onClick="halt()" value="pause">
<p id="mine"></p>
<br><h5 id="score"></h5>
</body>
</html>
The problem is here:
lastx=body[body.length-1].x;
lasty=body[body.length-1].y;
for(var i=1;i<body.length;i++)
{
body[i].x=body[i-1].x;
body[i].y=body[i-1].y;
}
In that loop, body[1] is assigned to body[0], then body [2] is assigned to body[1] etc. This means that everything from index 1 to the end will be set equal to body[0], then body[0] is altered based on direction - so there are only two positions.
Look into the javascript unshift method.
You could replace that loop with:
body.unshift(body[0]);

Categories

Resources