How to make this memory board game work? - javascript

I am trying to make a memory board game. I got the css part of the game done, but how it the JavaScript part suppose to work out. I tried using the codes below. When I click on the box, even if they are the same, the box won't disappear and when it's not the same number, the box doesn't turn back. Also, for my "gamebox", I want to add a picture to be the background. I couldn't get it to work. Can anyone help me. Thanks.
<html>
<style>
#gamebox
{
position: absolute;
top: 100px;
left: 100px;
background-image: url("https://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&cad=rja&uact=8&ved=&url=http%3A%2F%2Fwww.pokemontimes.it%2Fhome%2F2014%2F10%2Fannunciato-il-pokemon-center-mega-tokyo-in-apertura-a-dicembre%2F%3F%3Drelated&psig=AFQjCNFGPAm9tU9MR4AZJKe1s6F90F8UFg&ust=1454720806721506");
}
div.box
{
position: absolute;
background-color: red;
top: -800px;
left: -800px;
width: 100px;
height: 100px;
text-align: center;
font-size: 30px;
}
div.box:hover
{
background-color: blue;
}
</style>
<div id=gamebox></div>
<div id=boxdiv class=box onclick="clickedBox(this)"></div>
<script>
var squaresize = 100;
var numsquares = 6;
var numClicked = 0;
var firstClicked;
var secondClicked;
var game = [];
for (var i = 0; i < numsquares; i++)
{
game[i] = [];
for (var j = 0; j < numsquares; j++)
{
game[i][j] = Math.floor(Math.random()*5);
makeBox(i, j);
}
}
function theSame(abox, bbox)
{
var boxParts = abox.id.split("-");
var i = boxParts[1];
var j = boxParts[2];
var boxaNum = game[i][j];
var boxParts = bbox.id.split("-");
i = boxParts[1];
j = boxParts[2];
var boxbNum = game[i][j];
return(boxaNum == boxbNum);
}
function nextTurn()
{
if (numClicked != 2)
return;
if (theSame(firstClicked, secondClicked))
{
deleteBox(firstClicked);
deleteBox(secondClicked);
}
else
{
hideBox(firstClicked);
hideBox(secondClicked);
}
numClicked = 0;
}
function hideBox(box)
{
box.innerHTML = "";
box.style.backgroundColor = "red";
}
function deleteBox(box)
{
//really delete the box
box.style.backgroundColor = "";
}
function showBox(box)
{
var boxParts = box.id.split("-");
var i = boxParts[1];
var j = boxParts[2];
box.innerHTML = game[i][j];
box.style.backgroundColor = "black";
box.style.color = "white";
}
function clickedBox(box)
{
showBox(box);
numClicked++;
if (numClicked == 1)
{
firstClicked = box;
return;
}
if (numClicked == 2)
{
secondClicked = box;
}
}
function makeBox(i, j)
{
var boxdiv = document.getElementById("boxdiv");
var newBox = boxdiv.cloneNode(true);
newBox.style.left = i * (squaresize + 5);
newBox.style.top = j * (squaresize + 5);
newBox.style.width = squaresize;
newBox.style.height = squaresize;
newBox.id = 'box-' + i + '-' + j;
var gamebox = document.getElementById("gamebox");
gamebox.appendChild(newBox);
}
</script>
</html>

I think you're not calling nextTurn() anywhere in your code, meaning theSame() is never called, so nothing gets compared to eachother.
Maybe try calling nextTurn() when the numClicked === 2 in the clickedBox() function.

Related

List elements not being added correctly

