Uncaught TypeError: current.distance is not a function - javascript

I'm developing a little game of nothing at all more commonly called "Pathfinding"; and I am crashing on a small error that I have never encountered (I am young dev);
I have searched everywhere but I do not understand why this error appears.
I am experiencing this error:
Uncaught TypeError: current.distance is not a function
at search_min_distance (pathfinding.js:127)
at game (pathfinding.js:151)
at HTMLDocument. (pathfinding.js:173)
document.addEventListener("DOMContentLoaded", function() {
const NBR_POINT = 10;
const MIN_SPACING = 100;
const HEIGHT = window.innerHeight;
const WIDTH = window.innerWidth;
class point {
constructor(x, y, name, id) {
this.x = x;
this.y = y;
this.part = document.createElement("div");
this.part.className = name;
this.part.id = id;
}
distance(cmp) {
return Math.sqrt(Math.pow(cmp.x - this.x, 2) + Math.pow(cmp.y - this.y, 2));
}
}
function random(mode) {
if (!mode)
return Math.random() * ((WIDTH - 100) - 100) + 100;
else
return Math.random() * ((HEIGHT - 100) - 100) + 100;
}
function printPoint(stk, crt) {
var block = 0;
do {
block = 0;
var x = random(0);
var y = random(1);
if (stk.length != 0) {
for (let i = 0; i < stk.length; i++) {
if (x < (stk[i].x + MIN_SPACING) && x > (stk[i].x - MIN_SPACING) && y < (stk[i].y + MIN_SPACING) && y > (stk[i].y - MIN_SPACING)) {
block = 1;
break;
}
}
}
} while (block == 1);
var ids = stk.length + 1;
if (crt == "current")
var p = new point(x, y, "point courant", ids);
else
var p = new point(x, y, "point", ids);
p.part.style.bottom = p.y + "px";
p.part.style.left = p.x + "px";
document.body.appendChild(p.part);
return p;
}
function polyPoint() {
var stk = new Array();
for (let i = 0; i < NBR_POINT - 1; i++) {
stk.push(printPoint(stk, null));
}
printPoint(stk, "current");
return stk;
}
function imp_session() {
var dark_status = sessionStorage.getItem('dark_mode');
if (dark_status == 1)
document.body.classList.add("darkmode");
if (dark_status == 0)
document.body.classList.remove("darkmode");
}
function srv_DarkMode() {
document.addEventListener("keypress", function(event) {
let keypress = event.key;
var dark_status = sessionStorage.getItem('dark_mode');
if (keypress == "d") {
if (dark_status == null) {
dark_status = 0;
sessionStorage.setItem('dark_mode', dark_status);
}
if (dark_status == 1) {
this.body.classList.remove("darkmode");
dark_status = 0;
//To be able to delete sessions and not add them afterwards and error duplicate key.
sessionStorage.removeItem('dark_mode');
sessionStorage.setItem('dark_mode', dark_status);
} else {
this.body.classList.add("darkmode");
dark_status = 1;
//To be able to delete sessions and not add them afterwards and error duplicate key.
sessionStorage.removeItem('dark_mode');
sessionStorage.setItem('dark_mode', dark_status);
}
}
});
}
function search_min_distance(stk, current) {
let min = current.distance(stk[0]);
let tmp;
let real = min;
for (let i = 1; i < stk.length; i++) {
if (stk[i].id = current.id)
continue;
tmp = current.distance(stk[i]);
if (tmp < min)
real = i;
}
return real;
}
function game(stk) {
var cp = document.getElementsByClassName('courant');
cp[0].addEventListener("click", function(event) {
alert("txt");
});
var distId = search_min_distance(stk, cp[0]);
var p = document.getElementsByClassName('point');
for (let i = 0; i < p.length; i++) {
if (p[i].id != cp[0].id || p[i].id != distId) {
p[i].addEventListener("click", function(event) {
alert("txt");
});
}
}
}
function init() {
imp_session();
srv_DarkMode();
return polyPoint();
}
game(init());
});
-> current and stk [0] are indeed of "type" point.
All the remaining code does not seem important to me, but if necessary I will provide it.
I thank you in advance ! Be indulgent...

