Javascript not working while inserting image object in html - javascript

MAJOR EDIT: Re-Did a lot of things. But similar error.
var white = 1;
var turn = white;
var table = document.getElementById("game");
function createTable(table, white) {
var i,j,tr;
for(i=0;i<8;i++)
{
tr = document.createElement('tr');
for(j=0;j<8;j++)
tr.appendChild(document.createElement('td')).id = String.fromCharCode( (white == 1 ? j : 8-j) +97)+(white == 1 ? 8-i : i+1);
table.appendChild(tr);
}
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
table.rows[i].cells[j].setAttribute("class","cell");
}
}
}
function onImageLoad(t) {
console.log(t);
}
function createImageArray() {
var w,c,p;
var image = new Array(2);
for(w=0;w<2;w++)
{
image[w] = new Array(2);
for(c=0;c<2;c++)
{
image[w][c] = new Array(6);
for(p=0;p<6;p++)
{
image[w][c][p] = new Array(2);
}
}
}
return image;
}
function createBlankimageArray() {
var blank = new Array(2);
return blank;
}
function bufferImages(image,blank) {
var w, c, p, s, word;
for(w=0;w<2;w++)
{
for(c=0;c<2;c++)
{
for(p=0;p<6;p++)
{
for(s=0;s<2;s++)
{
word = w.toString() + c.toString() + (p+1).toString() + s.toString() + ".png";
//console.log(word);
image[w][c][p][s] = new Image();
image[w][c][p][s].onload = onImageLoad(word);
image[w][c][p][s].src='final images/'+ word;
}
}
}
}
for(i=0;i<2;i++)
{
blank[i] = new Image();
word = i.toString() + '.png';
blank[i].onload = onImageLoad(word);
blank[i].src= 'final images/'+ word;
}
}
function intializeState() {
var x,y,temp;
var state = new Array(8);
for(y=0;y<8;y++)
{
state[y] = new Array(8);
for(x=0;x<8;x++)
{
state[y][x] = new Array(3);
// Set Cell White or Black.
state[y][x][0] = (x+y)%2;
if(y==1 || y == 6)
{
temp = 0;
state[y][x][1] = temp;
state[y][x][2] = ( white==1 ? 0 : 1);
}
else if(x==0 || x==7) {temp = 1;}
else if(x==1 || x==6) {temp = 2;}
else if(x==2 || x==5) {temp = 3;}
else if(x==3) {temp = 4;}
else if(x==4) {temp = 5;}
if(temp!=0)
{
if(y==0)
{
state[y][x][1] = temp;
state[y][x][2] = (white == 1 ? 0 : 1);
}
else if(y==7)
{
state[y][x][1] = temp;
state[y][x][2] = (white == 1 ? 1 : 0);
}
else
{
state[y][x][1] = 7;
state[y][x][2] = 7;
}
}
}
}
return state;
}
function drawState(table,state,image,blank) {
var y,x;
//var table = document.getElementById("game");
var w,c,p;
for(y=0;y<8;y++)
{
for(x=0;x<8;x++)
{
c = state[y][x][0];
w = state[y][x][1];
p = state[y][x][2];
if(p!=7)
{
table.rows[y].cells[x].appendChild(image[w][c][p][0]);
}
else
{
table.rows[y].cells[x].appendChild(blank[c]);
}
}
}
}
var state = intializeState();
var image = createImageArray();
var blank = createBlankimageArray();
createTable(table, white);
bufferImages(image,blank);
intializeState(state);
drawState(table,state,image,blank);
HTML code:
<!DOCTYPE html>
<html>
<head>
<title>Anti Chess</title>
<link rel="stylesheet" type="text/css" href="screen2.css">
</head>
<body>
<h1 id="game_title">Anti Chess by theManikJindal</h1>
Visit Blog!
<br />
<br />
<table id="game"></table>
<script src="req_logic.js"></script>
</body>
</html>
The above script is required to create a chess board in the initial position.
The problem that I am encountering is in the drawState function.
Console: (has printed out all the image names after loading them) After that:
Uncaught TypeError: Cannot read property '1' of undefined req_logic.js:154
Which is the line: table.rows[y].cells[x].appendChild(image[w][c][p][0]);
so where have I gone wrong.
EDIT: jsFiddle.net link : http://jsfiddle.net/8H3Ha/1/

