├── img ├── 10-chip.png ├── 25-chip.png ├── 50-chip.png ├── Clubs-2.png ├── Clubs-3.png ├── Clubs-4.png ├── Clubs-5.png ├── Clubs-6.png ├── Clubs-7.png ├── Clubs-8.png ├── Clubs-9.png ├── favicon.ico ├── 100-chip.png ├── Clubs-10.png ├── Clubs-Ace.png ├── Diamond-2.png ├── Diamond-3.png ├── Diamond-4.png ├── Diamond-5.png ├── Diamond-6.png ├── Diamond-7.png ├── Diamond-8.png ├── Diamond-9.png ├── Hearts-10.png ├── Hearts-2.png ├── Hearts-3.png ├── Hearts-4.png ├── Hearts-5.png ├── Hearts-6.png ├── Hearts-7.png ├── Hearts-8.png ├── Hearts-9.png ├── Spades-10.png ├── Spades-2.png ├── Spades-3.png ├── Spades-4.png ├── Spades-5.png ├── Spades-6.png ├── Spades-7.png ├── Spades-8.png ├── Spades-9.png ├── card_back.png ├── pile-chip.png ├── Clubs-Jack.png ├── Clubs-King.png ├── Clubs-Queen.png ├── Diamond-10.png ├── Diamond-Ace.png ├── Diamond-Jack.png ├── Diamond-King.png ├── Hearts-Ace.png ├── Hearts-Jack.png ├── Hearts-King.png ├── Hearts-Queen.png ├── Spades-Ace.png ├── Spades-Jack.png ├── Spades-King.png ├── Spades-Queen.png ├── blank-chip.png ├── chip_red_top.png ├── Diamond-Queen.png └── chip_yellow_top.png ├── css ├── keyframes.css └── style.css ├── js ├── game-win-logic.js ├── button-actions.js ├── main.js ├── game-play-logic.js └── cards.js ├── README.md └── index.html /img/10-chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/10-chip.png -------------------------------------------------------------------------------- /img/25-chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/25-chip.png -------------------------------------------------------------------------------- /img/50-chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/50-chip.png -------------------------------------------------------------------------------- /img/Clubs-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-2.png -------------------------------------------------------------------------------- /img/Clubs-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-3.png -------------------------------------------------------------------------------- /img/Clubs-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-4.png -------------------------------------------------------------------------------- /img/Clubs-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-5.png -------------------------------------------------------------------------------- /img/Clubs-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-6.png -------------------------------------------------------------------------------- /img/Clubs-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-7.png -------------------------------------------------------------------------------- /img/Clubs-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-8.png -------------------------------------------------------------------------------- /img/Clubs-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-9.png -------------------------------------------------------------------------------- /img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/favicon.ico -------------------------------------------------------------------------------- /img/100-chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/100-chip.png -------------------------------------------------------------------------------- /img/Clubs-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-10.png -------------------------------------------------------------------------------- /img/Clubs-Ace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-Ace.png -------------------------------------------------------------------------------- /img/Diamond-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-2.png -------------------------------------------------------------------------------- /img/Diamond-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-3.png -------------------------------------------------------------------------------- /img/Diamond-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-4.png -------------------------------------------------------------------------------- /img/Diamond-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-5.png -------------------------------------------------------------------------------- /img/Diamond-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-6.png -------------------------------------------------------------------------------- /img/Diamond-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-7.png -------------------------------------------------------------------------------- /img/Diamond-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-8.png -------------------------------------------------------------------------------- /img/Diamond-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-9.png -------------------------------------------------------------------------------- /img/Hearts-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-10.png -------------------------------------------------------------------------------- /img/Hearts-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-2.png -------------------------------------------------------------------------------- /img/Hearts-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-3.png -------------------------------------------------------------------------------- /img/Hearts-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-4.png -------------------------------------------------------------------------------- /img/Hearts-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-5.png -------------------------------------------------------------------------------- /img/Hearts-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-6.png -------------------------------------------------------------------------------- /img/Hearts-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-7.png -------------------------------------------------------------------------------- /img/Hearts-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-8.png -------------------------------------------------------------------------------- /img/Hearts-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-9.png -------------------------------------------------------------------------------- /img/Spades-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-10.png -------------------------------------------------------------------------------- /img/Spades-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-2.png -------------------------------------------------------------------------------- /img/Spades-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-3.png -------------------------------------------------------------------------------- /img/Spades-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-4.png -------------------------------------------------------------------------------- /img/Spades-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-5.png -------------------------------------------------------------------------------- /img/Spades-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-6.png -------------------------------------------------------------------------------- /img/Spades-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-7.png -------------------------------------------------------------------------------- /img/Spades-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-8.png -------------------------------------------------------------------------------- /img/Spades-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-9.png -------------------------------------------------------------------------------- /img/card_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/card_back.png -------------------------------------------------------------------------------- /img/pile-chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/pile-chip.png -------------------------------------------------------------------------------- /img/Clubs-Jack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-Jack.png -------------------------------------------------------------------------------- /img/Clubs-King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-King.png -------------------------------------------------------------------------------- /img/Clubs-Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Clubs-Queen.png -------------------------------------------------------------------------------- /img/Diamond-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-10.png -------------------------------------------------------------------------------- /img/Diamond-Ace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-Ace.png -------------------------------------------------------------------------------- /img/Diamond-Jack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-Jack.png -------------------------------------------------------------------------------- /img/Diamond-King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-King.png -------------------------------------------------------------------------------- /img/Hearts-Ace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-Ace.png -------------------------------------------------------------------------------- /img/Hearts-Jack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-Jack.png -------------------------------------------------------------------------------- /img/Hearts-King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-King.png -------------------------------------------------------------------------------- /img/Hearts-Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Hearts-Queen.png -------------------------------------------------------------------------------- /img/Spades-Ace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-Ace.png -------------------------------------------------------------------------------- /img/Spades-Jack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-Jack.png -------------------------------------------------------------------------------- /img/Spades-King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-King.png -------------------------------------------------------------------------------- /img/Spades-Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Spades-Queen.png -------------------------------------------------------------------------------- /img/blank-chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/blank-chip.png -------------------------------------------------------------------------------- /img/chip_red_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/chip_red_top.png -------------------------------------------------------------------------------- /img/Diamond-Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/Diamond-Queen.png -------------------------------------------------------------------------------- /img/chip_yellow_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacquelynmarcella/blackjack/HEAD/img/chip_yellow_top.png -------------------------------------------------------------------------------- /css/keyframes.css: -------------------------------------------------------------------------------- 1 | /* Animations for card dealing based on location */ 2 | /* TO DO: Add webkit keyframes also */ 3 | 4 | @keyframes deal-player { 5 | 0% { 6 | transform: translate(-90px, -150px); 7 | } 8 | 50% { 9 | transform: translate(-50px, -50px); 10 | } 11 | 100% { 12 | transform: translate(0, 0); 13 | } 14 | } 15 | 16 | @keyframes deal-player-split { 17 | 0% { 18 | transform: translate(-90px, -450px); 19 | } 20 | 50% { 21 | transform: translate(-50px, -150px); 22 | } 23 | 100% { 24 | transform: translate(0, 0); 25 | } 26 | } 27 | 28 | @keyframes deal-dealer { 29 | 0% { 30 | transform: translate(-100px, 0px); 31 | } 32 | 50% { 33 | transform: translate(-50px, 0px); 34 | } 35 | 100% { 36 | transform: translate(0, 0); 37 | } 38 | } 39 | 40 | @keyframes dealer-cardflip { 41 | 0% { 42 | transform: rotateY(25deg); 43 | } 44 | 50% { 45 | transform: rotateY(100deg); 46 | } 47 | 100% { 48 | transform: none; 49 | } 50 | } 51 | 52 | 53 | /* Card animations called using keyframes */ 54 | /* Animation angle different for each */ 55 | #dealer .card { 56 | animation: deal-dealer .25s linear; 57 | } 58 | 59 | #user-hand .card { 60 | animation: deal-player .5s linear; 61 | } 62 | 63 | #user-split-hand .card { 64 | animation: deal-player-split .5s linear; 65 | } 66 | 67 | #dealer .card.flipped { 68 | animation: dealer-cardflip .25s linear; 69 | } -------------------------------------------------------------------------------- /js/game-win-logic.js: -------------------------------------------------------------------------------- 1 | // This file contains logic for what happens after the round is determined to be over 2 | 3 | function gameOver() { 4 | isGameOver = true; 5 | setTimeout(function(){ 6 | flipHiddenCard(); 7 | }, 750); 8 | disableButton(standButton); 9 | disableButton(hitButton); 10 | disableButton(splitButton); 11 | disableButton(doubleDownButton); 12 | if (dealerHandTotal === 21) { 13 | if (playerHandTotal === 21 || playerSplitHandTotal === 21) { 14 | gameWinner = "tie"; 15 | } else { 16 | gameWinner = "dealer"; 17 | } 18 | } else if (dealerHandTotal > 21) { 19 | if (playerHandTotal <= 21) { 20 | gameWinner = "player"; 21 | } else if (splitGame === true && playerSplitHandTotal <= 21) { 22 | gameWinner = "player"; 23 | } else { 24 | gameWinner = "tie"; 25 | } 26 | } else if (dealerHandTotal < 21) { 27 | if (playerHandTotal === 21 || playerSplitHandTotal === 21) { 28 | gameWinner = "player"; 29 | } else if (playerHandTotal < 21 && playerHandTotal > dealerHandTotal) { 30 | gameWinner = "player"; 31 | } else if (playerSplitHandTotal < 21 && playerSplitHandTotal > dealerHandTotal) { 32 | gameWinner = "player"; 33 | } else if (playerSplitHandTotal < 21 && playerSplitHandTotal === dealerHandTotal || 34 | playerHandTotal < 21 && playerHandTotal === dealerHandTotal) { 35 | gameWinner = "tie"; 36 | } else { 37 | gameWinner = "dealer"; 38 | } 39 | } 40 | updateChipBalance(); 41 | setTimeout(announceWinner, 2500); // Slight delay to give time to see the final cards play out 42 | } 43 | 44 | function updateChipBalance() { 45 | if (gameWinner === "player") { 46 | // Blackjack is 3:2 payout (and cannot occur on a split deck): 47 | if (splitGame === false && playerHasAce === true && playerHandTotal === 21 && playerHand.length === 2) { 48 | currentChipBalance += currentWager*(3/2) + currentWager; 49 | // Otherwise it's a 1:1 payout: 50 | } else { 51 | currentChipBalance += currentWager*2; 52 | } 53 | // If you tie, get just original wager back (no win or loss) 54 | } else if (gameWinner === "tie") { 55 | currentChipBalance += currentWager; 56 | } 57 | // Note: if dealer wins, nothing happens to player chip balance as their wager was already removed from it 58 | updateVisibleChipBalances(); 59 | } 60 | 61 | function announceWinner() { 62 | updateVisibleHandTotals(); 63 | currentWager = 0; 64 | updateVisibleChipBalances(); 65 | $("#game-board").hide(); 66 | enlargeDeck(playerSplitGameBoard, playerSplitHandTotalDisplay); 67 | enlargeDeck(playerGameBoard, playerHandTotalDisplay); 68 | 69 | // Move betting options from welcome screen to game over screen to play again 70 | $("#wager-options").appendTo($("#game-over")); 71 | $(playAgainButton).appendTo($("#wager-options")); // to move to bottom of container 72 | $(startButton).hide(); 73 | $("#game-over").show("drop", 500); 74 | 75 | if (gameWinner === "player") { 76 | $("#game-outcome").text("You won"); 77 | } else if (gameWinner === "dealer") { 78 | $("#game-outcome").text("Dealer won"); 79 | } else if (gameWinner === "tie") { 80 | $("#game-outcome").text("You tied"); 81 | } 82 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :spades: blackjack 2 | https://jacquelynmarcella.github.io/blackjack/ 3 | 4 | A JavaScript based Blackjack game. Beat the dealer by getting as close to 21 without going over. 5 | 6 | ![](http://www.jacquelynmarcella.com/img/blackjack-1.jpg) 7 | ![](http://www.jacquelynmarcella.com/img/blackjack-mobile.jpg) 8 | 9 | ## :diamonds: Requirements 10 | * Game is playable against dealer 11 | * Game is winnable and winner is displayed 12 | * Game has directions on how to play 13 | * Appropriate Use of GitHub and deployed on Github Pages 14 | * Long files appropriately split up 15 | * Appropriate use of functions 16 | * DRY Code 17 | * Draw detected (if applicable) 18 | * Good ease of triggering events 19 | 20 | ## :diamonds: Technologies Used 21 | * jQuery + jQuery UI 22 | * Materialize CSS Framework 23 | 24 | ## :diamonds: Process 25 | 1. Stubbed out overall game board structure and integrated initial card data. 26 | * Plotted out rules, dealer/player decks, hand totals, and key action buttons. 27 | * Installed Materialize framework and created grid system, which I utilized throughout the whole project to routinely check for how the integrated content was scaling smaller screen sizes. 28 | * Created cards.js file to store full deck of cards including images, value, and name. 29 | 1. Generated start game functionality to get the cards on the board. 30 | * Randomly sort the array to "shuffle" the deck. 31 | * Loop through the original deck and push/pop cards into both the dealer and player hands. 32 | * Display these card images on the appropriate sections of the screen. 33 | 1. Developed initial player interaction fuctionality ("hit" and "stand"). 34 | 1. Built out dealer logic. 35 | * Dealer's actions are based on standard blackjack rules (hit if under 17, stand if 17 or above). 36 | 1. Created win logic and detection for aces. 37 | * Aces can hold values of either 11 or 1. 38 | * Default value for aces is 11, however, if the user goes over 21 the aces will reduce to 1. 39 | * Got initial working win logic up, which was adjusted several times. 40 | 1. Added in chip betting functionality and ongoing chip balance total tracking. 41 | * Added in double down functionality once the betting process was up and running. 42 | 1. Added split card functionality (required a lot of reworking of win logic and player interactions since there are now 2 decks). 43 | 1. Worked through automated turn switching functionality to keep the game moving if the player goes over 21 on their current deck (without them needing to press "stand"). 44 | 1. Worked on an announce winner screen that shows who won, current chip balance, and final hand totals. 45 | * Implemented play again button to reset card deck values and start a new game. 46 | 1. Added ability to toggle in/out rules section using jQuery UI plugin. 47 | 1. Implemented CSS animations and transitions using keyframes to make the card game feel more interactive. 48 | * Dealer's second card appears to flip over when it is eventually displayed. 49 | * Cards move in on the screen and appear to be coming out of the deck. 50 | * Got cards to dynamically stack using offset properties as they are added in the JavaScript. 51 | * If the deck is split, the inactive deck scales down to both signify to the user what deck they are currently on, as well as make room on the page to fit both decks. When the user moves onto the second deck, the first deck scales down and the second deck scales up. 52 | * Set timeouts regularly to give a chance for these animations to complete before moving on to the next move. 53 | 1. Added modal for the rare chance that a player draws 2 aces - they need to be able to choose to split or not before the game automatically reduces their aces to value 1. 54 | 1. Further adjusted and tested layout for responsiveness using the Materialize framework. 55 | 1. Added local storage to chip balance. 56 | 57 | ## :diamonds: Next Steps 58 | * Further test the double ace drawing scenario to ensure it is working consistently. 59 | 60 | ## :diamonds: Resources Used 61 | * CSS Framework: http://materializecss.com/ 62 | * Card Deck Graphics: https://opengameart.org/content/cards-set 63 | * Chip Icons: 64 | * https://thenounproject.com/dorxela/ 65 | * https://thenounproject.com/meisandra0583/ 66 | -------------------------------------------------------------------------------- /js/button-actions.js: -------------------------------------------------------------------------------- 1 | // This file contains key interactions that will occur after the player has clicked a button 2 | 3 | var startGame = function() { 4 | getCards(); 5 | if (currentWager === 0) { 6 | Materialize.toast("You must select a bet to play", 1000); 7 | } else if (currentChipBalance < 10) { 8 | Materialize.toast("You're out of chips! Reset the game to continue" , 2000); 9 | } else if (currentChipBalance < currentWager) { 10 | Materialize.toast("Insufficient chip balance, please select a lower bet" , 1500); 11 | } else { 12 | currentChipBalance -= currentWager; 13 | updateVisibleChipBalances(); 14 | $("#welcome").hide(); 15 | $("#game-over").hide(); 16 | $(".brand-logo").text("blackjack"); 17 | $("#game-board").show("fade", 1000); 18 | cardsInDeck = cards; 19 | cardsInDeck.sort(function() {return 0.5 - Math.random()}); 20 | for (let i = 0; i <= 1; i++) { 21 | setTimeout(function(){ 22 | currentTurn = "player"; 23 | dealCard(playerHand, playerGameBoard); 24 | currentTurn = "dealer"; 25 | dealCard(dealerHand, dealerGameBoard); 26 | }, i*1500); 27 | } 28 | setTimeout(function(){ 29 | currentTurn = "player"; 30 | if (playerHand.length === 2 && playerHand[0].name === playerHand[1].name) { 31 | enableButton(splitButton, split); 32 | } 33 | }, 2500); 34 | 35 | } 36 | } 37 | 38 | var hit = function() { 39 | if (currentTurn === "player") { 40 | playerStatus = "hit"; 41 | dealCard(playerHand, playerGameBoard); 42 | } else if (currentTurn === "playerSplit") { 43 | playerSplitStatus = "hit"; 44 | dealCard(playerSplitHand, playerSplitGameBoard); 45 | } 46 | } 47 | 48 | var stand = function() { 49 | if (currentTurn === "player") { 50 | changeHand(playerStatus); 51 | } else if (currentTurn === "playerSplit") { 52 | changeHand(playerSplitStatus); 53 | } 54 | } 55 | 56 | var split = function() { 57 | splitGame = true; 58 | playerHandTotal = playerHandTotal - playerHand[1].value; 59 | playerSplitHandTotal = playerHand[1].value; 60 | updateVisibleHandTotals(); 61 | $(".split-hand-total").removeClass("inactive").show(); 62 | $(playerSplitGameBoard).removeClass("inactive").show(); 63 | var splitCard = playerHand.pop(); 64 | playerSplitHand.push(splitCard); 65 | var cardImage = $("#player-card-1").attr("id", "playerSplit-card-0"); 66 | 67 | cardImage.hide(); // Hide it at first to allow for the transition to occur 68 | // This is the first card in the deck, so want to cancel out the previous offset/stacking and have it go to the initial normal spot 69 | cardImage.appendTo($(playerSplitGameBoard)).offset({left: 60}).css("margin-right", "auto").show(); 70 | 71 | currentChipBalance -= currentWager; 72 | currentWager = currentWager * 2; 73 | updateVisibleChipBalances(); 74 | 75 | // Then, deal 1 new card for each newly split deck 76 | currentTurn = "player"; 77 | dealCard(playerHand, playerGameBoard); 78 | currentTurn = "playerSplit"; 79 | dealCard(playerSplitHand, playerSplitGameBoard); 80 | 81 | // Make split button no longer clickable as in this game you can only split once 82 | disableButton(splitButton); 83 | 84 | // Shrink the inactive deck to both signal what deck they are playing and to make room on the board 85 | setTimeout(function(){ 86 | scaleDownDeck(playerSplitGameBoard, playerSplitHandTotalDisplay); 87 | currentTurn = "player"; 88 | }, 1000); 89 | 90 | } 91 | 92 | function doubleDown() { 93 | if (currentChipBalance - currentWager <= 0) { 94 | Materialize.toast("Insufficient chip balance" , 1000); 95 | } 96 | else { 97 | currentChipBalance -= currentWager; //subtracts the same value again from current balance 98 | currentWager = currentWager * 2; 99 | updateVisibleChipBalances(); 100 | disableButton(doubleDownButton); 101 | } 102 | } 103 | 104 | function newGame() { 105 | getCards(); 106 | cardsInDeck = cards; 107 | gameWinner = "none"; 108 | dealerHand = []; 109 | dealerHandTotal = 0; 110 | dealerStatus = "start"; 111 | playerHand = []; 112 | playerHandTotal = 0; 113 | playerStatus = "start"; 114 | playerHasAce = false; 115 | splitGame = false; 116 | isGameOver = false; 117 | playerSplitHand = []; 118 | playerSplitHandTotal = 0; 119 | playerSplitStatus = "start"; 120 | 121 | if (currentWager === 0) { 122 | Materialize.toast("You must select a bet to play", 1000); 123 | } else { 124 | $(playerSplitGameBoard).hide(); 125 | $(".split-hand-total").hide(); 126 | enableButton(standButton, stand); 127 | enableButton(hitButton, hit); 128 | enableButton(doubleDownButton, doubleDown); 129 | dealerGameBoard.empty(); 130 | playerGameBoard.empty(); 131 | playerSplitGameBoard.empty(); 132 | updateVisibleHandTotals(); 133 | startGame(); 134 | } 135 | } 136 | 137 | function resetGame() { 138 | currentWager = 0; 139 | currentChipBalance = 500; 140 | updateVisibleChipBalances(); 141 | location.reload(); 142 | } -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | // Starting game board values 2 | var cardsInDeck; 3 | 4 | $( document ).ready(function() { 5 | getCards(); 6 | cardsInDeck = cards; 7 | updateVisibleChipBalances(); 8 | }); 9 | 10 | var currentTurn = "player"; 11 | var currentWager = 0; 12 | var currentChipBalance = localStorage.getItem('blackjackChips') || 500; 13 | var gameWinner = "none"; // To be declared at end of game 14 | var isGameOver = false; 15 | 16 | // Dealer hand and starting totals 17 | var dealerHand = []; 18 | var dealerHandTotal = 0; 19 | var dealerGameBoard = $("#dealer"); 20 | var dealerStatus = "start"; // Possible statuses are start (initial gameplay), stand, hit 21 | 22 | // Player hand and starting totals 23 | var playerHand = []; 24 | var playerHandTotal = 0; 25 | var playerGameBoard = $("#user-hand"); 26 | var playerHandTotalDisplay = $(".hand-total"); 27 | var playerStatus = "start"; // Possible statuses are start (initial gameplay), stand, hit 28 | 29 | // Because aces can equal 1 or 11, need to quickly know if player has aces so we can 30 | // adjust value from 11 to 1 if they go over 21 (default value is 11) 31 | var playerHasAce = false; 32 | 33 | // Player split game variables only used if the player splits their hand 34 | var splitGame = false; // default value is false, must be turned true 35 | var playerSplitHand = []; 36 | var playerSplitHandTotal = 0; 37 | var playerSplitGameBoard = $("#user-split-hand"); 38 | var playerSplitHandTotalDisplay = $(".split-hand-total"); 39 | var playerSplitStatus; 40 | 41 | // Buttons pulled from DOM 42 | var startButton = $("#start-game-button"); 43 | var doubleDownButton = $("#double-down-button"); 44 | var hitButton = $("#hit-button"); 45 | var standButton = $("#stand-button"); 46 | var splitButton = $(".split-button"); 47 | var playAgainButton = $(".new-game-button"); 48 | 49 | // Deactivates a button (both event listener and appearance) 50 | function disableButton(buttonName) { 51 | $(buttonName).off(); 52 | $(buttonName).addClass("disabled-button"); 53 | } 54 | 55 | // Activates a button (both event listener and appearance) 56 | function enableButton(buttonName, event) { 57 | $(buttonName).click(event); 58 | $(buttonName).removeClass("disabled-button"); 59 | } 60 | 61 | // Update chip totals displayed to user throughout the game 62 | function updateVisibleChipBalances() { 63 | $(".current-wager").text(currentWager); 64 | $(".current-chip-balance").text(currentChipBalance); 65 | localStorage.setItem('blackjackChips', currentChipBalance); 66 | } 67 | 68 | // Update card hand totals displayed to user throughout the game 69 | function updateVisibleHandTotals() { 70 | $(playerHandTotalDisplay).text(playerHandTotal); 71 | $(playerSplitHandTotalDisplay).text(playerSplitHandTotal); 72 | 73 | // If the dealer has not played yet or game is not over, only show value of 1st card 74 | // as the player is still making their initial moves 75 | if (dealerHand.length === 2 && isGameOver === false && dealerStatus === "start") { 76 | $(".dealer-hand-total").text(dealerHandTotal - dealerHand[1].value); 77 | } else { 78 | $(".dealer-hand-total").text(dealerHandTotal); 79 | } 80 | 81 | } 82 | 83 | // Called when player clicks on a chip 84 | function selectWager(amount){ 85 | currentWager = amount; 86 | updateVisibleChipBalances(); 87 | } 88 | 89 | // ANIMATIONS/INTERACTIVITY: 90 | function flipHiddenCard() { 91 | // If it's just the initial round, first we need to flip/reveal the hidden dealer card when this is called 92 | if (dealerHand.length === 2) { 93 | $("#dealer-card-1").addClass("flipped"); 94 | setTimeout(function(){ 95 | $("#dealer-card-1").attr("src", "img/" + dealerHand[1].src); 96 | updateVisibleHandTotals(); 97 | }, 250); 98 | } 99 | } 100 | 101 | // Used in split game mode, shrinks the inactive deck and totals 102 | function scaleDownDeck(deck, totalDisplay) { 103 | $(totalDisplay).addClass("splithand-scaledown"); 104 | $(deck).addClass("splithand-scaledown"); 105 | } 106 | 107 | // Used in split game mode, enlarges the deck and totals when turn active or when 108 | // dome with gameplay 109 | function enlargeDeck(deck, totalDisplay) { 110 | $(totalDisplay).removeClass("splithand-scaledown"); 111 | $(deck).removeClass("splithand-scaledown"); 112 | } 113 | 114 | // Toggling rules from main nav gives an animation effect 115 | $(".rules-nav").click(function(){ 116 | $("#rules").toggle("blind", 500); 117 | }); 118 | 119 | // But clicking close does not provide an animation effect 120 | $("#rules-close").click(function(){ 121 | $("#rules").hide(); 122 | }); 123 | 124 | // Materialize modal 125 | $(".modal").modal({ 126 | dismissible: false, 127 | opacity: .40, 128 | inDuration: 300, 129 | outDuration: 200, 130 | startingTop: "10%", // Starting top style attribute 131 | endingTop: "10%", // Ending top style attribute 132 | } 133 | ); 134 | 135 | // EVENT LISTENERS: 136 | $("#chip-10").click(function(){selectWager(10)}); 137 | $("#chip-25").click(function(){selectWager(25)}); 138 | $("#chip-50").click(function(){selectWager(50)}); 139 | $("#chip-100").click(function(){selectWager(100)}); 140 | 141 | // Button activation 142 | $(startButton).click(startGame); 143 | $(doubleDownButton).click(doubleDown); 144 | $(hitButton).click(hit); 145 | $(standButton).click(stand); 146 | $(playAgainButton).click(newGame); 147 | $("#reset-game").click(resetGame); 148 | 149 | $(".reduce-aces-button").click( // Can only see this if player draws 2 aces, would only be reducing in 1st deck 150 | function(){ 151 | reduceAcesValue(playerHand); 152 | disableButton(splitButton, split); 153 | }); 154 | -------------------------------------------------------------------------------- /js/game-play-logic.js: -------------------------------------------------------------------------------- 1 | // This file contains the main logic utilized during active gameplay, before the game is declared over 2 | 3 | function dealCard(hand, location) { 4 | var cardDrawn = cardsInDeck.pop(); 5 | hand.push(cardDrawn); 6 | var index = hand.length - 1; 7 | 8 | // Create card image for card, hide initially so it doesn't impact transition 9 | var cardImage = $("").attr("class", "card").attr("src", "img/" + hand[index].src).hide(); 10 | cardImage.attr("id", currentTurn + "-card-" + index); 11 | 12 | // To create stacked card effect 13 | if (index === 0) { 14 | cardImage.appendTo($(location)).show(); 15 | } else if (index > 0) { 16 | cardImage.appendTo($(location)).offset({left: -60}).css("margin-right", -60).show(); 17 | } 18 | if (hand[index].name === "ace" && currentTurn != "dealer") { 19 | playerHasAce = true; 20 | } 21 | // Note: tried to dry this out by putting totals as a param but couldn't get it working yet 22 | if (currentTurn === "player") { 23 | playerHandTotal += hand[index].value; 24 | } else if (currentTurn === "playerSplit") { 25 | playerSplitHandTotal += hand[index].value; 26 | } else if (currentTurn === "dealer") { 27 | dealerHandTotal += hand[index].value; 28 | } 29 | // Second card only for dealer should show face down 30 | if (dealerHand.length === 2 && currentTurn === "dealer") { 31 | cardImage.attr("src", "img/card_back.png"); 32 | } 33 | updateVisibleHandTotals(); 34 | evaluateGameStatus(); 35 | } 36 | 37 | function evaluateGameStatus() { 38 | // Player can only split or double down after first 2 cards drawn 39 | if (playerHand.length === 3 || dealerStatus === "hit") { 40 | disableButton(doubleDownButton); 41 | disableButton(splitButton); 42 | } 43 | if (currentTurn != "dealer") { 44 | if (playerHasAce === true) { 45 | if (currentTurn === "player") { // Dry out by having params in here 46 | reviewAcesValue(playerHand, playerHandTotal); 47 | } else if (currentTurn === "playerSplit") { 48 | reviewAcesValue(playerSplitHand, playerSplitHandTotal); 49 | } 50 | } else { 51 | isPlayerDone(); 52 | } 53 | } 54 | if (currentTurn === "dealer" && dealerStatus === "hit") { 55 | dealerPlay(); 56 | } 57 | } 58 | 59 | 60 | // The purpose of this function is to detect when a turn should be shifted without the player 61 | // needing to click "stand". This is also an important step for determining what the next move 62 | // is if there is a split deck. 63 | function isPlayerDone() { 64 | if (splitGame === false && playerHandTotal >= 21) { 65 | gameOver(); 66 | } else if (splitGame === true) { 67 | if (currentTurn === "player") { 68 | if (playerHandTotal === 21) { 69 | gameOver(); 70 | // If it's a split game, we can't just game over on the first hand if the player goes over 71 | } else if (playerHandTotal > 21) 72 | changeHand(playerStatus); 73 | } else if (currentTurn === "playerSplit") { 74 | if (playerSplitHandTotal === 21) { 75 | gameOver(); 76 | } else if (playerSplitHandTotal > 21) { 77 | // If the player was under 21 in their first game, the dealer should play before gameover 78 | if (playerHandTotal < 21) { 79 | changeHand(playerSplitStatus); 80 | } else { 81 | gameOver(); 82 | } 83 | } 84 | } 85 | } 86 | } 87 | 88 | function changeHand(currentDeckStatus) { 89 | currentDeckStatus = "stand"; 90 | if (currentTurn === "player") { 91 | if (splitGame === true) { 92 | currentTurn = "playerSplit"; 93 | // Scale down the player deck as we change turns, but only on split hand 94 | scaleDownDeck(playerGameBoard, playerHandTotalDisplay); 95 | enlargeDeck(playerSplitGameBoard, playerSplitHandTotalDisplay); 96 | } else if (splitGame === false) { 97 | currentTurn = "dealer"; 98 | dealerStatus = "hit"; 99 | } 100 | } else if (currentTurn === "playerSplit") { 101 | currentTurn = "dealer"; 102 | dealerStatus = "hit"; 103 | } 104 | evaluateGameStatus(); 105 | } 106 | 107 | function reviewAcesValue(hand, total) { 108 | if (total > 21) { 109 | // If they have exactly 2 aces in the first draw, prompt them to choose to split or not 110 | if (hand.length === 2) { 111 | enableButton(splitButton, split); 112 | $("#two-aces-prompt").modal("open"); 113 | // Otherwise, just reduce the aces value so they are no longer over 21 114 | } else if (hand.length > 2) { 115 | reduceAcesValue(hand); 116 | isPlayerDone(); 117 | } 118 | } else { 119 | isPlayerDone(); 120 | } 121 | } 122 | 123 | function reduceAcesValue(deck) { 124 | for (var i = 0; i < deck.length; i++) { 125 | if (deck[i].name === "ace" && deck[i].value === 11) { // Only focusing on aces that haven't been changed from 11 to 1 already 126 | deck[i].value = 1; 127 | if (currentTurn === "player") { 128 | playerHandTotal -= 10; 129 | } else if (currentTurn === "playerSplit") { 130 | playerSplitHandTotal -= 10; 131 | } 132 | updateVisibleHandTotals(); 133 | Materialize.toast("Your ace value changed from 11 to 1", 1500); 134 | } 135 | } 136 | } 137 | 138 | function dealerPlay() { 139 | flipHiddenCard(); 140 | disableButton(standButton); 141 | disableButton(hitButton); 142 | disableButton(splitButton); 143 | // The below logic is based on standard blackjack rules 144 | if (dealerHandTotal < 17) { 145 | setTimeout(function(){ 146 | dealCard(dealerHand, dealerGameBoard); 147 | }, 1000); 148 | } else if (dealerHandTotal >= 21) { 149 | setTimeout(function(){ 150 | gameOver(); 151 | }, 1100); 152 | } else if (dealerHandTotal >= 17) { 153 | setTimeout(function(){ 154 | dealerStatus = "stand"; 155 | gameOver(); 156 | }, 1100); 157 | } 158 | } -------------------------------------------------------------------------------- /js/cards.js: -------------------------------------------------------------------------------- 1 | //Full array of possible cards 2 | var cards; 3 | 4 | function getCards(){ 5 | cards = [ 6 | { 7 | "suit": "clubs", 8 | "name": "2", 9 | "src": "Clubs-2.png", 10 | "value": 2 11 | }, 12 | { 13 | "suit": "clubs", 14 | "name": "3", 15 | "src": "Clubs-3.png", 16 | "value": 3 17 | }, 18 | { 19 | "suit": "clubs", 20 | "name": "4", 21 | "src": "Clubs-4.png", 22 | "value": 4 23 | }, 24 | { 25 | "suit": "clubs", 26 | "name": "5", 27 | "src": "Clubs-5.png", 28 | "value": 5 29 | }, 30 | { 31 | "suit": "clubs", 32 | "name": "6", 33 | "src": "Clubs-6.png", 34 | "value": 6 35 | }, 36 | { 37 | "suit": "clubs", 38 | "name": "7", 39 | "src": "Clubs-7.png", 40 | "value": 7 41 | }, 42 | { 43 | "suit": "clubs", 44 | "name": "8", 45 | "src": "Clubs-8.png", 46 | "value": 8 47 | }, 48 | { 49 | "suit": "clubs", 50 | "name": "9", 51 | "src": "Clubs-9.png", 52 | "value": 9 53 | }, 54 | { 55 | "suit": "clubs", 56 | "name": "10", 57 | "src": "Clubs-10.png", 58 | "value": 10 59 | }, 60 | { 61 | "suit": "clubs", 62 | "name": "ace", 63 | "src": "Clubs-Ace.png", 64 | "value": 11 65 | }, 66 | { 67 | "suit": "clubs", 68 | "name": "jack", 69 | "src": "Clubs-Jack.png", 70 | "value": 10 71 | }, 72 | { 73 | "suit": "clubs", 74 | "name": "king", 75 | "src": "Clubs-King.png", 76 | "value": 10 77 | }, 78 | { 79 | "suit": "clubs", 80 | "name": "queen", 81 | "src": "Clubs-Queen.png", 82 | "value": 10 83 | }, 84 | { 85 | "suit": "diamonds", 86 | "name": "2", 87 | "src": "Diamond-2.png", 88 | "value": 2 89 | }, 90 | { 91 | "suit": "diamonds", 92 | "name": "3", 93 | "src": "Diamond-3.png", 94 | "value": 3 95 | }, 96 | { 97 | "suit": "diamonds", 98 | "name": "4", 99 | "src": "Diamond-4.png", 100 | "value": 4 101 | }, 102 | { 103 | "suit": "diamonds", 104 | "name": "5", 105 | "src": "Diamond-5.png", 106 | "value": 5 107 | }, 108 | { 109 | "suit": "diamonds", 110 | "name": "6", 111 | "src": "Diamond-6.png", 112 | "value": 6 113 | }, 114 | { 115 | "suit": "diamonds", 116 | "name": "7", 117 | "src": "Diamond-7.png", 118 | "value": 7 119 | }, 120 | { 121 | "suit": "diamonds", 122 | "name": "8", 123 | "src": "Diamond-8.png", 124 | "value": 8 125 | }, 126 | { 127 | "suit": "diamonds", 128 | "name": "9", 129 | "src": "Diamond-9.png", 130 | "value": 9 131 | }, 132 | { 133 | "suit": "diamonds", 134 | "name": "10", 135 | "src": "Diamond-10.png", 136 | "value": 10 137 | }, 138 | { 139 | "suit": "diamonds", 140 | "name": "ace", 141 | "src": "Diamond-Ace.png", 142 | "value": 11 143 | }, 144 | { 145 | "suit": "diamonds", 146 | "name": "jack", 147 | "src": "Diamond-Jack.png", 148 | "value": 10 149 | }, 150 | { 151 | "suit": "diamonds", 152 | "name": "king", 153 | "src": "Diamond-King.png", 154 | "value": 10 155 | }, 156 | { 157 | "suit": "diamonds", 158 | "name": "queen", 159 | "src": "Diamond-Queen.png", 160 | "value": 10 161 | }, 162 | { 163 | "suit": "hearts", 164 | "name": "2", 165 | "src": "Hearts-2.png", 166 | "value": 2 167 | }, 168 | { 169 | "suit": "hearts", 170 | "name": "3", 171 | "src": "Hearts-3.png", 172 | "value": 3 173 | }, 174 | { 175 | "suit": "hearts", 176 | "name": "4", 177 | "src": "Hearts-4.png", 178 | "value": 4 179 | }, 180 | { 181 | "suit": "hearts", 182 | "name": "5", 183 | "src": "Hearts-5.png", 184 | "value": 5 185 | }, 186 | { 187 | "suit": "hearts", 188 | "name": "6", 189 | "src": "Hearts-6.png", 190 | "value": 6 191 | }, 192 | { 193 | "suit": "hearts", 194 | "name": "7", 195 | "src": "Hearts-7.png", 196 | "value": 7 197 | }, 198 | { 199 | "suit": "hearts", 200 | "name": "8", 201 | "src": "Hearts-8.png", 202 | "value": 8 203 | }, 204 | { 205 | "suit": "hearts", 206 | "name": "9", 207 | "src": "Hearts-9.png", 208 | "value": 9 209 | }, 210 | { 211 | "suit": "hearts", 212 | "name": "10", 213 | "src": "Hearts-10.png", 214 | "value": 10 215 | }, 216 | { 217 | "suit": "hearts", 218 | "name": "ace", 219 | "src": "Hearts-Ace.png", 220 | "value": 11 221 | }, 222 | { 223 | "suit": "hearts", 224 | "name": "jack", 225 | "src": "Hearts-Jack.png", 226 | "value": 10 227 | }, 228 | { 229 | "suit": "hearts", 230 | "name": "king", 231 | "src": "Hearts-King.png", 232 | "value": 10 233 | }, 234 | { 235 | "suit": "hearts", 236 | "name": "queen", 237 | "src": "Hearts-Queen.png", 238 | "value": 10 239 | }, 240 | { 241 | "suit": "spades", 242 | "name": "2", 243 | "src": "Spades-2.png", 244 | "value": 2 245 | }, 246 | { 247 | "suit": "spades", 248 | "name": "3", 249 | "src": "Spades-3.png", 250 | "value": 3 251 | }, 252 | { 253 | "suit": "spades", 254 | "name": "4", 255 | "src": "Spades-4.png", 256 | "value": 4 257 | }, 258 | { 259 | "suit": "spades", 260 | "name": "5", 261 | "src": "Spades-5.png", 262 | "value": 5 263 | }, 264 | { 265 | "suit": "spades", 266 | "name": "6", 267 | "src": "Spades-6.png", 268 | "value": 6 269 | }, 270 | { 271 | "suit": "spades", 272 | "name": "7", 273 | "src": "Spades-7.png", 274 | "value": 7 275 | }, 276 | { 277 | "suit": "spades", 278 | "name": "8", 279 | "src": "Spades-8.png", 280 | "value": 8 281 | }, 282 | { 283 | "suit": "spades", 284 | "name": "9", 285 | "src": "Spades-9.png", 286 | "value": 9 287 | }, 288 | { 289 | "suit": "spades", 290 | "name": "10", 291 | "src": "Spades-10.png", 292 | "value": 10 293 | }, 294 | { 295 | "suit": "spades", 296 | "name": "ace", 297 | "src": "Spades-Ace.png", 298 | "value": 11 299 | }, 300 | { 301 | "suit": "spades", 302 | "name": "jack", 303 | "src": "Spades-Jack.png", 304 | "value": 10 305 | }, 306 | { 307 | "suit": "spades", 308 | "name": "king", 309 | "src": "Spades-King.png", 310 | "value": 10 311 | }, 312 | { 313 | "suit": "spades", 314 | "name": "queen", 315 | "src": "Spades-Queen.png", 316 | "value": 10 317 | } 318 | ] 319 | } 320 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | /* Broad site-wide styles */ 2 | body { 3 | background: #1f513b; 4 | background: linear-gradient(to top right, #1f513b, #0F2725) fixed; 5 | text-align: center; 6 | font-family: 'Lato', sans-serif; 7 | color: white; 8 | } 9 | 10 | h1, h2, h3, h4, h5, .brand-logo { 11 | font-family: 'Arvo', serif; 12 | } 13 | 14 | h1 { 15 | font-size: 4em; 16 | } 17 | 18 | h4 { 19 | font-size: 1.75em; 20 | } 21 | 22 | p { 23 | font-size: 1.25em; 24 | line-height: 1.75em; 25 | } 26 | 27 | strong { 28 | font-family: 'Arvo', serif; 29 | padding: 4px 0; 30 | display: block; 31 | font-size: 1.10em; 32 | } 33 | 34 | 35 | button, button:focus { 36 | margin: 5px; 37 | padding: 10px 20px; 38 | background: #d60438; 39 | color: white; 40 | font-size: 1.25em; 41 | font-weight: 400; 42 | letter-spacing: 1px; 43 | border: 0; 44 | } 45 | 46 | button.secondary { 47 | background: #1E6692; 48 | } 49 | 50 | button:active { 51 | background: black; 52 | } 53 | 54 | button.disabled-button, button.secondary.disabled-button { 55 | background: #0F2725; 56 | } 57 | 58 | /* Welcome screen */ 59 | #welcome p { 60 | width: 50%; 61 | margin: 10px auto; 62 | } 63 | 64 | /* Rules section hidden at start and can toggle in from above */ 65 | #rules { 66 | padding: 30px 20px 20px 20px; 67 | /* margin: 20px auto 30px auto;*/ 68 | text-align: left; 69 | display: none; 70 | background: #0F2725; 71 | position: absolute; 72 | top: 55px; 73 | right: 0; 74 | width: 100%; 75 | z-index: 99; 76 | font-size: .75em; 77 | } 78 | 79 | #rules button { 80 | float: right; 81 | margin-right: 20px; 82 | } 83 | 84 | #rules h4 { 85 | text-align: center; 86 | } 87 | 88 | /* Card decks during gameplay */ 89 | 90 | #deck-pile, #dealer, #user-hand, #user-split-hand { 91 | display: inline-block; 92 | position: relative; 93 | } 94 | 95 | .card { 96 | transition: all 3s; 97 | display: inline-block; 98 | background-color: none !important; 99 | border-radius: 12.5px; 100 | outline-offset: -6px; 101 | outline: 6px solid white; 102 | box-shadow: -3px 4px rgba(15, 39, 37, .25); 103 | } 104 | 105 | .card:hover { 106 | z-index: 100; 107 | } 108 | 109 | .pile { 110 | margin-right: 30px; 111 | } 112 | 113 | /* Chips and wagers */ 114 | 115 | .wager { 116 | height: 60px; 117 | width: 60px; 118 | margin: 2px; 119 | display: inline-block; 120 | } 121 | 122 | .wager-clickable { 123 | margin: 15px 2px; 124 | } 125 | 126 | .wager-clickable:hover { 127 | transform: scale(1.10); 128 | } 129 | 130 | /* For bet screen where the supporting icons don't need to be full size */ 131 | .wager-small { 132 | margin-left: 30px; 133 | margin-right: 10px; 134 | height: 40px; 135 | width: 40px; 136 | } 137 | 138 | /*For when user is choosing what their bet is */ 139 | #wager-options { 140 | margin: 15px auto 5px auto; 141 | } 142 | 143 | #wager-options span { 144 | display: inline-block; 145 | margin: 20px auto; 146 | font-size: 2em; 147 | line-height: 1.5em; 148 | position: relative; 149 | bottom: 10px; 150 | } 151 | 152 | /* For displaying during the game */ 153 | .wager-gameplay { 154 | font-size: 2.5em; 155 | position: relative; 156 | top: 50px; 157 | } 158 | 159 | .wager-gameplay span { 160 | display: block; 161 | } 162 | 163 | /* Gameover scoreboard table */ 164 | table { 165 | width: 50%; 166 | margin: 0 auto; 167 | padding: 0; 168 | } 169 | 170 | .total-label { 171 | text-align: right; 172 | padding-right: 20px; 173 | } 174 | 175 | .total-output { 176 | text-align: left; 177 | } 178 | 179 | /* Card totals */ 180 | .hand-total, .split-hand-total, .dealer-hand-total { 181 | background: black; 182 | padding: 10px 0; 183 | margin: 2px; 184 | display: inline-block; 185 | font-size: 1.25em; 186 | text-align: center; 187 | width: 50px; 188 | } 189 | 190 | /* On the gameboard, these totals get positioned differently over the decks */ 191 | .game-board-totals { 192 | position: relative; 193 | left: -15px; 194 | bottom: 40px; 195 | margin-right: -15px; 196 | } 197 | 198 | #user-split-hand { 199 | margin-left: 20px; 200 | } 201 | 202 | /* For whenever split hand state is engaged, we will scale decks up and down */ 203 | .splithand-scaledown { 204 | transition: all 1s; 205 | transform: scale(.75); 206 | left: -80px; 207 | margin-right: -40px; 208 | } 209 | 210 | #user-hand.splithand-scaledown, #user-split-hand.splithand-scaledown { 211 | transform: scale(.4); 212 | left: 0; 213 | margin-right: -30px; 214 | } 215 | 216 | /* Game button action items are styled bigger than the other buttons */ 217 | #sidebar button { 218 | width: 100%; 219 | height: 70px; 220 | margin: 5px 0 10px 0; 221 | overflow: none; 222 | padding: 0; 223 | } 224 | 225 | /* For any items invisible at start that we will toggle/show later */ 226 | .inactive { 227 | display: none; 228 | } 229 | 230 | 231 | /* Materialize framework style overrides*/ 232 | .nav-wrapper { 233 | background-color: black !important; 234 | text-align: left !important; 235 | box-shadow: 0 !important; 236 | } 237 | 238 | .navbar-fixed { 239 | margin-bottom: 25px !important; 240 | } 241 | 242 | .brand-logo { /* Text in nav bar */ 243 | padding-left: 20px !important; 244 | font-size: 1.5em !important; 245 | } 246 | 247 | .rules-nav { /* Icon to toggle rules */ 248 | padding-right: 20px !important; 249 | } 250 | 251 | .modal { 252 | padding: 40px 0 !important; 253 | width: 75% !important; 254 | height: 75% !important; 255 | opacity: .90 !important; 256 | overflow: hidden !important; 257 | max-height: 100% !important; 258 | } 259 | 260 | .modal-content h4, .modal-content p { 261 | color: black; 262 | } 263 | 264 | .modal-body { 265 | max-height: 600px; 266 | } 267 | 268 | .row { 269 | margin: 0 auto; 270 | } 271 | 272 | /* Resposive mobile adjustments*/ 273 | @media all and (max-width: 600px){ 274 | .wager-gameplay { 275 | top: 0; 276 | } 277 | } 278 | 279 | @media only screen and (min-device-width : 320px) and (max-device-width : 480px) { 280 | 281 | .navbar-fixed { 282 | margin-bottom: 8px !important; 283 | } 284 | 285 | .game-board h4 { 286 | font-size: 1.25em; 287 | } 288 | 289 | .game-over h3 { 290 | font-size: 2.25em; 291 | } 292 | 293 | p { 294 | font-size: 1.4em; 295 | } 296 | 297 | 298 | table { 299 | width: 100%; 300 | } 301 | 302 | #welcome p { 303 | width: 100%; 304 | } 305 | 306 | .card { 307 | width: 77px; 308 | height: 103.5px; 309 | } 310 | 311 | #sidebar button { 312 | width: 70px; 313 | height: 40px; 314 | font-size: .75em; 315 | } 316 | 317 | .total-label { 318 | padding-right: 0; 319 | } 320 | 321 | .total-output { 322 | padding-left: 10px; 323 | } 324 | 325 | .wager-gameplay { 326 | font-size: 1.75em; 327 | position: relative; 328 | top: 0; 329 | margin: 0 auto; 330 | } 331 | 332 | .wager-gameplay .wager { 333 | height: 30px; 334 | width: 30px; 335 | } 336 | 337 | .wager-gameplay span { 338 | font-size: .75em; 339 | display: inline-block; 340 | margin-left: 20px; 341 | position: relative; 342 | bottom: 10px; 343 | } 344 | 345 | } 346 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | blackjack 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 28 |
29 |
30 |
31 |