The point you are getting using the getElement function just returns
the js object, it does not contain any functions from the class.
You need to create a new class instance from this obtained point as follows inside the search_min_distance function
const { x, y, name, id } = current;
const currentPoint = new Point(x, y, name, id);
let min = currentPoint.distance(stk[0]);
I suggest you write a util function to calculate the distance between two points, passing the two points as arguments. It will be a cleaner approach.

Bind distance function to this inside constructor
class point {
constructor(x, y, name, id) {
this.x = x;
this.y = y;
this.part = document.createElement("div");
this.part.className = name;
this.part.id = id;
// bind distance method
this.distance = this.distance.bind(this);
}
distance(cmp) {
return Math.sqrt(Math.pow(cmp.x - this.x, 2) + Math.pow(cmp.y - this.y, 2));
}
}

The name of error is "TypeError". And That's not just for fun. Possible problems in search_min_distance:
stk is not defined or its length is 0
stk is not array of points (typeof point[])
point is not defined or it's not point (typeof point)
Sure problems:
point.id is not defined, it's only in point.part
if (stk[i].id = current.id)
to
if (stk[i].part.id = current.part.id)
Your code is only errors.

Finally all this for a simple mistake of inattention; I took dom for my array and put an assignment where there should have been an equal .. thanks everyone.
if (stk[i].id = current.id)
as
if (stk[i].id == current.id)
and
var distId = search_min_distance(stk, cp[0]);
as
var distId = search_min_distance(stk, stk[cp[0].id]);

Related

Referencing different objects in a class depending on user input

I'm trying to create a very basic physics simulation in p5.js and I am using a class to create multiple instances of the shapes (which are currently all circles), I have a function that checks if the user clicks inside the area of a circle and if so allows them to drag it around but I ran into a problem. I need to have the program work out which object it is hovering but I'm not sure how I would do so, below I have the function working for only the first object (obj1). can I do something like {classname}.posX instead?
function whilePressed()
{
if (Math.pow(mouseX-obj1.posX,2)+(Math.pow(mouseY-obj1.posY,2))<=(Math.pow(obj1.size/2,2)) | grabbed == true)
{
grabbed = true;
if (firstGrab == true)
{
difX = (obj1.posX-mouseX);
difY = (obj1.posY-mouseY);
firstGrab = false;
}
obj1.posX = mouseX+difX;
obj1.posY = mouseY+difY;
}
}
below is the class (the draw function has a switch statement in it because I used to have a square as well but decided to get a circle working before implementing a square)
class primitive
{
constructor()
{
this.size = 50;
this.posX = canvasSize/2;
this.posY = canvasSize/2;
this.velX = 0;
this.velY = 0;
this.terminalVel = 15;
}
pos(x,y)
{
this.posX = x;
this.posY = y;
}
draw(shape = 'circle')
{
stroke(168,198,159);
fill(204,226,163);
switch (shape)
{
case 'circle':
circle(this.posX,this.posY,this.size);
break;
}
}
gravity()
{
if (this.velY < this.terminalVel)
{
this.velY = (this.velY+1);
}
else
{
this.velY = 20;
}
this.posY = this.posY+this.velY;
if (this.posY > groundLevel-(this.size/2))
{
this.posY = groundLevel-(this.size/2);
this.velY = 0;
}
}
}
You can create a static method on the primitive class like so:
First, create an array which has all the instances of the class in it.
This is the code:
Remember: I added the parameter name to the constructor. That means when creating an instance do it like so:
var foo = new primitive("foo");
var PRIMITIVES = [];
// ...
constructor(name)
{
this.name = name;
this.size = 50;
this.posX = canvasSize/2;
this.posY = canvasSize/2;
this.velX = 0;
this.velY = 0;
this.terminalVel = 15;
PRIMITIVES.push(name);
}
Now, using the same mouse find principle, you can create a static method that finds and return the right instance.
static findInstance(mouseX, mouseY) {
for (var i = 0; i < PRIMITIVES.length; i++)
{
obj = window[PRIMITIVES[i]];
if (Math.pow(mouseX-obj.posX,2)+(Math.pow(mouseY-obj.posY,2))<=(Math.pow(obj.size/2,2)))
{
return obj;
}
}
}
Then, you can call primitive.findInstance(mouseX, mouseY), and it will return the right instance. If this doesn't work, please comment. I hope this helped you.
Create an array of objects:
let objects = []
objects.push(obj1);
objects.push(obj2);
Implement an algorithm in the mousePressed() callback that detects the clicked object:
let draggedObject;
let dragOffsetX;
let dragOffsetY;
function mousePressed() {
draggedObject = null;
for (let i=0; i < objects.lenght; i++) {
obj = objects[i];
if (Math.pow(mouseX-obj.posX,2) + Math.pow(mouseY-obj.posY,2) <= Math.pow(obj.size/2,2)) {
draggedObject = obj;
dragOffsetX = draggedObject.posX - mouseX;
dragOffsetY = draggedObject.posY - mouseY;
break;
}
}
}
Change the position of the object in the mouseDragged() callback:
function mouseDragged() {
if (dragged_object) {
draggedObject.posX = mouseX + dragOffsetX;
draggedObject.posY = mouseY + dragOffsetY;
}
}