Change the definition ot initializeState() to:
function intializeState() {
var x,y,temp;
var state = new Array(8);
for(y=0;y<8;y++)
{
state[y] = new Array(8);
for(x=0;x<8;x++)
{
state[y][x] = new Array(3);
// Set Cell White or Black.
state[y][x][0] = (x+y)%2;
if(y==1 || y == 6)
{
temp = 0;
state[y][x][1] = temp;
state[y][x][2] = ( white==1 ? 0 : 1);
}
else if(x==0 || x==7) {temp = 1;}
else if(x==1 || x==6) {temp = 2;}
else if(x==2 || x==5) {temp = 3;}
else if(x==3) {temp = 4;}
else if(x==4) {temp = 5;}
if(temp!=0)
{
if(y==0)
{
state[y][x][1] = temp;
state[y][x][2] = (white == 1 ? 0 : 1);
}
else if(y==7)
{
state[y][x][1] = temp;
state[y][x][2] = (white == 1 ? 1 : 0);
}
else
{
state[y][x][1] = 7;
state[y][x][2] = 7;
}
}
}
}
return state;
}
Then call it as:
state = initializeState();
The problem is that the parameter variable named state was shadowing the global variable with the same name inside initializeState.
I also suggest that the elements of the state array should be objects, not arrays. Arrays should be used when the elements are uniform, but each of these sub-elements have different purposes: [0] is the cell color, [1] is the piece, and [2] is the piece color.

Related

Javascript Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')

