diff --git a/.vscode/favicon.ico b/.vscode/favicon.ico new file mode 100644 index 00000000..44c132b1 Binary files /dev/null and b/.vscode/favicon.ico differ diff --git a/7cardstudrules.js b/7cardstudrules.js new file mode 100644 index 00000000..2a013ef3 --- /dev/null +++ b/7cardstudrules.js @@ -0,0 +1,240 @@ +/* A function that draws 3 cards when deal button is pressed for the first time. This is only for the 7 Card Stud Game. + * @param container is where all cards will be append to + * @param allCards is an empty array and all cards that are drawn will be pushed into said array + * return 2 face down cards and 1 face up card + */ +const playerClick7 = () => { + document.body.appendChild(table); + container = document.createElement("div"); + container.setAttribute("id", "container"); + container.classList.add("container"); + document.body.appendChild(container); + // setting for loop with 1 so that it will give the ID of #1 onwards for each card instead of #0 + for (i = 1; i < 4; i++) { + playerCard = deck.pop(); + allCards.push(playerCard); + // Displaying sorted full display cards + playerCardHand.push(playerCard); + // For comparing sorted cards rank later on + playerHandRank.push(playerCard.rank); + let cardElement = createCard(playerCard); + cardElement.setAttribute("id", `card${i}`); + container.appendChild(cardElement); + if (cardElement.getAttribute("id") === "card3") { + flipCard7(); + } + } + + document.body.appendChild(buttonContainer); + document.body.appendChild(outputMessage); +}; + +/* A function that flips the 3rd cards onwards + * @param flipTheCard that does not contain the front-card class in it, will be toggled to front-card + * @return the flipped card of the front side with the card elements on it + */ +const flipCard7 = () => { + const flipTheCard = document.getElementsByClassName("inner-card"); + + for (let i = 2; i < flipTheCard.length; i += 1) { + if (flipTheCard.item(i).classList.contains("front-card") === false) { + flipTheCard.item(i).classList.toggle("front-card"); + } + } +}; +/* + * A function that flips all the cards at the end of the round when user locks in their final hand + * @return all cards to the front side + */ +const finalFlip = () => { + const flipTheCard = document.getElementsByClassName("inner-card"); + + for (let i = 0; i < flipTheCard.length; i++) { + if (flipTheCard.item(i).classList.contains("front-card") === false) { + flipTheCard.item(i).classList.toggle("front-card"); + } + } +}; + +/* A function that will ensure the 4th cards onwards will show the front side of the cards when deal button is pressed + * @param container[0] is the element selected to append the new cards that area created + * @return 4th,5th and 6th card face up + */ +const playerDeal7 = () => { + container = document.getElementsByClassName("container"); + // setting for loop with 1 so that it will give the ID of #1 onwards for each card instead of #0 + for (i = dealCount; i < dealCount + 1; i++) { + playerCard = deck.pop(); + allCards.push(playerCard); + // Displaying sorted full display cards + playerCardHand.push(playerCard); + // For comparing sorted cards rank later on + playerHandRank.push(playerCard.rank); + let cardElement = createCard(playerCard); + cardElement.setAttribute("id", `card${i}`); + container[0].appendChild(cardElement); + if ( + cardElement.getAttribute("id") === `card4` || + cardElement.getAttribute("id") === `card5` || + cardElement.getAttribute("id") === `card6` + ) { + flipCard7(); + } + } +}; + +// FUNCTIONS FOR THE BUTTONS CREATED AND THIS IS SPECIALLY FOR 7 CARD STUD GAME +const buttonFunctions7 = () => { + let tableCont = document.getElementById("table"); + let allRows = tableCont.querySelectorAll("tr"); + let coinsPouringAudio = new Audio(); + coinsPouringAudio.src = "coins-pouring.mp3"; + let coinAudio = new Audio(); + coinAudio.src = "coin.ogg"; + let dealAudio = new Audio(); + dealAudio.src = "shuffle.wav"; + // OUTPUT MESSAGE IS TO UPDATE THE AMOUNT THAT IS GAMBLE AND BALANCE IN HAND + document.body.appendChild(outputMessage); + betAllButton.addEventListener("click", () => { + coinsPouringAudio.play(); + // If user has no money left, they have to restart the game + if (balanceAmount <= 0) { + removeElement("deal-button"); + removeElement("bet-one"); + removeElement("bet-all"); + removeElement("container"); + buttonContainer.appendChild(restartButton); + outputMessage.innerHTML = `You've run out of money.

Please proceed to the nearest ATM to withdraw money and restart the game.`; + // If user has left than $5 but wants to max bet, it will deduct whatever they have left + } else if (balanceAmount < 5 && balanceAmount > 0) { + clickCount = balanceAmount; + bettingMoney = balanceAmount; + tableHighlights(clickCount); + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}`; + // If user has more than $5, it will take a maximum of only $5 + } else if (balanceAmount >= 5) { + clickCount = 5; + bettingMoney = 5; + tableHighlights(clickCount); + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}`; + } + // DISABLING/ENABLING SOME OF THE OTHER BUTTONS WHEN BET ALL IS CLICKED. MAX TO BET IS $5 AT ONE GO + balanceAmount -= bettingMoney; + dealButton.disabled = false; + betAllButton.disabled = true; + betOneButton.disabled = true; + }); + betOneButton.addEventListener("click", () => { + clickCount++; + coinAudio.play(); + dealButton.disabled = false; + bettingMoney++; + balanceAmount -= 1; + tableHighlights(clickCount); + // If user has no money left, they have to restart the game + if (balanceAmount < 0) { + removeElement("deal-button"); + removeElement("bet-one"); + removeElement("bet-all"); + removeElement("container"); + buttonContainer.appendChild(restartButton); + outputMessage.innerHTML = `You've run out of money.

Please proceed to the nearest ATM to withdraw money and restart the game.`; + } + // DISABLING/ENABLING SOME OF THE OTHER BUTTONS WHEN BET ALL IS CLICKED. MAX TO BET IS $5 AT ONE GO + else if (bettingMoney === 5) { + dealButton.disabled = false; + betAllButton.disabled = true; + betOneButton.disabled = true; + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}`; + } else { + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}`; + } + }); + + dealButton.addEventListener("click", () => { + betAllButton.disabled = true; + betOneButton.disabled = true; + dealAudio.play(); + // firstRound is the mode for the game status when it first starts. + if (mode === "firstRound") { + // Clicking the deal button will draw its 4th card and so on. + playerDeal7(); + // dealCount is introduced to ensure that it stops at 6th card(for face up cards) + dealCount++; + // dealCount more than 7 will disable the deal button to avoic players from drawing more cards + if (dealCount > 7) { + dealButton.disabled = true; + } + // User will be given a choice to lock in their cards in hand when they have 5 cards or more. They dont necessarily have to draw all 7 cards. + if (dealCount >= 6) { + // ONCE DEAL IS CLICKED, FINAL DEAL BUTTON WILL COME ON TO DOUBLE CONFIRM THEIR HAND + buttonContainer.appendChild(finalDealButton); + } + } + + // for second round onwards, user needs to get a fresh deck of card starting with 2 face down cards and 1 face up card + if (mode === "notFirstRound") { + // dealCount above 7 will disable dealButton, this ensures on a new round, dealButton is enabled again + dealButton.disabled = false; + removeElement("container"); + // dealCount starts at 4 so that when playerDeal7() is eventually executed, it will setattribute correctly the card number starting with 4 onwards. + dealCount = 4; + // allCards need to be reset or else it will bring forward the cards from previous rounds. + allCards = []; + // To deal 3 cards to start the new round + playerClick7(); + // reset all tallies to ensure fresh combinations + cardNameTally = {}; + cardSuitTally = {}; + cardRankInHand = []; + // new mode to run after the first 3 cards are drawn. + mode = "timeToDeal"; + } else if (mode === "timeToDeal") { + playerDeal7(); + dealCount++; + if (dealCount > 7) { + dealButton.disabled = true; + } + // User will be given a choice to lock in their cards in hand when they have 5 cards or more. They dont necessarily have to draw all 7 cards. + if (dealCount >= 6) { + // ONCE DEAL IS CLICKED, FINAL DEAL BUTTON WILL COME ON TO DOUBLE CONFIRM THEIR HAND + buttonContainer.appendChild(finalDealButton); + } + } + }); + + finalDealButton.addEventListener("click", () => { + // set timeout here to remove all highlights when final cards in hand are locked in + setTimeout(() => { + // selecting all rows in the table + for (i = 0; i < allRows.length; i++) { + // selecting all cells in the table + let allColumns = allRows[i].querySelectorAll("td"); + // going through all the cells to change each one back to its original color + for (j = 0; j < allColumns.length; j++) { + allColumns[j].style.backgroundColor = ""; + } + } + }, 1500); + + buttonContainer.appendChild(betOneButton); + buttonContainer.appendChild(betAllButton); + buttonContainer.appendChild(dealButton); + dealButton.disabled = true; + betAllButton.disabled = false; + betOneButton.disabled = false; + // REMOVE FINAL DEAL BUTTON BECAUSE IT ISNT NEEDED + removeElement("finaldeal-button"); + + // CALL OUT THE FUNCTION FOR THE FINAL CARDS IN HAND TO BE ASSESSED + finalFlip(); + clickCount = 0; + cardTally(allCards); + winningCombos(); + mode = "notFirstRound"; + dealCount = 4; + }); + restartButton.addEventListener("click", () => { + location.reload(); + }); +}; diff --git a/README.md b/README.md index 1d3a8a65..3baa4704 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ -# Rocket Academy Coding Bootcamp: Video Poker +# Rocket Academy Coding Bootcamp: Video Poker by Aqif S +# Link to demo video: https://youtu.be/wkfiz1hydgI diff --git a/coin.ogg b/coin.ogg new file mode 100644 index 00000000..e1cd5730 Binary files /dev/null and b/coin.ogg differ diff --git a/coins-pouring.mp3 b/coins-pouring.mp3 new file mode 100644 index 00000000..463c441f Binary files /dev/null and b/coins-pouring.mp3 differ diff --git a/doms.js b/doms.js new file mode 100644 index 00000000..16f1c0f6 --- /dev/null +++ b/doms.js @@ -0,0 +1,33 @@ +//---DOCUMENT OBJECT MODEL---// +let restartButton = document.createElement("button"); +restartButton.setAttribute("id", "restart"); +restartButton.innerHTML = "RESTART"; +let readyButton = document.createElement("button"); +let gameMessage = document.createElement("div"); +let dealButton = document.createElement("button"); +dealButton.setAttribute("id", "deal-button"); +dealButton.innerHTML = "DEAL"; +dealButton.disabled = true; +let outputMessage = document.createElement("div"); +outputMessage.id = "output-message"; +let table = document.getElementById("table"); +// BET ONCE BUTTON // +let betOneButton = document.createElement("button"); +betOneButton.innerHTML = "BET ONE"; +betOneButton.setAttribute("id", "bet-one"); +// BET ALL BUTTON // +let betAllButton = document.createElement("button"); +betAllButton.innerHTML = "MAX BET"; +betAllButton.setAttribute("id", "bet-all"); +// FINAL DEAL BUTTON AFTER CHOOSING CARDS TO BE HELD // +let finalDealButton = document.createElement("button"); +finalDealButton.setAttribute("id", "finaldeal-button"); +finalDealButton.innerHTML = "LOCK IT IN"; +// CONTAINER FOR ALL BUTTONS // +const buttonContainer = document.createElement("div"); +buttonContainer.classList.add("button-cont"); +buttonContainer.appendChild(betOneButton); +buttonContainer.appendChild(betAllButton); +buttonContainer.appendChild(dealButton); + +let tableCont = document.getElementById("table"); diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 00000000..25ee3cfd Binary files /dev/null and b/favicon.ico differ diff --git a/gamelogic.js b/gamelogic.js new file mode 100644 index 00000000..0fa40f4a --- /dev/null +++ b/gamelogic.js @@ -0,0 +1,486 @@ +//---SHUFFLING AND MAKING OF DECK---// +// GET A RANDOM INDEX RANGING FROM 0 (INCLUSIVE) TO MAX (EXCLUSIVE) // +const getRandomIndex = (max) => Math.floor(Math.random() * max); + +// CREATE A SHUFFLE AN ARRAY OF CARDS FUNCTION // +const shuffleCards = (cards) => { + // Loop over the card deck array once + for (let currentIndex = 0; currentIndex < cards.length; currentIndex += 1) { + // Select a random index in the deck + const randomIndex = getRandomIndex(cards.length); + // Select the card that corresponds to randomIndex + const randomCard = cards[randomIndex]; + // Select the card that corresponds to currentIndex + const currentCard = cards[currentIndex]; + // Swap positions of randomCard and currentCard in the deck + cards[currentIndex] = randomCard; + cards[randomIndex] = currentCard; + } + // Return the shuffled deck + return cards; +}; + +// GENERATE 52 CARDS // +const makeDeck = (cardAmount) => { + // create the empty deck at the beginning + const newDeck = []; + const suits = ["❤", "♦", "♣", "♠"]; + + for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) { + // make a variable of the current suit + const currentSuit = suits[suitIndex]; + + // loop to create all cards in this suit + // rank 1-13 + for (let rankCounter = 1; rankCounter <= 13; rankCounter++) { + // Convert rankCounter to string + let cardName = `${rankCounter}`; + + // 1, 11, 12 ,13 + if (cardName === "1") { + cardName = "A"; + } else if (cardName === "11") { + cardName = "J"; + } else if (cardName === "12") { + cardName = "Q"; + } else if (cardName === "13") { + cardName = "K"; + } + if (currentSuit === "❤" || currentSuit === "♦") { + var color = "red"; + } else if (currentSuit === "♣" || currentSuit === "♠") { + var color = "black"; + } + + // make a single card object variable + const card = { + name: cardName, + suit: currentSuit, + rank: rankCounter, + cardColor: color, + }; + + // add the card to the deck + newDeck.push(card); + } + } + return newDeck; +}; + +// SHUFFLE ALL 52 CARDS // +let deck = shuffleCards(makeDeck()); + +/* A function that highlights the table according to the amount of bet put in + * @param clickCount is the amount of bet put in + * @param tableCont is a dom for the table + * returns grey background color + */ +const tableHighlights = (clickCount) => { + for (i = 0; i < tableCont.rows.length; i++) { + tableCont.rows[i].cells[clickCount].style.backgroundColor = "grey"; + + if ( + tableCont.rows[i].cells[clickCount - 1].style.backgroundColor === "grey" + ) { + tableCont.rows[i].cells[clickCount - 1].style.backgroundColor = ""; + } + } +}; + +// FUNCTIONS FOR SOME OF THE BUTTONS CREATED // +const buttonFunctions = () => { + let tableCont = document.getElementById("table"); + let allRows = tableCont.querySelectorAll("tr"); + + let coinsPouringAudio = new Audio(); + coinsPouringAudio.src = "coins-pouring.mp3"; + let coinAudio = new Audio(); + coinAudio.src = "coin.ogg"; + let dealAudio = new Audio(); + dealAudio.src = "shuffle.wav"; + // OUTPUT MESSAGE IS TO UPDATE THE AMOUNT THAT IS GAMBLE AND BALANCE IN HAND + document.body.appendChild(outputMessage); + + betAllButton.addEventListener("click", () => { + coinsPouringAudio.play(); + // If user has no money left, they have to restart the game + if (balanceAmount <= 0) { + removeElement("deal-button"); + removeElement("bet-one"); + removeElement("bet-all"); + removeElement("container"); + buttonContainer.appendChild(restartButton); + outputMessage.innerHTML = `You've run out of money.