I've been trying to make a little neural network. It plays a copy of the No-Wifi Google dinosaure game. It is not the most efficient (and probably has a tons of leaks), but it works after a hundred generations more or less. But I've notived something: the best elements of the previous generations do not copy to the next or don't act as before, shown by how the best before always jumped and then the next generation doesn't jump at all. Where is the problem? Btw it is a large code but I don't know how to attach files, can you comment on how?
HTML file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" name="viewport" content="width=device-width,initial-scale=1">
<title>Dino</title>
<script type="text/javascript" src="genetic.js" defer></script>
<script type="text/javascript" src="dino.js" defer></script>
<script type="text/javascript" src="population_dino.js" defer></script>
<link rel="stylesheet" href="dino.css">
</head>
<body>
<div id="score">Score: 0</div>
<div id="line"></div>
<div id="test"></div>
</body>
</html>
genetic.js:
function sigmoid(t) {
return 1/(1+Math.pow(Math.E, -t));
}
function weightedRand(spec) {
var i, j, table=[];
for (i in spec) {
for (j=0; j<spec[i]*10; j++) {
table.push(i);
}
}
//console.log(table,spec)
return table[Math.floor(Math.random() * table.length)];
}
function randomfromminustoone(){
return Math.random()*2-1;
}
class Connection {
constructor(weight) {
if (weight==null){
this.weight=randomfromminustoone();
} else{
this.weight = weight;
}
}
get_weight() {
return this.weight;
}
set_weight(weight) {
return this.weight = weight;
}
}
class Neuron {
constructor(numOuputs = 0, neuronIndex, weights = []) {
this.outputWeights = [];
this.outputVal = null;
this.neuronIndex = neuronIndex;
for (let c = 0; c < numOuputs; c++) {
var weight = weights[c] || null;
this.outputWeights.push(new Connection(weight));
}
}
setOutputVal(outputVal) {
this.outputVal = outputVal;
}
getOutputVal(inputs,inputWeights) {
this.outputVal=0;
for (var i = inputs.length - 1; i >= 0; i--) {
this.outputVal+=inputs[i]*inputWeights[i];
}
this.outputVal=sigmoid(this.outputVal);
return this.outputVal;
}
getNeuronIndex() {
return this.neuronIndex;
}
getOuputWeight(i){
return this.outputWeights[i].get_weight();
}
updateInputWeights(prevLayer) {
for (let n = 0; n < prevLayer.length-1; n++) {
let neuron = prevLayer[n];
// neuron.outputWeights[this.neuronIndex].weight += ;
}
}
}
class Net {
constructor(topology = [],model=false) {
if (model){
this.layers=model.layers;
//console.log("flag");
} else {
this.topology = topology;
// number of layers
this.numLayers = topology.length;
this.layers = [];
for (let layerNum = 0; layerNum < this.numLayers; layerNum++) {
var layer = [];
var numOuputs = topology[layerNum + 1] ? topology[layerNum + 1] : 0;
for (let neuronNum = 0; neuronNum < topology[layerNum]; neuronNum++) {
let neuron = new Neuron(numOuputs, neuronNum);
layer.push(neuron);
}
this.layers.push(layer);
}
}
}
/*
getResults() {
this.resultVals = [];
var lastLayer = this.layers[this.layers.length-1];
for (let n = 0; n < lastLayer.length-1; n++) {
this.resultVals.push(lastLayer[n].getOutputVal());
}
return this.resultVals;
}*/
feedLayer(inputs,layerNum){
let layer=this.layers[layerNum];
let outputs=[];
for (let i = 0; i < layer.length; i++) {
let neuron = layer[i];
let neuronWeights=[];
for (let a = 0; a < this.layers[layerNum-1].length; a++) {
neuronWeights.push(this.layers[layerNum-1][a].getOuputWeight(i));
}
outputs.push(neuron.getOutputVal(inputs,neuronWeights));
}
return outputs;
}
feedAll(inputs){
let prevOutputs=inputs;
for (let i = 1; i < this.layers.length; i++) {
prevOutputs=this.feedLayer(prevOutputs,i);
}
return prevOutputs;
}
};
class Population{
constructor (PopNumber,topology,bestResults=[]){
if (bestResults.length>1){
this.population=[];
for (var i = 0; i < bestResults.length; i++) {
this.population.push(bestResults[i][1]);
console.log(bestResults[i][1].feedAll([0.05,0]))
}
for (var i = 0; i < PopNumber-bestResults.length; i++) {
let addNet= this.choose(bestResults);
/*if (randomfromminustoone()>0.5){
addNet=this.mix_elements(addNet,this.choose(bestResults));
}*/
addNet=this.mutate_values(addNet);
this.population.push(addNet);
}
} else {
this.population=[];
for (var i = 0; i < PopNumber; i++) {
let addNet= new Net(topology);
this.population.push(addNet);
}
}
}
choose(results){
let dic={};
for (var i = 0; i < results.length; i++) {
dic[i]=results[i][0];
}
return results[weightedRand(dic)][1];
}
mix_elements(elem1,elem2){
var output= new Net();
output.topology = elem2.topology;
output.numLayers = elem2.numLayers;
output.layers = elem2.layers;
for (var i = 0; i < elem1.layers.length; i++) {
for (var a = 0; a < elem1.layers[i].length; a++) {
if (randomfromminustoone()>0.5){
output.layers[i][a]=elem1.layers[i][a];
}
}
}
return output;
}
mutate_values(model){
if (model==null){
return [];
}
var output= new Net();
output.topology = model.topology;
output.numLayers = model.numLayers;
output.layers = model.layers;
for (var layer = 0; layer < output.layers.length; layer++) {
for (var neuron = 0; neuron < output.layers[layer].length; neuron++) {
for (var i = 0; i < output.layers[layer][neuron].outputWeights.length; i++) {
if (randomfromminustoone()>0.75){
output.layers[layer][neuron].outputWeights[i].weight =output.layers[layer][neuron].outputWeights[i].get_weight()+randomfromminustoone()/5;
}
}
}
}
return output;
}
};
dino.js:
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1) ) + min;
};
function Dino(brain,pop){
this.cooldown=0;
this.score=0;
this.alive=true;
this.y=300;
this.before_jump=this.y;
this.inertia=0;
this.population=pop;
this.div = document.createElement('div');
this.div.className="Dino";
this.div.main=this;
this.div.style.top=this.y+"px";
document.body.appendChild(this.div);
this.brain = brain;
};
Dino.prototype.jump = function(dino){
if (dino.y==dino.before_jump){
//dino.y=dino.before_jump;
dino.inertia=3;
dino.jumpInterval=setInterval( jump => {
dino.y-=dino.inertia
dino.div.style.top=dino.y+"px";
dino.inertia -= 0.05;
if (dino.y>dino.before_jump){
dino.inertia=0;
clearInterval(dino.jumpInterval);
dino.y=dino.before_jump;}
});
}
};
Dino.prototype.down = function(dino){
if (dino.y<dino.before_jump && dino.inertia>-5){
dino.inertia-=1.5;
}
};
Dino.prototype.lost =function(dino){
dino.alive=false;
dino.div.remove();
dino.score=dino.population.score;
dino.population.still_alive-=1;
dino.population.records.push(dino.brain);
delete dino;
};
Dino.prototype.check_collision = function(dino) {
cactuses=document.getElementsByClassName("cactus");
for (var i = cactuses.length - 1; i >= 0; i--) {
if (cactuses[i].main.x<=280 && dino.y>=280 && dino.alive){
dino.lost(dino);
}
};
};
Dino.prototype.smart = function(dino){
var cactuses=Array.from(document.getElementsByClassName("cactus"));
cactuses.sort(function(cactus){
return cactus.main.x;
});
if (cactuses.length>0){
var distance_nearest_cactus=(cactuses[0].main.x-240)/660;
} else{
var distance_nearest_cactus=1;
};
let results = dino.brain.feedAll([distance_nearest_cactus,(300-dino.y)/100*(-dino.inertia/3)]);
let high_score=results.indexOf(Math.max.apply(Math,results))
if (high_score==0){
dino.jump(dino);
} else if (high_score==1){
dino.down(dino);
};
};
function Dot(height){
this.y=height
this.x=900
//-- cree le DIV
this.div = document.createElement('div');
this.div.className = 'dot';
this.div.style.top=this.y+"px";
this.div.style.left=this.x+"px";
this.div.main=this;
document.body.appendChild(this.div);
};
Dot.prototype.delete =function(leave_div)
{
if (leave_div == false){
this.div.remove();
}
delete this;
};
function CreateDot(){
new Dot(getRndInteger(346,350));
};
function Cactus(){
this.x=900
this.div = document.createElement('div');
this.div.style.left=this.x+"px";
this.div.className="cactus";
this.div.main=this;
document.body.appendChild(this.div);
};
Cactus.prototype.delete =function(leave_div)
{
if (leave_div == false){
this.div.remove();}
delete this;
}
function CreateCactus(){
new Cactus();
}
function move_object(object){
object.main.x -= 1;
object.main.div.style.left = object.main.x+'px';
if (object.main.x<230)
{
object.main.delete(false);
}
};
population_dino.js:
class Dino_population{
constructor(nbPopulation,id,prevPop=[]){
this.population=[];
this.id=id;
document.getElementById("test").innerHTML=this.id;
this.brains=new Population(nbPopulation,[2,5,5,3],prevPop);
for (var i = 0; i < nbPopulation; i++) {
this.population.push(new Dino(this.brains.population[i],this));
}
this.number=nbPopulation;
this.still_alive=nbPopulation;
this.score=0;
this.speed=4.5;
var self= this;
this.move_interval=setInterval(function(){self.move_all(self)},self.speed);
this.last_cactus=1000;
this.records=[];
}
move_all(self){
if (getRndInteger(0,60)<10){
CreateDot();
}
self.last_cactus-=getRndInteger(1,10);
if (self.last_cactus<10){
self.last_cactus=getRndInteger(500,5000);
CreateCactus();
}
var cactuses=document.getElementsByClassName("cactus");
for (var i = cactuses.length - 1; i >= 0; i--) {
move_object(cactuses[i]);
};
var dots=document.getElementsByClassName("dot");
for (var v = dots.length - 1; v >= 0; v--) {
move_object(dots[v]);
}
self.score+=1;
document.getElementById("score").innerHTML = "Score: "+Math.floor(self.score/10).toString();
for (var i = self.population.length - 1; i >= 0; i--) {
let dino=self.population[i];
dino.cooldown-=1;
if (dino.cooldown<=0){
dino.cooldown=10;
dino.smart(dino);
}
dino.check_collision(dino);
}
if (self.still_alive==0){
clearInterval(self.move_interval);
var cactuses=document.getElementsByClassName("cactus");
while (cactuses.length>0){
delete cactuses[0].main;
cactuses[0].remove();
};
var dots=document.getElementsByClassName("dot");
while (dots.length>0){
delete dots[0].main;
dots[0].remove();
};
self.new_pop(self);
}
}
new_pop(old){
let old_bests= old.records.slice(Math.max(old.records.length - 10, 0));
let old_best_weighted=[]
for(let i=0;i<old_bests.length;i++){
console.log([old_bests[i].feedAll([0.05,0])])
old_best_weighted.push([10-i,old_bests[i]]);
}
let old_nb=old.number;
let old_id=old.id;
globalThis.pop= new Dino_population(old_nb,old_id+1,old_best_weighted);
}
}
var pop=new Dino_population(200,1);
dino.css:
.Dino{
background-image: url("Dinausaure.png");
background-repeat: no-repeat;
background-size: contain;
width: 60px;
height: 45px;
left: 240px;
position: absolute;
z-index: 3;
}
#ground{
width: 1000px;
height: 200px;
top:270px;
left: 240px;
position: absolute;
}
#line{
width: 670px;
height: 0px;
top:345px;
left:230px;
border-top: 2px solid black;
position: absolute;
z-index: 1;
}
.dot{
border-top: 2px solid black;
width: 2px;
position: absolute;
z-index: 1;
}
.cactus{
background-image: url("cactus.png");
background-repeat: no-repeat;
background-size: contain;
width: 60px;
height: 40px;
top:310px;
position: absolute;
z-index: 0;
}
#score{
top:180px;
left:230px;
position: absolute;
}
Here are the images:
Do no doubht in telling me any optimisation, mistake or bug. I am new at neural networks and do not have much experience with Js.
Any question ask me on comments.

