I'm attempting to make a genetic algorithm simulation in JavaScript using the P5.JS library, but i'm experiencing some issues. Here's what i have so far:
//var popS = 2;
var popu;
//var balls = [];
var target;
function setup() {
createCanvas(800, 300);
popu = new Population();
target = createVector(width - 15, height / 2);
}
function draw() {
background(50);
popu.run();
var ballsC = 0;
for (var a = 0; a < popu.balls.length; a++) {
if (popu.balls[a].done == true){
ballsC ++;
}
}
if (ballsC >= popu.popS) {
//popu = new Population();
popu.evaluate();
//popu.selection();
}
fill(255, 0, 30);
noStroke();
ellipse(target.x, target.y, 20, 20);
}
function DNA() {
this.genes = [];
this.changes = 7;//random(2, 50);
for (var a = 0; a < this.changes; a++) {
this.genes[a] = random(0, 15);
}
this.crossover = function (pB) {
var newdna = new DNA();
var mid = floor(random(0, this.genes.length));
for (var a = 0; a < this.genes.length; a++) {
if (a < mid) {
newdna.genes[a] = this.genes[a];
}else {
newdna.genes[a] = pB.genes[a];
}
}
return newdna;
}
}
function Population() {
this.balls = [];
this.popS = 50;
this.maxfit = 0;
this.matingpool = [];
for (var a = 0; a < this.popS; a++) {
this.balls[a] = new Ball();
}
this.evaluate = function() {
for (var a = 0; a < this.balls.length; a++) {
this.balls[a].calcF();
if (this.balls[a].fitness > this.maxfit) {
this.maxfit = this.balls[a].fitness;
}
}
this.matingpool = [];
for (var b = 0; b < this.balls.length; b++) {
var n = this.balls[b].fitness * 100;
for (var c = 0; c < n; c++) {
this.matingpool.push(this.balls[c]);
}
}
this.selection();
}
this.selection = function () {
var newBalls = [];
for (var a = 0; a < this.balls.length; a++) {
var parentA = this.matingpool[floor(random(0, this.matingpool.length))];
var parentB = this.matingpool[floor(random(0, this.matingpool.length))];
var child = parentA.dna.crossover(parentB.dna);
newBalls[a] = new Ball(child);
}
this.balls = newBalls;
}
this.run = function() {
for (var a = 0; a < this.balls.length; a++) {
this.balls[a].update();
this.balls[a].checkCol();
this.balls[a].show();
}
}
}
function Ball(dna) {
this.pos = createVector(10, height / 2);
this.speed = createVector(2, 2.5);
this.mul = -1;
this.time = 0;
this.a = 0;
if (dna) {
this.dna = dna;
} else {
this.dna = new DNA();
}
this.done = false;
this.fitness = 0;
this.reached;
this.update = function() {
if (this.done == false) {
if (this.time >= this.dna.genes[this.a]) {
this.a++;
this.time = 0;
this.mul *= -1;
}
this.speed.set(2, 2.5 * this.mul);
this.pos.add(this.speed);
}
}
this.show = function() {
this.time += 0.1;
fill(255, 70);
noStroke();
ellipse(this.pos.x, this.pos.y, 10, 10);
}
this.checkCol = function() {
if (this.pos.y > height || this.pos.y < 0 || this.pos.x > width) {
//print("col");
this.done = true;
}
if (dist(this.pos.x, this.pos.y, target.x, target.y) <= (10 / 2) + (20 / 2)) {
//print("done!");
this.done = true;
this.reached = true;
}
}
this.calcF = function() {
var a = dist(this.pos.x, this.pos.y, target.x, target.y);
var b = this.dna.genes.length;
var c = 0;
if (this.reached){
c = 1;
}
this.fitness = map(map(a, 0, width, 1, 0) + map(b, 2, 50, 1, 0) + c, 0, 3, 0, 1);
}
}
This is the most essential part of the code:
var popu;
function setup() {
createCanvas(800, 300);
popu = new Population();
}
function draw() {
background(50);
//popu = new Population();
popu.evaluate();
//popu.selection();
}
function DNA() {
this.genes = [];
this.changes = 7; //random(2, 50);
for (var a = 0; a < this.changes; a++) {
this.genes[a] = random(0, 15);
}
this.crossover = function(pB) {
var newdna = new DNA();
var mid = floor(random(0, this.genes.length));
for (var a = 0; a < this.genes.length; a++) {
if (a < mid) {
newdna.genes[a] = this.genes[a];
} else {
newdna.genes[a] = pB.genes[a];
}
}
return newdna;
}
}
function Population() {
this.balls = [];
this.popS = 50;
this.maxfit = 0;
this.matingpool = [];
for (var a = 0; a < this.popS; a++) {
this.balls[a] = new Ball();
}
this.evaluate = function() {
this.matingpool = [];
for (var b = 0; b < this.balls.length; b++) {
var n = this.balls[b].fitness * 100;
for (var c = 0; c < n; c++) {
this.matingpool.push(this.balls[c]);
}
}
this.selection();
}
this.selection = function() {
var newBalls = [];
for (var a = 0; a < this.balls.length; a++) {
var parentA = this.matingpool[floor(random(0, this.matingpool.length))];
var parentB = this.matingpool[floor(random(0, this.matingpool.length))];
var child = parentA.dna.crossover(parentB.dna);
newBalls[a] = new Ball(child);
}
this.balls = newBalls;
}
}
function Ball(dna) {
this.pos = createVector(10, height / 2);
this.speed = createVector(2, 2.5);
this.mul = -1;
this.time = 0;
this.a = 0;
if (dna) {
this.dna = dna;
} else {
this.dna = new DNA();
}
this.done = false;
this.fitness = 0;
this.reached;
}
So whenever it gets to here:
this.selection = function () {
var newBalls = [];
for (var a = 0; a < this.balls.length; a++) {
var parentA = random(this.matingpool);
var parentB = random(this.matingpool);
var child = parentA.dna.crossover(parentB.dna);
newBalls[a] = new Ball(child);
}
this.balls = newBalls;
}
i get the error: "Cannot read property 'dna' of undefined", why on earth is this happening?? When i use the debugger in chrome i can clearly see that matingpool has 2000 elements but when i try to get a random one it returns "undefined".
var parentA = random(this.matingpool);
var parentB = random(this.matingpool);
The weird thing is that parentB works, but parentA dosn't.
Any help is much appreciated. Entire code running here: http://codepen.io/felipe_mare/pen/bgOYMN
If it helps, i sometimes get the error: "Cannot read property '0' of undefined" instead, at line 138
this.update = function() {
if (this.done == false) {
//line 138
if (this.time >= this.dna.genes[this.a]) {
//line 138
this.a++;
this.time = 0;
this.mul *= -1;
}
this.speed.set(2, 2.5 * this.mul);
this.pos.add(this.speed);
}
}
In the future, please please please try to narrow your questions down to an MCVE. I understand that this was a complicated problem to debug, but you'll have much better luck if you try to narrow your problem down to a minimal (under 20 lines) example. Most of the time, you'll end up finding your error in the process of creating the MCVE.
But your problem is actually when you create the matingpool array, here:
this.matingpool = [];
for (var b = 0; b < this.balls.length; b++) {
var n = this.balls[b].fitness * 100;
for (var c = 0; c < n; c++) {
this.matingpool.push(this.balls[c]);
}
}
If I add a print statement inside the inner for loop, like this:
this.matingpool = [];
for (var b = 0; b < this.balls.length; b++) {
var n = this.balls[b].fitness * 100;
for (var c = 0; c < n; c++) {
console.log("pushing: " + this.balls[c]);
this.matingpool.push(this.balls[c]);
}
}
Then I see that you're pushing undefined into the array a bunch of times:
(1178) pushing: [object Object]
(3) pushing: undefined
(482) pushing: [object Object]
(3) pushing: undefined
(216) pushing: [object Object]
Then you choose randomly from this array, which is why your error shows up in random places in your code.
You're going to have to debug this further to figure out why that's happening- it seems weird that you're looping based on a fitness instead of an array length, but I don't really understand the code well enough to be sure. In any case, hopefully this gets you on the right track.
Related
I'm new to both languages, and I'm trying to convert this program I found on github and edited, to p5.js so I can include it in a webpage. I tried following guides and replacing void() with function(), int i with var i etc.. but there seems to be something wrong. The first code is the original .pde and the second one is my attempt at converting it. Many thanks!
final int STAGE_WIDTH = 1200;
final int STAGE_HEIGHT = 950;
final int NB_PARTICLES = 60000;
final float MAX_PARTICLE_SPEED = 5;
final int MIN_LIFE_TIME = 20;
final int MAX_LIFE_TIME = 80;
final String IMAGE_PATH = "starrynight.jpg";
myVector tabParticles[];
float particleSize = 1.2;
PImage myImage;
int imageW;
int imageH;
color myPixels[];
FlowField ff;
GUI gui;
void setup()
{
size(1200, 950, P3D);
background(0);
initializeImage();
initializeParticles();
ff = new FlowField(5);
gui = new GUI(this);
gui.setup();
}
void initializeImage()
{
myImage = loadImage(IMAGE_PATH);
imageW = myImage.width;
imageH = myImage.height;
myPixels = new color[imageW * imageH];
myImage.loadPixels();
myPixels = myImage.pixels;
image(myImage, 0, 0);
}
void setParticle(int i) {
tabParticles[i] = new myVector((int)random(imageW), (int)random(imageH));
tabParticles[i].prevX = tabParticles[i].x;
tabParticles[i].prevY = tabParticles[i].y;
tabParticles[i].count = (int)random(MIN_LIFE_TIME, MAX_LIFE_TIME);
tabParticles[i].myColor = myPixels[(int)(tabParticles[i].y)*imageW + (int)(tabParticles[i].x)];
}
void initializeParticles()
{
tabParticles = new myVector[NB_PARTICLES];
for (int i = 0; i < NB_PARTICLES; i++)
{
setParticle(i);
}
}
void draw()
{
ff.setRadius(gui.getR());
ff.setForce(gui.getF());
particleSize = gui.getS();
float vx;
float vy;
PVector v;
for (int i = 0; i < NB_PARTICLES; i++)
{
tabParticles[i].prevX = tabParticles[i].x;
tabParticles[i].prevY = tabParticles[i].y;
v = ff.lookup(tabParticles[i].x, tabParticles[i].y);
vx = v.x;
vy = v.y;
vx = constrain(vx, -MAX_PARTICLE_SPEED, MAX_PARTICLE_SPEED);
vy = constrain(vy, -MAX_PARTICLE_SPEED, MAX_PARTICLE_SPEED);
tabParticles[i].x += vx;
tabParticles[i].y += vy;
tabParticles[i].count--;
if ((tabParticles[i].x < 0) || (tabParticles[i].x > imageW-1) ||
(tabParticles[i].y < 0) || (tabParticles[i].y > imageH-1) ||
tabParticles[i].count < 0) {
setParticle(i);
}
strokeWeight(1.5*particleSize);
stroke(tabParticles[i].myColor, 250);
line(tabParticles[i].prevX, tabParticles[i].prevY, tabParticles[i].x, tabParticles[i].y);
}
ff.updateField();
}
void mouseDragged() {
if(mouseX>950 && mouseY>830) return;
ff.onMouseDrag();
}
void keyPressed() {
//if (key =='s' || key == 'S') {
// ff.saveField();
//}
}
class myVector extends PVector
{
myVector (float p_x, float p_y) {
super(p_x, p_y);
}
float prevX;
float prevY;
int count;
color myColor;
}
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
class FlowField {
PVector[][] field;
PVector[][] tempField;
int cols, rows;
int resolution;
int affectRadius;
float force;
File file = new File(dataPath("field.txt"));
FlowField(int r) {
resolution = r;
cols = 1200 / resolution;
rows = 950 / resolution;
field = new PVector[cols][rows];
tempField = new PVector[cols][rows];
init();
affectRadius = 3;
force = 1;
}
void setRadius(int r) {
affectRadius = r;
}
void setForce(float f) {
force = f;
}
void init() {
try {
for (int i=0; i<cols; i++) {
for (int j=0; j<rows; j++) {
tempField[i][j] = new PVector(0, 0);
}
}
readField();
}
catch(Exception e) {
for (int i=0; i<cols; i++) {
for (int j=0; j<rows; j++) {
field[i][j] = new PVector(0, 0);
}
}
}
}
PVector lookup(float x, float y) {
int column = int(constrain(x/resolution, 0, cols-1));
int row = int(constrain(y/resolution, 0, rows-1));
return PVector.add(field[column][row],tempField[column][row]);
}
void drawBrush() {
pushStyle();
noFill();
stroke(255, 255, 255);
ellipse(mouseX, mouseY, affectRadius*10, affectRadius*10);
popStyle();
}
void drawField(float x, float y, PVector v) {
int column = int(constrain(x/resolution, 0, cols-1));
int row = int(constrain(y/resolution, 0, rows-1));
for (int i=-affectRadius; i<=affectRadius; i++) {
for (int j=-affectRadius; j<=affectRadius; j++) {
if (i*i+j*j<affectRadius*affectRadius) {
try {
tempField[column+i][row+j].add(v).mult(0.9);
}
catch(Exception e) {
}
}
}
}
}
void updateField(){
for (int i=0; i<cols; i++) {
for (int j=0; j<rows; j++) {
tempField[i][j].mult(0.992);
}
}
}
void onMouseDrag() {
PVector direc = new PVector(mouseX-pmouseX, mouseY-pmouseY).normalize();
drawField(pmouseX, pmouseY, direc.mult(force));
}
void saveField() {
try {
FileWriter out = new FileWriter(file);
for (int i=0; i<cols; i++) {
for (int j=0; j<rows; j++) {
out.write(field[i][j].x+","+field[i][j].y+"\t");
}
out.write("\r\n");
}
out.close();
}
catch(Exception e) {
}
}
void readField() throws IOException {
try {
BufferedReader in = new BufferedReader(new FileReader(file));
String line;
for (int i = 0; (line = in.readLine()) != null; i++) {
String[] temp = line.split("\t");
for (int j=0; j<temp.length; j++) {
String[] xy = temp[j].split(",");
float x = Float.parseFloat(xy[0]);
float y = Float.parseFloat(xy[1]);
field[i][j] = new PVector(x, y);
}
}
in.close();
}
catch(Exception e) {
throw new IOException("no field.txt");
}
}
}
import controlP5.*;
class GUI {
ControlP5 cp5;
Slider sliderR;
Slider sliderF;
Slider sliderS;
GUI(PApplet thePApplet){
cp5 = new ControlP5(thePApplet);
}
void setup(){
cp5.setColorBackground(0x141414);
sliderR = cp5.addSlider("Radius")
.setPosition(980,890)
.setRange(1,20)
.setValue(12).setSize(150,25);
sliderF = cp5.addSlider("Force")
.setPosition(980,918)
.setRange(0.1,0.5)
.setValue(0.3).setSize(150,25);
sliderS = cp5.addSlider("Particle Size")
.setPosition(980,862)
.setRange(0.8,2)
.setValue(1.5).setSize(150,25);
}
int getR(){
return int(sliderR.getValue());
}
float getF(){
return sliderF.getValue();
}
float getS(){
return sliderS.getValue();
}
}
final var STAGE_WIDTH = 1200;
final var STAGE_HEIGHT = 950;
final var NB_PARTICLES = 60000;
final let MAX_PARTICLE_SPEED = 5;
final var MIN_LIFE_TIME = 20;
final var MAX_LIFE_TIME = 80;
final let IMAGE_PATH = "starrynight.jpg";
myVector tabParticles[];
let particleSize = 1.2;
PImage myImage;
var imageW;
var imageH;
color myPixels[];
FlowField ff;
GUI gui;
function setup()
{
var canvas = createCanvas(1200, 950, P3D);
canvas.parent('canvasForHTML');
background(0);
initializeImage();
initializeParticles();
ff = new FlowField(5);
gui = new GUI(this);
gui.setup();
}
function preload() { img = loadImage('data/starrynight.jpg');
}
function initializeImage()
{ imageW = myImage.width;
imageH = myImage.height;
myPixels = new color[imageW * imageH];
myImage.loadPixels();
myPixels = myImage.pixels;
image(myImage, 0, 0);
}
function setParticle(var i) {
tabParticles[i] = new myVector((var)random(imageW), (var)random(imageH));
tabParticles[i].prevX = tabParticles[i].x;
tabParticles[i].prevY = tabParticles[i].y;
tabParticles[i].count = (var)random(MIN_LIFE_TIME, MAX_LIFE_TIME);
tabParticles[i].myColor = myPixels[(var)(tabParticles[i].y)*imageW + (var)(tabParticles[i].x)];
}
function initializeParticles()
{
tabParticles = new myVector[NB_PARTICLES];
for (var i = 0; i < NB_PARTICLES; i++)
{
setParticle(i);
}
}
function draw()
{
ff.setRadius(gui.getR());
ff.setForce(gui.getF());
particleSize = gui.getS();
let vx;
let vy;
PVector v;
for (var i = 0; i < NB_PARTICLES; i++)
{
tabParticles[i].prevX = tabParticles[i].x;
tabParticles[i].prevY = tabParticles[i].y;
v = ff.lookup(tabParticles[i].x, tabParticles[i].y);
vx = v.x;
vy = v.y;
vx = constrain(vx, -MAX_PARTICLE_SPEED, MAX_PARTICLE_SPEED);
vy = constrain(vy, -MAX_PARTICLE_SPEED, MAX_PARTICLE_SPEED);
tabParticles[i].x += vx;
tabParticles[i].y += vy;
tabParticles[i].count--;
if ((tabParticles[i].x < 0) || (tabParticles[i].x > imageW-1) ||
(tabParticles[i].y < 0) || (tabParticles[i].y > imageH-1) ||
tabParticles[i].count < 0) {
setParticle(i);
}
strokeWeight(1.5*particleSize);
stroke(tabParticles[i].myColor, 250);
line(tabParticles[i].prevX, tabParticles[i].prevY, tabParticles[i].x, tabParticles[i].y);
}
ff.updateField();
}
function mouseDragged() {
if(mouseX>950 && mouseY>830) return;
ff.onMouseDrag();
}
function keyPressed() {
//if (key =='s' || key == 'S') {
// ff.saveField();
//}
}
class myVector extends PVector
{
myVector (let p_x, let p_y) {
super(p_x, p_y);
}
let prevX;
let prevY;
var count;
color myColor;
}
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
class FlowField {
PVector[][] field;
PVector[][] tempField;
var cols, rows;
var resolution;
var affectRadius;
let force;
File file = new File(dataPath("field.txt"));
FlowField(var r) {
resolution = r;
cols = 1200 / resolution;
rows = 950 / resolution;
field = new PVector[cols][rows];
tempField = new PVector[cols][rows];
init();
affectRadius = 3;
force = 1;
}
function setRadius(var r) {
affectRadius = r;
}
function setForce(let f) {
force = f;
}
function init() {
try {
for (var i=0; i<cols; i++) {
for (var j=0; j<rows; j++) {
tempField[i][j] = new PVector(0, 0);
}
}
readField();
}
catch(Exception e) {
for (var i=0; i<cols; i++) {
for (var j=0; j<rows; j++) {
field[i][j] = new PVector(0, 0);
}
}
}
}
PVector lookup(let x, let y) {
var column = var(constrain(x/resolution, 0, cols-1));
var row = var(constrain(y/resolution, 0, rows-1));
return PVector.add(field[column][row],tempField[column][row]);
}
function drawBrush() {
pushStyle();
noFill();
stroke(255, 255, 255);
ellipse(mouseX, mouseY, affectRadius*10, affectRadius*10);
popStyle();
}
function drawField(let x, let y, PVector v) {
var column = var(constrain(x/resolution, 0, cols-1));
var row = var(constrain(y/resolution, 0, rows-1));
for (var i=-affectRadius; i<=affectRadius; i++) {
for (var j=-affectRadius; j<=affectRadius; j++) {
if (i*i+j*j<affectRadius*affectRadius) {
try {
tempField[column+i][row+j].add(v).mult(0.9);
}
catch(Exception e) {
}
}
}
}
}
function updateField(){
for (var i=0; i<cols; i++) {
for (var j=0; j<rows; j++) {
tempField[i][j].mult(0.992);
}
}
}
function onMouseDrag() {
PVector direc = new PVector(mouseX-pmouseX, mouseY-pmouseY).normalize();
drawField(pmouseX, pmouseY, direc.mult(force));
}
function saveField() {
try {
FileWriter out = new FileWriter(file);
for (var i=0; i<cols; i++) {
for (var j=0; j<rows; j++) {
out.write(field[i][j].x+","+field[i][j].y+"\t");
}
out.write("\r\n");
}
out.close();
}
catch(Exception e) {
}
}
function readField() throws IOException {
try {
BufferedReader in = new BufferedReader(new FileReader(file));
let line;
for (var i = 0; (line = in.readLine()) != null; i++) {
let[] temp = line.split("\t");
for (var j=0; j<temp.length; j++) {
let[] xy = temp[j].split(",");
let x = let.parselet(xy[0]);
let y = let.parselet(xy[1]);
field[i][j] = new PVector(x, y);
}
}
in.close();
}
catch(Exception e) {
throw new IOException("no field.txt");
}
}
}
import controlP5.*;
class GUI {
ControlP5 cp5;
Slider sliderR;
Slider sliderF;
Slider sliderS;
GUI(PApplet thePApplet){
cp5 = new ControlP5(thePApplet);
}
function setup(){
cp5.setColorBackground(0x141414);
sliderR = cp5.addSlider("Radius")
.setPosition(980,890)
.setRange(1,20)
.setValue(12).setSize(150,25);
sliderF = cp5.addSlider("Force")
.setPosition(980,918)
.setRange(0.1,0.5)
.setValue(0.3).setSize(150,25);
sliderS = cp5.addSlider("Particle Size")
.setPosition(980,862)
.setRange(0.8,2)
.setValue(1.5).setSize(150,25);
}
var getR(){
return var(sliderR.getValue());
}
let getF(){
return sliderF.getValue();
}
let getS(){
return sliderS.getValue();
}
}
I felt like doing nothing this evening, so here you go:
Also, I recommend getting the "Better Comments" extension/plugin for your code editor of choice, since I used those here a lot
const STAGE_WIDTH = 1200;
const STAGE_HEIGHT = 950;
const NB_PARTICLES = 60000;
const MAX_PARTICLE_SPEED = 5;
const MIN_LIFE_TIME = 20;
const MAX_LIFE_TIME = 80;
const IMAGE_PATH = "starrynight.jpg";
let tabParticles = [];
let particleSize = 1.2;
let myImage;
let imageW;
let imageH;
let myPixels = [];
let ff;
let gui;
function setup()
{
size(1200, 950, WEBGL);
background(0);
initializeImage();
initializeParticles();
ff = new FlowField(5);
// ! CHANGE THIS AND ALL OF THE OTHER GUI STUFF THAT COME AFTER IT!
// gui = new GUI(this);
// gui.setup();
}
function initializeImage()
{
myImage = loadImage(IMAGE_PATH);
imageW = myImage.width;
imageH = myImage.height;
myPixels = new color[imageW * imageH]; // ? dunno
// myImage.loadPixels();
// myPixels = myImage.pixels;
image(myImage, 0, 0);
}
function setParticle(i) {
tabParticles[i] = new myVector(random(imageW), random(imageH));
tabParticles[i].prevX = tabParticles[i].x;
tabParticles[i].prevY = tabParticles[i].y;
tabParticles[i].count = random(MIN_LIFE_TIME, MAX_LIFE_TIME);
tabParticles[i].myColor = myPixels[(int)(tabParticles[i].y)*imageW + (int)(tabParticles[i].x)];
}
function initializeParticles()
{
// tabParticles = new myVector[NB_PARTICLES];
for(let i = 0; i < NB_PARTICLES; i ++)
tabParticles.push(new myVector())
for (let i = 0; i < NB_PARTICLES; i++)
{
setParticle(i);
}
}
function draw()
{
ff.setRadius(gui.getR());
ff.setForce(gui.getF());
particleSize = gui.getS();
let vx;
let vy;
let v;
for (let i = 0; i < NB_PARTICLES; i++)
{
tabParticles[i].prevX = tabParticles[i].x;
tabParticles[i].prevY = tabParticles[i].y;
v = ff.lookup(tabParticles[i].x, tabParticles[i].y);
vx = v.x;
vy = v.y;
vx = constrain(vx, -MAX_PARTICLE_SPEED, MAX_PARTICLE_SPEED);
vy = constrain(vy, -MAX_PARTICLE_SPEED, MAX_PARTICLE_SPEED);
tabParticles[i].x += vx;
tabParticles[i].y += vy;
tabParticles[i].count--;
if ((tabParticles[i].x < 0) || (tabParticles[i].x > imageW-1) ||
(tabParticles[i].y < 0) || (tabParticles[i].y > imageH-1) ||
tabParticles[i].count < 0) {
setParticle(i);
}
strokeWeight(1.5*particleSize);
stroke(tabParticles[i].myColor, 250);
line(tabParticles[i].prevX, tabParticles[i].prevY, tabParticles[i].x, tabParticles[i].y);
}
ff.updateField();
}
function mouseDragged() {
if(mouseX>950 && mouseY>830) return;
ff.onMouseDrag();
}
function keyPressed() {
//if (key =='s' || key == 'S') {
// ff.saveField();
//}
}
class myVector extends PVector
{
constructor (p_x, p_y) {
super(p_x, p_y);
this.prevX
this.prevY
this.count
this.myColor
}
}
class FlowField {
constructor(r) {
this.field; // PVector[][]
this.tempField; // PVector[][]
this.cols; this.rows; // int
this.resolution; // int
this.affectRadius; // int
this.force; // float
this.file = new File(dataPath("field.txt")); // File
// ! You'll need to have a preload loadStrings(filepath) or fetch(filename).then(blob => blob.text()).then(text => ... )
// ! can't be bothered to do this right now
throw "Ult1: change this!!! also delete this line (just incase: ~129th line)"
resolution = r;
cols = 1200 / resolution;
rows = 950 / resolution;
field = new PVector[cols][rows];
tempField = new PVector[cols][rows];
init();
affectRadius = 3;
force = 1;
}
setRadius(r) {
affectRadius = r;
}
setForce(f) {
force = f;
}
// FROM HERE ON I CONVERTED IT WHILE HALF ASLEEP (11pm)
init() {
try {
for (let i=0; i<cols; i++) {
for (let j=0; j<rows; j++) {
tempField[i][j] = createVector()
}
}
readField();
}
catch(e) {
for (let i=0; i<cols; i++) {
for (let j=0; j<rows; j++) {
field[i][j] = createVector()
}
}
}
}
lookup(x, y) {
let column = int(constrain(x/resolution, 0, cols-1));
let row = int(constrain(y/resolution, 0, rows-1));
return p5.Vector.add(field[column][row],tempField[column][row]);
}
drawBrush() {
pushStyle();
noFill();
stroke(255, 255, 255);
ellipse(mouseX, mouseY, affectRadius*10, affectRadius*10);
popStyle();
}
drawField(x, y, v) {
let column = int(constrain(x/resolution, 0, cols-1));
let row = int(constrain(y/resolution, 0, rows-1));
for (let i=-affectRadius; i<=affectRadius; i++) {
for (let j=-affectRadius; j<=affectRadius; j++) {
if (i*i+j*j<affectRadius*affectRadius) {
try {
tempField[column+i][row+j].add(v).mult(0.9);
}
catch(e) {
}
}
}
}
}
updateField(){
for (let i=0; i<cols; i++) {
for (let j=0; j<rows; j++) {
tempField[i][j].mult(0.992);
}
}
}
onMouseDrag() {
let direc = createVector(mouseX-pmouseX, mouseY-pmouseY).normalize()
drawField(pmouseX, pmouseY, direc.mult(force));
}
saveField() {
try {
// FileWriter out = new FileWriter(file);
throw "FileWriter doesn't exist in Javascript, line: 215"
// ! this doesn't exist! in javascript, I don't remember how to do this, but you can just search it on Google
for (let i=0; i<cols; i++) {
for (let j=0; j<rows; j++) {
out.write(field[i][j].x+","+field[i][j].y+"\t");
}
out.write("\r\n");
}
out.close();
}
catch(e) {
}
}
readField() {
throw "once again, BufferedReader is just not a thing, but it's for file reading, so you can just loadString(\"file\") or fetch... line: 230"
try {
let _in = new BufferedReader(new FileReader(file));
let line;
for (let i = 0; (line = _in.readLine()) != null; i++) {
let temp = line.split("\t");
for (let j=0; j<temp.length; j++) {
let xy = temp[j].split(",");
let x = Float.parseFloat(xy[0]);
let y = Float.parseFloat(xy[1]);
field[i][j] = createVector(x, y);
}
}
_in.close();
}
catch(e) {
throw new IOException("no field.txt");
}
}
}
// I think you should just do this with html to be honest
// copy this into your body (below the <script src="sketch.js"></script>, or above it):
/*
<div id="GUI">
<label for="Radius">Radius</label>
<input type="range" name="Radius" id="slider-radius" min="1" max="20" step="0.5" value="10">
<br>
<label for="Force">Force</label>
<input type="range" name="Force" id="slider-force" min="0.1" max="0.5" step="0.01" value="0.3">
<br>
<label for="Particle-size">Particle size</label>
<input type="range" name="Particle-size" id="slider-particle-size" min="0.8" max="2" step="0.05" value="1.5">
</div>
<style>
html, body {
background-color: #141414;
}
label {
color: #ccc;
}
</style>
*/
// color: #ccc is the same as text-color = #CCCCCC in some other language, maybe...
class GUI {
constructor(){
throw "don't declare the GUI class, instead do GUI.getR(), GUI.getF() ... line: 288, you should be able to see line # in your console"
}
static getR(){
return document.getElementById("slider-radius").value;
}
static getF(){
return document.getElementById("slider-force").value
}
static getS(){
return document.getElementById("slider-particle-size").value
}
}
// static = same between ALL the classes(instances) of a class thing, so:
// class A { static x = 7; this.y = 5 }
// * console.log(A.x) -> 7
// ! console.log(A.y) -> probably null, since you need to do console.log(new A().y)
// here I have it to keep the GUI class, but there is no need to keep this stuff
You will still need to do A LOT of work to get this going, like translating classes, for example class myVector extends PVector {...}. In p5.js there is no PVector, but I'm pretty sure there's p5.Vector though, so class myVector extends p5.Vector might work. File reading and writing will also be messed up, since JavaScript doesn't have the whole new File() and all the stuff like that.
You will also need to deal with CORS, good luck! I also changed most of the GUI stuff to .html stuff and a static class, bit hard words there, but can't really change them to anything.
Anyways, I probably made mistakes here!
It's 11:40 pm here by now, so yeah! this is very more or less transferrrr
Sorry I am bad at asking questions, if you don't understand what I am asking please let me know
let node = this.createSvgNode("rect", {
'data-id': section.id || '',
x: section.x,
y: section.y,
width: section.width,
height: section.height,
fill: section.backgroundColor || "#EEEEEE"
});
let thisObject = this;
let paths = thisObject.findPaths(7, 3) // Doesn't work
node.addEventListener("click", function (e) {
let paths = thisObject.findPaths(7, 3) // works
});
I don't understand why let paths = thisObject.findPaths(7, 3) works when it is inside the event listener and doesn't when it is outside of the event listener. isn't it the same?
btw this is the findPaths function:
findPaths: function (startId, endId) {
let paths = [];
let startDoors = doors[startId];
let endDoors = doors[endId];
for (let i = 0; i < startDoors.length; i++) {
let startingPoint = this.findPointByCoordinates(startDoors[i]);
// console.log("Starting Point: " + JSON.stringify(startingPoint));
for (let j = 0; j < doors[endId].length; j++) {
let endingPoint = this.findPointByCoordinates(endDoors[j]);
// console.log("Ending Point: " + JSON.stringify(endingPoint));
let potentialPath = this.recursiveIterationOfPoints([startingPoint], endingPoint);
// console.log(potentialPath);
paths = paths.concat(potentialPath);
}
}
for (let id in paths) {
paths[id] = this.linkRoomsWithPath(paths[id], startId, endId);
}
return paths;
},
I get this error when I put let paths = thisObject.findPaths(7, 3) above the event listener:
Uncaught TypeError: Cannot read property 'length' of undefined
here is the full code
(function (global) {
var IndoorMaps = function (options) {
return new IndoorMaps.init(options);
};
let svgRootNode;
let doors = {};
let hallwayPoints = {};
let currentZIndex = 0;
let validZIndexes = [0];
let showHallwayPoints = false;
//let svgDimensions = {};
let floorPlan = [];
let mapSelection = null;
IndoorMaps.init = function (options) {
this.parseConfiguration(options || {});
this.parseFloorPlan(options.floorSections || {});
this.parseHallwayPoints(options.hallway || {});
//svgDimensions = this.calculateSVGWidthAndHeight();
svgRootNode = this.createSvgNode("svg", {
width: '100%',
height: '100%'
});
this.appendToBody(svgRootNode);
// Render the Map
this.drawMap(floorPlan[currentZIndex] || {});
if (showHallwayPoints) {
this.displayHallwayPoints(options.hallway || {});
}
return svgRootNode;
};
IndoorMaps.init.prototype = {
createSvgNode: function (elementName, attributes = {}, value) {
if (elementName === undefined) {
throw "Element name not found!";
}
let node = document.createElementNS("http://www.w3.org/2000/svg", elementName);
for (let attributeKey in attributes) {
node.setAttribute(attributeKey, attributes[attributeKey]);
}
if (value !== undefined) {
node.innerHTML = value;
}
return node;
},
appendToBody: function (node) {
window.document.body.appendChild(node);
},
draw: function (node) {
let panZoom = svgRootNode.querySelector('.svg-pan-zoom_viewport');
if (!panZoom) {
svgRootNode.append(node);
} else {
panZoom.append(node);
}
},
addDoors: function(roomId, doorPoints) {
doors[roomId] = doorPoints;
for (let i = 0; i < doorPoints.length; i++) {
let coordinates = doorPoints[i];
let attributes = {
x: coordinates.x,
y: coordinates.y,
width: coordinates.width || 0,
height: coordinates.height || 0,
fill: "#FF0000"
};
if (coordinates.width > coordinates.height) {
attributes.x -= coordinates.width / 2;
attributes.y -= coordinates.height;
}
if (coordinates.height > coordinates.width) {
attributes.x -= coordinates.width;
attributes.y -= coordinates.height / 2;
}
let rect = this.createSvgNode("rect", attributes);
this.draw(rect);
}
},
drawMap: function (floorSections) {
for (let i = 0; i < floorSections.length; i++) {
let section = floorSections[i];
if (
section.x === undefined
|| section.y === undefined
|| section.width === undefined
|| section.height === undefined
) {
throw "The x,y coordinates and the width and height are required fields.";
}
let node = this.createSvgNode("rect", {
'data-id': section.id || '',
x: section.x,
y: section.y,
width: section.width,
height: section.height,
fill: section.backgroundColor || "#EEEEEE"
});
let thisObject = this;
node.addEventListener("click", function (e) {
if (mapSelection === null) {
thisObject.removeRouteIndicators();
mapSelection = this;
this.classList.add('selected');
} else {
console.log(mapSelection.dataset.id + " : " + this.dataset.id);
let paths = thisObject.findPaths(mapSelection.dataset.id, this.dataset.id);
let shortestPath = thisObject.findShortestPath(paths);
thisObject.drawPath(shortestPath);
mapSelection = null;
this.classList.add('destination');
}
});
this.draw(node);
this.addDoors(section.id, section.doors);
if (section.label === undefined) {
continue;
}
if (section.label.text === undefined) {
throw "The text must be included for the label to be shown. Set label as null if you do not wish to display a label.";
}
xCoordinate = section.x + (section.label.x || 0);
yCoordinate = section.y + (section.label.y || 0);
let attributes = {
'x': xCoordinate,
'y': yCoordinate,
'fill': section.label.color || '#333333',
'font-family': section.label.fontStyle || 'Verdana',
'font-size': section.label.fontSize || '10'
};
if (section.label.alignment === undefined) {
section.label.alignment = "center|center";
}
if (section.label.alignment !== undefined) {
switch (section.label.alignment) {
case "center|center":
attributes['text-anchor'] = "middle";
attributes['dominant-baseline'] = "middle";
attributes['x'] = (section.width / 2) + section.x;
attributes['y'] = (section.height / 2) + section.y;
break;
case "horizontal_center":
attributes['text-anchor'] = "middle";
attributes['x'] = (section.width / 2) + section.x;
break;
case "vertical_center":
attributes['dominant-baseline'] = "middle";
attributes['y'] = (section.height / 2) + section.y;
break;
default:
throw "Alignment mode requested was not found.";
}
}
let textNode = this.createSvgNode("text", attributes, section.label.text);
this.draw(textNode);
}
},
drawPath: function(path) {
for (let i = 0; i < (path.length - 1); i++) {
let lineNode = this.createSvgNode('line', {
x1: path[i].x,
y1: path[i].y,
x2: path[i + 1].x,
y2: path[i + 1].y,
stroke: "green",
'data-type': "route"
});
this.draw(lineNode);
}
},
removeRouteIndicators: function () {
let nodes = svgRootNode.querySelectorAll('[data-type="route"]');
let panZoom = svgRootNode.querySelector('.svg-pan-zoom_viewport');
for (let index = 0; index < nodes.length; index++) {
if (!panZoom) {
svgRootNode.removeChild(nodes[index]);
} else {
panZoom.removeChild(nodes[index]);
}
}
nodes = svgRootNode.getElementsByClassName('selected');
for (let index = 0; index < nodes.length; index++) {
nodes[index].classList.remove('selected');
}
nodes = svgRootNode.getElementsByClassName('destination');
for (let index = 0; index < nodes.length; index++) {
nodes[index].classList.remove('destination');
}
},
displayHallwayPoints: function (hallwayNodes) {
for (let i = 0; i < hallwayNodes.length; i++) {
this.draw(
this.createSvgNode("circle", {
cx: hallwayNodes[i].x,
cy: hallwayNodes[i].y,
r: 2,
fill: hallwayNodes[i].fill || "black",
'data-id': hallwayNodes[i].id
})
);
}
},
findPaths: function (startId, endId) {
let paths = [];
let startDoors = doors[startId];
let endDoors = doors[endId];
for (let i = 0; i < startDoors.length; i++) {
let startingPoint = this.findPointByCoordinates(startDoors[i]);
console.log("Starting Point: " + JSON.stringify(startingPoint));
for (let j = 0; j < doors[endId].length; j++) {
let endingPoint = this.findPointByCoordinates(endDoors[j]);
console.log("Ending Point: " + JSON.stringify(endingPoint));
let potentialPath = this.recursiveIterationOfPoints([startingPoint], endingPoint);
console.log(potentialPath);
paths = paths.concat(potentialPath);
}
}
for (let id in paths) {
paths[id] = this.linkRoomsWithPath(paths[id], startId, endId);
}
return paths;
},
recursiveIterationOfPoints: function(path, end) {
let results = [];
let current = path[path.length - 1];
console.log(current);
if (current.id === end.id) {
return [path];
}
for (let i = 0; i < current.connected.length; i++) {
let nextPoint = hallwayPoints[current.connected[i]];
let found = false;
path.forEach( function (point, index) {
if (point.id === nextPoint.id) {
found = true;
}
});
if (found)
continue;
var newPath = path.slice();
newPath.push(nextPoint);
results = results.concat(this.recursiveIterationOfPoints(newPath, end));
}
return results;
},
findPointByCoordinates: function (coordinates) {
for (let id in hallwayPoints) {
let point = hallwayPoints[id];
if (point.x === coordinates.x && point.y === coordinates.y) {
return point;
}
}
},
findActualCoordinatesOfDoorByCoordinates: function (coordinates, roomId) {
let validDoors = doors[roomId];
for (let id in validDoors) {
if (validDoors[id].x === coordinates.x && validDoors[id].y === coordinates.y) {
return validDoors[id].actual;
}
}
},
parseHallwayPoints: function (points) {
for (let i = 0; i < points.length; i++) {
hallwayPoints[points[i].id] = points[i];
}
},
findShortestPath: function(paths) {
if (paths.length === 1)
return paths[0];
// Set benchmark range
let shortestDistance = this.calculateDistanceForPath(paths[0]);
let shortestPath = paths[0];
// Skip the first since it's already calculated.
for (let i = 1; i < paths.length; i++) {
let distance = this.calculateDistanceForPath(paths[i]);
if (distance < shortestDistance) {
shortestDistance = distance;
shortestPath = paths[i];
}
}
return shortestPath;
},
calculateDistanceForPath: function(path) {
let totalDistance = 0;
for (let i = 0; i < (path.length - 1); i++) {
// Formula: sqrt[(x0 - x1)^2 + (y0 - y1)^2]
totalDistance += Math.sqrt(Math.pow(path[i].x - path[i + 1].x, 2) + Math.pow(path[i].y - path[i + 1].y, 2));
}
return totalDistance;
},
linkRoomsWithPath: function (path, startId, endId) {
let first = this.findActualCoordinatesOfDoorByCoordinates(path[0], startId);
let last = this.findActualCoordinatesOfDoorByCoordinates(path[path.length - 1], endId);
path.unshift(first);
path.push(last);
return path;
},
parseConfiguration: function (options) {
currentZIndex = options.config.defaultZIndex || 0;
validZIndexes = options.config.validZIndexes || [0];
showHallwayPoints = options.config.showHallwayPoints || false;
},
parseFloorPlan: function (floorLayout) {
for (let i in floorLayout) {
if (floorLayout[i].z === undefined) {
floorLayout[i].z = 0;
}
if (!(floorLayout[i].z in floorPlan)) {
floorPlan[floorLayout[i].z] = [];
}
floorPlan[floorLayout[i].z].push(floorLayout[i]);
}
},
calculateSVGWidthAndHeight: function () {
let dimensions = {
width: 0,
height: 0
};
let floorLayout = floorPlan[currentZIndex];
let first = true;
for (let i in floorLayout) {
let calculatedWidth = floorLayout[i].width + floorLayout[i].x;
let calculatedHeight = floorLayout[i].height + floorLayout[i].y;
if (first) {
dimensions.width = calculatedWidth;
dimensions.height = calculatedHeight;
first = false;
}
if (calculatedWidth > dimensions.width) {
dimensions.width = calculatedWidth;
}
if (calculatedHeight > dimensions.height) {
dimensions.height = calculatedHeight;
}
}
for (let i in hallwayPoints) {
let currentWidth = hallwayPoints[i].x;
let currentHeight = hallwayPoints[i].y;
if (currentWidth > dimensions.width) {
dimensions.width = currentWidth;
}
if (currentHeight > dimensions.height) {
dimensions.height = currentHeight;
}
}
return dimensions;
}
};
window.indoorMaps = IndoorMaps;
}(window));
From the comment above, it seems that at the point you are calling findPaths(), doors exists, but is empty when you call findPaths(), though it is not when the event is triggered. Make sure that doors is filled before try to use it.
I am trying to create a bingo game.
It's an assignment that was given to us. I wrote all the functions I need however the "main" function which runs the entire thing, it has a loop which doesn't stop.
I don't seem to know what makes it infinite since I gave a condition for it to stop at the end.
The code is a bit long. I hope you can help me out.
var gNums = []
var gPlayers = [
{
name: 'player1',
hitCounts: 0,
board: creatBingoBoard()
},
{
name: 'player2',
hitCounts: 0,
board: creatBingoBoard()
}
]
// var check=gPlayers[0].board[0][0].isHit = true
// console.table(printBingoBoard(gPlayers[0].board))
// console.table(printBingoBoard(gPlayers[1].board))
// var check = gPlayers[0].board[0][0].isHit = true
playBingo()
// console.table(gPlayers[0].board)
function playBingo() {
// debugger
resetNums()
var isVictory = false
while (!isVictory) {
// console.log('still running!')
var calledNum = drawNum(gNums)
// console.log(calledNum)
for (var i = 0; !isVictory && i < gPlayers.length; i++) {
var player = gPlayers[i]
markBoard(player, calledNum)
isVictory = checkBingo(player)
}
}
}
function creatBingoBoard() {
resetNums()
var board = [];
const SIZE = 5;
for (var i = 0; i < SIZE; i++) {
board[i] = [];
for (var j = 0; j < SIZE; j++) {
board[i][j] = {
value: getRandomIntInclusive(0, 25),
isHit: false
}
}
}
return board;
}
function printBingoBoard(board) {
var bingoBoardCopy = []
var size = board.length
for (var i = 0; i < size; i++) {
bingoBoardCopy[i] = []
for (var j = 0; j < size; j++) {
if (board[i][j].isHit === true) {
bingoBoardCopy[i][j] = board[i][j].value + 'v'
} else bingoBoardCopy[i][j] = board[i][j].value
}
}
return bingoBoardCopy
}
function resetNums() {
gNums = []
for (var i = 0; i < 25; i++) {
gNums.push(i)
}
return gNums
}
function drawNum(nums) {
var index = getRandomIntInclusive(0, nums.length);
var num = nums[index];
nums.splice(index, 1);
return num;
}
function markBoard(player, calledNum) {
for (var i = 0; i < player.board.length; i++) {
for (var j = 0; j < player.board.length; j++) {
var cell = player.board[i][j]
if (cell === calledNum) {
player.hitCounts++
cell.isHit = true
}
}
}
printBingoBoard(player.board)
}
function checkBingo(player) {
// for (var i = 0; i < player.length; i++) {
// if (player.hitsCount === 25) return true
if (player.hitCounts === 25) {
return true
}
return false;
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive
}
In markBoard, you check the value of player.board[i][j]. That's an object, yet you're comparing it to a number. The numeric value you're after appears to be player.board[i][j].value.
As others have stated in the comments, the best way to approach this type of problem is to use a debugger. Chrome Developer Tools allows you to attach breakpoints and inspect the value of your objects in code. However, logging the values of your variables is also a good debugging tool.
Got it to work!
I tried not to mess with your code too much.
My changes are marked with // <- fix.
Just showing who's the winner :)
You never pushed 25.
Off-by-one.
You were comparing the drawn number with the cell, instead of the cell's value.
var gNums = []
var gPlayers = [
{
name: 'player1',
hitCounts: 0,
board: creatBingoBoard()
},
{
name: 'player2',
hitCounts: 0,
board: creatBingoBoard()
}
]
// var check=gPlayers[0].board[0][0].isHit = true
// console.table(printBingoBoard(gPlayers[0].board))
// console.table(printBingoBoard(gPlayers[1].board))
// var check = gPlayers[0].board[0][0].isHit = true
playBingo()
// console.table(gPlayers[0].board)
function playBingo() {
// debugger
resetNums()
var isVictory = false
let totalNumbersCalled = 0;
while (!isVictory) {
var calledNum = drawNum(gNums)
console.log(++totalNumbersCalled, '->', calledNum);
for (var i = 0; !isVictory && i < gPlayers.length; i++) {
var player = gPlayers[i]
markBoard(player, calledNum)
isVictory = checkBingo(player)
}
}
console.log('Player', i - 1, 'wins!'); // <- fix 1
}
function creatBingoBoard() {
resetNums()
var board = [];
const SIZE = 5;
for (var i = 0; i < SIZE; i++) {
board[i] = [];
for (var j = 0; j < SIZE; j++) {
board[i][j] = {
value: getRandomIntInclusive(0, 25),
isHit: false
}
}
}
return board;
}
function printBingoBoard(board) {
var bingoBoardCopy = []
var size = board.length
for (var i = 0; i < size; i++) {
bingoBoardCopy[i] = []
for (var j = 0; j < size; j++) {
if (board[i][j].isHit === true) {
bingoBoardCopy[i][j] = board[i][j].value + 'v'
} else bingoBoardCopy[i][j] = board[i][j].value
}
}
return bingoBoardCopy
}
function resetNums() {
gNums = []
for (var i = 0; i <= 25; i++) { // <- fix 2
gNums.push(i)
}
return gNums
}
function drawNum(nums) {
var index = getRandomIntInclusive(0, nums.length - 1); // <- fix 3
var num = nums[index];
nums.splice(index, 1);
return num;
;
}
function markBoard(player, calledNum) {
for (var i = 0; i < player.board.length; i++) {
for (var j = 0; j < player.board.length; j++) {
var cell = player.board[i][j]
if (cell.value === calledNum) { // <- fix 4
player.hitCounts++
cell.isHit = true
}
}
}
printBingoBoard(player.board)
}
function checkBingo(player) {
// for (var i = 0; i < player.length; i++) {
// if (player.hitsCount === 25) return true
if (player.hitCounts === 25) {
return true
}
return false;
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
//The maximum is inclusive and the minimum is inclusive
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var gNums = []
var gPlayers = [
{
name: 'player1',
hitCounts: 0,
board: creatBingoBoard()
},
{
name: 'player2',
hitCounts: 0,
board: creatBingoBoard()
}
]
// var check=gPlayers[0].board[0][0].isHit = true
console.table(printBingoBoard(gPlayers[0].board))
console.table(printBingoBoard(gPlayers[1].board))
// var check = gPlayers[0].board[0][0].isHit = true
playBingo()
// console.table(gPlayers[0].board)
function playBingo() {
// debugger
resetNums()
var isVictory = false
while (!isVictory) {
// console.log('still running!')
var calledNum = drawNum();
//<-- Fix 1 for some reason callednum is coming as Undefined
if(calledNum){
// console.log(calledNum)
for (var i = 0; !isVictory && i < gPlayers.length; i++) {
var player = gPlayers[i]
markBoard(player, calledNum)
isVictory = checkBingo(player)
}
}
//<-- Fix 2 I am stopping fo gNums is empty
if(gNums.length == 0) isVictory=true;
}
console.table(printBingoBoard(gPlayers[0].board))
console.table(printBingoBoard(gPlayers[1].board))
}
function creatBingoBoard() {
resetNums()
var board = [];
const SIZE = 5;
for (var i = 0; i < SIZE; i++) {
board[i] = [];
for (var j = 0; j < SIZE; j++) {
board[i][j] = {
value: getRandomIntInclusive(0, 25),
isHit: false
}
}
}
return board;
}
function printBingoBoard(board) {
var bingoBoardCopy = []
var size = board.length
for (var i = 0; i < size; i++) {
bingoBoardCopy[i] = []
for (var j = 0; j < size; j++) {
if (board[i][j].isHit === true) {
bingoBoardCopy[i][j] = board[i][j].value + 'v'
} else bingoBoardCopy[i][j] = board[i][j].value
}
}
return bingoBoardCopy
}
function resetNums() {
gNums = []
for (var i = 0; i < 25; i++) {
gNums.push(i)
}
return gNums
}
function drawNum() {
var index = getRandomIntInclusive(0, gNums.length);
var num = gNums[index];
gNums.splice(index, 1);
return num;
}
function markBoard(player, calledNum) {
for (var i = 0; i < player.board.length; i++) {
for (var j = 0; j < player.board.length; j++) {
var cell = player.board[i][j]
//<-- Fix3 Cell is a object so we need to check with value
if (cell.value === calledNum) {
player.hitCounts++
cell.isHit = true
}
}
}
printBingoBoard(player.board)
}
function checkBingo(player) {
// for (var i = 0; i < player.length; i++) {
// if (player.hitsCount === 25) return true
if (player.hitCounts === 25) {
return true
}
return false;
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive
}
Recently i have used code in project that is still working it it http://kreditka.testovi-site.pw. But when i tried to reuse javascript the default rules js got broken and i got an error in console explaining that varibale cannot be found. Is it somehow related that sme o the code is not resusable and each line should be rewritten one by one for defferent projects?
(function () {
console.log("()");
"use strict";
var polosa = document.querySelector("#polosa");
alert(polosa);
var x = document.querySelectorAll("#slide1");
var o;
for (o = 0; o < x.length; o++) {
x[o].style.left = o*300+"px";
}
var x = document.querySelectorAll("#slide");
var a;
for (a = 0; a < x.length; a++) {
x[a].style.left = a*300+"px";
}
var doc = document.querySelectorAll('.btn-click');
for (var i = 0; i < doc.length; i++) {
doc[i].addEventListener("click", highlightThis, true);
}
var doc1 = document.querySelectorAll('.btn1-click');
for (var j = 0; j < doc.length; j++) {
doc1[j].addEventListener("click", highlightThis1, true);
}
var polosa = document.querySelector('#polosa');
polosa.style.left = '0px';
var left = 0;
var sliderItem = document.querySelector('#slide');
function highlightThis(event) {
console.log("highlightThis");
var currentActiveButton = document.querySelector(".btn-click.btn-slide-active");
currentActiveButton.classList.toggle("btn-slide-active");
event.target.classList.toggle("btn-slide-active");
console.log(event.target.dataset.value);
shiftSlide({
prev: currentActiveButton.dataset.value,
next: event.target.dataset.value
});
}
function highlightThis1(event) {
console.log("highlightThis1");
var currentActiveButton1 = document.querySelector(".btn1-click.btn-slide-active");
currentActiveButton1.classList.toggle("btn-slide-active");
event.target.classList.toggle("btn-slide-active");
console.log(event.target.dataset.value);
shiftSlide1({
prev: currentActiveButton1.dataset.value,
next: event.target.dataset.value
});
}
function shiftSlide(obj) {
var polosa = document.querySelector('#polosa');
console.log("shiftSlide");
var currentSliderPosition = parseInt(polosa.style.left);
if (obj.prev === obj.next) {
return
} else {
var left = (obj.prev - obj.next) * 300;
polosa.style.left = currentSliderPosition + left + "px";
}
}
function shiftSlide1(obj) {
var polosa = document.querySelector('#polosa1');
console.log("shiftSlide");
var currentSliderPosition = parseInt(polosa1.style.left);
if (obj.prev === obj.next) {
return
} else {
var left = (obj.prev - obj.next) * 300;
polosa1.style.left = currentSliderPosition + left + "px";
}
}
})();
Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
continue nextVehicle;
});
}
}
}
};
The code above does not work. I have a feeling this is to do with scope, I can't reach the nextVehicle label from inside the oldVehicle.getPosition method. How can I get around this?
Separate the matching logic from the update logic.
Map.prototype.updateMap = function (vehicles) {
// Only need to look up array lengths once
var vehiclesLength = vehicles.length,
oldVehiclesLength = this.oldVehicles.length;
for (var i = 0; i < vehiclesLength; i++) {
var vehicle = vehicles[i];
var oldVehicle = null;
// Find oldVehicle
for (var j = 0; j < oldVehiclesLength; j++) {
if (vehicle.registration == oldVehicle[j].registration) {
oldVehicle = oldVehicles[j];
break;
}
}
// Check for update if found
if (oldVehicle){
// Create closure for async callbacks
(function(oldV, lat,lng){
oldV.getPosition(function(latLng) {
if (lat != oldV.lat) {
var newPos = new plugin.google.maps.LatLng(lat,lng);
oldV.setPosition(newPos);
}
});
})(oldVehicle, vehicle.latitude, vehicle.longitude);
}
}
};
Just move the continue nextVehicle; line from inside the callback to immediately following the call to oldVehicle.getPosition(...):
Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
});
continue nextVehicle;
}
}
}
};
This assumes the call to getPosition is a synchronous operation.
Edit:
Now if getPosition is asynchronous, you will need to use an asynchronous loop:
Something along this line might do the trick:
Map.prototype.updateMap = function (vehicles) {
var i = 0, j = -1, self = this;
var updatePosition = function() {
j++;
if (j == self.oldVehicles.length) {
j = 0;
i++;
}
if (i === vehicles.length) {
return; // We're done
}
var vehicle = vehicles[i];
var oldVehicle = self.oldVehicles[j];
if (vehicle.registration !== oldVehicle.registration) {
updatePosition();
}
else {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
updatePosition();
}
});
}
};
updatePosition();
};