how to generate random points in a circle (fractal trees)

I am making a tree with space-colonization algorithm in javascript. (with p5.js)
I followed the tutorial of https://www.youtube.com/watch?v=kKT0v3qhIQY&ab_channel=TheCodingTrain
or in C#
http://www.jgallant.com/procedurally-generating-trees-with-space-colonization-algorithm-in-xna/
I want to make a customized area (in this case a circle) where the leaves are generated randomly.
in Leaf.js I try to include some calculations of how the leaves get the random Coordinates within the circle.
So there is sketch.js , leaf.js, branch.js, tree.js
//leaf.js
function Leaf() {
function getChord(){
var r = 150;
var angle = random(0, 2 * PI);
var xChord = 2*r + sqrt(r) * cos(angle);
var yChord = r + sqrt(r) * sin(angle);
return (createVector(xChord, yChord));
}
this.pos = getChord();
this.reached = false;
// // var t = 2 * PI * random(0,1);
// // var r = sqrt(random(0,1));
// // var x = r * cos(t);
// // var y = r * sin(t);
// // this.pos = createVector(x, y);
// this.reached = false;
this.show = function() {
fill(58, 126, 34);
noStroke();
ellipse(this.pos.x, this.pos.y, 4, 4);
};
}
//branch.js
function Branch(parent, pos, dir) {
this.pos = pos;
this.parent = parent;
this.dir = dir;
this.origDir = this.dir.copy();
this.count = 0;
this.len = 3;
this.reset = function() {
this.dir = this.origDir.copy();
this.count = 0;
};
this.next = function() {
var nextDir = p5.Vector.mult(this.dir, this.len);
var nextPos = p5.Vector.add(this.pos, nextDir);
var nextBranch = new Branch(this, nextPos, this.dir.copy());
return nextBranch;
};
this.show = function() {
if (parent != null) {
stroke(151, 53, 48);
strokeWeight(1);
line(this.pos.x, this.pos.y, this.parent.pos.x, this.parent.pos.y);
}
};
}
And then in tree.js I push every leaf into leaves.
//tree.js
function Tree() {
this.leaves = [];
this.branches = [];
for (var i = 0; i < 1500; i++) {
this.leaves.push(new Leaf());
}
var pos = createVector(width / 2, height);
var dir = createVector(0, -1);
var root = new Branch(null, pos, dir);
this.branches.push(root);
var current = root;
var found = false;
while (!found) {
for (var i = 0; i < this.leaves.length; i++) {
var d = p5.Vector.dist(current.pos, this.leaves[i].pos);
if (d < max_dist) {
found = true;
}
}
if (!found) {
var branch = current.next();
current = branch;
this.branches.push(current);
}
}
this.grow = function() {
for (var i = 0; i < this.leaves.length; i++) {
var leaf = this.leaves[i];
var closestBranch = null;
var record = max_dist;
for (var j = 0; j < this.branches.length; j++) {
var branch = this.branches[j];
var d = p5.Vector.dist(leaf.pos, branch.pos);
if (d < min_dist) {
leaf.reached = true;
closestBranch = null;
break;
} else if (d < record) {
closestBranch = branch;
record = d;
}
}
if (closestBranch != null) {
var newDir = p5.Vector.sub(leaf.pos, closestBranch.pos);
newDir.normalize();
closestBranch.dir.add(newDir);
closestBranch.count++;
}
}
for (var i = this.leaves.length - 1; i >= 0; i--) {
if (this.leaves[i].reached) {
this.leaves.splice(i, 1);
}
}
for (var i = this.branches.length - 1; i >= 0; i--) {
var branch = this.branches[i];
if (branch.count > 0) {
branch.dir.div(branch.count + 1);
this.branches.push(branch.next());
branch.reset();
}
}
};
this.show = function() {
for (var i = 0; i < this.leaves.length; i++) {
this.leaves[i].show();
}
for (var i = 0; i < this.branches.length; i++) {
this.branches[i].show();
}
};
}
//sketch.js
var tree;
var max_dist = 30;
var min_dist = 10;
function setup() {
createCanvas(600, 600);
tree = new Tree();
}
function draw() {
background(111, 149, 231);
tree.show();
tree.grow();
}
Some how in the function getChord I think there is an infinite loop or having trouble getting the random value? Because it is not loading at all... It works when I change this.pos = getChord(); to this.pos = createVector(random(width),random(height-100);
Does anyone know how to solve this?
Or how to write codes to make an area of the circle where the leaves can be generated?
Thank you!

Flood Fill tool P5.js

I'm here again because I'm still having trouble trying to implement a flood fill tool in my drawing app.
I am attempting to make a fairly simple 2d paint application using p5.js with each drawing tool having its own constructor function. I've been having trouble understanding what I am doing wrong and why it is not working which is causing lots of frustration.
I have read a few articles on here and followed a tutorial on youtube but I still don't quite understand it. I will include what I have done so far so you can see. Specifically, I am not sure what to write for the draw function. I would like the flood fill to happen on mouseX and mouseY coordinates when the mouse is pressed. Also, I would like for the target colour to be a colour selected from a separate constructor function ColourPalette().
HTML:
<!DOCTYPE html>
<html>
<head>
<script src="lib/p5.min.js"></script>
<script src="lib/p5.dom.js"></script>
<script src="sketch.js"></script>
<!-- add extra scripts below -->
...
<script src="fillTool.js"></script>
</body>
</html>
The sketch file:
function setup() {
//create a canvas to fill the content div from index.html
canvasContainer = select('#content');
var c = createCanvas(canvasContainer.size().width, canvasContainer.size().height);
c.parent("content");
//create helper functions and the colour palette
helpers = new HelperFunctions();
colourP = new ColourPalette();
...
toolbox.addTool(new FillTool());
background(255);
}
function draw() {
//call the draw function from the selected tool.
//if there isn't a draw method the app will alert the user
if (toolbox.selectedTool.hasOwnProperty("draw")) {
toolbox.selectedTool.draw();
} else {
alert("it doesn't look like your tool has a draw method!");
}
}
The flood fill constructor function I need help with. I'm getting "Uncaught ReferenceError: floodFill is not defined" for line 112 (within the draw function) in the console and I'm a little stuck on how to fix it.:
function FillTool() {
//set an icon and a name for the object
this.icon = "assets/freehand.jpg";
this.name = "FillTool";
var colourNew = ColourPalette(colourP); //Placeholder - How do I do this?
function getPixelData(x,y){
var colour = [];
for (var i = 0; i < d; i++) {
for (var j = 0; j < d; j++) {
idx = 4 * ((y * d + j) * width * d + (x * d + i));
colour[0] = pixels[idx];
colour[1] = pixels[idx+1];
colour[2] = pixels[idx+2];
colour[3] = pixels[idx+3];
}
}
return colour;
}
function setPixelData(x, y, colourNew) {
for (var i = 0; i < d; i++) {
for (var j = 0; j < d; j++) {
idx = 4 * ((y * d + j) * width * d + (x * d + i));
pixels[idx] = colourNew[0];
pixels[idx+1] = colourNew[1];
pixels[idx+2] = colourNew[2];
pixels[idx+3] = colourNew[3];
}
}
}
function matchColour(xPos,yPos,oldColour){
var current = get(xPos,yPos);
if(current[0] == oldColour[0] && current[1] == oldColour[1] && current[2] == oldColour[2] && current[3] == oldColour[3]){
return true;
}
}
function checkPixel(x1,y1,pixelArray){
for (var i = 0 ; i < pixelArray.length; i+=2){
if(x1 == pixelArray[i] && y1 == pixelArray[i+1]){
return false;
}
else {
console.log(pixelArray.length)
return true;
}
}
}
function floodFill (xPos,yPos){
loadPixels();
colourOld = getPixelData(xPos, yPos);
var stack = [];
var pixelList = [];
stack.push(xPos,yPos);
pixelList.push(xPos,yPos);
console.log(stack);
while(stack.length > 0){
var yPos1 = stack.pop();
var xPos1 = stack.pop();
setPixelData(xPos1,yPos1,colourNew);
if(xPos1 + 1 <= width && xPos1 + 1 > 0 ){
if(matchColour(xPos1+1,yPos1,colourOld) && checkPixel(xPos1+1,yPos1,pixelList)){
stack.push(xPos1+1,yPos1);
pixelList.push(xPos1+1,yPos1);
}
}
if(xPos1+1 <= width && xPos1+1 > 0 ){
if(matchColour(xPos1-1,yPos1,colourOld) && checkPixel(xPos1-1,yPos1,pixelList)){
stack.push(xPos1-1,yPos1);
pixelList.push(xPos1-1,yPos1);
}
}
if(yPos1+1 <= height && yPos1+1 > 0 ){
if(matchColour(xPos1,yPos1+1,colourOld) && checkPixel(xPos1,yPos1+1,pixelList)){
stack.push(xPos1,yPos1+1);
pixelList.push(xPos1,yPos1+1);
}
}
if(yPos1-1 <= height && yPos1-1 > 0 ){
if(matchColour(xPos1,yPos1-1,colourOld) && checkPixel(xPos1,yPos1-1,pixelList)){
stack.push(xPos1,yPos1-1);
pixelList.push(xPos1,yPos1-1);
}
}
}
updatePixels();
console.log(pixelList);
}
}
this.draw = function() {
if(mouseIsPressed){
floodFill(mouseX,mouseY);
}
}
Sorry if its a bit of a mess, it's an accurate representation of my brain at the moment.
The function checkPixel was very very slow because pixelArray grows as you draw new pixels, so verifying if a new pixel was in the stack or had already been drawn took longer each time.
In javascript it is possible to use an object {} to store key/value pair like :
var colours = { 'red':{'r':255,'g':0,'b':0,'a':255}, 'black':{'r':0,'g':0,'b':0,'a':255} };
And calling the method hasOwnPorperty to verify the presence of the key is very fast.
colours.hasOwnPorperty('red') // is true
colours.hasOwnPorperty('green') // is false
If you had a 1,000,000 colours in colours, it would not take longer for hasOwnPorperty to find a colour in colours than if you had only 1 colour in colours. (It's O(1) has opposed to O(n) for your version of checkPixel)
Try clicking inside the circle ... or outside
let toolbox, d;
function setup() {
createCanvas(600, 400);
d = pixelDensity();
//create helper functions and the colour palette
//...
let colourRed = ColourPalette(255,0,0,255);
//...
toolbox = {'selectedTool': new FillTool() };
toolbox.selectedTool.setColour(colourRed);
background(255);
push();
strokeWeight(1);
stroke(0);
circle(75,75,100);
noStroke();
fill(0,255,0,255);
circle(125,75,100);
pop();
}
function draw() {
if (! toolbox.selectedTool.hasOwnProperty("draw")) {
alert("it doesn't look like your tool has a draw method!");
return;
}
toolbox.selectedTool.draw();
}
function FillTool() {
let self = this;
//set an icon and a name for the object
self.icon = "assets/freehand.jpg";
self.name = "FillTool";
self.colour = ColourPalette(0,0,0,255);
self.draw = function () {
if (mouseIsPressed) {
floodFill(mouseX, mouseY);
}
};
self.setColour = function (col) {
self.colour = col;
};
function matchColour (pos, oldColour) {
var current = getPixelData(pos.x, pos.y);
return ( current[0] === oldColour[0] && current[1] === oldColour[1]
&& current[2] === oldColour[2] && current[3] === oldColour[3] );
}
function getKey (pos) {
return ""+pos.x+"_"+pos.y;
}
function checkPixel(pos, positionSet) {
return ! positionSet.hasOwnProperty( getKey(pos) );
}
function floodFill (xPos, yPos) {
var stack = [];
var pixelList = {};
var first = {'x':xPos,'y':yPos};
stack.push( first );
pixelList[ getKey(first) ] = 1;
//console.log( JSON.stringify(stack) );
loadPixels();
var firstColour = getPixelData(xPos, yPos);
while (stack.length > 0) {
var pos1 = stack.pop();
setPixelData(pos1.x, pos1.y, self.colour);
var up = {'x':pos1.x, 'y':pos1.y-1};
var dn = {'x':pos1.x, 'y':pos1.y+1};
var le = {'x':pos1.x-1,'y':pos1.y};
var ri = {'x':pos1.x+1,'y':pos1.y};
if (0 <= up.y && up.y < height && matchColour(up, firstColour)) addPixelToDraw(up);
if (0 <= dn.y && dn.y < height && matchColour(dn, firstColour)) addPixelToDraw(dn);
if (0 <= le.x && le.x < width && matchColour(le, firstColour)) addPixelToDraw(le);
if (0 <= ri.x && ri.x < width && matchColour(ri, firstColour)) addPixelToDraw(ri);
}
updatePixels();
//console.log( JSON.stringify(pixelList) );
function addPixelToDraw (pos) {
if (checkPixel(pos, pixelList) ) {
stack.push( pos );
pixelList[ getKey(pos) ] = 1;
}
}
}
}
function ColourPalette (r,g,b,a) {
var self = (this !== window ? this : {});
if (arguments.length === 0) {
self['0'] = 0; self['1'] = 0; self['2'] = 0; self['3'] = 0;
} else if (arguments.length === 1) {
self['0'] = r[0]; self['1'] = r[1]; self['2'] = r[2]; self['3'] = r[3];
} else if (arguments.length === 4) {
self['0'] = r; self['1'] = g; self['2'] = b; self['3'] = a;
} else {
return null;
}
return self;
}
function getPixelData (x, y) {
var colour = [];
for (var i = 0; i < d; ++i) {
for (var j = 0; j < d; ++j) {
let idx = 4 * ((y * d + j) * width * d + (x * d + i));
colour[0] = pixels[idx];
colour[1] = pixels[idx+1];
colour[2] = pixels[idx+2];
colour[3] = pixels[idx+3];
}
}
return colour;
}
function setPixelData (x, y, colour) {
for (var i = 0; i < d; ++i) {
for (var j = 0; j < d; ++j) {
let idx = 4 * ((y * d + j) * width * d + (x * d + i));
pixels[idx] = colour[0];
pixels[idx+1] = colour[1];
pixels[idx+2] = colour[2];
pixels[idx+3] = colour[3];
}
}
}
body { background-color:#efefef; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

Similarity Matrix chart js plugin?

I want to draw a self-similarity matrix based on data points, I'm wondering if there is a JavaScript plugin to render it, similar to xy.js or chart.js
this chart should look like:
searching google keeps giving me results using D3 or cubism which seem to target realtime data flow, while I only have a single list of numbers that does not change.
I did not manage to find an answer, so I made my own (so plugins still appreciated)
(function(w){
function extend (target, source) {
target = target || {};
for (var prop in source) {
if (typeof source[prop] === 'object') {
target[prop] = extend(target[prop], source[prop]);
} else {
target[prop] = source[prop];
}
}
return target;
}
w.Squares = function(ctx, options){
var default_opts = {
};
options = extend(default_opts, options);
if(!this instanceof Squares){
return new Squares(ctx, options);
}
var amount = 0;
this.draw = function(data){
var max_x = 0, max_y = 0, max_z = 0;
// count the number of data points
data.forEach(function(row, x){
if(x+1 > max_x) {
max_x = x+1;
}
row.forEach(function(val, y){
if(y+1 > max_y) {
max_y = y+1;
}
if(val > max_z) {
max_z = val;
}
});
});
var w = parseInt(ctx.canvas.width / max_x, 10);
var h = parseInt(ctx.canvas.height / max_y, 10);
if(w>0 && h>0) {
// draw the graph
data.forEach(function (row, x) {
row.forEach(function (val, y) {
amount = parseInt(val / max_z * 255, 10);
ctx.fillStyle = "rgb(" + parseInt(amount / 1.5, 10) + "," + parseInt(amount / 1.5, 10) + "," + amount + ")";
ctx.fillRect(x * w, y * h, w, h);
});
});
}
};
};
})(window);
How to use
html:
<canvas id="canvas" width="900" height="900"></canvas>
<script>
var data = [];
for (var i = 0; i < 10; i ++) {
if(!data[i]){
data[i] = [];
}
for (var j = 0; j < 10; j ++) {
data[i][j] = Math.random();
}
}
var ctx = document.getElementById('canvas').getContext('2d');
var sqr = new Squares(ctx, {});
sqr.draw(data);
</script>
it looks like this

How to access variables within another function

I'm writing code for a blackjack game and have run into some problems. I have written two functions: one for the initial deal and one for each consecutive hit. this is the deal function:
var deck = [1,2,3,4,5,6,7,8,9,10,"Jack","Queen","King","Ace"];
function deal() {
var card1_val = Math.floor(Math.random() * deck.length);
var card2_val = Math.floor(Math.random() * deck.length);
var card1 = deck[card1_val];
var card2 = deck[card2_val];
var hand = card1 + ", " + card2;
{//card1 Conditionals
if (card1 == "Jack") {
card1_val = 10;
}
else if (card1 == "Queen") {
card1_val = 10;
}
else if (card1 == "King") {
card1_val = 10;
}
else if (card1 == "Ace") {
card1_val = 11;
}
}
{//card2 Conditionals
if (card2 == "Jack") {
card2_val = 10;
}
else if (card2 == "Queen") {
card2_val = 10;
}
else if (card2 == "King") {
card2_val = 10;
}
else if (card2 == "Ace") {
card2_val = 11;
}
}
var res = card1_val + card2_val;
document.getElementById("result").innerHTML = hand;
//document.getElementById("test").innerHTML = card1_val + ", " + card2_val;
if (res > 21) {
alert("Blackjack!");
}
}
This is the hit function:
function hit() {
var card_val = Math.floor(Math.random() * deck.length);
var nhand = deck[card_val];
bucket = hand + nhand
}
If you look at hit() I am using the var hand from deal(). I can't make it global because I need the value to be a fresh random each time. How do I access this same variable without rewriting lines of code? Any help would be appreciated.
You can either
Declare hand outside of the function scope with just var hand; and use hand in the deal function without redeclaring it as a var;
Or use window.hand when declaring hand in the deal function
global variables are evil. i would take more object oriented approach, like this
var Hand = function(bjcallback) {
this.cards = [];
this.onblackjack = bjcallback;
this.deck = [1,2,3,4,5,6,7,8,9,10,"Jack","Queen","King","Ace"];
this.values = {
"Jack": 10,
"Queen": 10,
"King": 10,
"Ace": 11
};
this.sum = function() {
var i, x, res = 0;
for (i in this.cards) {
x = this.cards[i];
if (typeof(x) != 'number') { x = this.values[x] };
res += x;
};
return res
};
this.pick = function() {
var pos = Math.floor(Math.random() * this.deck.length);
var card = this.deck[pos];
console.log(card);
return card
};
this.deal = function(n) {
n = n || 2;
for (var i=0; i<n; i++) this.cards.push(this.pick())
};
this.hit = function() {
this.cards.push(this.pick());
if (this.sum() > 21) this.onblackjack();
}
}
var hurray = function() { alert('Blackjack!') };
var hand = new Hand(hurray);
hand.deal();
hand.hit();
note that i'm not much into cards so i might have confused terminology or counting

Categories

Resources