Game Rules

32 |
33 |
34 |
35 |
36 |

Goal Beat the dealer by getting a hand as close to 21 as possible, without going over 21. A blackjack occurs when you get one ace and one 10 point card, without having split the deck first.

37 |

Gameplay The dealer will give 2 cards to themself and 2 cards to you. The dealer's second card will be played face down. You can choose to either hit (receive more cards) or stand (move on to the next hand). You can hit as many times as you choose so long as your deck is under 21.

38 |

Card Values Queens, Kings, and Jacks are worth 10, pip cards are worth their face value, but Aces can be worth either 11 or 1. In this game, Aces have a default value is 11 unless you go over 21 on your hand.

39 |
40 |
41 |

Splitting Pairs If you receive 2 cards of the same face value, you may choose to split your pairs and play each hand separately. At this table, you can only split once. After you split, one new card will be dealt to each hand then you can choose to either hit or stand for each hand accordingly.

42 |

Betting Bets must be placed prior to playing. After receiving your first 2 cards, you can choose to double down (double your original bet). After your next move, you can no longer choose to double down.

43 |

Payout Payout is 1:1 unless you get a blackjack. For a blackjack, payout is 3:2.

44 | 45 |
46 |
47 |
48 |
49 |
50 |
51 |

blackjack

52 |

Start playing by selecting your bet below. To view the rules at any time, click the icon in the top right.

53 |
54 | 55 | 56 | 57 | 58 |
59 | 0 60 | 61 | 500 62 |
63 | 64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |

Dealer

72 |
73 | 74 |
75 |
76 | 77 |
78 |
79 |
80 |
81 | 82 | ___ 83 |
84 |
85 | 86 | ___ 87 |
88 |
89 |
90 |
91 |
92 |
93 |

Player

94 |
95 | 0 96 |
97 | 0 98 |
99 | 115 |
116 |
117 | 126 |
127 |
128 |
129 |

Win message here

130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 |
Dealer
Player
140 | 141 |
142 |
143 |
144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | --------------------------------------------------------------------------------