Please proceed to the nearest ATM to withdraw money and restart the game.`; + // If user has left than $5 but wants to max bet, it will deduct whatever they have left + } else if (balanceAmount < 5 && balanceAmount > 0) { + clickCount = balanceAmount; + bettingMoney = balanceAmount; + tableHighlights(clickCount); + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}`; + // If user has more than $5, it will take a maximum of only $5 + } else if (balanceAmount >= 5) { + clickCount = 5; + bettingMoney = 5; + tableHighlights(clickCount); + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}`; + } + // DISABLING/ENABLING SOME OF THE OTHER BUTTONS WHEN BET ALL IS CLICKED. MAX TO BET IS $5 AT ONE GO + balanceAmount -= bettingMoney; + dealButton.disabled = false; + betAllButton.disabled = true; + betOneButton.disabled = true; + }); + betOneButton.addEventListener("click", () => { + clickCount++; + coinAudio.play(); + dealButton.disabled = false; + bettingMoney++; + balanceAmount -= 1; + tableHighlights(clickCount); + // If user has no money left, they have to restart the game + if (balanceAmount < 0) { + removeElement("deal-button"); + removeElement("bet-one"); + removeElement("bet-all"); + removeElement("container"); + buttonContainer.appendChild(restartButton); + outputMessage.innerHTML = `You've run out of money.

