why is comparing two values isn't working? - javascript

I'm trying to make a winning algorithm for a simple connect four game, this code is for checking if there is 4 same values in a horizontal line:
function win(clicked) {
var cellco = clicked.className.match(/[a-zA-Z]+|[0-9]+/g); // example output:["col", "3", "row", "7"]
var playervalue = document.getElementById('tbl').rows[cellco[3]].cells[cellco[1]].children[0];
var count = 0;
for (var i = 0; i < GRID_SIZE; i++) {
var slot = document.getElementById('tbl').rows[cellco[3]].cells[i].children[0];
if (slot == playervalue) {
count++;console.log(count)//it only shows 1 even after having 4 objects
if (count >=4) {
return true;
} else {
count = 0;
}
}
}
return false;
}

var count = 0;
The count starts at zero.
count++;console.log(count)
You increment it and log it. It is now 1.
if (count >=4) {
It is not. 1 is less than 4.
count = 0;
You set it to zero.
(Then you go back to the step where you increment it to 1 and log it).

Related

Connect Four game in Javascript - how do I detect a horizontal win?

I try to code a Connect Four game and define a winner when 4 pieces are aligned horizontally. I haven't moved to the diagonal part yet, want to get this one first.
What I try to achieve - check if the current location (i) and i+6, meaning the next column, same row, have the same player's class.
Problem - "Count" never adds up for horizontal victory.
The problematic part starts from checkForHorizontalVictory.
Pay attention that I switched for loop to go through allSlots.length, not slots.length, as I want all 42 slots. You'll see the rest.
Anyway, how do I write a code to understand where the player's button is, get the index, and check if index+6 (and later -6) has the same class?
var currentPlayer = "player1";
var column = $(".column");
var allSlots = $(column.children());
function switchPlayer() {
if (currentPlayer === "player1") {
currentPlayer = "player2";
} else {
currentPlayer = "player1";
}
}
$(".column").on("click", function (e) {
var col = $(e.currentTarget);
var slots = col.children();
for (var i = slots.length - 1; i >= 0; i--) {
var currentSlot = slots.eq(i);
var hole = currentSlot.children();
if (!hole.hasClass("player1") && !hole.hasClass("player2")) {
hole.addClass(currentPlayer);
var verticalVictory = checkForVerticalVictory(slots);
var horizontalVictory = checkForHorizontalVictory(slots);
if (verticalVictory) {
}
if (horizontalVictory) {
}
switchPlayer();
break;
}
}
});
function checkForVerticalVictory(slots) {
var count = 0;
for (var i = 0; i < slots.length; i++) {
console.log(slots.length, "this is slots length in vertical");
var currentSlot = slots.eq(i);
var hole = currentSlot.children();
if (hole.hasClass(currentPlayer)) {
count++;
} else {
count = 0;
}
console.log(count, "this is count!");
if (count == 4) {
alert("you won! 🎉");
return true;
}
}
console.log("no wins yet ❌");
return false;
}
function checkForHorizontalVictory(slots) {
var count = 0;
for (var i = 0; i < allSlots.length; i++) {
var thisSlot = allSlots.eq(i);
var thisHole = thisSlot.children(i);
if (
thisHole.hasClass(currentPlayer) && allSlots.eq(i + 6).hasClass(currentPlayer)
) {
count++;
console.log("this is count", count);
} else {
count = 0;
}
console.log("this is count", count);
if (count == 4) {
// 3. If the counter reaches 4 - we have a win
alert("you won! 🎉");
return true;
}
}
console.log("no wins yet ❌");
return false;
}
I can't be sure, since I can't reproduce your issue. But here is what I think:
In the for loop, when it reaches the indexes of the last column and checks for i + 6 it makes allSlots.eq(42) to allSlots.eq(47)... And that ends up in a false. So count gets resetted to zero.
So change the loop too:
for (var i = 0; i < allSlots.length - 6; i++) {
I also would move that after the loop. Notice the condition change.
if (count <= 4) {
// 3. If the counter reaches 4 - we have a win
alert("you won! 🎉");
return true;
}
In short, column #7 was already checked while checking column #6... ;)
EDIT
Using the full code from your gitHub, I changed the way you are checking the holes of a particular row.
First, pass the slot index to checkForHorizontalVictory
So in that function, you know exactly which slot is the starting point of your logic.
You can now get all the slots on the same row by filtering allSlots.
I used Arra.from() to be able to use JS .filter with a modulo of the deducted rowNum.
Then, recreate a jQuery object from that filtered element list.
function checkForHorizontalVictory(currentSlotIndex) {
var count = 0;
let rowNum = currentSlotIndex % 6; // rows from 0 to 5, top to bottom
console.log("rowNum", rowNum);
// Get a JS array from the jQuery collection
var thisrow = Array.from(allSlots).filter((s, i) => i % 6 == rowNum);
console.log("thisrow", thisrow);
console.log("thisrow length", thisrow.length);
// Create a jQuery collection from the filtered above
var $thisrow = $(thisrow)
for (var i = 0; i < thisrow.length; i++) {
// var thisrow = allSlots.eq(currentRow);
console.log(thisrow[i]);
// Tests to confirm you are checking the right row
// thisHole.addClass("test");
// thisHole.text(i)
if (
// jQuery object for the specific row
$thisrow
.eq(i + 1)
.children()
.hasClass(currentPlayer)
) {
count++;
}
console.log("this is count", count);
if (count == 4) {
console.log("you won! 🎉");
return true;
}
}
console.log("no wins yet ❌");
return false;
}
CodePen with your modified code
For fun, uncomment the Tests to confirm you are checking the right row.

Why aren’t my two values comparing correctly?

I have objects that I am trying to compare their values and make a function happen if one value is greater than the other. But My code seems to be wrong because even though the value is greater than the other, it still console logs "false" instead of true. I even console logged the value to check if it was greater and it was. Here's my code.
var clicks1 = 0;
function onClick() {
clicks1 += 1;
document.getElementById("clicks1").innerHTML = clicks1;
document.getElementById("clicks1").value = clicks1;
var clicks2 = 0;
function onClick() {
clicks2 += 1;
document.getElementById("clicks2").innerHTML = clicks2;
document.getElementById("clicks2").value = clicks2;
playbutton.onclick = function () {
const click1var = document.getElementById("clicks1").value
const click2var = document.getElementById("clicks2").value
console.log(click1var)    //Console shows 3
console.log(click2var)    //Console shows 1
if (click1var < click2var) {
console.log('true')
} else {
console.log('false')  //Console shows false.  
}
}
click1var is 3
click2var is 1
if (click1var < click2var){ // are you asking if 3 is lower than 1 (FALSE)
then it will go to the else.

Why is my code executing far more times than it's supposed to?

I'm currently working on a poker odds generator and it's pretty much done, except for one thing. The program runs far more often than it should. I know that this is coming from the compare() function, because when I add a variable Q to keep track of the number of times the main function playPoker() has run, it produces a huge number until I comment it out - at which point it returns the exact number I'd expect.
Can any of you point out where I'm going wrong with this. I can't see why one function should lead to Q being incremented so much more than it should be. Literally, the last time I ran it the number was (32,487 instead of 100). I present the code below (without the poker hand-checking functions because they're not really important). Why is playPoker() running so many times?!
var Q = 0;
function playPoker(tableSize) {
//Create the players, the deck and the card table which stores the 5 cards the players have in common
var players = createPlayers(tableSize);
var deck = createDeck();
var cardTable = new CardTable();
//Deal each player two cards
for (i = 0; i < 2; i++) {
for (j = 0; j < players.length; j++) {
deal(deck, players[j]);
}
}
//Put five cards down on the table
for (k = 0; k < 5; k++) {
deal(deck, cardTable);
}
//Check for various winning hands here for each player
for (m = 0; m < players.length; m++) {
//Merge the player's two cards with the five cards on the table
var subjectCards = (players[m].cards).concat(cardTable.cards);
//Make an array of the values of each of the seven cards, which will be used to determine 4 of a kind, 3 of a kind and pairs
var valuesInOrder = getValuesInOrder(subjectCards);
//Create a dummy array, so that valuesInOrder remains unchanged
var straightValues = valuesInOrder.slice();
//Remove any duplicate card, meaning that the array contains only unique values (i.e. 2, 4, 5, 7, K ... NOT 2, 2, 2, 8, K, K, A)
var straightValues = straightenUp(straightValues);
//Calculate how many pairs are in the hand
var numPairs = howManyPairs(valuesInOrder, straightValues, players[m]);
//Find out whether the 5 table cards contain three cards of the same suit. If not, then a flush is impossible.
var flushPotential = threeSameSuit(cardTable.cards);
//Find out which hand each player has (i.e. straight, 3OAK, pair)
checkPokerHand(subjectCards, straightValues, valuesInOrder, flushPotential, numPairs, players[m])
}
var rankedPlayers = compare(players);
//return players;
Q++;
return Q;
}
And here's the for-loop that sets it off.
for (z = 0; z < 100; z++;) {
playPoker(4);
}
And here's the compare() function:
function compare(players) {
var remPlayers = players.slice();
var rankings = [];
var potentialWinners = [];
//Collect all the players' rankings in an array
for (i = 0; i < remPlayers.length; i++) {
rankings.push(remPlayers[i].rank);
}
//Find the highest ranking
var highestRank = getHighestValue(rankings);
//Move any players with the highest ranking to an array for potential winners
for (j = 0; j < remPlayers.length; j++) {
if (remPlayers[j].rank == highestRank) {
potentialWinners.push(remPlayers[j]);
remPlayers.splice(j, 1);
j--;
}
}
//With all potential winners gone, mark all other players with an L for losing.
for (k = 0; k < remPlayers.length; k++) {
remPlayers[k].result = 'L'
}
var foundWinner = false;
if (potentialWinners.length < 2) {
potentialWinners[0].result = 'W';
foundWinner = true;
}
//Check there is more than one potential winner. If not, the only guy in the array has won.
if (!foundWinner) {
//Loop through all players first cards and find the highest value, then delete any who don't have that, marking them with 'L'.
//If there is no single remnant, do the same for second cards, then third, then fourth, etc.
for (p = 0; p < 5; p++) {
var subRankings = [];
for (q = 0; q < potentialWinners.length; q++) {
subRankings.push(potentialWinners[q].bestHand[p]);
}
var highestSubRanking = getHighestValue(subRankings);
//Mark 'L' and remove any player who does not meet the highest subranking
for (m = 0; m < potentialWinners.length; m++) {
if (potentialWinners[m].bestHand[p] < highestSubRanking) {
potentialWinners[m].result = 'L';
potentialWinners.splice(m, 1);
}
if (potentialWinners.length < 2) {
potentialWinners[0].result = 'W';
//Set this flag to true to break the loop because a winner has been found
foundWinner = true;
break;
}
}
//Break the loop if we have found a winner
if (foundWinner) {
break;
}
//If we still haven't found a winner by the end of the 5th loop, all remaining players draw
if (p == 4) {
for (z = 0; z < potentialWinners.length; z++) {
potentialWinners[z].result = 'D';
}
}
if (foundWinner) {
break;
}
}
}
return players;
}
Try using var declarations on your variables to manage their scope within their relevant functions?

"Look and say sequence" in javascript

1
11
12
1121
122111
112213
122211
....
I was trying to solve this problem. It goes like this.
I need to check the former line and write: the number and how many time it was repeated.
ex. 1 -> 1(number)1(time)
var antsArr = [[1]];
var n = 10;
for (var row = 1; row < n; row++) {
var lastCheckedNumber = 0;
var count = 1;
antsArr[row] = [];
for (var col = 0; col < antsArr[row-1].length; col++) {
if (lastCheckedNumber == 0) {
lastCheckedNumber = 1;
antsArr[row].push(lastCheckedNumber);
} else {
if (antsArr[row-1][col] == lastCheckedNumber) {
count++;
} else {
lastCheckedNumber = antsArr[row-1][col];
}
}
}
antsArr[row].push(count);
antsArr[row].push(lastCheckedNumber);
}
for (var i = 0; i < antsArr.length; i++) {
console.log(antsArr[i]);
}
I have been on this since 2 days ago.
It it so hard to solve by myself. I know it is really basic code to you guys.
But still if someone who has a really warm heart help me out, I will be so happy! :>
Try this:
JSFiddle Sample
function lookAndSay(seq){
var prev = seq[0];
var freq = 0;
var output = [];
seq.forEach(function(s){
if (s==prev){
freq++;
}
else{
output.push(prev);
output.push(freq);
prev = s;
freq = 1;
}
});
output.push(prev);
output.push(freq);
console.log(output);
return output;
}
// Sample: try on the first 11 sequences
var seq = [1];
for (var n=0; n<11; n++){
seq = lookAndSay(seq);
}
Quick explanation
The input sequence is a simple array containing all numbers in the sequence. The function iterates through the element in the sequence, count the frequency of the current occurring number. When it encounters a new number, it pushes the previously occurring number along with the frequency to the output.
Keep the iteration goes until it reaches the end, make sure the last occurring number and the frequency are added to the output and that's it.
I am not sure if this is right,as i didnt know about this sequence before.Please check and let me know if it works.
var hh=0;
function ls(j,j1)
{
var l1=j.length;
var fer=j.split('');
var str='';
var counter=1;
for(var t=0;t<fer.length;t++)
{
if(fer[t]==fer[t+1])
{
counter++;
}
else
{
str=str+""+""+fer[t]+counter;
counter=1;
}
}
console.log(str);
while(hh<5) //REPLACE THE NUMBER HERE TO CHANGE NUMBER OF COUNTS!
{
hh++;
//console.log(hh);
ls(str);
}
}
ls("1");
You can check out the working solution for in this fiddle here
You can solve this by splitting your logic into different modules.
So primarily you have 2 tasks -
For a give sequence of numbers(say [1,1,2]), you need to find the frequency distribution - something like - [1,2,2,1] which is the main logic.
Keep generating new distribution lists until a given number(say n).
So split them into 2 different functions and test them independently.
For task 1, code would look something like this -
/*
This takes an input [1,1,2] and return is freq - [1,2,2,1]
*/
function find_num_freq(arr){
var freq_list = [];
var val = arr[0];
var freq = 1;
for(i=1; i<arr.length; i++){
var curr_val = arr[i];
if(curr_val === val){
freq += 1;
}else{
//Add the values to the freq_list
freq_list.push([val, freq]);
val = curr_val;
freq = 1;
}
}
freq_list.push([val, freq]);
return freq_list;
}
For task 2, it keeps calling the above function for each line of results.
It's code would look something like this -
function look_n_say(n){
//Starting number
var seed = 1;
var antsArr = [[seed]];
for(var i = 0; i < n; i++){
var content = antsArr[i];
var freq_list = find_num_freq(content);
//freq_list give an array of [[ele, freq],[ele,freq]...]
//Flatten so that it's of the form - [ele,freq,ele,freq]
var freq_list_flat = flatten_list(freq_list);
antsArr.push(freq_list_flat);
}
return antsArr;
}
/**
This is used for flattening a list.
Eg - [[1],[1,1],[1,2]] => [1,1,1,1,2]
basically removes only first level nesting
**/
function flatten_list(li){
var flat_li = [];
li.forEach(
function(val){
for(ind in val){
flat_li.push(val[ind]);
}
}
);
return flat_li;
}
The output of this for the first 10 n values -
OUTPUT
n = 1:
[[1],[1,1]]
n = 2:
[[1],[1,1],[1,2]]
n = 3:
[[1],[1,1],[1,2],[1,1,2,1]]
n = 4:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1]]
n = 5:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3]]
n = 6:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3],[1,2,2,2,1,1,3,1]]
n = 7:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3],[1,2,2,2,1,1,3,1],[1,1,2,3,1,2,3,1,1,1]]
n = 8:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3],[1,2,2,2,1,1,3,1],[1,1,2,3,1,2,3,1,1,1],[1,2,2,1,3,1,1,1,2,1,3,1,1,3]]
n = 9:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3],[1,2,2,2,1,1,3,1],[1,1,2,3,1,2,3,1,1,1],[1,2,2,1,3,1,1,1,2,1,3,1,1,3],[1,1,2,2,1,1,3,1,1,3,2,1,1,1,3,1,1,2,3,1]]

Panels not adding to columns

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;

Categories

Resources