faild to move the element in between? - javascript

i have been try to solve the sudoku with Blacktracking algo, everything is good, canvar is called and i able to see the number but the things is number are not moving i.e the logic is not exectuing
current.i === 0; is where i'm get the error! even i have declared a sperate variable for the num also the problem is not sloved. only if i remove the .num current == 0 than its not showing any error but still the number is not moving
enter image description here
var cell = [];
var stack = [];
var sudoku = [2,3,0,9,4,0,6,7,0,
8,0,0,3,2,5,9,1,4,
9,0,0,7,6,0,3,2,0,
1,0,0,0,0,0,7,9,2,
5,0,3,2,1,0,4,8,6,
4,0,0,6,8,0,5,3,1,
7,0,0,1,0,0,0,0,9,
6,5,9,8,7,2,1,4,3,
3,0,0,0,9,0,0,0,7];
var current;
var number = 1;
function setup(){
createCanvas(450,450);
var a=0;
var b=0;
for(var i=0;i<81;i++){
if(a%9==0 && i!=0){
b = b+50;
a = 0;
}
each[i] = new each(a,b,i,sudoku[i]);
a = a+50;
}
current = cell[0];
}
function draw(){
background(10);
for(var i=0;i<81;i++){
each[i].show();
}
if(current.num === 0){ //the error is typeerror can't read the property of num
if(! sameColumn(current.i,number) && ! sameRow(current.i,number) && ! sameSquare(current.i,number) && number<(10)){
current.num = number;
stack.push(current);
number = 0;
current.each[current.i+1];
}
else {
if(number > 8){
current.num = 0;
current = stack.pop();
number = current.num;
current.num = 0;
}
}
}
else{
current = each[current+1];
number = 0;
}
number++;
}
function each(a,b,i,num){
this.a = a;
this.b = b;
this.i = i;
this.num = num;
this.show = function(){
noFill();
stroke(255);
rect(this.a,this.b,50,50);
textSize(32);
text(this.num,a+12,b+40);
}
}

The error is pretty much straight forward. current = cell[0]; becomes undefined since you defined cell as an empty array and didn't manipulated it after that.
From what I have observed so far, many parts of your code logically does not work, for example,
same Column(current.i,number) && ! sameRow(current.i,number) && ! sameSquare(current.i,number)
will definitely throw you an error is it is executed (it is not since the execution does not reach to that line), unless you have a separate js file that contains these functions.
Another one is
current = cell[current+1];
if the current variable is to store the cell object, it does not make sense to add 1 to it, and vice versa.
Now I believe this is how setup function was meant to look like:
function setup(){
createCanvas(450,450);
var a=0;
var b=0;
for(var i=0;i<81;i++){
if(a%9==0 && i!=0){
b = b+50;
a = 0;
}
cell[i] = new Cell(a,b,i,sudoku[i]); //changed each[i] to cell[i], also renamed the 'each' class
a = a+50;
}
current = cell[0];
}
If possible, please edit in a little more information about what exactly does your code do. Cheers :)

Related

why does my a star algorithm not work in javascript?

