Game of life in JavaScript - using Table - javascript

I finished coding Conway's Game of Life in JavaScript and HTML table.
logic cells in a table will be assigned with unique id's and based on the id operations(based 4 rules) take place.
You can find the working code at Codepen or i have put the code below.
The thing is it works well with any number of rows and 9 columns and if more than 9 columns are given their wont be unique id's so it works in undesired manner.
Query Is their a way where i can assign the whole table with unique id's.
Code block tableInitialization is the initialization part.
(function(){
$(document).ready(function(){
var column = "", appendRow = "", inc = 1, selectedCells = [], toRemoveClass = [], toAddClass = [], maxValue;
var tableInitialization = function(noOfRow, noOfColumn){
for(var row=1; row<=noOfRow; row++){
for(var col=1; col<=noOfColumn; col++){
column += "<td id =" + inc+col + "> </td>";
}
appendRow += "<tr>"+column+"</tr>";
column= "";
inc++;
}
$(".table").append(appendRow);
};
$("#submit").click(function(data){
var noOfRow = parseInt($("#rowNo").val());
var noOfColumn = parseInt($("#columnNo").val());
maxValue = parseInt(noOfRow.toString() + noOfColumn.toString());
if(isNaN(noOfRow) || isNaN(noOfColumn)){
alert("Please enter number");
} else {
tableInitialization(noOfRow, noOfColumn);
$("#container").hide();
$("td").click( function(data){
selectedCells.push(parseInt(this.id));
$(this).addClass("valid");
});
}
});
var checkAgain = function(selectedCells){
var check = 0, toBeReplaced = [], inArray = [], livingCell;
var currentNumber = 0;
var north, northEast, East, southEast, south, southWest, west, northWest;
for(var i=0; i<selectedCells.length; i++){
check = 0;
currentNumber = parseInt(selectedCells[i]);
if($("#"+(currentNumber)).hasClass("valid")){
livingCell = true;
} else {
livingCell = false;
}
if(currentNumber > 0 && currentNumber < maxValue){
/*North*/
if((currentNumber-10) > 0 && (currentNumber-10) < maxValue){
if($("#"+(currentNumber-10)).hasClass("valid")){
check ++;
}
}
/*North East*/
if((currentNumber-9) > 0 && (currentNumber-9) < maxValue){
if($("#"+(currentNumber-9)).hasClass("valid")){
check ++;
}
}
/*East*/
if((currentNumber+1) > 0 && (currentNumber+1) < maxValue){
if($("#"+(currentNumber+1)).hasClass("valid")){
check ++;
}
}
/*South East*/
if((currentNumber+11) > 0 && (currentNumber+11) < maxValue){
if($("#"+(currentNumber+11)).hasClass("valid")){
check ++;
}
}
/*South*/
if((currentNumber+10) > 0 && (currentNumber+10) < maxValue){
if($("#"+(currentNumber+10)).hasClass("valid")){
check ++;
}
}
/*South West*/
if((currentNumber+9) > 0 && (currentNumber+9) < maxValue){
if($("#"+(currentNumber+9)).hasClass("valid")){
check ++;
}
}
/*West*/
if((currentNumber-1) > 0 && (currentNumber-1) < maxValue){
if($("#"+(currentNumber-1)).hasClass("valid")){
check ++;
}
}
/*North West*/
if((currentNumber-11) > 0 && (currentNumber-11) < maxValue){
if($("#"+(currentNumber-11)).hasClass("valid")){
check ++;
}
}
if(livingCell){
if(check === 0 || check === 1 ){
if(toRemoveClass.indexOf(currentNumber) == -1){
toRemoveClass.push(currentNumber);
}
}
if(check == 4 || check == 5 || check == 6 || check == 7 || check == 8 ){
if(toRemoveClass.indexOf(currentNumber) == -1){
toRemoveClass.push(currentNumber);
}
}
if(check == 2 || check == 3){
if(toAddClass.indexOf(currentNumber) == -1){
toAddClass.push(currentNumber);
}
}
} else {
if(check == 3){
if(toAddClass.indexOf(currentNumber) == -1){
toAddClass.push(currentNumber);
}
}
}
}
}
};
var gol = function(selectedCells){
var check = 0, inArray = [];
var currentNumber = 0, livingCell;
for(var i=0; i<selectedCells.length; i++){
toBeReplaced = [];
check = 0;
currentNumber = parseInt(selectedCells[i]);
if($("#"+(currentNumber)).hasClass("valid")){
livingCell = true;
} else {
livingCell = false;
}
if(currentNumber > 0 && currentNumber < maxValue){
/*North*/
if((currentNumber-10) > 0 && (currentNumber-10) < maxValue){
if($("#"+(currentNumber-10)).hasClass("valid")){
check ++;
}
if(toBeReplaced.indexOf((currentNumber-10)) == -1){
toBeReplaced.push(currentNumber-10);
}
}
/*North East*/
if((currentNumber-9) > 0 && (currentNumber-9) < maxValue){
if($("#"+(currentNumber-9)).hasClass("valid")){
check ++;
}
if(toBeReplaced.indexOf((currentNumber-9)) == -1){
toBeReplaced.push(currentNumber-9);
}
}
/*East*/
if((currentNumber+1) > 0 && (currentNumber+1) < maxValue){
if($("#"+(currentNumber+1)).hasClass("valid")){
check ++;
}
if(toBeReplaced.indexOf((currentNumber+1)) == -1){
toBeReplaced.push(currentNumber+1);
}
}
/*South East*/
if((currentNumber+11) > 0 && (currentNumber+11) < maxValue){
if($("#"+(currentNumber+11)).hasClass("valid")){
check ++;
}
if(toBeReplaced.indexOf((currentNumber+11)) == -1){
toBeReplaced.push(currentNumber+11);
}
}
/*South*/
if((currentNumber+10) > 0 && (currentNumber+10) < maxValue){
if($("#"+(currentNumber+10)).hasClass("valid")){
check ++;
}
if(toBeReplaced.indexOf((currentNumber+10)) == -1){
toBeReplaced.push(currentNumber+10);
}
}
/*South West*/
if((currentNumber+9) > 0 && (currentNumber+9) < maxValue){
if($("#"+(currentNumber+9)).hasClass("valid")){
check ++;
}
if(toBeReplaced.indexOf((currentNumber+9)) == -1){
toBeReplaced.push(currentNumber+9);
}
}
/*West*/
if((currentNumber-1) > 0 && (currentNumber-1) < maxValue){
if($("#"+(currentNumber-1)).hasClass("valid")){
check ++;
}
if(toBeReplaced.indexOf((currentNumber-1)) == -1){
toBeReplaced.push(currentNumber-1);
}
}
/*North West*/
if((currentNumber-11) > 0 && (currentNumber-11) < maxValue){
if($("#"+(currentNumber-11)).hasClass("valid")){
check ++;
}
if(toBeReplaced.indexOf((currentNumber-11)) == -1){
toBeReplaced.push(currentNumber-11);
}
}
if(livingCell){
if(check == 0 || check == 1 ){
if(toRemoveClass.indexOf(currentNumber) == -1){
toRemoveClass.push(currentNumber);
}
}
if(check == 4 || check == 5 || check == 6 || check == 7 || check == 8 ){
if(toRemoveClass.indexOf(currentNumber) == -1){
toRemoveClass.push(currentNumber);
}
}
if(check == 2 || check == 3){
if(toAddClass.indexOf(currentNumber) == -1){
toAddClass.push(currentNumber);
}
}
} else {
if(check == 3){
if(toAddClass.indexOf(currentNumber) == -1){
toAddClass.push(currentNumber);
}
}
}
}
checkAgain(toBeReplaced);
}
for(var i=0; i<toRemoveClass.length; i++){
$("#"+toRemoveClass[i]).removeClass("valid");
}
for(var i=0; i<toAddClass.length; i++){
$("#"+toAddClass[i]).addClass("valid");
}
toBeReplaced = toAddClass;
if(toAddClass.length == 0){
//exit
return;
} else {
setInterval(function(){
gol($.unique(toBeReplaced));
},1000);
}
selectedCells = [];
toAddClass =[];
toRemoveClass = [];
};
start = function(){
if(selectedCells.length == 0){
alert("select cell");
} else {
gol(selectedCells);
}
};
});
})();
body{
background: #BBDEFB ;
}
td {
width: 20px;
height: 20px;
background: #eee;
}
table {
cursor: default;
}
.valid {
background: #00BFA5;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<title>Conways Game of Life</title>
<link rel="stylesheet" type="text/css" href="gameOfLife.css">
</head>
<body>
<h1><code>Conway's game of life</code></h1>
<div id="container">
<h2><code>enter row * columns</code></h2>
<form>
<code>row ★ column : </code>
<input id="rowNo" type="text"/> ★
<input id="columnNo" type="text"/>
</form>
<button id="submit"> Submit </button>
<br><br>
</div>
<table class="table"></table>
<br><br>
<button onClick="start()"> start </button>
<br><br>
<h2><code> Rules </code></h2>
<code>1. Any live cell with fewer than two live neighbours dies,
as if caused by underpopulation.</code><br>
<code>2. Any live cell with more than three live neighbours dies,
as if by overcrowding.</code><br>
<code>3. Any live cell with two or three live neighbours lives
on to the next generation.</code><br>
<code>4. Any dead cell with exactly three live neighbours becomes
a live cell.</code>
<script type="text/javascript" src="gameOfLife.js"></script>
</body>
</html>

Without digging really deep into your code. You build the IDs by using col and row index, so you'll get something like 11, 12, 13, 14, 15, ... 110, 111, 112 etc. for the first row. Without a delimiter the ID of the eleventh row first element would be 111 too. As soon as you use a kind of delimiter like '_' your IDs are unique: 1_1, 1_2 again.
for(var row=1; row<=noOfRow; row++){
for(var col=1; col<=noOfColumn; col++){
column += "<td id =" + inc+"_"+col + "> </td>";
/* you also could add data attributes:
data-row=\""+row+"\" data-col=\""+col+"\"
*/
}
appendRow += "<tr>"+column+"</tr>";
column= "";
inc++;
}
Looking into your code, I think you will get other problems, because there is a lot of code related to "10". For example: if((currentNumber-9) > 0 && (currentNumber-9) < maxValue){ - this won't work in case you'll have more than 9 rows. But fixing this would be a rewritten version of the complete game.

Related

How to combine two filters

I have circle, triangle, square in four color, each this shape have own value
I want to make filter for shape, color and numerical range.
this is code for filter html:
<div class="searchColor" id="filterColor">
Color: <br/>
<input type="checkbox" id="Red" value="Red" />Red <br/>
<input type="checkbox" id="Blue" value="Blue"/>Blue <br/>
<input type="checkbox" id="Green" value="Green"/>Green <br/>
<input type="checkbox" id="Gold" value="Gold"/>Gold <p/>
</div>
<div class="searchColor" id="searchShape">
Shape:<br/>
<div class="paintSelect">
<input type="checkbox" id="triangle" value="triangle" />triangle <br/>
<input type="checkbox" id="circle" value="circle"/>circle <br/>
<input type="checkbox" id="square" value="square"/>square
</div>
</div>
<div class="searchSelectedNumber" id="searchNumber">
Number:<br/>
<input type="checkbox" id="number01" value="1" />10-30
<br/>
<input type="checkbox" id="number02" value="2"/>20-40
</div>
This code for JS.
var arrayNumber = [];
var arrayMax = [];
$("div[class='searchSelectedNumber'] input").change(function () {
arrayMax = $("[class^=number]");
for (i=0; i<arrayMax.length; i++){
arrayNumber[i] = arrayMax[i].innerHTML;
}
var firstIntervalStart = 0;
var firstIntervalEnd = 0;
var secondIntervalStart = 0;
var secondIntervalEnd = 0;
if ( $("#searchNumber input:checked").length == 0){
$('.color').show();
} else {
var oneChecked = $("#number01").is(':checked');
var twoChecked = $("#number02").is(':checked');
if (oneChecked) {
firstIntervalStart = 0;
firstIntervalEnd = 30;
if (twoChecked) {
firstIntervalEnd = 40;
}
}
else if (twoChecked) {
firstIntervalStart = 20;
firstIntervalEnd = 40;
}
for (i = 0; i < arrayMax.length; i++) {
if (arrayNumber[i] > firstIntervalStart && arrayNumber[i] <= firstIntervalEnd) {
$($(".color")[i]).show();
} else {
$($(".color")[i]).hide();
}
}
if (secondIntervalStart != 0) {
for (i = 0; i < arrayMax.length; i++) {
if (arrayNumber[i] > secondIntervalStart && arrayNumber[i] <= secondIntervalEnd) {
console.log("secondIntervalStart < arrayPrice[i] <= secondIntervalEnd " + $($(".color")[i]));
$($(".color")[i]).show();
} else {
$($(".color")[i]).hide();
}
}
}
}
});
$("div[class='searchColor'] input").change(function () {
if($("#filterColor input:checked").length == 0 && $("#searchShape input:checked").length == 0
){
$('.color').show();
}else if($("#filterColor input:checked").length == 0 && $("#searchShape input:checked").length > 0){
$('.color').show();
$("#searchShape input:not(:checked)").each(function() {
var k = $(this).val();
$('.' + k).hide();
});
}else if($("#filterColor input:checked").length > 0 && $("#searchShape input:checked").length == 0){
$('.color').show();
$("#filterColor input:not(:checked)").each(function() {
$('.' + $(this).attr('value')).hide();
});
}else{
$('.color').show();
$("#searchShape input:not(:checked)").each(function() {
$('.' + $(this).attr('value')).hide();
});
$("#filterColor input:not(:checked)").each(function() {
$('.' + $(this).attr('value')).hide();
});
}
});
Code is working, but the numerical range code works separately from color and shape. And I don't understand how to force this script to work together.
When I select numeric range and shape or color(or together color and shape) I want to see this shape or color in the numeric range. I try the many varients, but no one variant not work.
This link on example that I have
jsfiddle.net/this my code
As the number of filters increases you need to check various possibility as you have three filters here conditions is :
None of the filter is selected
Any one filter is selected
All the filter is selected
if(color.length == 0 && shape.length == 0 && number.length > 0){
showEle(number)
}else if(color.length == 0 && shape.length > 0 && number.length == 0){
showEle(shape)
}else if(color.length > 0 && shape.length == 0 && number.length == 0){
showEle(color)
}else if(color.length > 0 && shape.length > 0 && number.length == 0){
var temp = [];
color.forEach(function(oe){
shape.forEach(function(ie){
temp.push(oe +"."+ie);
});
});
showEle(temp);
}else if(color.length == 0 && shape.length > 0 && number.length > 0){
var temp = [];
shape.forEach(function(oe){
number.forEach(function(ie){
temp.push(oe +"."+ie);
});
});
showEle(temp);
}else if(color.length > 0 && shape.length == 0 && number.length > 0){
var temp = [];
color.forEach(function(oe){
number.forEach(function(ie){
temp.push(oe +"."+ie);
});
});
showEle(temp);
}else{
var temp = [];
color.forEach(function(oe){
number.forEach(function(ie){
shape.forEach(function(iie){
temp.push(oe +"."+ie + "." + iie);
});
});
});
showEle(temp);
}
See this fiddle for more info https://jsfiddle.net/y2b3qebr/23/

jQuery search input

I have got this HTML:
<input type="text" placeholder="Type country name" class="Cinp">
<div class="contres"></div>
And this jQuery code:
var country_list= ["Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan"];
var results = [];
var selected= [];
$(".Cinp").keyup(function(e) {
var value=$(this).val();
if (e.which >= 65 && e.which <= 90 || e.which==8) {
if (value.length!=0) {
function filter(letter) {
var len = country_list.length;
var i = 0;
while(i < len) {
if (country_list[i].indexOf(letter) == 0 || country_list[i].indexOf(letter.toUpperCase()) == 0 ) {
results.push(country_list[i]);
$(".contres").append(country_list[i]);
}
i++;
}
}
}
}
}
So it works perfectly when I type only first letter, but when I type Az it should return Azerbaijan only but it returns all countries that start with a.
$(".contres").clear(); /// whether need that?
while(i < len) {
if (country_list[i].indexOf(letter) == 0 || country_list[i].indexOf(letter.toUpperCase()) == 0 ){
results.push(country_list[i]);
$(".contres").append(country_list[i]);
}
i++;
}
}

Matching variables not updating

The concept is simliar to a slider. Here is the JsFiddle
Each section is set to:
visibility: hidden;
until assigned the "anim-in" class. The issue is with var $currSection and $nextSection that need the var $rightCounter to correctly evaluate.
var $currSection = $rightCounter;
var $nextSection = $rightCounter + 1;
$rightCounter is updated in the counter function:
function counter (event){
var $counterSelect = $(this).attr('id');
if ( $counterSelect == "right") {
if ( $rightCounter >= 0 && $rightCounter <= 4){
$rightCounter += 1;
console.log($rightCounter);
if ($leftCounter <= 0) {
$leftCounter = 0;
console.log($leftCounter);
}
else {
$leftCounter -= 1;
console.log($leftCounter);
}
}
}
else {
if ($leftCounter >= 0 && $leftCounter <= 4){
$leftCounter += 1;
console.log($leftCounter);
if ($rightCounter <= 0) {
$rightCounter = 0;
console.log($rightCounter);
}
else {
$rightCounter -= 1;
console.log($rightCounter);
}
}
}
animOut();
return $rightCounter;
};
The animOut function uses $currSection and $nextSection to redistribute classes, but they are not updating with the $rightCounter?
Note: the console logs are there to show what the vars are evaluating to

Wait till user completes Multiple choice quiz or check form again in jQuery .change()

I'm writing a multiple choice quiz in jQuery that shows a total score at the end and shows a user a message based on the total score. The odd part about it is that there are 2 questions that depending on if the user selects 6a, 6b, or 6c for example, they cannot answer questions 7 or 8 or both. I coded if/else statements in .change() to block or allow the next questions. The problem is that with adding .change() the scoring does not work (all the questions are not counted to the score variable).
For some reason as soon as the page loads it is counting all the questions before the user even selects any question and I cannot use .change() if I call a function holding it using .click();
How do I have the program check or wait till the user completes the quiz (user doesnt have to answer all questions) and count all the questions answered for scoring and still allow the question using the if else statement in .change() to be used on the fly?
jQuery(document).ready(function(){
var score = 0;
var scoreQ1 = 0;
var scoreQ2 = 0;
var scoreQ3 = 0;
var scoreQ4 = 0;
//QUESTION 1
if (jQuery("input#question_1a").is(":checked")) {
scoreQ1 = 0;
}
else if (jQuery("input#question_1b").is(":checked")) {
scoreQ1 = 1;
}
else if (jQuery("input#question_1c").is(":checked")) {
scoreQ1 = 2;
} else if (jQuery("input#question_1d").is(":checked")) {
scoreQ1 = 3;
//FIND HIGHEST NUMBER OF QUESTIONS 1 - 4
if(scoreQ1 === 3 || scoreQ2 === 3 || scoreQ3 === 3 || scoreQ4 === 3 ){
score = score + 3;
}
else if(scoreQ1 === 2 || scoreQ2 === 2 || scoreQ3 === 2 || scoreQ4 === 2){
score = score + 2;
}
else if(scoreQ1 === 1 || scoreQ2 === 1 || scoreQ3 === 1 || scoreQ4 === 1){
score = score + 1;
}else if(scoreQ1 === 0 || scoreQ2 === 0 || scoreQ3 === 0 || scoreQ4 === 0){
score = score + 0;
}else {
score = score + 0;
}
//QUESTION 6 (do not score, choose next question)
jQuery("input[name=R6]").change(function()
{
if (jQuery("input#question_6a").is(":checked")) {
jQuery("input[name=R7]").removeAttr("checked");
jQuery('input[name=R7]').attr("disabled",true);
jQuery("input[name=R8]").removeAttr("checked");
jQuery('input[name=R8]').attr("disabled",true);
} else if(jQuery("input#question_6b").is(":checked"))
{
jQuery("input[name=R7]").removeAttr("checked");
jQuery('input[name=R7]').attr("disabled",false);
jQuery("input[name=R8]").removeAttr("checked");
jQuery('input[name=R8]').attr("disabled",false);
} else if(jQuery("input#question_6c").is(":checked")){
jQuery("input[name=R7]").removeAttr("checked");
jQuery('input[name=R7]').attr("disabled",false);
jQuery("input[name=R8]").removeAttr("checked");
jQuery('input[name=R8]').attr("disabled",true);
}
})
//Questions 7 and 8 look like question 1
var scoreQ7 = 0;
var scoreQ8 = 0;
var scoreQ9 = 0;
var scoreQ10 = 0;
var scoreQ11 = 0;
//QUESTION 7
if (jQuery("input#question_7a").is(":checked")) {
scoreQ7 += 1;
} else if(jQuery("input#question_7b").is(":checked")){
scoreQ7 += 2;
} else if(jQuery("input#question_7c").is(":checked")){
scoreQ7 += 3;
} else if( jQuery("input[name=R7]:checked").val()=="" ){
scoreQ7 += 0;
}
//QUESTION 8
if (jQuery("input#question_8a").is(":checked")) {
scoreQ8 += 1;
} else if(jQuery("input#question_8b").is(":checked")){
scoreQ8 += 2;
} else if(jQuery("input#question_8c").is(":checked")){
scoreQ8 += 3;
} else if( jQuery("input[name=R8]:checked").val()=="" ){
scoreQ8 += 0;
}
jQuery("input#Submit1").click(function(){
//RESULTS
if( !jQuery("input[name=lastquestion]:checked").val()=="" ){
if(score <= 5){
jQuery( "#container" ).hide();
jQuery( "div#divScore" ).html("display some text");
} else if( (score > 5 )&& (score < 11) ){
jQuery( "#container" ).hide();
jQuery( "div#divScore" ).html("display some text");
}
}
});

Multi-dimensional loop assistance

Trying to check possible combos in this sort of array:
[ ["X","X","X"], ["","",""], ["","",""] ]
Combos include:
tic tac toe logic
So, these are true:
[ ["X","",""], ["","X",""], ["","","X"] ]
[ ["","","X"], ["","X",""], ["X","",""] ]
[ ["","X",""], ["","X",""], ["","X",""] ]
So far, I have it working as long as my array[0][0] is the one of the selected choices, but I feel I'm moving towards a stack of code.
function testWin(){
var cs=b.length, ph=0, pv=0, pd=0;
for(var i=0;i<cs;i++){
if(b[0][i]==="X"){ ph++; }
if(b[i][0]==="X"){ pv++; }
if(b[i][i]==="X"){ pd++; }
}
if(ph===cs || pv===cs || pd===cs){ alert("YOU WIN!"); }
}
Fiddle here: http://jsfiddle.net/z4XLj/
Been trying another for loop to no success to identify 0
Tried a while loop, but it crashed and I don't think that is the most effective anyway.
Need to find if...
ANY array[i][this] contains nothing but X
ANY array[this][i] contains nothing but X
I now this looks like black magic, but here you have:
function testWin(){
var cs = b.length, I = [], J = [], d = [0, 0];
for(var i=0; i<cs; i++){
for(var j=0; j<cs; j++){
if(b[i][j] != 'X') continue;
I[i] = (I[i] || 0) + 1;
J[j] = (J[j] || 0) + 1;
if(i == j) d[0]++; //Diagonal \
if(i == cs-j-1) d[1]++; //Diagonal /
}
}
if(d.concat(I).concat(J).indexOf(cs) >=0) alert("You win");
}
jsfiddle: http://jsfiddle.net/edgarinvillegas/z4XLj/3/
It considers any horizontal, vertical or diagonal victory for board of any size
:O It works! :)
Cheers, from La Paz, Bolivia
function testWin() {
var xCount;
var rowsCount = b.length;
// First check rows
for (var row = 0; row < rowsCount; row++) {
xCount = 0;
colsCount = b[row].length;
for (var col = 0; col < colsCount; col++) {
if (b[row][col] == "X") {
xCount++;
} else {
break;
}
}
if (xCount == colsCount) {
alert ("YOU WIN!");
return true;
}
}
// Now check columns -- just invert the above nested loops
colsCount = b[0].length;
for (var col = 0; col < colsCount; col++) {
xCount = 0;
for (var row = 0; row < rowsCount; row++) {
if (b[row][col] == "X") {
xCount++;
} else {
break;
}
}
if (xCount == rowsCount) {
alert ("YOU WIN!");
return true;
}
}
// Check diagonals
if (b[1][1] == "X" &&
((b[0][0] == "X" && b[2][2] == "X") || (b[0][2] == "X" && b[2][0] == "X"))) {
alert ("YOU WIN!");
return true;
}
return false;
}

Categories