Please proceed to the nearest ATM to withdraw money and restart the game.`; + } + // DISABLING/ENABLING SOME OF THE OTHER BUTTONS WHEN BET ALL IS CLICKED. MAX TO BET IS $5 AT ONE GO + else if (bettingMoney === 5) { + dealButton.disabled = false; + betAllButton.disabled = true; + betOneButton.disabled = true; + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}`; + } else { + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}`; + } + }); + + dealButton.addEventListener("click", () => { + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}

Click on card to hold it in hand.`; + + dealAudio.play(); + // ONCE DEAL IS CLICKED, FINAL DEAL BUTTON WILL COME ON TO DOUBLE CONFIRM THEIR HAND + buttonContainer.appendChild(finalDealButton); + // REMOVE ALL THE OTHER BUTTONS THAT ARE NOT NEEDED + removeElement("deal-button"); + removeElement("bet-one"); + removeElement("bet-all"); + if (mode === "firstRound") { + // FLIP TO SHOW FRONT OF CARD + flipCard(); + } else { + removeElement("container"); + allCards = []; + playerClick(); + holdArray = []; + flipCard(); + cardNameTally = {}; + cardSuitTally = {}; + cardRankInHand = []; + } + }); + + finalDealButton.addEventListener("click", () => { + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney}