function algorithm(){
if(startPoint === true && endPoint === true){
//add the heuristic distance to the start position from the final position
startPosition.h = distance([startPosition.x, startPosition.y]);
let openList = []
openList.push(startPosition)
let closedList = []
while (openList.length > 0){
//print(openList)
lowPos = 0;
for(let i = 0; i < openList.length; i++){
if(openList[i].f < openList[lowPos].f){
lowPos = i;
}
}
let currentPosition = openList[lowPos];
//currentPosition.check()
//if the currentPosition is the endPosition, retrace steps and find the path, then return this path
if(currentPosition === endPosition){
let curr = currentPosition;
let ret = [];
while(curr.parent != null){
curr.path()
ret.push(curr);
curr = curr.parent;
}
endPosition.end()
return ret.reverse();
}
openList.splice(lowPos, 1);
closedList.push(currentPosition);
let neighbours = neighbors(currentPosition);
for(let i = 0; i < neighbours.length; i++){
let neighbour = neighbours[i];
if(closedList.includes(neighbour) || neighbour.colour == "black"){
continue;
}
neighbour.check()
let gScore = currentPosition.g + 1;
let gScoreBest = false;
if(openList.includes(neighbour) == false){
gScoreBest = true;
neighbour.h = distance([neighbour.x, neighbour.y]);
openList.push(neighbour);
}
else if(gScore < neighbour.g){
gScoreBest = true;
}
if(gScoreBest == true){
neighbour.parent = currentPosition;
neighbour.g = gScore;
neighbour.f = neighbour.g + neighbour.h;
}
}
}
}
//meaning that either the path is not possible or the final node/initial node
has not yet been placed.
return [];
}
this is my a star algorithm in p5, i'm trying to make an a star visualisation project, but for some reason a lot more of blocks are highlighted than expected.
[: https://i.stack.imgur.com/ILlOr.png
In reality it is supposed to be something like this: : https://i.stack.imgur.com/nsF5r.png
The second picture isn't mine, its from someone else's implementation: https://qiao.github.io/PathFinding.js/visual/ = link to the second picture
I think it's something to do with the order of the line: neighbour.check() which changes the colour of the block.
Here is a diagonal solution, as you can see for some reason there is purple in the top left, that is my issue. The top left should not be searched, but it is for some reason.
If you need more of my code, please let me know.
It looks like you are not checking the diagonals.
It is not a mistake. You are doing great.
I got it to fix, surprisingly the thing that was wrong was my distance formulae, I called the wrong variable.
here's what it looks like now! :)

NodeJS require with asynch functions when synch is wanted

I have the following code
var utils = require(`${__dirname}/../../utils/utils.js`);
...
let object = utils.parse(input);
if (object === undefined){
let helper = utils.recognize(input);
msg.channel.sendMessage("\"" + input + "\" not recognized. Did you mean \"" + helper[0] + "\"?");
object = utils.parse(helper[0]);
}
//code related to object
console.log(object.strLength);
where "parse" tries to match the input to an object in a database, and "recognize" tries to find the best match if the input is spelled incorrectly (Levenshtein) (along with additional info such as how close the match was).
Currently the issue is that the code is ran asynchronously; "object.strLength" returns an undefined before utils.recognize() returns a value. If I copy/paste the recognize() and parse() functions into the file, then the code is run synchronously and I do not run into any issues. However I would rather keep those functions in a separate file as I reuse them in other files.
Is there a way to specify that the functions in utils must be synch? I know that there are libraries that convert asynch into synch but I prefer to use as few libraries as I can help it. I tried to have the recognize functions return a Promise but it ended up as a jumbled mess
edit: here's parse. I did not think it was necessary to answer this question so I did not include it initially:
var db = require(`${__dirname}/../data/database.js`);
...
var parse = (input) => {
let output = db[output];
if (output === null) {
Object.keys(db).forEach((item) => {
if (db[item].num === parseInt(input) || (db[item].color + db[item].type === input)){
output = db[item];
return false;
}
});
}
return output;
}
I solved the issue, thanks everyone. Here's what was wrong, it was with recognize(). It was my mistake to not show the code for it initially.
Original recognize:
var recognize = (item) => {
//iterate through our databases and get a best fit
let bestItem = null;
let bestScore = 99999; //arbitrary large number
//let bestType = null;
//found algorithm online by milot-mirdita
var levenshtein = function(a, b) {
if (a.length == 0) { return b.length; }
if (b.length == 0) { return a.length; }
// swap to save some memory O(min(a,b)) instead of O(a)
if(a.length > b.length) {
let tmp = a;
a = b;
b = tmp;
}
let row = [];
for(let i = 0; i <= a.length; i++) {
row[i] = i;
}
for (let i = 1; i <= b.length; i++) {
let prev = i;
for (let j = 1; j <= a.length; j++) {
let val;
if (b.charAt(i-1) == a.charAt(j-1)) {
val = row[j-1]; // match
} else {
val = Math.min(row[j-1] + 1, // substitution
prev + 1, // insertion
row[j] + 1); // deletion
}
row[j - 1] = prev;
prev = val;
}
row[a.length] = prev;
}
return row[a.length];
}
//putting this here would make the code work
//console.log("hi");
Object.keys(db).forEach((key) => {
if (levenshtein(item, key) < bestScore) {
bestItem = key;
bestScore = levenshtein(item, key);
}
});
return [bestItem, bestScore];
}
My solution was to move the levenshtein function outside of the recognize function, so if I wanted to I can call levenshtein from another function
#user949300 and #Robert Moskal, I changed the forEach loop into a let...in loop. There is no functional difference (as far as I can tell) but the code does look cleaner.
#Thomas, I fixed the let output = db[output]; issue, oops.
Again, thanks for all of your help, I appreciate it. And happy New Year too

javascript for loop is not incrementing

I am trying to using a for loop for trying to validate the input of the user and this is the code i got.
function Valid() {
objfieldid = ["userMail", "userCont"]
objboxid = ["cancelMail", "cancelCont"]
return objfieldid.every(callnonvalid)
}
function callnonvalid(id) {
var valid = false
var objlength = objfieldid.length
objlength--;
for (var i = objlength; i >= 0; i--){
var cobj = document.getElementById(objboxid[i]).checked;
if (document.getElementById(id).value != "" ){
var obj = document.getElementById(id).value;
} else if (cobj == true) {
alert(i); //return 1, 1
return true
} else {
return false
}
}
}
As you can see, in the code, the for loop is running twice. but the i variable is left unchanged. Why would this happen?
btw, I did read different material about closure and i am sure there didnt got a closure problem
EDIT:guys please note that i did noticed the array is zero based, and i did minus the objlength by one.
Mistakes were found after checking the code carefully. The Mistake that I made was that I should not use the return for the out since that would stop the function from working, however that array.every Called the function twice which make the i not decreasing
I'm not sure why you're decrementing in your loop, because the performance gain would be infinitesimally small (it may even be slower, e.g. in Chrome/V8) and working in reverse order can get confusing further down the line, but that's your choice and I don't know enough about what you're doing to judge.
Either way, I don't think you'd want to decrement objlength before the loop begins as you are doing now. The whole point of a loop is to handle the incrementing/decrementing in the condition statement of the loop.
You would only decrement manually like that if you were going to move your if/else if/else statement into a closed over function and execute it recursively, decrementing the objlength from within the closure. Which would work, but it's unnecessarily complicated for what you're doing and you would gain nothing for rewriting the whole thing.
So, sticking with the looping approach, perhaps try either of these:
function Valid() {
objfieldid = ["userMail", "userCont"];
objboxid = ["cancelMail", "cancelCont"];
return objfieldid.every(callnonvalid);
}
function callnonvalid(id) {
var valid = false;
var objlength = objfieldid.length;
for(var i = 0; i < objlength; i++){
var cobj = document.getElementById(objboxid[i]).checked;
if (document.getElementById(id).value != "" ){
var obj = document.getElementById(id).value;
} else if (cobj == true) {
alert(i);
return true;
} else {
return false;
}
}
}
or, if you want to decrement, use while instead of for:
function Valid() {
objfieldid = ["userMail", "userCont"];
objboxid = ["cancelMail", "cancelCont"];
return objfieldid.every(callnonvalid);
}
function callnonvalid(id) {
var valid = false;
var i = objfieldid.length;
while(i--){
var cobj = document.getElementById(objboxid[i]).checked;
if (document.getElementById(id).value != "" ){
var obj = document.getElementById(id).value;
} else if (cobj == true) {
alert(i);
return true;
} else {
return false;
}
}
}
Because the array objboxid[] has only two elements, the first time through your loop objboxid[2] will be attempting to fetch an array index that is out-of-bounds.
You probably meant something like:
for (var i = objlength; i > 0; i--){
var cobj = document.getElementById(objboxid[i-1]).checked;
or perhaps
for (var i = objlength-1; i >= 0; i--){
var cobj = document.getElementById(objboxid[i]).checked;

Javascript: Detect and Remove a loop from cylic linked list

I have used Javascript to write a circular linked list and to detect and remove the loop.It is working fine untill the part of loop detection. How ever it is failing to remove the loopnode. More specifically: the removeLoop function of this code doesnot work.
Here is my code:
function Node(element){
this.element = element;
this.next = null;
}
//circular linked list class
function LList() {
this.head = new Node("head");
this.head.next = this.head;
this.find = find;
this.insert = insert;
this.display = display;
}
function find(item){
var curr = this.head;
while(curr.element != item){
curr = curr.next;
}
return curr;
}
//inserting items into linked list
function insert(newElem, after){
var newNode = new Node(newElem);
var curr = this.find(after);
newNode.next = curr.next;
curr.next = newNode;
}
function display() {
var currNode = this.head;
while ((currNode.next !== null) &&
(currNode.next.element !== "head")) {
console.log(currNode.next.element);
currNode = currNode.next;
}
}
function findPrevious(item){
var curr = this.head;
while(curr.next !== null && curr.next.element !== item){
curr =curr.next;
}
return curr;
}
//creating a linkedlist object
var furniture = new LList();
furniture.insert("chair","head");
furniture.insert("table", "chair");
furniture.insert("couch", "table");
furniture.insert("stool","couch");
//furniture.display();
//detecting if a linked list is circular
function detectALoop(list){
var slow = list.head;
var fast = list.head;
while(slow && fast && fast.next){
slow = slow.next;
fast = fast.next.next;
if(slow === fast){
removeLoop (slow, list);
return 1;
}
}
return 0;
}
//This part of the code doesnot work
function removeLoop(loopNode, list)
{
var ptr1 = loopNode;
var ptr2 = loopNode;
var looplen = 1,i;
// count the number of nodes in loop
while(ptr1.next != ptr2)
{
ptr1 = ptr1.next;
looplen++;
}
console.log(looplen)
ptr1 = list.head;
ptr2 = list.head;
for(i=0; i <= looplen; i++)
{
ptr2 = ptr2.next;
}
while(ptr2.next != ptr1.next)
{
ptr1 = ptr1.next;
ptr2 = ptr2.next;
}
ptr2.next = null; // breaking the loop
}
console.log(detectALoop(furniture))
furniture.display();
You are making this a lot more complicated than it needs to be if the loop has to be back onto the first element.
function breakLoop(list) {
var head = list.head, tail = head, len = 1;
while (tail.next != head) {
len++;
tail = tail.next;
}
tail.next = null;
console.log(len.toString());
}
Now if you may need to handle any arbitrary loop, I still have no idea what you need 3 loops for. Use an ES6 Set; most browsers now support this, I believe. I'm going to go ahead and return the length instead of logging it.
function breakLoopAnywhere(list) {
var seen = new Set, node = list.head;
while (!seen.has(node.next)) {
seen.add(node);
node = node.next;
}
node.next = null;
return seen.size;
}
If you don't have sets, you can hack it with an array, replacing has with indexOf and add with push.
If you feel you must have the ability to detect a loop vs a non-looping list without breaking it:
// takes a node, returns the node
// that points backwards on its next
function getLoopNode(node) {
var seen = new Set;
do {
seen.add(node);
} while (!seen.has(node.next) && node = node.next)
return node;
}
function detectLoop(node) {
return getLoopNode(node) != null;
}
function breakLoop(node) {
node = getLoopNode(node);
if (node) node.next = null;
}
Your detectALoop is less complicated, but it's wrong. The only loop this will detect is if node 2i loops back onto node i. But the list could be 3 elements long looping onto the start; it could be lots of numbers that aren't 2i and i. Since there are probably a lot of numbers, way too many to try them all, you can't fix this strategy. There is no clever way to find cycles in a graph that is any faster or more intuitive than the one I wrote above. As far as I know.
This variable is messed up...
var looplen = 1,i;
It looks like you want it to be a 1.
Your removeLoop code is wrong, it never terminates:
let's assume this list:
A -> B -> C -> A
with loop length 3.
You correctly find the loop length, 3, you then set ptr1 and ptr2 to the head of the list, and then call .next on ptr2 for the length of the loop + 1 times (because of <=).
// for i = 0; i <= 3
A.next -> B // i = 0
B.next -> C // i = 1
C.next -> A // i = 2
A.next -> B // i = 33
So in the end you have ptr2 = B and ptr1 = A, i.e. ptr2 === ptr1.next!
One is the next of the other, and in the while loop you advance both until one is equal to the other, but they will never be, because they always be one the next of the other!
If you change the <= to just < it works, but the second while loop is actually useless.

Why are my variables "undefined"

I am new to Javascript and I am building my very first simple game "battle ship". Now I have a very frustrating problem.
I declared a variable in the global scope, but I cannot seem to use it in my program. If I do console.log(x); it says the variable is undefined.
When the user clicks a button called "Play" I want the background color of all cells to turn back to lightblue again;
function playGame() {
x.style.backgroundColor = 'lightblue';
}
This is the error message:
Uncaught TypeError: Cannot set property 'backgroundColor' of undefined
Even if I would replace the x with document.getElementsByTagName("td"); it does not work
var tabel = document.getElementById("slagveld");
var x = document.getElementsByTagName("td");
var gekozenVakken = [];
var hit = 0;
var pogingen = 0;
function reset() {
location.reload();
}
function veranderKleur(geklikteCel) {
if (gekozenVakken.length < 3) {
geklikteCel.style.backgroundColor = 'yellow';
gekozenVakken.push(parseInt(geklikteCel.innerHTML));
}
if (gekozenVakken.length === 3) {
alert("guess the position of the ship.");
}
}
function playGame() {
geklikteCel.style.backgroundColor = 'lightblue';
}
for (var i = 0; i < tabel.rows.length; i++) {
for (var j = 0; j < tabel.rows[i].cells.length; j++) {
tabel.rows[i].cells[j].onclick = function() {
veranderKleur(this);
}
};
}
I hope someone could help me out.
GetElementsByTagName() returns an array of objects, even if there is only 1 object with that tag. Since the array itself does not have the property .style, you get an 'undefined' message when accessing sub-members of .style.
You need to select an element from that array to access its properties:
x[0].style.backgroundColor = 'lightblue';
With the [] square braces you can access any element of an array. In my example, we're accessing the first element (at index 0). Which element you need is up for you to determine.
That function returns a list of nodes, even though there's only one
use document.getElementsByTagName("td")[0].style.color= 'lightblue';
function playGame() {
x[0].style.backgroundColor = 'lightblue';
}
fiddle
If the line
var x = document.getElementsByTagName("td");
is before your <table>, that element won't exist when the line is executed.
Ensure you are adding your script at the end of your HTML document or it will return an empty array (please note that the function is called "get elements by tag name", in plural).
I assume you're running this in your browser and this is your entire code.
Problem here: You're trying to read content from the DOM, however, your DOM might not be entirely loaded at the time you try to read from it.
This is easily fixable though:
In your HTML:
<body onload="start();"></body>
And in your JS code:
function reset() {
location.reload();
}
function veranderKleur(geklikteCel) {
if (gekozenVakken.length < 3) {
geklikteCel.style.backgroundColor = 'yellow';
gekozenVakken.push(parseInt(geklikteCel.innerHTML));
}
if (gekozenVakken.length === 3) {
alert("guess the position of the ship.");
}
}
function playGame() {
geklikteCel.style.backgroundColor = 'lightblue';
}
function start() {
var tabel = document.getElementById("slagveld");
var x = document.getElementsByTagName("td");
var gekozenVakken = [];
var hit = 0;
var pogingen = 0;
for (var i = 0; i < tabel.rows.length; i++) {
for (var j = 0; j < tabel.rows[i].cells.length; j++) {
tabel.rows[i].cells[j].onclick = function() {
veranderKleur(this);
}
};
}
}
This will ensure that all your reading/executing will perform when the entire DOM was loaded.
If you're not running code in your browser, please give more details in your question.
I would guess it's because the code for initializing the variables never actually gets called. Try doing it as follows (you need jQuery for it):
$('document').ready(function(){
var tabel = document.getElementById("slagveld");
var x = document.getElementsByTagName("td");
var gekozenVakken = [];
var hit = 0;
var pogingen = 0;
});
This way as soon as your DOM is loaded into the browser the variables will get initialized.
getElementsByTagName return a list of elements with the name "td" and you don't have the property backgroundColor for the list of elements, you must use a function like foreach.
Array.prototype.forEach.call(x, function(el, i){
el.style.backgroundColor = 'yellow';
});
And each element will in "x" will have the background color yellow.
You're looking for document.getElementById

Categories