.forEach only moving half of array elements - javascript

Firstly, I'm new to JavaScript and in an effort to gain a better understanding of OOP I've decided to build solitaire (the three-card version mind you). In solitaire--as I'm sure is well known-- you deal out the cards in the whatever pattern and the remaining cards are placed off to the side; I'm calling these the 'reserve' deck. Then you move the cards you dealt around following the rules of the game (can only place a red 6 on a black 7, etc.) and when you run out of options you can pull three cards off the top of 'reserve' and see if you can use the third card to continue playing. If not, you pull three more cards, so on and so forth until you run out of cards in the 'reserve' deck. At this point, all the cards you pulled off the top of 'reserve' deck can then get placed back into the 'reserve' deck and then reused in the same manner.
And this is where my javascript is breaking. So I've created a Table object with the properties playSlots, winSlots, reserve and pick. playSlots is an array of arrays in which cards get dealt into, reserve is an array of the cards existent within the 'reserve' deck, winSlots isn't relative to this question and pick is an array that becomes populated with cards from reserve as it becomes necessary throughout game play. Pretty self-explanatory. When reserve becomes empty and you want to put the pick cards back into it, my code for this is currently:
if(!Array.isArray(newGame.reserve) || !newGame.reserve.length){
newGame.pick.forEach(function(cur, i, arr){
newGame.reserve.push(arr.shift());
});
}
The problem with this is that this only iterates through half of the cards in the pick array. I went through it in the debugger and it is, in fact adding the cards back into the reserve deck one at a time but once it gets to the 13th card it breaks out of the loop (28 cards cards get dealt out in the solitaire pattern, leaving 24 in the reserve deck...).
I was pretty sure this issue has something to do with the !newGame.reserve.length condition. That condition is something I found here:
Check if array is empty / does not exist. JS
and although the answer-er is pretty clear in his his explanation of this, I'm still kinda fuzzy on what it means. Thing is, I also tried this for a condition:
if(newGame.reserve[0] === undefined)
and had the exact same result. The .forEach loop is only iterating over half of the array elements.... What am I missing here?

You can achieve this easier using Array splice
Note: this reverses pick to the end of reserve, whereas your code does not
If you do not need it reversed, simply remove the .reverse()
It's not clear if you want pick reversed into reserve or not
var newGame = {
pick: [1,2,3,4],
reserve: [10,11,12]
};
newGame.reserve.push(...newGame.pick.splice(0, newGame.pick.length).reverse());
console.log(newGame);
in "old school" javascript, this can be written using .push.apply
var newGame = {
pick: [1,2,3,4],
reserve: [10,11,12]
};
newGame.reserve.push.apply(newGame.reserve, newGame.pick.splice(0, newGame.pick.length).reverse());
console.log(newGame);

Related

I am trying to remove items from an array of objects used as projectiles for players or enemies to shoot in games made with JavaScript

I am practicing with making players and enemies for 2d games using vanilla JavaScript and HTML Canvas. The only problem I have is that I am trying to remove the projectiles from the playerProjectiles array when the projectile goes off of the screen. This is so that the game doesn't have to keep track of a bunch of projectiles that are not even on the screen, so the game will run smoother. I have tried sifting through the array using .forEach and splicing the current projectile that it is looping through as long as that projectile is off the screen. However, using this method, if there are multiple projectiles on the screen and one of them goes off of the screen, the entire array gets spliced and all of the projectiles are removed. What am I doing wrong here? Also, would it be better to put the code for the different mechanics of the projectiles in a different function? Etc. moving the projectiles up when they are shot out, actually drawing them to the screen, splicing them from the array when they go off the screen.
function populatePlayerProjectilesArray() {
playerProjectiles.forEach(projectile => {
projectile.draw();
projectile.y -= pdy;
if(projectile.y <= 0 - projectile.rad) {
playerProjectiles.splice(projectile)
}
})
}
Array.prototype.splice()
Examples:
splice(start)
splice(start, deleteCount)
deleteCount Optional An integer indicating the number of elements in the array to remove from start. If deleteCount is omitted [...], then all the elements from start to the end of the array will be deleted.
I think you want to change your splice statement to:
playerProjectiles.splice(projectile, 1)

Determine direction of change in array

Given a sorted array, eg. [1,2,3,4,5] and a variation of this array, where one of the items got moved to a different position (so no longer sorted) eg. [1,2,5,3,4] or [2,3,4,1,5] I need to reliably determine the "direction" of the move - left or right depending on which way that one element got moved
(5 got moved left in first example, 1 got moved right in a second example)
At the moment I have a solution that walks (from the left) over arrays and compares their values at index i - as soon as they are not the same (to determine point of discrepancy), it then compares values at i+1. if old[i+1] > new[i+1] then left, otherwise right
//pseudocode:
function(old, now) {
for(var i in old) {
if (old[i] !== now[i]) {
return old[i+1] > now[i+1] ? "left" : "right"
}
}
}
EDIT
is there a more reliable (and potentially more efficient) solution to that problem? at the moment it gives "false positives" in certain situations. Do we event need the first array? its always sorted and sequential.
There is not really any room for improvements in your solution - You won't find a way to solve your problem without going trough all members of the array and checking them against the member in the other array.
Your current time complexity is O(n), which is actually not too bad. Therefore you should not worry about this function and if your application is working too slow, you should look for other fields to improve on.
Not really an answer, more discussion of the algorithm.
If you want guaranteed iteration from 0 and to ignore inherited enumerable properties, replace for..in with a for, while or do loop.
Given iteration from index 0, the algorigthm you have doesn't work. e.g. in the following:
var old = [1,2,3];
var now = [2,1,3];
value 1 has been moved right. The algorithm will find a miss-match at index 0, then compare the values at index 1. old[1] is greater than now[1] so "left" is returned.
It's also impossible to determine the direction of some moves, e.g. in the above was 1 moved right or 2 moved left? Another example:
var old = [1,2,3,4,5];
var new = [1,2,3,5,4];
Did 4 move right or 5 move left? A rule is required to determine which takes precidence.