Random boxes in a grid JavaScript

I created a grid with random boxes, yellow and one red.
The problem is that when I refresh the page sometimes the red box doesn't appear, is hidden somewhere, I guess under a yellow box. Also, sometimes even the yellow boxes are not all displayed.
I guess there's a problem in the loop to create them?
var grid = document.getElementById("grid-box");
for (var i = 1; i <= 100; i++) {
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var obstacles = [];
while (obstacles.length < 10) {
var randomIndex = parseInt(99 * Math.random());
if (obstacles.indexOf(randomIndex) === -1) {
obstacles.push(randomIndex);
document.getElementById('square' + randomIndex).style.backgroundColor = 'yellow';
}
}
var playerOne = [];
while (playerOne.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerOne.indexOf(randomIndex) === -1) {
playerOne.push(randomIndex);
document.getElementById('square' + randomIndex).style.backgroundColor = 'red';
}
}
#grid-box {
width: 400px;
height: 400px;
margin: 0 auto;
font-size: 0;
position: relative;
}
#grid-box>div.square {
font-size: 1rem;
vertical-align: top;
display: inline-block;
width: 10%;
height: 10%;
box-sizing: border-box;
border: 1px solid #000;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<div id="grid-box"></div>
You have to change 2 things:
1. initial value of i should be 0 when you create squares
2. when you make red box then
replace
if (playerOne.indexOf(randomIndex)
with
if (playerOne.indexOf(randomIndex) === -1 && obstacles.indexOf(randomIndex) === -1) {
Here is the final code:
var grid = document.getElementById("grid-box");
// create 100 squares
for (var i = 0; i < 100; i++) { // first change
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var obstacles = [];
while (obstacles.length < 10) {
var randomIndex = parseInt(99 * Math.random());
if (obstacles.indexOf(randomIndex) === -1) {
obstacles.push(randomIndex);
document.getElementById('square' + randomIndex).style.backgroundColor = 'yellow';
}
}
var playerOne = [];
while (playerOne.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerOne.indexOf(randomIndex) === -1 && obstacles.indexOf(randomIndex) === -1) { // second change
playerOne.push(randomIndex);
document.getElementById('square' + randomIndex).style.backgroundColor = 'red';
}
}
It is because, when randomIndex would be zero(0), then you are searching element whose id is "square0" and it is not available because your for loop starts runs from 1 to 100.
Math.random() would sometimes return 0, but your ids are starting from 1 eg: 'square1', there is no 'square0' div.
Make your loop starts from 0:
for (var i = 0; i < 100; i++){
// Code here
}

Grid if box has specific class stop JavaScript

I have a grid with a player, yellow box, and obstacles (.ob) and black boxes. I don't want the player to go in the obstacle squares when I click the 'UP' button.
I was thinking to check if the next class has .ob do not go there. Any suggestions?
let moveCounter = 0;
var grid = document.getElementById("grid-box");
for (var i = 1; i <= 50; i++) {
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var obstacles = [];
while (obstacles.length < 20) {
var randomIndex = parseInt(49 * Math.random());
if (obstacles.indexOf(randomIndex) === -1) {
obstacles.push(randomIndex);
var drawObstacle = document.getElementById('square' + randomIndex);
$(drawObstacle).addClass("ob")
}
}
var playerTwo = [];
while (playerTwo.length < 1) {
var randomIndex = parseInt(49 * Math.random());
if (playerTwo.indexOf(randomIndex) === -1) {
playerTwo.push(randomIndex);
var drawPtwo = document.getElementById('square' + randomIndex);
$(drawPtwo).addClass("p-1")
}
};
$('#button_up').on('click', function() {
moveCounter += 1;
$pOne = $('.p-1')
var id = $pOne.attr('id')
var idNumber = +id.slice(6);
var idMove = idNumber - 10
var idUpMove = 'square' + idMove;
$pOne.removeClass('p-1');
$('#' + idUpMove).addClass('p-1');
});
#grid-box {
width: 400px;
height: 400px;
margin: 0 auto;
font-size: 0;
position: relative;
}
#grid-box > div.square {
font-size: 1rem;
vertical-align: top;
display: inline-block;
width: 10%;
height: 10%;
box-sizing: border-box;
border: 1px solid #000;
}
.p-1 {
background-color: yellow;
}
.ob {
background-color: black;
}
<div id="grid-box"></div>
<div class="move">
<button id="button_up">UP</button><br>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
jsFifddle
Use the following code
$('#button_up').on('click', function() {
moveCounter += 1;
$pOne = $('.p-1')
var id = $pOne.attr('id')
var idNumber = +id.slice(6);
var idMove = idNumber - 10
var idUpMove = 'square' + idMove;
if($('#' + idUpMove).hasClass('ob')){
return false;
}
$pOne.removeClass('p-1');
$('#' + idUpMove).addClass('p-1');
});
Here we check the next selected class having ".ob" class if its return true then we stop the process if it returns false then process continues
if($('#' + idUpMove).hasClass('ob')){
return false;
}
Fiddle

Updating HTML element's content during script execution in vanilla JS

I'm writing simple Sudoku solver as an exercise and I've thought that I will show entire process by displaying it step by step on 9x9 grid.
I'm using HTML table with nested divs for displaying game board (probably not relevant) and recursive function for solving preseeded Sudoku. My solution is in "spaghetti" state right now, so below I give you pseudocode for what I have:
function fillBoard() {
for(let i = 0; i < 9; i++) {
for(let j = 0; j < 9; j++) {
const cell = document.querySelector(`div[data-row="${i}"][data-column="${j}"]`);
cell.innerHTML = gameState.solution[i][j];
}
}
}
function solve(row, column) {
/* simplified, it's working :) */
for(let guess = 1; guess < 10; guess++) {
this.solution[row][column] = guess; <--- SHOW THIS STEP TO USER
let conflicts = checkConflicts(row, column)
if(!conflicts) {
let emptyCell = this.findNextEmptyCell(row, column);
if(emptyCell) {
let result = this.solve(emptyCell.i, emptyCell.j);
if(!result) continue;
else return true;
}
return true;
}
else continue;
}
}
I've tried putting fillBoard() function call inside solve() but that obviously didn't worked as I'm getting only the final result in form of solved grid. I've also tried using setInterval(fillBoard, 100) but solve() function is executing too fast.
How can I achieve "incremental" displaying of entire solving process by updating HTML after each solve() call?
I'm trying to get something like this: https://www.youtube.com/watch?v=ChjQRIhH414 but I'm filling the board left-right, top-bottom
Current solution: Codepen
You'll want to slow down your html rendering process, which suggests animation to me. You can look into this approach, and maybe throttle it if you want. Without having a complete example I can't run it to be sure. I'll give you some pseudo code in response for the way I would test it to start with, and hopefully that'll point you in the right direction:
function fillBoard(i=0, j=0) {
const cell = document.querySelector(`div[data-row="${i}"][data-column="${j}"]`);
cell.innerHTML = gameState.solution[i][j];
j++;
if( j >= 9) { j = 0; i++; }
if(i < 9)
requestAnimationFrame(function() { fillBoard(i,j) });
}
If you want, you can replace requestAnimationFrame with a setTimeout on a given delay. You can set it to 1-2 seconds or something to start with to see if it gives you the results you're looking for.
Unoptimized, but working example, by following #loctrice advice from comments above. Still looking for other solutions to this problem.
console.clear();
let states = [];
let x = 0;
document.addEventListener("DOMContentLoaded", function() {
const start = document.getElementById("start");
const check = document.getElementById("check");
const sudoku = document.getElementById("sudoku");
function fillBoard(index) {
console.log(`Displaying ${index}/${states.length}`);
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
const cell = document.querySelector(
`div[data-row="${i}"][data-column="${j}"]`
);
cell.innerHTML =
states[index][i][j] == 0 ? "" : states[index][i][j];
}
}
}
class Sudoku {
checkRow(row) {
for (let i = 0; i < 9; i++) {
let number = this.solution[row][i];
if (!number) continue;
for (let j = 0; j < 9; j++) {
if (i == j) continue;
const challenge = this.solution[row][j];
if (number == challenge) return number;
}
}
return false;
}
checkColumn(column) {
for (let i = 0; i < 9; i++) {
let number = this.solution[i][column];
if (!number) continue;
for (let j = 0; j < 9; j++) {
if (i == j) continue;
const challenge = this.solution[j][column];
if (number == challenge) return number;
}
}
return false;
}
checkBox(box) {
const rowModifier = Math.floor(box / 3) * 3;
const colModifier = (box % 3) * 3;
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
let number = this.solution[i + rowModifier][j + colModifier];
if (!number) continue;
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
if (x == i && y == j) continue;
const challenge = this.solution[x + rowModifier][y + colModifier];
if (number == challenge) return number;
}
}
}
}
return false;
}
solve(row, column, array) {
for (let guess = 1; guess < 11; guess++) {
if (guess == 10) {
this.solution[row][column] = 0;
return false;
}
this.solution[row][column] = guess; // <=== SHOW ENTIRE BOARD HERE
let state = this.solution.map(a => [...a]);
array.push(state);
const rowError = this.checkRow(row);
const columnError = this.checkColumn(column);
const boxError = this.checkBox(
3 * Math.floor(row / 3) + Math.floor(column / 3)
);
if (!rowError && !columnError && !boxError) {
// find next empty cell
let emptyCell = this.findNextEmptyCell(row, column);
if (emptyCell) {
let result = this.solve(emptyCell.i, emptyCell.j, array);
if (!result) continue;
else return true;
}
return true;
} else continue;
}
}
findNextEmptyCell(row, column) {
for (let i = row; i < 9; i++) {
if (column == 8) column = 0;
for (let j = column; j < 9; j++) {
if (this.solution[i][j]) continue;
else return { i: i, j: j };
}
column = 0;
}
return false;
}
generateBox(boxNumber) {
let numbers = [];
for (let i = 0; i < 9; i++) {
numbers.push(i);
}
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
const length = numbers.length;
const index = Math.floor(Math.random() * length);
const number = numbers.splice(index, 1);
const row = i + boxNumber * 3 / 4;
const col = j + boxNumber * 3 / 4;
this.solution[row][col] = parseInt(number) + 1;
}
}
}
initialize() {
this.solution = [];
for (let i = 0; i < 9; i++) {
this.solution.push([]);
for (let j = 0; j < 9; j++) {
this.solution[i][j] = 0;
}
}
for (let i = 0; i < 3; i++) {
this.generateBox(i * 4);
}
}
}
let gameState = new Sudoku();
gameState.initialize();
start.onclick = function() {
gameState.solve(0, 3, states);
window.setInterval(function() {if(x < states.length) fillBoard(x++);}, 15);
};
check.onclick = function() {
for (let i = 0; i < 9; i++) {
let error = gameState.checkRow(i);
if (error) {
for (let j = 0; j < 9; j++) {
const cell = document.querySelector(
`div[data-row="${i}"][data-column="${j}"]`
);
cell.classList.add("incorrect-area");
if (cell.innerHTML == error) cell.classList.add("incorrect");
}
return;
}
error = gameState.checkColumn(i);
if (error) {
const cells = document.querySelectorAll(`div[data-column="${i}"]`);
cells.forEach(c => {
c.classList.add("incorrect-area");
if (c.innerHTML == error) c.classList.add("incorrect");
});
return;
}
error = gameState.checkBox(i);
if (error) {
const cells = document.querySelectorAll(`div[data-box="${i}"]`);
cells.forEach(c => {
c.classList.add("incorrect-area");
if (c.innerHTML == error) c.classList.add("incorrect");
});
return;
}
}
};
for (let i = 0; i < 9; i++) {
const row = document.createElement("tr");
row.classList.add("row");
for (let j = 0; j < 9; j++) {
let td = document.createElement("td");
let cell = document.createElement("div");
cell.classList.add("cell");
cell.dataset.row = i;
cell.dataset.column = j;
let a = Math.floor(i / 3);
let b = Math.floor(j / 3);
cell.dataset.box = 3 * a + b;
cell.innerHTML =
gameState.solution[i][j] == "0" ? "" : gameState.solution[i][j];
if (!cell.innerHTML)
cell.onclick = function(e) {
const row = e.target.dataset.row;
const col = e.target.dataset.column;
gameState.solution[row][col] =
++gameState.solution[row][col] > 9
? 0
: gameState.solution[row][col];
cell.innerHTML =
gameState.solution[row][col] == "0"
? ""
: gameState.solution[row][col];
document
.querySelectorAll("div.cell")
.forEach(c =>
c.classList.remove("correct", "incorrect", "incorrect-area")
);
};
td.appendChild(cell);
row.appendChild(td);
}
sudoku.appendChild(row);
}
});
.incorrect-area {
background-color: #A55 !important;
border-color: #F00 !important;
}
.correct {
background-color: #1A1 !important;
border-color: #0F0 !important;
}
.incorrect {
background-color: #A11 !important;
border-color: #F00 !important;
}
div[data-box='1'],
div[data-box='3'],
div[data-box='5'],
div[data-box='7'] {
background-color: #444;
}
.button {
display: inline-block;
min-height: 30px;
width: 120px;
background-color: white;
font-size: 32px;
cursor: pointer;
}
#buttons {
text-align: center;
}
div {
padding: 0px;
}
body {
background-color: #000;
}
#game {
width: 500px;
margin-left: auto;
margin-right: auto;
margin-top: 0px;
}
#sudoku {
width: 500px;
height: 500px;
margin-left: auto;
margin-right: auto;
background-color: #111;
border: dashed 1px white;
color: white;
}
.row {
border: 1px solid yellow;
}
.cell {
cursor: default;
height: 40px;
width: 40px;
padding: 0;
margin: 0;
border: solid white 1px;
text-align: center;
font-weight: bold;
display: table-cell;
vertical-align: middle;
user-select: none;
}
.cell:hover {
background-color: #765;
transform: scale(1.3);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>SudoQ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<script src="main.js"></script>
</head>
<body>
<div id="game">
<div id="buttons">
<div id="start" class="button">SOLVE</div>
<div id="check" class="button">CHECK</div>
</div>
<table id="sudoku">
</table>
</div>
</body>
</html>

JS OOP - multiple timer created by object but only one works

This js is to create "lyricLine" and showing strings on random position of the page.
While creating an object of oLyricLine and calling drawText, it supposed to display each string of array lyricLines one by one until last line is shown. When last line is time-out, the timer should stop and the created div.lyricline should be deleted.
While different objects are created, (in this case LyricGen1 and LyricGen2) their timer should be ticking simultaneously.
But currently only timer of LyricGen2 is working.
Code is attached below.
<script src="jquery-min.js"></script>
<div id="container">
<div class="lyricline" id="0">
demo
</div>
</div>
<style>
body{
background: #000;
color: #fff;
font-family: sans-serif;
}
#container{
position: relative;
width: 100%;
height: 100%;
}
.lyricline{
position: absolute;
text-align: center;
}
</style>
<script>
var idarray = [];
//Object oLyricLine
function oLyricLine(obj){
this.lyricLines = [];
this.textSize = 30;
this.toppx = -1;
this.leftpx = -1;
this.unixtime = -1;
this.widthpx = -1;
this.colorhex = "#fff";
this.obj = obj;
}
oLyricLine.prototype.drawText = function(){
if (this.toppx != -1 && this.leftpx != -1 && this.unixtime != -1 && this.widthpx != -1){
var transitionInTime = 10;
var transitionOutTime = 10;
var tickfactor = 5;
$("#"+this.unixtime).css({
"color": this.colorhex,
"left": this.leftpx,
"top": this.toppx,
"width": this.widthpx,
"font-size":this.textSize
}).attr({"class":"lyricline","id":this.unixtime}).text(this.lyricLines[0]);
var tickCount = 0;
lyricLinesCount = 0;
var lyricLinesTick = [];
for (var i =0; i <= this.lyricLines.length - 1; i++) {
lyricLinesTick[i] = this.lyricLines[i].length * tickfactor;
if(i>0){lyricLinesTick[i]+=lyricLinesTick[i-1];}
};
var nLyricLines = this.lyricLines;
var nUnixtime = this.unixtime;
idarray[nUnixtime] = setInterval(function () {
tickCount += 1;
if (tickCount == lyricLinesTick[lyricLinesCount]){
lyricLinesCount +=1;
if(lyricLinesCount != lyricLinesTick.length){
$("#"+nUnixtime).text(nLyricLines[lyricLinesCount]);
}else{
$("#"+nUnixtime).remove();
clearInterval(idarray[nUnixtime]);
}
}
},100);
}
};
oLyricLine.prototype.widthGen = function() {
this.widthpx = maxWidth(this.lyricLines, this.textSize);
};
var unixtime1=Date.now();
$("#container").append($("<div></div>").attr("id",unixtime1));
var obj1=$("#"+unixtime1);
var LyricGen1 = new oLyricLine(obj1);
LyricGen1.lyricLines = ["gen1 line1","1.line2","1-------LINE#3"];
LyricGen1.textSize = 50;
LyricGen1.toppx = Math.floor(Math.random()*($(window).height()-LyricGen1.textSize));
LyricGen1.widthGen();
LyricGen1.leftpx = Math.floor(Math.random()*($(window).width()-parseInt(LyricGen1.widthpx)));
LyricGen1.unixtime = unixtime1;
LyricGen1.drawText();
$("#container").append($("<div></div>").attr("id","Datenow"));
var obj2=$("#Datenow");
var LyricGen2 = new oLyricLine(obj2);
LyricGen2.lyricLines = ["2.1","TWO=two","2........3","gen2 line number 4","2>>line5"];
LyricGen2.textSize = 80;
LyricGen2.toppx = Math.floor(Math.random()*($(window).height()-LyricGen1.textSize));
LyricGen2.widthGen();
LyricGen2.leftpx = Math.floor(Math.random()*($(window).width()-parseInt(LyricGen1.widthpx)));
LyricGen2.unixtime = "Datenow";
LyricGen2.drawText();
function strlen(str){ var len = 0; for (var i=0; i<str.length; i++) { var c = str.charCodeAt(i); if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f)) { len++; } else { len+=2; } } return len; }
function maxWidth (lyricLines, textSize) {
var maxStringLength=0, maxStringId=-1;
for (var i = lyricLines.length - 1; i >= 0; i--) {
if (maxStringLength < strlen(lyricLines[i])){
maxStringLength = strlen(lyricLines[i]);
maxStringId = i;
};
};
$("#container").append($("<div></div>").css({
"background":"#fff",
"color":"#000",
"visibility":"hidden",
"font-size":textSize
}).attr({"class":"lyricline","id":"widgen"}).text(lyricLines[maxStringId]));
var maxPxLength = $("#widgen").css("width");
$("#widgen").remove();
return maxPxLength;
}
</script>
lyricLinesCount = 0;
You're missing a var here, making lyricLinesCount an implicit global variable. You want to have it local to each timer, though.

Categories