Start betting to begin game.`; + // set timeout here to remove all highlights when final cards in hand are locked in + setTimeout(() => { + // selecting all rows in the table + for (i = 0; i < allRows.length; i++) { + // selecting all cells in the table + let allColumns = allRows[i].querySelectorAll("td"); + + // going through all the cells to change each one back to its original color + for (j = 0; j < allColumns.length; j++) { + allColumns[j].style.backgroundColor = ""; + } + } + }, 1500); + + if (mode === "firstRound") { + buttonContainer.appendChild(betOneButton); + buttonContainer.appendChild(betAllButton); + buttonContainer.appendChild(dealButton); + dealButton.disabled = true; + betAllButton.disabled = false; + betOneButton.disabled = false; + mode = "notFirstRound"; + // REMOVE FINAL DEAL BUTTON BECAUSE IT ISNT NEEDED + removeElement("finaldeal-button"); + // CALL OUT THE FUNCTION FOR THE FINAL CARDS IN HAND TO BE ASSESSED + secondFlipCard(); + } else { + // REMOVE FINAL DEAL BUTTON BECAUSE IT ISNT NEEDED + removeElement("finaldeal-button"); + buttonContainer.appendChild(betOneButton); + buttonContainer.appendChild(betAllButton); + buttonContainer.appendChild(dealButton); + dealButton.disabled = true; + betAllButton.disabled = false; + betOneButton.disabled = false; + secondFlipCard(); + } + clickCount = 0; + }); + restartButton.addEventListener("click", () => { + location.reload(); + }); +}; + +// CREATE CARD USING DOM // +const createCard = (cardInfo) => { + const innerCard = document.createElement("div"); + innerCard.classList.add("inner-card"); + const suit = document.createElement("div"); + suit.setAttribute("id", "front-card-suit"); + suit.setAttribute("data-value", cardInfo.suit); + suit.classList.add("front-card", "suit", cardInfo.cardColor); + suit.innerText = cardInfo.suit; + const name = document.createElement("div"); + name.classList.add("front-card", "name"); + name.setAttribute("id", "front-card-name"); + name.setAttribute("data-value", cardInfo.name); + name.innerText = cardInfo.name; + + card = document.createElement("div"); + card.classList.add("free-card"); + + innerCard.appendChild(name); + innerCard.appendChild(suit); + + card.appendChild(innerCard); + return card; +}; + +// REMOVE ELEMENTS IN HTML USING ELEMENT IDS // +const removeElement = (elementId) => { + let element = document.getElementById(elementId); + element.parentNode.removeChild(element); +}; + +// REMOVE ELEMENTS IN HTML USING ELEMENT CLASS // +const removeElementByClass = (className) => { + const elements = document.getElementsByClassName(className); + while (elements.length > 0) { + elements[0].parentNode.removeChild(elements[0]); + } +}; + +/* A function that tallies the cards by name,suit and rank. + * @param cardSuitTally tallies cards by suit + * @param cardNameTally tallies cards by name + * @param cardRankInHand push card ranks into array + * returns objects and arrays + */ +const cardTally = (card) => { + // for loop to get tally for nameTally and suitTally + for (let i = 0; i < card.length; i++) { + cardName = card[i].name; + cardSuit = card[i].suit; + cardRank = card[i].rank; + + // Tally for card suit + // If we have seen the card suit before, increment its count + if (cardSuit in cardSuitTally) { + cardSuitTally[cardSuit] += 1; + } + // Else, initialise count of this card suit to 1 + else { + cardSuitTally[cardSuit] = 1; + } + // Tally for card name + // If we have seen the card name before, increment its count + if (cardName in cardNameTally) { + cardNameTally[cardName] += 1; + } + // Else, initialise count of this card name to 1 + else { + cardNameTally[cardName] = 1; + } + cardRankInHand.push(cardRank); + } +}; + +// SHOWN AT THE START OF THE GAME PAGE // +const startOfGame = () => { + gameMessage.id = "game-message"; + gameMessage.innerHTML = " Y O U   R E A D Y ?"; + document.body.appendChild(gameMessage); + + // indicate ready to begin + readyButton.id = "ready-button"; + readyButton.innerHTML = "R E A D Y"; + document.body.appendChild(readyButton); + readyButton.addEventListener("click", initGame); + removeElement("table"); +}; + +// AFTER READY BUTTON IS CLICKED, GAME INITILIAZED // +const initGame = () => { + let introAudio = new Audio(); + introAudio.src = "intro.wav"; + introAudio.play(); + gameMessage.innerHTML = ""; + let modal = document.getElementById("myModal"); + let submit = document.getElementsByClassName("submit")[0]; + modal.style.display = "block"; + submit.onclick = function () { + modal.style.display = "none"; + let amount = Number(document.getElementById("amount").value); + balanceAmount = amount; + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Start betting to begin game.`; + if (amount === 777) { + balanceAmount = 100; + removeElement("ready-button"); + playerClick7(); + buttonFunctions7(); + outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Start betting to begin game.`; + } else { + removeElement("ready-button"); + playerClick(); + buttonFunctions(); + } + // removeElement("ready-button"); + // playerClick(); + // buttonFunctions(); + // outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Start betting to begin game.`; + }; + + // This will prompt user how much they want to start the game with + // balanceAmount = Number( + // window.prompt( + // "How much money do you want to start with?", + // "Enter amount here" + // ) + // ); + // if (balanceAmount === 777) { + // balanceAmount = Number( + // window.prompt( + // "How much money do you REALLY want to start with?", + // "Enter amount here" + // ) + // ); + // removeElement("ready-button"); + // playerClick7(); + // buttonFunctions7(); + // } + // } else { + // removeElement("ready-button"); + // playerClick(); + // buttonFunctions(); + // outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Start betting to begin game.`; + // } +}; + +// CALLING OUT 5 CARDS INTO CONTAINER TO BE DISPLAYED FOR THE FIRST FLIP CARD // +const playerClick = () => { + document.body.appendChild(table); + container = document.createElement("div"); + container.setAttribute("id", "container"); + container.classList.add("container"); + document.body.appendChild(container); + // setting for loop with 1 so that it will give the ID of #1 onwards for each card instead of #0 + for (i = 1; i < 6; i++) { + playerCard = deck.pop(); + allCards.push(playerCard); + // Displaying sorted full display cards + playerCardHand.push(playerCard); + // For comparing sorted cards rank later on + playerHandRank.push(playerCard.rank); + let cardElement = createCard(playerCard); + cardElement.setAttribute("id", `card${i}`); + container.appendChild(cardElement); + } + + document.body.appendChild(buttonContainer); + + document.body.appendChild(outputMessage); +}; + +/* A function that flips the cards when deal button is pressed for the first time + * @param cardNameTally set to empty to give a fresh start + * @param cardSuitTally set to empty to give a fresh start + * @param cardRankInHand set to empty to give a fresh start + * @return the flipped card of the front side with the card elements on it + */ +const flipCard = () => { + const flipTheCard = document.getElementsByClassName("inner-card"); + for (let i = 0; i < flipTheCard.length; i += 1) { + flipTheCard.item(i).classList.toggle("front-card"); + } + cardClick(); +}; + +/* A function that creates a hold button div to every single card that is being pushed on the screen + * @param cardChoice will select all the cards that are not being held (free-card class) + * @param holdButton will be added to every single free-card and set its ID according to the for loop index + * @param holdArray is an array that will take in all the cards that are being held. + * @param allCards[i] is the index of the card in allCards array that is being selected to be held. these cards will be pushed into holdArray if chosen to be held + * @return holdArray + */ +const cardClick = () => { + let cardChoice = document.querySelectorAll(".free-card"); + for (let i = 0; i < cardChoice.length; i++) { + document.querySelector(`#card${i + 1}`).addEventListener("click", () => { + let holdButton = document.createElement("div"); + holdButton.setAttribute("id", `hold${i + 1}`); + holdButton.innerHTML = "Hold"; + if ( + document.getElementById(`card${i + 1}`).classList.contains("held-card") + ) { + document.getElementById(`card${i + 1}`).classList.remove("held-card"); + document.getElementById(`card${i + 1}`).classList.toggle("free-card"); + let hold = document.getElementById(`hold${i + 1}`); + document.getElementById(`card${i + 1}`).removeChild(hold); + + // This is to remove the index from the hold array when unhold is clicked + let index = holdArray.indexOf(allCards[i]); + holdArray.splice(index, 1); + } else { + document.getElementById(`card${i + 1}`).classList.remove("free-card"); + document.getElementById(`card${i + 1}`).classList.toggle("held-card"); + document.getElementById(`card${i + 1}`).appendChild(holdButton); + holdArray.push(allCards[i]); + } + }); + } + + return holdArray; +}; + +/* A function that flips the cards when deal button is pressed for the second time + * after the player has chosen which card wants to be held or changed + * @param cardNameTally set to empty to give a fresh start + * @param cardSuitTally set to empty to give a fresh start + * @param cardRankInHand set to empty to give a fresh start + * @return the flipped card of the front side with the card elements on it + */ +const secondFlipCard = () => { + // compare original array to the one that is held + // if original array and held array is the same, go straight to tally cards + // remove the ones that are not held + // insert new cards into those that are removed + // show on the front of card + // update on player hand and tally it + + for (let i = 0; i < allCards.length; i += 1) { + if (holdArray.includes(allCards[i]) === false) { + playerCard = deck.pop(); + allCards.splice(i, 1, playerCard); + } + } + let newContainer = document.getElementsByClassName("container"); + newContainer[0].innerHTML = ""; + for (j = 0; j < allCards.length; j++) { + let newCard = createCard(allCards[j]); + newContainer[0].appendChild(newCard); + let showCard = document.getElementsByClassName("inner-card"); + showCard.item(j).classList.add("front-card"); + } + cardTally(allCards); + winningCombos(); + return outputMessage; +}; + +startOfGame(); diff --git a/globals.js b/globals.js new file mode 100644 index 00000000..930a41f9 --- /dev/null +++ b/globals.js @@ -0,0 +1,35 @@ +// GLOBAL VARIABLES // +//---FOR WINNING COMBOS---// +let twoPairs = false; +let threeKinds = false; +let straight = false; +let flush = false; +let fullHouse = false; +let fourKinds = false; +let straightFlush = false; +let royalFlush = false; +let jackOrBetter = false; +//---FOR BETTING---// +let bettingMoney = 0; +let balanceAmount = 0; +let winnings = 0; +let returns = 0; +let clickCount = 0; +let dealCount = 4; +//---FOR CARDS---// +let container; +let playerCardHand = []; +let playerHandRank = []; +let cardName; +let cardSuit; +let cardRank; +let card; +let hold; +let holdArray = []; +let allCards = []; +//---FOR CARD TALLY---// +let cardNameTally = {}; +let cardSuitTally = {}; +let cardRankInHand = []; +//---FOR MODES---// +let mode = "firstRound"; diff --git a/index.html b/index.html new file mode 100644 index 00000000..ae3ed376 --- /dev/null +++ b/index.html @@ -0,0 +1,113 @@ + + + + + + Video Poker + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Coins12345
Royal Flush25050075010004000
Straight Flush50100150200250
Four of a Kind255075100125
Full House918273645
Flush612182430
Straight48121620
Three of a Kind3691215
Two Pair246810
Jacks or Better12345
+ + + + + +

