I am trying to make a function to check diagonal win in connect four. Already done with vertical and horizontal checks. I am adding a class to my class .slot with "player1" or "player2" depending on the var currentPlayer. I have an array of all possible combinations to victory and I am iterating over the combinations and setting a counter. But the counter doesn´t goes up. I run out of ideas whats happening there. Not sure if it has to do with jQuery and the way I am iterating, but otherwise I got an error.
Someone sees the error in the function?
var combinations = [
[$(".hole").eq(2), $(".hole").eq(9), $(".hole").eq(16), $(".hole").eq(23)],
[$(".hole").eq(1), $(".hole").eq(8), $(".hole").eq(15), $(".hole").eq(22)],
[$(".hole").eq(8), $(".hole").eq(15), $(".hole").eq(22), $(".hole").eq(29)],
[$(".hole").eq(0), $(".hole").eq(7), $(".hole").eq(14), $(".hole").eq(21)],
[$(".hole").eq(7), $(".hole").eq(14), $(".hole").eq(21), $(".hole").eq(28)],
[$(".hole").eq(14), $(".hole").eq(21), $(".hole").eq(28), $(".hole").eq(35)],
[$(".hole").eq(6), $(".hole").eq(13), $(".hole").eq(20), $(".hole").eq(27)],
[$(".hole").eq(13), $(".hole").eq(20), $(".hole").eq(27), $(".hole").eq(34)],
[$(".hole").eq(20), $(".hole").eq(27), $(".hole").eq(34), $(".hole").eq(41)],
[$(".hole").eq(12), $(".hole").eq(19), $(".hole").eq(26), $(".hole").eq(33)],
[$(".hole").eq(19), $(".hole").eq(26), $(".hole").eq(33), $(".hole").eq(40)],
[$(".hole").eq(18), $(".hole").eq(25), $(".hole").eq(32), $(".hole").eq(39)]
];
function checkDiagonal() {
for (var i = 0; i < combinations.length; i ++) {
for (var j = 0; j < combinations[i].length; j++) {
var count = 0;
if (combinations[i][j].hasClass(currentPlayer)) {
// console.log(combinations[i][j]);
// console.log(count);
count++;
if (count == 4) {
return true;
} else {
count = 0;
}
}
}
}
}
Try this, it's not elegant to remove the j loop but I think it will work for you:
function checkDiagonal() {
for (var i = 0; i < combinations.length; i ++) {
const test1 = combinations[i][0].hasClass(currentPlayer);
const test2 = combinations[i][1].hasClass(currentPlayer);
const test3 = combinations[i][2].hasClass(currentPlayer);
const test4 = combinations[i][3].hasClass(currentPlayer);
if (test1 && test2 && test3 && test4) {
console.log('diagonal win at i = ', i);
}
}
}
You can use .some and .every:
function checkDiagonal() {
return (combinations.some((combi, i) =>
combi.every(cell => cell.hasClass(currentPlayer)));
}
Related
I tried to count the number of times an element has a specific class. Sadly I am always getting
$(...)[c].css is not a function
Is jquery trying to bully me?
Here is my code:
// vanish the headings of the empty lists
let ulAll = document.querySelectorAll("ul.clearfix");
let counter = 0;
for(i = 0; i < ulAll.length; i++) {
let ul = $(ulAll)[i].children;
for(c = 0; c < ul.length; c++) {
console.log($(ul)[c]);
if($(ul)[c].css("display") == "none") {
counter++;
console.log(counter);
}
}
}
Thanks in advance!
The looks up on this are going to slow browser rendering.
This is an alternative approach.
First get all the html in one go like this:
var html = $('.parentOfContent').html();
Then look for the classes on that html:
const getClassCount = (html, myClass) => {
const regMatchClass = RegExp('class\\=(\\"|\\"[^\\"]*\\s+)' + myClass + '(\\s|\\")', 'g');
const count = 0;
while(arrM = regMatchClass.exec(html)) {
count +=1;
}
return count;
}
const html = $('.parentOfContent').html();
const myClass = 'clearfix';
const count = getClassCount(html, myClass);
I was coding in JavaScript, p5.js and came across this error line:
27646: Uncaught TypeError: Cannot read property '0' of undefined
and I don't know what this means since I am not very experienced with JavaScript. It is also suspicious to me because my project does not have line 27646 anywhere.
here is my code:
var particles = [];
const word0 = 'p5.js',
word1 = 'is nice';
var active, inactive;
var cooldown;
var font;
function preload() {
font = loadFont('data/LucidaSansRegular.ttf');
}
function setup() {
createCanvas(600, 300);
active = font.textToPoints(word0, 50, 200, 200);
inactive = font.textToPoints(word1, 50, 200, 200);
cooldown = 500;
for (var i = 0; i < active.length; i++) {
particles.push(new Particle(active[i].x, active[i].y));
}
}
function draw() {
background(60);
noStroke();
fill(255);
for (var i = 0; i < particles.length; i++) {
if (particle[i].radius < 0) {
particles.splice(i, 1);
continue;
}
if (cooldown < 0) {
particles[i].forceToDes();
} else {
particles[i].fleeFromDes();
}
particles[i].update();
particles[i].show();
}
if (cooldown < 500 && cooldown > -500) {
cooldown--;
} else {
cooldown++;
}
if (cooldown == -499) {
changeText();
}
}
function changeText() {
switchActive();
if (active.length == inactive.length) {
for (var i0 = 0; i0 < active.length; i0++) {
particles[i0].des = createVector(active[i0].x, active[i0].y)
}
} else if (active.length > inactive.length) {
for (var i1 = 0; i1 < particles.length; i1++) {
particles[i1].des = createVector(active[i1].x, active[i1].y);
}
for (var i2 = 0; i2 < active.length - inactive.length; i2++) {
var p = new Particle(active[i2].x, active[i2].y),
r = particles.random();
p.pos = r.pos;
particles.push(p);
}
} else {
for (var i3 = 0; i3 < inactive.length - active.length; i3++) {
var r = floor(random(particles.length));
particles[r].shrink();
}
for (var i4 = 0; i4 < particles.length; i4++) {
particles[i4].des = createVector(active[i4].x, active[i4].y);
}
}
}
function switchActive() {
var temp = active;
active = inactive;
inactive = temp;
}
I hope you can help me :)
Thank you already!
Please post your code as an MCVE that we can copy and paste to run. When I try to run your code, I get an error because I don't have the font you're trying to load. Either include the font file or modify your code so we don't need the font file.
But just looking at your code, this sticks out to me:
for (var i = 0; i < particles.length; i++) {
if (particle[i].radius < 0) {
Here you're looping over the particles array, but then using a variable called particle. This is probably a simple typo.
I'm also suspicious of this line:
r = particles.random();
Here you're setting a variable that you haven't defined yet.
When your code contains multiple errors like this, it usually means that you aren't testing in small chunks. You should really get into the habit of working in isolation, only testing one small part until you get that working perfectly. That also makes it easier to post an MCVE if you do get stuck.
Your problem is that your word1 string has a space in it.
textToPoints() doesn't handle non-printable characters.
Try a string with no space or split your string up into to strings and combine the points arrays afterwards.
On Line 1 You define:
var particles = [];
But then you do:
if (particle[i].radius < 0) {
You defined the array "particles", not "particle", so JavaScript can't read the first value as the array "particle" doesn't exist.
Solution:
change:
if (particle[i].radius < 0) {
to:
if (particles[i].radius < 0) {
What I am trying to achieve is to allocate a panel to the column with the least amount of panels in it, and if 2 of the columns have an equal amount of panels then I take the first column and insert it there. I have attempted to implement this, which I will show below however I want to first address the problem that I am having. I understand that my code may have many flaws, and so I am open to suggestion on how to make it better. so the error I am getting through firebug is
TypeError: columns[leastItems] is undefined
return columns[leastItems].id;
and here is my javascript code that I have implemented:
function DashboardAllocation() {
var columns = document.querySelectorAll('.col-md-4.column');
var noElemsInCol = new Array(columns.length);
//Get count of children in each column into array
for (var columnNumber = 0; columnNumber < columns.length; columnNumber++) {
noElemsInCol.push(countChildren(columns[columnNumber]));
}
//Compare all values to see if they are all the same or if the first column is 0
if (compareAllValues(noElemsInCol) || countChildren(columns[0] === 0)) {
//if it is then return the first columns id
return columns[0].id;
}
//Reference http://www.programmingsimplified.com/c/source-code/c-program-find-minimum-element-in-array
var leastItems = 1;
var minimum = countChildren(columns[0]);;
for (var i = 1; i < noElemsInCol.length; i++) {
if (noElemsInCol[i] < minimum) {
minimum = noElemsInCol[i];
leastItems = i + 1;
}
}
return columns[leastItems].id;
}
//Compares all the values in the array to check if they are equal
//Reference http://stackoverflow.com/questions/9973323/javascript-compare-3-values
function compareAllValues(a) {
for (var i = 0; i < a.length; i++) {
if (a[i] === null) { return false }
for (var j = 0; j < i; j++) {
if (a[j] !== a[i]) { return false }
}
}
return true;
}
function countChildren(Nodes) {
var childrenCount = 0;
for (var nodeType in Nodes.childNodes) {
//if the nodetype is an element then we will add one
if (nodeType == Node.ELEMENT_NODE) {
childrenCount++;
}
}
return childrenCount;
}
I have referenced the sources where I took code from and hope it helps to see where I am coming from and understand what I am trying to do
You are getting problem as an index leastItems of the array columns is out of range.
Currently You are getting error as in an array of [5] you are trying to fetch the sixth element, using leastItems variable
So either use change
var leastItems = 0;
OR, Use
return columns[leastItems -1 ].id;
I'm trying to create a cycling sliding animation for set of elements, i have two arrays:
var elms = [elm1, elm2, elm3];
var props = [{x,y,width,height,z-index,opacite,....}, {....}, {....}];
on initializing, elms will be positioned in the same order as props: "-> is not part of the syntax it's just to make things easier to explain and it means 'do something with'"
elms[0] -> props[0];
emls[1] -> props[1];
elms[2] -> props[2];
but then i want to cycle them like:
elms[0] -> props[2]
elms[1] -> props[0]
elms[2] -> props[1]
and then:
elms[0] -> props[1]
elms[1] -> props[2]
elms[2] -> props[0]
and so forth...
i tried this:
function index(n, array){
var m = n;
if(n > array.length){
m = n - array.lenth;
}else if(n < 0){
m = array.length + n;
}
return m;
}
var active = 0; //the front element
function slide(direction){
for (i=0; i< elms.length; i++)
{
elms[i] -> props[index(i - active, props)]
}
if(direction == 'fw'){
if(active++ => elms.length){
active = 0;
}else{
active++;
}
}else if(direction == 'bw'){
if(active-- < 0){
active += elms.length;
}else{
active--;
}
}
}
setInterval(function(){slide('fw')}, 3000);
now the above code works fine, but i'm sure this has been done many times before and i'm wondering does anyone know if there is a better less complicated way to do this which allows to loop forward and backward?
If you don't mind modifying the props array, you can just .shift() off the first element and then .push() is onto the end of the array and then once again do:
elms[0] -> props[0];
emls[1] -> props[1];
elms[2] -> props[2];
To rotate the props array, you could just do this:
function rotateProps() {
var front = props.shift();
props.push(front);
}
So, each cycle just call rotateProps() and then repeat what you did the first time.
How about using module? Have a global var that you increment each time you shift, then module that with the length of the arrays. You could access the arrays like: props[shift%len]
If len is 3 (as above), you could get these results if you are accessing the props in relation to the first elmsIdx (0):
POC: jsfiddle.net/Q8dBb, also this would work without modifying your arrays so I believe it would be faster
shift = 0; // (shift+elmsIdx)%len == 0;
shift = 1; // (shift+elmsIdx)%len == 1;
shift = 2; // (shift+elmsIdx)%len == 2;
shift = 3; // (shift+elmsIdx)%len == 0;
shift = 4; // (shift+elmsIdx)%len == 1;
etc
Actually, using an object could make it more flexible (shifting multiple ways, resetting, whatever you want to add). Here is an example for that:
function Shift(len) {
var _len = len;
var _s = 0;
this.left = function() {
_s = (_s + 1)% _len;
}
this.right = function() {
_s = (_s - 1);
if (_s < 0) {
_s = _s + _len;
}
}
this.get = function(idx) {
return (_s + idx)% _len;
}
this.reset = function() {
_s = 0;
}
}
in use: http://jsfiddle.net/6tSup/1/
I'm wondering for some time now why this fails:
if (longest.length >= 3) {
for ( var i = 0; i < longest.length-1; i++) {
var $last[i] = longest[i].splice(-1).toString();
//if ( $( $last[i] ).closest(':jqmData(role="panel")') == "popover" ) {
//var gotoPage = $last[i];
// }
}
}
longest is an array, which contains array elements.
I want to loop through the number of arrays in longest and create variables from each nested arrays' last element. The .splice(-1).toString() fails telling me "missing ; before statement"
What am I doing wrong?
EDIT:
longest will look something like this:
[[#menu, #menuSub1, #menuSub2], [#main, yield, yield], [#pop1, #pop1-1, #pop1-2]]
It's within a function to track the browser-history in a mobile-app with different panels.
EDIT2:
Finished code (Thx Mic):
if (longest.length >= 3) {
var $last = [];
for ( var i = 0; i < longest.length; i++) {
$last.push( longest[i][ longest[i].length - 1 ]);
if ( $( $last[i] ).closest(':jqmData(role="panel")').jqmData('panel') == "popover" ) {
var gotoPage = $last[i]; }
}
}
You should write something like:
if (longest.length >= 3) {
var $last = [];
for ( var i = 0; i < longest.length-1; i++) {
$last.push( longest[i][ longest[i].length - 1 ] );
}
}
and get the values with $last[0]
Or use a hash like:
if (longest.length >= 3) {
var hash = {};
for ( var i = 0; i < longest.length-1; i++) {
hash['$last'+ i] = longest[i][ longest[i].length - 1 ];
}
}
and get the content using for instance hash.$last0