I have got a pretty complicated issue, I tried everything and its not working properly. So the conception is (i just copied the interesting part of it, otherwise it would be few hundred more lines) :
The program is a card game and 24 cards (4 different colors, one is always stronger,it is called ADU) are distributed randomly among 4 players (4 arrays). The table where you put down the cards are represented by "asztal" array. First the human player puts a card, then the computers should reach in this order:
If they have same color and higher value - pick that card
If they have same color and any value - pick that card
If they dont have matching color, any car from the special color set (for being simple, its the first card the loop would find in the array)
If they dont have matching color, nor card from special color set, than the first element of the array (player[0]).
If you run my code, you would see it is not grabbing 1/1/1 card from each array, but sometimes more. And those cards do disappear, and not getting into the asztal array. My code: (https://jsfiddle.net/daxa3pL2/)
function CardA(name,value,adu){
this.name = name;
this.value = value;
};
function CardB(name,value,adu){
this.name = name;
this.value = value;
};
function CardC(name,value,adu){
this.name = name;
this.value = value;
};
function CardD(name,value,adu){
this.name = name;
this.value = value;
};
CardA.prototype.adu = false;
CardB.prototype.adu = false;
CardC.prototype.adu = false;
CardD.prototype.adu = false;
var a9 = new CardA("Tök kilenc",0);
var a10 = new CardA("Tök tíz",10);
var aal = new CardA("Tök alsó",2);
var afel = new CardA("Tök felső",3);
var akir = new CardA("Tök király",4);
var aasz = new CardA("Tök ász",11);
var b9 = new CardB("Levél kilenc",0);
var b10 = new CardB("Levél tíz",10);
var bal = new CardB("Levél alsó",2);
var bfel = new CardB("Levél felső",3);
var bkir = new CardB("Levél király",4);
var basz = new CardB("Levél ász",11);
var c9 = new CardC("Makk kilenc",0);
var c10 = new CardC("Makk tíz",10);
var cal = new CardC("Makk alsó",2);
var cfel = new CardC("Makk felső",3);
var ckir = new CardC("Makk király",4);
var casz = new CardC("Makk ász",11);
var d9 = new CardD("Szív kilenc",0);
var d10 = new CardD("Szív tíz",10);
var dal = new CardD("Szív alsó",2);
var dfel = new CardD("Szív felső",3);
var dkir = new CardD("Szív király",4);
var dasz = new CardD("Szív ász",11);
CardC.prototype.adu = true;
var player1 = [c9,b9,b10,d9,a9,d10];
var player2 = [a10,aal,dal,c10,cal,bal];
var player3 = [bfel,bkir,basz,dfel,dkir,dasz];
var player4 = [afel,akir,aasz,cfel,ckir,casz];
var asztal = [];
asztal.push(player1.splice(0,1)[0]);
var player2card1 = function() {
for (i = 0; i < player2.length; i++) {
if (Object.getPrototypeOf(player2[i]) == Object.getPrototypeOf(asztal[0]) && player2[i].value > asztal[0].value) {
asztal.push(player2.splice(i,i+1)[0])
return
}
}
if (asztal.length == 1) {
for (i = 0; i < player2.length; i++) {
if (Object.getPrototypeOf(player2[i]) == Object.getPrototypeOf(asztal[0])) {
asztal.push(player2.splice(i,i+1)[0])
return
}
}
}
if (asztal.length == 1){
for (i = 0; i < player2.length; i++) {
if (player2[i].adu == true) {
asztal.push(player2.splice(i,i+1)[0])
return
}
}
}
if (asztal.length == 1) {
asztal.push(player2.splice(0,1)[0])
return
}
};
var player3card1 = function() {
for (i = 0; i < player3.length; i++) {
if (Object.getPrototypeOf(player3[i]) == Object.getPrototypeOf(asztal[0]) && player3[i].value > asztal[0].value) {
asztal.push(player3.splice(i,i+1)[0])
return
}
}
if (asztal.length == 2) {
for (i = 0; i < player3.length; i++) {
if (Object.getPrototypeOf(player3[i]) == Object.getPrototypeOf(asztal[0])) {
asztal.push(player3.splice(i,i+1)[0])
return
}
}
}
if (asztal.length == 2){
for (i = 0; i < player3.length; i++) {
if (player3[i].adu == true) {
asztal.push(player3.splice(i,i+1)[0])
return
}
}
}
if (asztal.length == 2) {
asztal.push(player3.splice(0,1)[0])
return
}
};
var player4card1 = function() {
for (i = 0; i < player4.length; i++) {
if (Object.getPrototypeOf(player4[i]) == Object.getPrototypeOf(asztal[0]) && player4[i].value > asztal[0].value) {
asztal.push(player4.splice(i,i+1)[0])
return
}
}
if (asztal.length == 3) {
for (i = 0; i < player4.length; i++) {
if (Object.getPrototypeOf(player4[i]) == Object.getPrototypeOf(asztal[0])) {
asztal.push(player4.splice(i,i+1)[0])
return
}
}
}
if (asztal.length == 3){
for (i = 0; i < player4.length; i++) {
if (player4[i].adu == true) {
asztal.push(player4.splice(i,i+1)[0])
return
}
}
}
if (asztal.length == 3) {
asztal.push(player4.splice(0,1)[0])
return
}
};
player2card1();
player3card1();
player4card1();
console.log(player1);
console.log(player2);
console.log(player3);
console.log(player4);
console.log(asztal);
So I debugged your code and there are two fundamental mistakes I found:
1: When you use the splice inside a loop, the indices will change. So, when you do for example
asztal.push(player2.splice(i,i+1)[0])
and put it inside a loop, the indices for player2 matching your condition will change as soon as you do the splice. So the next iteration of your loop will give incorrect results/ miss an index of an object that should be removed.
A possible solution to this is that instead of splice, inside your for-loops, just insert elements into asztal, and DON'T splice the parent. Then outside the loop, splice them from from the players using a FILTER function as follows:
var player2card1 = function() {
for (i = 0; i < player2.length; i++) {
if (Object.getPrototypeOf(player2[i]) == Object.getPrototypeOf(asztal[0]) && player2[i].value > asztal[0].value) {
asztal.push({name: player2[i].name, value: player2[i].value, prototype: player2[i].prototype});
player2[i].name = "delete";
return
}
}
player2.filter((each)=>{return each.name!== "delete"});
2: The second mistake (that I don't think is the problem here but still can cause trouble) is your use of "==". In Javascript, try to use '===' as far as possible as it also checks the type along with equality.
A little refactoring can go a long way to making this clear.
// define a card type class
function CardType(type, adu)
{
// This simply says that if ADU is undefined (not passed) then
// ADU should be set to false by default
this.adu = (typeof adu === 'undefined' ? false : adu);
this.type = type;
}
function Card(name, value, type)
{
this.name = name;
this.value = value;
this.type = type;
}
// Define our card types
var CardA = new CardType("A");
var CardB = new CardType("B");
var CardC = new CardType("C", true);// set to be ADU
var CardD = new CardType("D");
// Define our cards
var a9 = new Card("Tök kilenc",0, CardA);
var a10 = new Card("Tök tíz",10, CardA);
var aal = new Card("Tök alsó",2, CardA);
var afel = new Card("Tök felső",3, CardA);
var akir = new Card("Tök király",4, CardA);
var aasz = new Card("Tök ász",11, CardA);
var b9 = new Card("Levél kilenc",0, CardB);
var b10 = new Card("Levél tíz",10, CardB);
var bal = new Card("Levél alsó",2, CardB);
var bfel = new Card("Levél felső",3, CardB);
var bkir = new Card("Levél király",4, CardB);
var basz = new Card("Levél ász",11, CardB);
var c9 = new Card("Makk kilenc",0, CardC);
var c10 = new Card("Makk tíz",10, CardC);
var cal = new Card("Makk alsó",2, CardC);
var cfel = new Card("Makk felső",3, CardC);
var ckir = new Card("Makk király",4, CardC);
var casz = new Card("Makk ász",11, CardC);
var d9 = new Card("Szív kilenc",0, CardD);
var d10 = new Card("Szív tíz",10, CardD);
var dal = new Card("Szív alsó",2, CardD);
var dfel = new Card("Szív felső",3, CardD);
var dkir = new Card("Szív király",4, CardD);
var dasz = new Card("Szív ász",11, CardD);
var player1 = [c9,b9,b10,d9,a9,d10];
var player2 = [a10,aal,dal,c10,cal,bal];
var player3 = [bfel,bkir,basz,dfel,dkir,dasz];
var player4 = [afel,akir,aasz,cfel,ckir,casz];
var asztal = [];
// It doesn't really make sense to splice the array because
// you are changing the array.
// asztal.push(player1.splice(0,1)[0]);
// This line can be replaced with a simple:
asztal.push(player1[0]);
// This function has lots of redundant code and we can simplify it greatly
// as well as generalize it to work for each player
function getNextCard(player, card){
// By default we take the first card unless we find a better one along the way.
var matchCase2 = null, // same type, any value
matchCase3 = null, // special set
matchCase4 = player[0]; // any card
for(i = 0; i < player.length; i++)
{
// Check our first case
if(player[i].type.type == card.type.type &&
player[i].value > card.value){
return player[i];
}
if(matchCase2 === null && player[i].type.type == card.type.type){
matchCase2 = player[i];
}
if(matchCase3 === null && player[i].type.adu === true){
matchCase3 = player[i];
}
}
if(matchCase2 !== null) return matchCase2;
if(matchCase3 !== null) return matchCase3;
return matchCase4;
}
console.log(getNextCard(player2, asztal[0]));
console.log(getNextCard(player3, asztal[0]));
console.log(getNextCard(player4, asztal[0]));
I am trying to add multiple instances of different objects to another object's array. I'm having trouble however.
*Creates the player*
function Player(){
this.name = "";
this.status = "Alive";
this.primaryClass = null;
this.secondaryClass = null;
this.strength = 0;
this.stamina = 0;
this.mystica = 0;
this.health = 0;
this.primaryWeapon = null;
this.offHand = null;
this.accuracy = 0;
this.block = 0;
this.baseDamage = 0;
this.maxDamage = 0;
this.attackSpeed = 0;
this.shield = null;
this.armor = null;
this.armorRating = 0;
this.exp = 0;
}
*Creates the sword weapon*
function LongSword(){
this.name = "";
this.attackSpeed = 1;
this.baseDamage = 10;
this.maxDamage = 15;
this.durability = 100;
this.block = 5;
this.exp = 0;
}
*Creates the Long Sword skills*
function Stab(){
this.name = "Stab";
this.status = "Unlocked";
this.damage = 0;
this.damageModifier = 0.75;
this.cooldown = 5;
this.exp = 0;
this.desc = "Stabs your opponent for an additional " +parseInt(this.damageModifier * 100) +"% of your base damage.";
}
*Equips the Player weapon(s)*
Player.prototype.equipWeapon = function equipWeapon(main, offHand){
if(this.primaryClass.dualWield){
this.primaryWeapon = main;
if(offHand){
this.offHand = offHand;
this.baseDamage += (this.strength + (main.baseDamage + (offHand.baseDamage / 2))) / 10;
this.maxDamage += (this.strength + (main.maxDamage + (offHand.maxDamage / 2))) / 5;
this.attackSpeed += main.attackSpeed + (offHand.attackSpeed / 2);
this.block += main.block + offHand.block;
}
}
else{
this.primaryWeapon = main;
this.offHand = null;
this.baseDamage += (this.strength + main.baseDamage) / 10;
this.maxDamage += (this.strength + main.maxDamage) / 5;
this.attackSpeed += main.attackSpeed;
this.block += main.block;
}
if(!this.primaryClass.dualWield && offHand){
console.log("Your class can not wield dual weapons.");
}
}
*Equips the Weapon skills*
LongSword.prototype.skills = function skills(skill){
this.skills = [];
skill.damage = parseFloat((this.baseDamage / skill.damageModifier).toFixed(1));
this.skills.push(skill);
}
These objects construct the basic elements of what I'm trying to do. So when I go to instantiate each one,
var Robert = new Player();
Robert.equipWeapon(new LongSword());
Robert.primaryWeapon.skills(new Stab());
I am getting the results I want. However, if I were to try to add another instance of Stab() so that it looks like this
var Robert = new Player();
Robert.equipWeapon(new LongSword());
Robert.primaryWeapon.skills(new Stab());
Robert.primaryWeapon.skills(new Stab());
I get the TypeError: Robert.primaryWeapon.skills is not a function. Why would it work correctly once, but not a second time. The end result of which I'm trying to achieve is that if consoled out Robert.primaryWeapon.skills, I should see two instances of the Stab object.
There are two issues in your Longsword's prototype.
First, you are replacing your function with your storing skill array, which have the same name :
LongSword.prototype.skills = function skills(skill){
this.skills = []; //Overrides your function
...
Which leads to your error, Robert.primaryWeapon.skills is not a function, cause once you call it, it is an array indeed.
To fix it, just change the name of one of the function or of the array.
Secondly, you are initializing your skills array to an empty array each time you call the function, resetting it every time. You should initialize it in Longsword's protoype.
Here's a an example with these fixes (fiddle with it if you want):
function LongSword(){
this.skills = [];
...
LongSword.prototype.addSkill = function skills(skill){
...
Then, you'll be able to add multiple skills :
var Robert = new Player();
Robert.equipWeapon(new LongSword());
Robert.primaryWeapon.addSkill(new Stab());
Robert.primaryWeapon.addSkill(new Stab());
I'm attempting to build a poker game. The method in question is very simple, and it works when it runs the first time.
This part isn't perfect convention because I'm just using it to test my methods:
var $ = function (id) { return document.getElementById(id); };
var test = function() {
var deck = new POKER.Deck();
var hand = new POKER.Hand();
for (var i = 0; i < 7; i++){
hand.addCard(deck.dealCard());
}
hand.sortByRank();
for (var j = 0; j < 7; j++){
var img = document.createElement("img");
var card = hand.getCardAtIndex(j); //** <------- WORKS HERE**
img.src = card.getImage();
$("images").appendChild(img);
}
var testHand = new POKER.Hand();
testHand = hand.removePairs();
for (var k = 0; k < testHand.length; k++) {
var img2 = document.createElement("img");
var card2 = testHand.getCardAtIndex(k); // **<------FAILS HERE**
img2.src = card2.getImage();
$("handImg").appendChild(img2);
}
};
window.onload = function() {
test();
};
The first and second loop work, and the hand is displayed and everything. When it gets to the last loop, the debugger tells me "TypeError: testHand.getCardAtIndex is not a function"
I was attempting to test the removePairs method (to test for straights more easily), and when watching the variables in the debugger, testHand clearly gets populated correctly. The method seems to work just fine.
getCardAtIndex:
POKER.Hand.prototype.getCardAtIndex = function(index) {
return this.cards[index];
};
removePairs:
POKER.Hand.prototype.removePairs = function(){
var allCards = this.cards;
var tempCards = [];
var uniqueRanks = [];
var unique;
for(var i = 0; i < allCards.length; i++){
unique = true;
for(var j = 0; j < uniqueRanks.length; j++){
if(allCards[i].getRank() == uniqueRanks[j]){
unique = false;
break;
}
}
if(unique){
uniqueRanks.push(allCards[i].getRank());
tempCards.push(allCards[i]);
}
}
return tempCards;
};
I'm completely perplexed.
var testHand = new POKER.Hand();
testHand = hand.removePairs();
hand.removePairs() returns an Array, not a Hand object.
That's why you don't have access to the getCardAtIndex method.
If cards is a public property you could do:
testHand.cards = hand.removePairs();
Or you can have a setter method:
testHand.setCards(hand.removePairs);
I am working on a card game with HTML5 canvas and javascript with create.js library. The problem i have is that, I have an onclick function that deletes the clicked card from player's hand(removes the object from the array with splice and then redraws the canvas/redraws on canvas the new array of player's cards without the deleted one). When i do this for first time it does well.But if I click again on the card that it should be for example at index 1 in the array(after the splice method) it doesn't work.
Look at this code:
Here is my code for class Card:
function Card(suit,rank,imageFrontUrl,imageBackUrl)
{
this.imageFront = new createjs.Bitmap(imageFrontUrl);
this.imageBack = new createjs.Bitmap(imageBackUrl);
this.suit = suit;
this.rank = rank;
}
function Deck(){
this.cards = new Array();
this.makeDeck = function()
{
this.cards[0]= new Card("clubs",1,"images/114.png","images/155.png");
this.cards[1]= new Card("clubs",2,"images/115.png","images/155.png");
this.cards[2]= new Card("clubs",3,"images/116.png","images/155.png");
this.cards[3]= new Card("clubs",4,"images/117.png","images/155.png");
this.cards[4]= new Card("clubs",5,"images/118.png","images/155.png");
this.cards[5]= new Card("clubs",6,"images/119.png","images/155.png");
...
}
this.shuffleDeck = function()
{
var j,k;
for (j = 0; j < this.cards.length; j++) {
k = Math.floor(Math.random() * this.cards.length);
temp = this.cards[j];
this.cards[j] = this.cards[k];
this.cards[k] = temp;
}
}
this.dealCardsPlayer = function()
{
var playerDeck = new Array();
for(var i = 0; i<6;i++)
{
var x = this.cards.pop();
playerDeck.push(x);
}
return playerDeck;
}
}
Here is my code for class Player:
function Player()
{
this.playerTurn = false;
this.id = this;
this.name = this;
this.score = this;
this.playerHand = new Array();
this.playerTakenCards = new Array();
this.playerPickCard = function(n)
{
var card = this.playerHand(n);
return card;
}
this.tempArray = this;}
Here is my init function:
function init(){
var canvas = document.getElementById("tutorialCanvas");
var stage = new createjs.Stage(canvas);
var deck = new Deck();
var player1 = new Player();
deck.makeDeck();
deck.shuffleDeck();
player1.playerHand = deck.dealCardsPlayer();
function drawPlayerCards(){
var rotation=280;
for(var i =0;i<player1.playerHand.length;i++)
{
player1.playerHand[i].imageFront.x=330;
player1.playerHand[i].imageFront.y=750;
player1.playerHand[i].imageFront.regX = 0;
player1.playerHand[i].imageFront.regY = 96;
player1.playerHand[i].imageFront.rotation = rotation;
rotation = player1.playerHand[i].imageFront.rotation+20;
stage.addChild(player1.playerHand[i].imageFront);
}
}
createjs.Ticker.addEventListener("tick", stage);}
And here is the function i have problem with:
player1.playerHand[1].imageFront.addEventListener('click',function(event)
{
stage.removeAllChildren();
player1.playerHand.splice(1,1);
drawTableDeck();
drawPlayerCards();
}
After some researching I realized that the function works just for the first bitmap player1.playerHand[1].imageFront . If i change the array with the first onclick event and after that player1.playerHand[1].imageFront is some other image/bitmap, it doesn't work for it. Please help!
Why are you "hardcoding" the index of a card in your hand?
player1.playerHand.forEach(function(card) {
card.imageFront.addEventListener("click", function() {
var index = player1.playerHand.indexOf(card);
if (index != -1) {
stage.removeAllChildren();
player1.playerHand.splice(index, 1);
drawPlayerCards();
}
});
});
Some other notes:
It's a convention to use [] instead of new Array()
We normally put the opening brace { on the same line
Your Player constructor has an error: this.playerHand[n] instead of this.playerHand(n)