I'm trying to make a Farm Clicker game myself with javascript. In other words, as you click the Add Gold button, the player will have more gold and will be able to buy new animals with the gold he has earned. But in my code I come across the following error: script.js:42 Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')
at addGold (script.js:42:54)
at HTMLButtonElement. (script.js:11:42)
What is this error caused by? I leave the codes below.
// global variables
const myContent = document.getElementById("content");
var gold = 0;
let animals = {};
var goldToAdd = 0;
// global functions
function addGoldButton() {
let myButton = document.createElement("button");
myButton.addEventListener("click", () => addGold(1)); // add one
myButton.innerHTML = "Add Gold!";
myContent.appendChild(myButton);
}
function passiveGold() {
if (animals.goats > 0) {
goldToAdd += animals.goats * 5; //50=>5 10=>1
}
if (animals.pigs > 0) {
goldToAdd += animals.pigs * 10; //90=>10 9=>1
}
if (animals.cows > 0) {
goldToAdd += animals.cows * 15; //120=>15 8=>1
}
addGold(goldToAdd);
}
addGoldButton();
function addGold(goldToAdd) {
console.trace();
if (gold = null) {
gold = goldToAdd;
let goldCounter = document.createElement("h2");
goldCounter.id = "goldCounter";
goldCounter.innerHTML = "Gold: " + gold;
myContent.appendChild(goldCounter);
} else {
gold += goldToAdd;
document.getElementById("goldCounter").innerHTML = "Gold: " + gold;
}
// check for events on current gold level
checkGold();
}
function checkGold() {
if (gold >= 50 && document.getElementById("goatBuyButton") == null) {
let buttonBar = document.createElement("div");
buttonBar.id = "buttonBar";
let buyButton = document.createElement("button");
buyButton.id = "goatBuyButton";
buyButton.innerHTML = "Buy Goat (50g)";
buyButton.addEventListener("click", () => buyAnimal("goat"));
myContent.appendChild(buttonBar);
buttonBar.appendChild(buyButton);
}
if (gold >= 90 && document.getElementById("pigBuyButton") == null) {
let buttonBar = document.getElementById("buttonBar");
let buyButton = document.createElement("button");
buyButton.id = "pigBuyButton";
buyButton.dinnerHTML = "Buy Pig (90g)";
buyButton.addEventListener("click", () => buyAnimal("pig"));
buttonBar.appendChild(buyButton);
}
if (gold >= 120 && document.getElementById("cowBuyButton") == null) {
buttonBar = document.getElementById("buttonBar");
let buyButton = document.createElement("button");
buyButton.id = "cowBuyButton";
buyButton.innerHTML = "Buy Cow (120g)";
buyButton.addEventListener("click", () => buyAnimal("cow"));
buttonBar.appendChild(buyButton);
}
function buyAnimal(animal) {
let itemBar = document.getElementById('itemBar');
if (itemBar == null) {
itemBar = document.createElement("div");
itemBar.id != "itemBar";
myContent.appendChildren(itemBar);
}
switch (animal) {
//do something, don't and forget the break;
case "goat":
if (gold >= 50) {
addGold(-50);
if (animals.goats == null) {
animals.goats = 1;
let myElement = document.createElement("div");
myElement.id = "goats";
myElement.innerHTML = "Goat Quantity: " + animals.goats;
itemBar.appendChild(myElement);
} else {
animals.goats += 1;
document.getElementById("goats").innerHTML = "Goat Quantity: " + animals.goats;
}
}
break;
case "pig":
if (gold >= 90) {
addGold(-90);
if (animals.pigs == null) {
animals.pigs = 1;
let myElement = document.createElement("div");
myElement, id = "pigs";
myElement.innerHTML = "Pig Quantity: " + animals.pigs;
itemBar.appendChild(myElement);
} else {
animals.pigs += 1;
document.getElementById("pigs").innerHTML = "Pig Quantity: " + animals.pigs;
}
}
break;
case "cow":
if (gold >= 120) {
addGold(-120);
if (animals.cows == null) {
animals.cows = 1;
let myElement = document.createElement("div");
myElement.id = "cows";
myElement.innerHTML = "Cow Quantity: " + animals.cows;
itemBar.appendChild(myElement);
} else {
animals.cows += 1;
document.getElementById("cows").innerHTML = "Cow Quantity: " + animals.cows;
}
}
break;
default:
console.log("geen dier gevonden");
}
}
// add elements
// start application
setInterval(passiveGold, 5000);
}
<div id="content"></div>
<!--<script src="script.js"></script> script is referenced right before </body> -->
the element goldCounter is never going to be added to your dom, that's why it says "Cannot set properties of null". At line number 33, in the if statement there is an error.
Replace line 33, this
if (gold = null) {
with
if (gold == 0) {
Hope, it helps!!
The null do not equals to 0, so if the gold contents 0, gold==null will return false and try find the element with goldCounter id (but the easyest way if(!gold))
At the passiveGold function, you do not have to check the animals bigger than 0, because n*0=0, so nothing will happen (it just make your code nicer).
And the buyAnimal function's front: not appendChildren (perhaps you just misspelled it)

Increase size of confetti like mouse effect

I am new to js, I would like to increase the size of the confetti like animation shown here
var colour="random"; // "random" can be replaced with any valid colour ie: "red"...
var sparkles=100;// increase or decrease for number of sparkles falling
var x=ox=800;
var y=oy=300;
var swide=800;
var shigh=600;
var sleft=sdown=0;
var tiny=new Array();
var star=new Array();
var starv=new Array();
var starx=new Array();
var stary=new Array();
var tinyx=new Array();
var tinyy=new Array();
var tinyv=new Array();
colours=new Array('#ff0000','#00ff00','#ffffff','#ff00ff','#ffa500','#ffff00','#00ff00','#ffffff','#ff00ff')
n = 0;
y = 0;
x = 0;
n6=(document.getElementById&&!document.all);
ns=(document.layers);
ie=(document.all);
d=(ns||ie)?'document.':'document.getElementById("';
a=(ns||n6)?'':'all.';
n6r=(n6)?'")':'';
s=(ns)?'':'.style';
// if (ns){
// for (i = 0; i < n; i++)
// document.write('<layer name="dots'+i+'" top=0 left=0 width='+i/2+' height='+i/2+' bgcolor=#ff0000></layer>');
// }
// if (ie)
// document.write('<div id="con" style="position:absolute;top:0px;left:0px"><div style="position:relative">');
if (ie||n6){
for (i = 0; i < n; i++)
document.write('<div id="dots'+i+'" style="position:absolute;top:0px;left:0px;width:'+i/2+'px;height:'+i/2+'px;background:#ff0000;font-size:'+i/2+'"></div>');
}
if (ie)
document.write('</div></div>');
(ns||n6)?window.captureEvents(Event.MOUSEMOVE):0;
function Mouse(evnt){
y = (ns||n6)?evnt.pageY+4 - window.pageYOffset:event.y+4;
x = (ns||n6)?evnt.pageX+1:event.x+1;
}
(ns)?window.onMouseMove=Mouse:document.onmousemove=Mouse;
function animate(){
o=(ns||n6)?window.pageYOffset:0;
if (ie)con.style.top=document.body.scrollTop +'px';
for (i = 0; i < n; i++){
var temp1 = eval(d+a+"dots"+i+n6r+s);
randcolours = colours[Math.floor(Math.random()*colours.length)];
(ns)?temp1.bgColor = randcolours:temp1.background = randcolours;
if (i < n-1){
var temp2 = eval(d+a+"dots"+(i+1)+n6r+s);
temp1.top = parseInt(temp2.top) + 'px';
temp1.left = parseInt(temp2.left) + 'px';
}
else{
temp1.top = y+o + 'px';
temp1.left = x + 'px';
}
}
setTimeout("animate()",10);
}
animate();
window.onload=function() { if (document.getElementById) {
var i, rats, rlef, rdow;
for (var i=0; i<sparkles; i++) {
var rats=createDiv(3, 3);
rats.style.visibility="hidden";
rats.style.zIndex="999";
document.body.appendChild(tiny[i]=rats);
starv[i]=0;
tinyv[i]=0;
var rats=createDiv(5, 5);
rats.style.backgroundColor="transparent";
rats.style.visibility="hidden";
rats.style.zIndex="999";
var rlef=createDiv(5, 5);
var rdow=createDiv(5, 5);
rats.appendChild(rlef);
rats.appendChild(rdow);
rlef.style.top="2px";
rlef.style.left="0px";
rdow.style.top="0px";
rdow.style.left="2px";
document.body.appendChild(star[i]=rats);
}
set_width();
sparkle();
}}
function sparkle() {
var c;
if (Math.abs(x-ox)>1 || Math.abs(y-oy)>1) {
ox=x;
oy=y;
for (c=0; c<sparkles; c++) if (!starv[c]) {
star[c].style.left=(starx[c]=x) +"px";
star[c].style.top=(stary[c]=y+1)+"px";
star[c].style.clip="rect(0px, 5px, 5px, 0px)";
star[c].childNodes[0].style.backgroundColor=star[c].childNodes[1].style.backgroundColor=(colour=="random")?newColour():colour;
star[c].style.visibility="visible";
starv[c]=100; // fade out value
break;
}
}
for (c=0; c<sparkles; c++) {
if (starv[c]) update_star(c);
if (tinyv[c]) update_tiny(c);
}
setTimeout("sparkle()", 20); // speed 40
}
function update_star(i) {
if (--starv[i]==25) star[i].style.clip="rect(1px, 4px, 4px, 1px)";
if (starv[i]) {
stary[i]+=1+Math.random()*3;
starx[i]+=(i%5-2)/5;
if (stary[i]<shigh+sdown) {
star[i].style.top=stary[i]+"px";
star[i].style.left=starx[i]+"px";
}
else {
star[i].style.visibility="hidden";
starv[i]=0;
return;
}
}
else {
tinyv[i]=50;
tiny[i].style.top=(tinyy[i]=stary[i])+"px";
tiny[i].style.left=(tinyx[i]=starx[i])+"px";
tiny[i].style.width="2px";
tiny[i].style.height="2px";
tiny[i].style.backgroundColor=star[i].childNodes[0].style.backgroundColor;
star[i].style.visibility="hidden";
tiny[i].style.visibility="visible"
}
}
function update_tiny(i) {
if (--tinyv[i]==25) {
tiny[i].style.width="1px";
tiny[i].style.height="1px";
}
if (tinyv[i]) {
tinyy[i]+=1+Math.random()*3;
tinyx[i]+=(i%5-2)/5;
if (tinyy[i]<shigh+sdown) {
tiny[i].style.top=tinyy[i]+"px";
tiny[i].style.left=tinyx[i]+"px";
}
else {
tiny[i].style.visibility="hidden";
tinyv[i]=0;
return;
}
}
else tiny[i].style.visibility="hidden";
}
document.onmousemove=mouse;
function mouse(e) {
if (e) {
y=e.pageY;
x=e.pageX;
}
else {
set_scroll();
y=event.y+sdown;
x=event.x+sleft;
}
}
window.onscroll=set_scroll;
function set_scroll() {
if (typeof(self.pageYOffset)=='number') {
sdown=self.pageYOffset;
sleft=self.pageXOffset;
}
else if (document.body && (document.body.scrollTop || document.body.scrollLeft)) {
sdown=document.body.scrollTop;
sleft=document.body.scrollLeft;
}
else if (document.documentElement && (document.documentElement.scrollTop || document.documentElement.scrollLeft)) {
sleft=document.documentElement.scrollLeft;
sdown=document.documentElement.scrollTop;
}
else {
sdown=0;
sleft=0;
}
}
window.onresize=set_width;
function set_width() {
var sw_min=999999;
var sh_min=999999;
if (document.documentElement && document.documentElement.clientWidth) {
if (document.documentElement.clientWidth>0) sw_min=document.documentElement.clientWidth;
if (document.documentElement.clientHeight>0) sh_min=document.documentElement.clientHeight;
}
if (typeof(self.innerWidth)=='number' && self.innerWidth) {
if (self.innerWidth>0 && self.innerWidth<sw_min) sw_min=self.innerWidth;
if (self.innerHeight>0 && self.innerHeight<sh_min) sh_min=self.innerHeight;
}
if (document.body.clientWidth) {
if (document.body.clientWidth>0 && document.body.clientWidth<sw_min) sw_min=document.body.clientWidth;
if (document.body.clientHeight>0 && document.body.clientHeight<sh_min) sh_min=document.body.clientHeight;
}
if (sw_min==999999 || sh_min==999999) {
sw_min=800;
sh_min=600;
}
swide=sw_min;
shigh=sh_min;
}
function createDiv(height, width) {
var div=document.createElement("div");
div.style.position="absolute";
div.style.height=height+"px";
div.style.width=width+"px";
div.style.overflow="hidden";
return (div);
}
function newColour() {
var c=new Array();
c[0]=255;
c[1]=Math.floor(Math.random()*256);
c[2]=Math.floor(Math.random()*(256-c[1]/2));
c.sort(function(){return (0.5 - Math.random());});
return ("rgb("+c[0]+", "+c[1]+", "+c[2]+")");
}
// ]]>
the rest of the code can be found here:
https://codepen.io/dimitris_ps-the-animator/pen/KKgQdeR
As a second part of the question, is there a way to substitute the heart like objects with confetti like.
Thank you.
Try changing -
star[c].style.clip="rect(0px, 5px, 5px, 0px)";
To
star[c].style.clip="rect(0px, 10px, 10px, 0px)";
And
createDiv(5, 5);
To
createDiv(10, 10);
Wherever you find it.

The new child element contains the parent JS error

I encountered a little problem. I have:
html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="chart.css">
<script type="text/javascript" src="chart.js"></script>
<title>Chart</title>
</head>
<body>
<div id="lifespan-chart">
<div id="lifespan-chart-content"></div>
</div>
</body>
</html>
javascript:
class Polyline {
constructor(input) {
this.input = input;
this.nodes = this.convertNodes(input["nodes"]);
this.color = input["color"];
this.width = input["width"];
this.height = input["height"];
if (input["fill"] === undefined) {
this.fill = "";
} else {
this.fill = input["fill"];
}
if (input["stroke"] === undefined) {
this.stroke = "black";
} else {
this.stroke = input["stroke"];
}
if (input["stroke_width"] === undefined) {
this.stroke_width = "1.5";
} else {
this.stroke_width = input["stroke_width"];
}
// for (var key in input) {
// console.log(input[key]);
// }
}
changeParams(input) {
if ("nodes" in input) {
this.nodes = this.convertNodes(input["nodes"]);
}
if ("color" in input) {
this.color = input["color"];
}
if ("width" in input) {
this.width = input["width"];
}
if ("height" in input) {
this.height = input["height"];
}
if ("fill" in input) {
this.fill = input["fill"];
}
if ("stroke" in input) {
this.stroke = input["stroke"];
}
if ("stroke_width" in input) {
this.stroke_width = input["stroke_width"];
}
}
convertNodes(list) {
let result = "";
let i = 0;
while (i < list.length) {
result += list[i];
result += ",";
result += list[i+1];
result += " ";
i = i + 2;
}
return result;
}
setSvg() {
this.svg = `
<svg height='${this.height}', width='${this.width}'>
<polyline points='${this.nodes}', style='fill:${this.fill}, stroke:${this.stroke},stroke-width:${this.stroke_width}' />
</svg>
`;
//console.log(this.svg);
}
loadChart() {
var div = document.getElementById('lifespan-chart-content');
div.innerHTML = this.svg;
document.getElementById('lifespan-chart-content').appendChild(div);
}
}
window.addEventListener('load', function() {
input = {
"nodes" : [0,0,50,50,100,100,200,200,300,300,350,350,450,500,550,650],
"color" : "red",
"width" : 500,
"height": 300,
"fill" : "bisque",
"stroke" : "orange",
"stroke_width" : 2
};
p1 = new Polyline(input);
p1.setSvg();
p1.loadChart(); // ??? error on this place
})
And everything is ok, but when I want to add block to html in function loadChart I see an error in console:
Uncaught DOMException: Failed to execute 'appendChild' on 'Node': The new child element contains the parent. at Polyline.loadChart. What I should do to avoid such an error? I commented a place where error occures. Thanks in advance!
EDIT 1 : Forgot to execute setSvg before loadChart, I added it above, now it draws ok, but error is still here. Is it ok?
You are appending the div lifespan-chart-content to itself.
This will append a div with only the svg to lifespan-chart-content
loadChart() {
var div = document.createElement('div');
div.innerHTML = this.svg;
document.getElementById('lifespan-chart-content').appendChild(div);
}

javascript random gen nr + loops

I'm trying to make an program where it randomly picks 10 questions out of X questions(got 14 random ones written at the moment) without it picking the same questions again but i've been stuck for 4 hours on this junk.
My problem is with "randomNumbers()" function. This function generates random number (which marks the question respectively) and then checks if the numberArray already has generated number. If it doesnt, the number is supposed to be pushed to array.
I think I figured out the problem to be ## VERSION 1 ## for-loops if/else conditions. Any help ? :(
//edit, is while (true) correct way to handle this?
// dont mind ##VERSION 2## it was the first way I tried solving the problem.
(a lot of console logs to determine the bug :P )
HTML
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Testimiskeskkond</title>
<!--<link rel="stylesheet" type="text/css" href="style.css"/> -->
<script src="scripts/jquery-2.1.4.min.js"></script>
<script src="scripts/js.js"></script>
</head>
<body>
<button onclick="startQuiz()">Alusta testimist</button>
<div id="question1"></div>
<div id=questions></div>
</body>
JAVASCRIPT
var amountOfQuestions = 11;
var questionCounter = 0;
var numberArray = new Array();
var questions = new Array();
questions[0] = 'Mitu kassi elab P2rnus?',
questions[1] = 'Mis on kassi nimi?',
questions[2] = 'Mida kass teeb?',
questions[3] = 'Millal kass syndis?',
questions[4] = 'Mitu hammast kassil on?',
questions[5] = 'Mitu kyynt on kassil?',
questions[6] = 'Mitu k6rva on kassil?',
questions[7] = 'Mis v2rvi on kass?',
questions[8] = 'Tooli v2rvus?',
questions[9] = 'Laua suurus?',
questions[10] = 'Lemmik jook?',
questions[11] = 'Lemmik s88k?',
questions[12] = 'Raamatupoe nimi?',
questions[13] = 'Viinapoe nimi?';
function startQuiz() {
var setQuestions = "";
while (questionCounter < amountOfQuestions) {
var random = randomNumbers();
console.log(random + "appppppi");
if (questionCounter < amountOfQuestions) {
setQuestions += questions[random] + "<br>";
questionCounter += 1;
} else {
setQuestions += questions[random];
questionCounter += 1;
}
}
$('#questions').html(setQuestions);
}
function randomNumbers() {
var arrLength = numberArray.length;
while (true) {
console.log(arrLength);
var randomNr = Math.floor(Math.random() * 14);
console.log(randomNr + " tereeeeeeeeee");
/*
######################
########### VERSION 1
######################*/
if (arrLength == 0) {
console.log("pppppppppppp");
numberArray.push(randomNr);
break;
} else if (arrLength == 1) {
console.log("oooooooooooo");
if (numberArray[0] == randomNr) {
console.log("xxxxxxxxxxxxx");
break;
} else {
console.log("rrrrrrrrrrrrrrr");
numberArray.push(randomNr);
break;
}
} else {
for (var i = 0; i < arrLength-1; i++) {
console.log("yyyyyyyyyyyyyyyyyyyy");
if (numberArray[i] == randomNr) {
console.log("qqqqqqqqqqqqqqqqqqqq");
continue;
} else {
console.log("zzzzzzzzzzzzzz")
numberArray.push(randomNr);
break;
}
}
}
/*
######################
########### VERSION 2
######################
if (arrLength > 0) {
console.log("oooooooooooo");
for (var i = 0; i < arrLength; i++) {
console.log("yyyyyyyyyyyyyyyyyyyy");
if (numberArray[i] == randomNr) {
console.log("qqqqqqqqqqqqqqqqqqqq");
continue;
} else {
console.log("zzzzzzzzzzzzzz")
numberArray.push(randomNr);
break;
}
}
} else {
console.log("pppppppppppp");
numberArray.push(randomNr);
break;
} */
}
return randomNr;
}
let selectionCount = 10;
let randomQuestions = [];
while(randomQuestions.length < selectionCount) {
let randomNr = Math.floor(Math.random() * questionList.length);
if(!randomQuestions.includes(randomNr)) {
randomQuestions.push(randomNbr);
}
}

Undefined index after running function a few times

So I was trying to create my own Blackjack in javascript for learning purposes and even though the code is overall working, I came across a weird bug.
After some clicks on the Deal html button, which calls the function deal(), I will get either a playerHand[i] undefined or dealerHand[i] undefined error on line 114 or 118, respectively, of the code posted below.
I noticed this also happened if I clicked the button very fast for whatever reason.
I suspected it had something to do with memory optimization so I used the delete command to reset those arrays between game turns, but the error persists.
So, why do my arrays break after some use?
Thanks.
JS:
var deck = [];
var dealerHand = [];
var playerHand = [];
var dscore = 0;
var pscore = 0;
var turn = 0;
function Card(suit, src) {
this.src = src;
this.suit = getSuit(suit);
this.value = getValue(src);
};
function getSuit(suit) {
if (suit == 1) return "Clubs";
if (suit == 2) return "Diamonds";
if (suit == 3) return "Hearts";
if (suit == 4) return "Spades";
};
function getValue(src) {
if (src == 1) return 11;
if (src < 10) return src;
else return 10;
};
function createDeck() {
for (i=1; i<=4; i++) {
for(j=1; j<=13; j++) {
var card = new Card(i, j);
deck.push(card);
};
};
};
function getCard() {
var rand = Math.floor(Math.random()*deck.length);
deck.splice(rand,1);
return deck[rand];
};
function deal() {
if(turn == 0) {
dealerHand.push(getCard());
playerHand.push(getCard());
};
dealerHand.push(getCard());
playerHand.push(getCard());
};
function stand() {
dealerHand.push(getCard());
};
function clearBoard () {
$('#player').html("");
$('#dealer').html("");
};
function resetDeck () {
delete deck;
deck = [];
};
function resetHands () {
delete dealerHand;
delete playerHand;
dealerHand = [];
playerHand = [];
};
function resetScore () {
pscore = 0;
dscore = 0;
};
function isAce (arr) {
for(i=0; i<arr.length; i++) {
if (arr[i].src == 1) return true;
else return false;
};
}
function updateScore() {
resetScore();
if (playerHand.length > 0 && dealerHand.length > 0) {
for(i=0; i<playerHand.length; i++) {
pscore += playerHand[i].value;
};
for(i=0; i<dealerHand.length; i++) {
dscore += dealerHand[i].value;
};
//Regra do Às
if(pscore > 21 && isAce(playerHand)) {
pscore -= 10;
};
if(dscore > 21 && isAce(dealerHand)) {
dscore -= 10;
};
} else {
pscore = 0;
dscore = 0;
};
};
function showScore () {
$('#pscore').html("<p>Player Score: " + pscore + "</p>");
$('#dscore').html("<p>Dealer Score: " + dscore + "</p>");
};
function showCards () {
for(i=0; i<playerHand.length; i++) {
var div = $("<div>");
var img = $("<img>");
img.attr('src', 'img/cards/' + playerHand[i].suit + '/' + playerHand[i].src + '.png');
div.append(img);
$('#player').append(div);
};
for(i=0; i<dealerHand.length; i++) {
var div = $("<div>");
var img = $("<img>");
img.attr('src', 'img/cards/' + dealerHand[i].suit + '/' + dealerHand[i].src + '.png');
div.append(img);
$('#dealer').append(div);
};
};
function cleanUp () {
if (pscore == 21) {
alert("Blackjack!");
newGame();
};
if (pscore > 21) {
alert("Bust!");
newGame();
};
if (dscore == 21) {
alert("You lost!");
newGame();
};
if (dscore > 21) {
alert("You won!");
newGame();
};
};
function newGame () {
turn = 0;
clearBoard();
resetHands();
resetScore();
showScore();
resetDeck();
createDeck();
};
function gameTurn () {
clearBoard();
updateScore();
showCards();
showScore();
cleanUp();
turn++;
};
$(document).ready(function() {
newGame();
$('#deal').on('click', function(){
deal();
gameTurn();
});
$('#stand').on('click', function(){
stand();
gameTurn();
});
});
CSS:
body {
background: url(../img/greenbg.png);
}
.holder {
width:800px;
margin:auto;
}
.clearfix {
clear:both;
}
#pscore, #dscore {
color: white;
margin: 10px;
display: block;
font-size: 1.2rem;
text-shadow: 0 0 5px #000;
}
.container {
width: 600px;
height: 300px;
margin: 10px;
}
div img {
float: left;
margin: 10px;
}
div button {
margin: 10px;
}
HTML:
<html>
<head>
<div class="holder clearfix">
<div id="dscore"><p>Dealer Score: 0</p>
</div>
<div id="dealer" class="container">
</div>
<div id="pscore"><p>Player Score: 0</p>
</div>
<div id="player" class="container">
</div>
<div class="">
<button id="deal">Deal</button>
<button id="stand">Stand</button>
</div>
</div>
</body>
</html>
You have a problem in this function, which may be to blame:
function getCard() {
var rand = Math.floor(Math.random()*deck.length);
deck.splice(rand,1);
return deck[rand];
};
As written, it's removing a card, and then returning the card that now has that position in the deck. If rand was the last element in the array then there is no longer a card in that position, so it'll return undefined.
You should be returning the value of the removed card itself, part of the result of the splice call:
function getCard() {
var rand = Math.floor(Math.random() * deck.length);
var pick = deck.splice(rand, 1);
return pick[0];
};
p.s. it's worth learning modern ES5 utility functions for arrays. For example, your isAce function could be rewritten thus, avoiding the bug where you always return after testing the first element:
function isAce(arr) {
return arr.some(function(n) {
return n === 1;
});
};
or, more cleanly:
function isAce(card) {
return card === 1; // test a single card
};
function holdsAce(hand) {
return hand.some(isAce); // test an array (or hand) of cards
};

Categories