Key in 777 in the amount of money to enter 7 Stud Game.

+ + diff --git a/intro.wav b/intro.wav new file mode 100644 index 00000000..783ebfd8 Binary files /dev/null and b/intro.wav differ diff --git a/shuffle.wav b/shuffle.wav new file mode 100644 index 00000000..def27e6e Binary files /dev/null and b/shuffle.wav differ diff --git a/styles.css b/styles.css new file mode 100644 index 00000000..89b82c8c --- /dev/null +++ b/styles.css @@ -0,0 +1,320 @@ +body { + background-color: black; + background-image: url("https://i.pinimg.com/originals/40/16/cd/4016cd0da5dd95f171edbdb6dbd83806.gif"); + background-size: 100%; + max-width: 100%; +} + +#header { + color: white; + margin-left: 43%; +} + +#game-message { + font-size: 370%; + font-family: monospace; + color: white; + display: flex; + justify-content: center; + align-items: center; + margin-top: 10%; +} + +#output-message { + font-size: 150%; + font-family: monospace; + color: white; + display: flex; + justify-content: center; + align-items: center; + margin-top: 2%; + text-align: center; + background-color: rgba(128, 128, 128, 0.397); + width: 20%; + height: auto; + margin: 0px auto; + padding: 4px; + border: 1px solid black; + border-radius: 10px; +} + +#ready-button { + display: flex; + justify-content: center; + align-items: center; + margin-left: auto; + margin-right: auto; + + margin-top: 50px; + width: 100px; + height: 30px; + + background-color: rgba(255, 255, 255, 0.795); +} + +.container { + display: flex; + margin-top: 28px; + justify-content: center; + align-items: center; + height: 200px; +} + +.free-card { + font-family: monospace; + font-weight: bold; + font-size: 200%; + background-image: url("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQJGdUkfIIURWSMhi9JpnvfPBw3sVpyFwSH7A&usqp=CAU"); + display: flex; + margin-left: 0.5%; + width: 60px; + height: 100px; + padding: 5px; + border-radius: 8px; + perspective: 1000px; + position: relative; + border: 1px solid black; +} +.held-card { + font-family: monospace; + font-weight: bold; + font-size: 200%; + background-image: url("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQJGdUkfIIURWSMhi9JpnvfPBw3sVpyFwSH7A&usqp=CAU"); + display: flex; + margin-left: 0.5%; + width: 60px; + height: 100px; + padding: 5px; + border-radius: 8px; + perspective: 1000px; + position: relative; + border: 1px solid black; +} + +.inner-card { + position: relative; + margin-top: -22px; + width: 60px; + height: 100px; + text-align: left; + transition: transform 0.1s; + transform-style: preserve-3d; +} + +.back-card, +.front-card { + -webkit-backface-visibility: hidden; + position: absolute; + width: 60px; + height: 100px; + backface-visibility: hidden; + transition: transform 0.1s; + transform-style: preserve-3d; + margin-top: -3px; +} + +.front-card { + transform: rotateY(180deg); + margin-top: 0px; +} + +.black { + color: black; +} + +.red { + color: rgb(255, 0, 0); +} + +.suit { + margin-left: -28px; + margin-top: 7px; + font-size: 130%; + width: 50px; + height: 50px; +} + +.name { + width: 50px; + height: 50px; +} + +.button-cont { + display: flex; + justify-content: center; + align-items: center; + margin: 10px; +} + +button { + width: 100px; + height: 30px; + border-radius: 10px; + border: 1px solid #070707; + color: rgb(7, 7, 7); + position: relative; + margin: 5px; + box-shadow: inset 0 0 0 0 #ffffff; + transition: ease-out 0.3s; + outline: none; + z-index: 1; +} +button:hover { + cursor: pointer; + color: white; +} + +button:before { + transition: 0.5s; + position: absolute; + top: 0; + left: 50%; + right: 50%; + bottom: 0; + opacity: 0; + content: ""; + background-color: #0d0e0e; + border-radius: 5px; +} + +button:hover:before { + transition: 0.5s all ease; + left: 0; + right: 0; + opacity: 1; + z-index: -1; +} + +table { + background-color: rgba(128, 128, 128, 0.521); + display: flex; + justify-content: center; + align-items: center; + max-width: 100%; + width: 450px; + height: 282px; + border-radius: 10px; + margin-right: auto; + margin-left: auto; + color: white; + border: 1px; + border-style: solid; + border-color: black; +} + +tr, +td { + display: flex; + justify-content: left; + align-items: center; + width: 345px; + max-width: 100%; + height: 23px; + margin: 4px; + margin-right: auto; + margin-left: auto; + border: 2px; +} +#hold1, +#hold2, +#hold3, +#hold4, +#hold5 { + position: relative; + text-align: center; + justify-content: space-between; + background-color: rgba(255, 255, 255, 0.438); + color: rgb(8, 8, 8); + width: 60px; + border: 0cm; + margin: auto; +} + +#restart { + display: flex; + justify-content: center; + align-items: center; + margin-left: auto; + margin-right: auto; + margin-top: 50px; + width: 100px; + height: 20px; + background-color: rgba(255, 255, 255, 0.795); +} + +p { + display: flex; + justify-content: center; + font-family: monospace; + font-size: 10px; + color: rgba(255, 255, 255, 0.068); +} + +.modal { + display: none; + width: 100vw; + height: 100vh; + top: 0; + right: 0; + bottom: 0; + left: 0; + position: absolute; + z-index: 2; + text-align: center; + margin: 0px; + padding: 20px; + background-color: rgba(128, 128, 128, 0.521); +} + +.modal-content { + margin: 32% auto 0px auto; + border: solid 1px; + width: 15vw; + padding: 10px; + border-radius: 10px; + background-color: rgba(0, 0, 0, 0.678); +} + +#popuptext { + color: white; +} + +#amount { + font-size: 15px; + text-align: center; + border-radius: 5px; + width: 10vw; + border: 0; +} + +#submit { + z-index: 2; +} +@-webkit-keyframes animatetop { + from { + top: -300px; + opacity: 0; + } + to { + top: 0; + opacity: 1; + } +} + +@keyframes animatetop { + from { + top: -300px; + opacity: 0; + } + to { + top: 0; + opacity: 1; + } +} + +.submit:hover, +.submit:focus { + color: rgb(255, 255, 255); + text-decoration: none; + cursor: pointer; +} diff --git a/total-fail.wav b/total-fail.wav new file mode 100644 index 00000000..6225399f Binary files /dev/null and b/total-fail.wav differ diff --git a/winning-audio.wav b/winning-audio.wav new file mode 100644 index 00000000..b80f922e Binary files /dev/null and b/winning-audio.wav differ diff --git a/winningcombinations.js b/winningcombinations.js new file mode 100644 index 00000000..38d290e2 --- /dev/null +++ b/winningcombinations.js @@ -0,0 +1,220 @@ +/* A function that goes through cardRankInHand and sorts them + * @return true/false if hand has two pairs in it + */ +const twoPairsCombo = () => { + let pairs = []; + let sortedDeck = cardRankInHand.sort(function (a, b) { + return a - b; + }); + for (i = 0; i < 5; i++) { + if (sortedDeck[i] === sortedDeck[i + 1]) { + pairs.push(sortedDeck[i]); + } + } + if (pairs.length === 2 && pairs[0] !== pairs[1]) { + return (twoPairs = true); + } +}; + +/* A function that goes through cardNameTally to see if there are any three of the same card name and full house combos + * @return true/false if hand has threes or full houses + */ +const threeKindsAndFullHouseCombo = () => { + let duplicates = []; + for (cardName in cardNameTally) { + if (cardNameTally[cardName] === 3) { + duplicates.push(cardNameTally[cardName]); + } + if (cardNameTally[cardName] === 2) { + duplicates.push(cardNameTally[cardName]); + } + if ( + (duplicates[0] === 3 && duplicates[1] !== 2) || + (duplicates[1] === 3 && duplicates[0] !== 2) + ) { + threeKinds = true; + } + if ( + (duplicates[0] === 3 && duplicates[1] === 2) || + (duplicates[1] === 3 && duplicates[0] === 2) + ) { + // making threeKinds false so that it will not show both threeKinds and fullHouse true at the end + // if this happens, it will output that threeKinds is the one won and ignoring fullHouse + threeKinds = false; + fullHouse = true; + } + } +}; + +/* A function that goes through cardNameTally to see if there are four of the same card name + * @return true/false if hand has four of a kind in it + */ +const fourKindsCombo = () => { + for (cardName in cardNameTally) { + if (cardNameTally[cardName] === 4) { + fourKinds = true; + } + } +}; + +/* A function that goes through cardSuitTally and cardRankInHand + * and sorts them. This is to see if there are card ranks that + * are in proper numerical order of difference 1 OR if they have + * the same suit OR both. + * @return true/false if hand has said combos or not. + */ +const straightStraightFlushAndRoyalFlushCombo = () => { + let count = 1; + let sortedDeck = cardRankInHand.sort(function (a, b) { + return a - b; + }); + for (j = 0; j < 5; j++) { + if (sortedDeck[j] + 1 === sortedDeck[j + 1]) { + count += 1; + if (count === 5) { + straight = true; + } + } + } + for (cardSuit in cardSuitTally) { + if (cardSuitTally[cardSuit] === 5) { + flush = true; + } + if (count === 5 && flush === true) { + // making straight and flush false so that it will not ignore the straightFlush being true at the end of the game + straight = false; + flush = false; + straightFlush = true; + } + } + for (cardName in cardNameTally) { + if ( + "A" in cardNameTally && + "10" in cardNameTally && + "J" in cardNameTally && + "Q" in cardNameTally && + "K" in cardNameTally && + cardSuitTally[cardSuit] === 5 + ) { + // making flush and straightflush false so that it will not ignore the royalflush being true at the end of the game + flush = false; + straightFlush = false; + royalFlush = true; + } + } +}; + +/* A function that goes through all different combo functions to + * see if hand has at least Jack or better in it + * @return true/false if hand has Jack or better in it + */ +const jackOrBetterCombo = () => { + for (cardName in cardNameTally) { + if ( + cardName === "J" && + cardName === "Q" && + cardName === "K" && + cardName === "A" && + cardNameTally[cardName] >= 1 + ) { + jackOrBetter = true; + outputMessage.innerHTML = "You have Jacks or Better."; + } + } +}; + +/* A function that goes through all different combo functions to + * see if hand has any of it + * @param + * @return an output message of what combination you have in hand + */ +const winningCombos = () => { + twoPairsCombo(); + threeKindsAndFullHouseCombo(); + fourKindsCombo(); + straightStraightFlushAndRoyalFlushCombo(); + jackOrBetterCombo(); + let winningAudio = new Audio(); + winningAudio.src = "winning-audio.wav"; + let losingAudio = new Audio(); + losingAudio.src = "total-fail.wav"; + + if (twoPairs === true) { + returns = bettingMoney * 2; + winnings = bettingMoney * 3; + balanceAmount += winnings; + winningAudio.play(); + outputMessage.innerHTML = `You have Two pairs.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else if (threeKinds === true) { + returns = bettingMoney * 3; + winnings = bettingMoney * 4; + balanceAmount += winnings; + winningAudio.play(); + + outputMessage.innerHTML = `You have Three of a kind.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else if (fullHouse === true) { + returns = bettingMoney * 9; + winnings = bettingMoney * 10; + balanceAmount += winnings; + winningAudio.play(); + + outputMessage.innerHTML = `You have a Full House.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else if (fourKinds === true) { + returns = bettingMoney * 25; + winnings = bettingMoney * 26; + balanceAmount += winnings; + winningAudio.play(); + + outputMessage.innerHTML = `You have Four of a kind.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else if (straight === true) { + returns = bettingMoney * 4; + winnings = bettingMoney * 5; + balanceAmount += winnings; + winningAudio.play(); + outputMessage.innerHTML = `You have a Straight.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else if (flush === true) { + returns = bettingMoney * 6; + winnings = bettingMoney * 7; + balanceAmount += winnings; + winningAudio.play(); + outputMessage.innerHTML = `You have a Flush.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else if (straightFlush === true) { + returns = bettingMoney * 50; + winnings = bettingMoney * 51; + balanceAmount += winnings; + winningAudio.play(); + outputMessage.innerHTML = `You have a Straight Flush.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else if (royalFlush === true) { + returns = bettingMoney * 250; + winnings = bettingMoney * 251; + balanceAmount += winnings; + winningAudio.play(); + outputMessage.innerHTML = `You have a Royal Flush.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else if (jackOrBetter === true) { + returns = bettingMoney * 1; + winnings = bettingMoney * 2; + balanceAmount += winnings; + winningAudio.play(); + outputMessage.innerHTML = `You have Jacks or Better.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } else { + winnings = 0; + balanceAmount += winnings; + losingAudio.play(); + outputMessage.innerHTML = `You have no special combinations.

You've won $${returns}.

Your balance in hand: $${balanceAmount}

Start betting to play another round.`; + } + // ALL OF THIS BELOW IS TO RESET EVERYTHING BACK TO ITS DEFAULT STATE AFTER ROUND IS COMPLETED + returns = 0; + bettingMoney = 0; + deck = shuffleCards(makeDeck()); + twoPairs = false; + threeKinds = false; + straight = false; + flush = false; + fullHouse = false; + fourKinds = false; + straightFlush = false; + royalFlush = false; + jackOrBetter = false; +}; + +outputMessage.innerHTML = `Money in hand: $${balanceAmount}

Betting: $${bettingMoney} `;