Boolean Randomness - Recursion... or not?

Trying to create a random (0/1) boolean operation. I have a multidimensional array set up. So far, everything works. Am I on the right path? I currently use recursion; is there a more efficient way to do this?
function randomMove(){
var cs=b.length,
cr=Math.floor((Math.random()*cs)+1)-1,
cc=Math.floor((Math.random()*cs)+1)-1;
if(b[cr][cc]===""){ // THIS IS DEPENDENT ON EXISTING CODE. VIEW FIDDLE. //
// DO STUFF //
} else { randomMove(); }
}
Is this considered a good way to create a random move for 2 players? Or is recursion the wrong process here?
Fiddle
Select the cells that can possibly be selected, then choose a random one by index.
http://jsfiddle.net/Ehqka/1/
$.fn.random = function(){
return this.eq(Math.floor(Math.random()*this.length));
};
function randomMove(){
$("#board td").not(".o,.comp").random().addClass('comp');
testWin();
}
It selects all cells in the board, drops the ones that have a class of o or comp from the selection, generates a random number between 0 and the number of remaining cells, then selects the cell at that index to add a class to.
Note, however, your method will be "faster" than the above on the first move due to the fact that on the first move, every move is a valid one therefore it will never iterate past the first time. Mine can be slightly optimized to be more efficient on the first by removing the .not(), but your's should still be "faster" because it doesn't have to go to the DOM.
"faster" is relative, my method will grow less efficient as the table grows than yours will on the first move. As more and more moves happen, your method will become less and less efficient since more and more of the possible moves are invalid.

comparing cards from an array created with a for loop

First of all I am pretty new to Javascript and programming in general. So don't be offended if this is a stupid question. I am creating a browser game of Texas Hold'em and first of all I am starting of creating an array of cards in a for-loop then shuffling with Math.random that results in something like [C5,H4,S3,..]
and so on. My question is how do I best compare these cards. My worst fear is the flush and straight-flush.
#DamirDžilić - without any real code to comment on, we can only give conceptual advice. You're going to have to just compare each hand against all possible poker hands, starting with the highest rated hand down to a single pair.
I'd personally suggest that each card be an object:
var card = {suit: "S", value: 9};
Then, a hand would be an array of card objects.
You can then look at suit and card value separately. It would be easier if card values where 2 through 14 and you convert to J, Q, K, A only for display.
Then, each possible poker hand (pair, three of a kind, four of a kind, flush, straight, etc...) would get a score in order of their value in poker (pair = 1, two pair = 2, three of a kind = 3, straight = 4, flush = 5, full house = 6, straight flush = 7, four of a kind = 8, straight flush = 9).
Then, I'd suggest you give each type of hand a score which consist of 10000*hand value + 100*top card in hand + value of kicker. So, a pair of 8's with a K kicker would be worth:
(2*10000) + (8*100) + 13 = 20,813
And, three 2's with an A kicker would be:
(3*10000) + (2*100) + 14 = 30,214
With this type of scoring system, the hand value always dominates, then the top card that's part of the scoring piece of the hand (e.g. 3 queens beats 3 eights), then the kicker breaks any ties.
It would be up to you to write the code for figuring out what kind of hand you have, but basically you have to examine for straights, flushes and how many common cards you have. I'd probably look for pairs first and only if there are no pairs do you look for straights or flushes and I'd make a function to look for each.

Detect loops in computer player in a cardgame

A while ago I created a small cardgame web app for fun. The player plays against the computer and mostly it works fine. Sometimes though the computer player gets into a loop, the point of the game is to lose all your cards and if you don't have a card to play you take the pile. Sometimes the computer plays x,y,z, takes the pile, plays x,yz, takes the pile etc.
I keep track of the moves I've made, so at any point I have an array that looks something like : [C2,D5,H2,S4,C5,H2,S4,C5,H2,S4,C5]
In this case I can see that I've gotten into a loop of playing H2,S4,C5, then taking the pile and then repeating.
So, the generalized problem is, what's the best way to detect repeating patterns in a list? I could probably whip something up using a simple for loop, trying to find the card I'm about to play and if I find that in position x then I could check whether the pattern from x to n repeats at position x-(n-x) to x, but this seems like the kind of problem that could have a nice algorithm for it. How would you code this given the following function signature:
function findLoops(previousMoves, nextMove, maxPatternLength) {
//Return [loopLength, loopCount] or null if there are no loops
}
p.s. this is not a homework assignment, the game exists and is at http://www.idiot-cardgame.com if anyone is interested :)
First the general question: Your suggested method
trying to find the card I'm about to play and if I find that in position x then I could check whether the pattern from x to n repeats at position x-(n-x) to x,
looks really good. I would suggest basically the same. It is O(n) and needs a fixed amount of storage, and is simple: what else would you wish for?
Second: You can check for repetition in games generally if you keep a hash table of all previous game states (complete state, nothing left out). Everytime you reach a new state look up if it is in the hashtable, if its in it: you game state is looping.
In Javascript you have builtin hastables so this is very easy to do with something similar like this:
new_state = next_move(old_state);
new_encoded_state = encode(new_state); // make it into a string
if (allstates[new_encoded_state]) {
// we are looping!
} else {
allstates[new_encoded_state] = 1;
// no looping
}
The variable allstates is not an Array but of type Object. You can have array like access with strings and this uses the Object as hastable.

Categories

Resources