diff --git a/10_of_clubs.svg b/10_of_clubs.svg new file mode 100644 index 00000000..2e7788c1 --- /dev/null +++ b/10_of_clubs.svg @@ -0,0 +1,281 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +0 +1 +0 + diff --git a/10_of_diamonds.svg b/10_of_diamonds.svg new file mode 100644 index 00000000..3d0b1c0d --- /dev/null +++ b/10_of_diamonds.svg @@ -0,0 +1,401 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + + + + + + + + + + + + + + + + + + + + + +0 +1 +0 + diff --git a/10_of_hearts.svg b/10_of_hearts.svg new file mode 100644 index 00000000..c57575e2 --- /dev/null +++ b/10_of_hearts.svg @@ -0,0 +1,407 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + + + + + + + + + + + + + + + + + + + +0 +1 +0 + diff --git a/10_of_spades.svg b/10_of_spades.svg new file mode 100644 index 00000000..a14767c6 --- /dev/null +++ b/10_of_spades.svg @@ -0,0 +1,230 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + + + + + + +0 +1 +0 + diff --git a/2_of_clubs.svg b/2_of_clubs.svg new file mode 100644 index 00000000..0334dece --- /dev/null +++ b/2_of_clubs.svg @@ -0,0 +1,216 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +2 + + + + + +2 + + + + diff --git a/2_of_diamonds.svg b/2_of_diamonds.svg new file mode 100644 index 00000000..49562342 --- /dev/null +++ b/2_of_diamonds.svg @@ -0,0 +1,318 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +2 + + + + + + +2 + + + + + + diff --git a/2_of_hearts.svg b/2_of_hearts.svg new file mode 100644 index 00000000..f6c95407 --- /dev/null +++ b/2_of_hearts.svg @@ -0,0 +1,308 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +2 + + + + + + +2 + + + + + + diff --git a/2_of_spades.svg b/2_of_spades.svg new file mode 100644 index 00000000..759abf6b --- /dev/null +++ b/2_of_spades.svg @@ -0,0 +1,147 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +2 + + + +2 + + diff --git a/3_of_clubs.svg b/3_of_clubs.svg new file mode 100644 index 00000000..0fb95b38 --- /dev/null +++ b/3_of_clubs.svg @@ -0,0 +1,224 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +3 + + + + + + +3 + + + + + diff --git a/3_of_diamonds.svg b/3_of_diamonds.svg new file mode 100644 index 00000000..a562f1f3 --- /dev/null +++ b/3_of_diamonds.svg @@ -0,0 +1,319 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +3 + + + + + + + + +3 + + + + + + + + diff --git a/3_of_hearts.svg b/3_of_hearts.svg new file mode 100644 index 00000000..aecd1ff5 --- /dev/null +++ b/3_of_hearts.svg @@ -0,0 +1,318 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +3 + + + + + + + +3 + + + + + + + diff --git a/3_of_spades.svg b/3_of_spades.svg new file mode 100644 index 00000000..89631953 --- /dev/null +++ b/3_of_spades.svg @@ -0,0 +1,154 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +3 + + + +3 + + diff --git a/4_of_clubs.svg b/4_of_clubs.svg new file mode 100644 index 00000000..70f89044 --- /dev/null +++ b/4_of_clubs.svg @@ -0,0 +1,230 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 + + + + + + +4 + + + + + diff --git a/4_of_diamonds.svg b/4_of_diamonds.svg new file mode 100644 index 00000000..86777378 --- /dev/null +++ b/4_of_diamonds.svg @@ -0,0 +1,324 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 + + + + + + + +4 + + + + + + + diff --git a/4_of_hearts.svg b/4_of_hearts.svg new file mode 100644 index 00000000..9b7f0a74 --- /dev/null +++ b/4_of_hearts.svg @@ -0,0 +1,335 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 + + + + + + + +4 + + + + + + + diff --git a/4_of_spades.svg b/4_of_spades.svg new file mode 100644 index 00000000..01e27e49 --- /dev/null +++ b/4_of_spades.svg @@ -0,0 +1,163 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 + + + + +4 + + + diff --git a/5_of_clubs.svg b/5_of_clubs.svg new file mode 100644 index 00000000..864d2f28 --- /dev/null +++ b/5_of_clubs.svg @@ -0,0 +1,238 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 + + + + + + + +5 + + + + + + diff --git a/5_of_diamonds.svg b/5_of_diamonds.svg new file mode 100644 index 00000000..a8cb2b50 --- /dev/null +++ b/5_of_diamonds.svg @@ -0,0 +1,333 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 + + + + + + + + +5 + + + + + + + + diff --git a/5_of_hearts.svg b/5_of_hearts.svg new file mode 100644 index 00000000..af7415ab --- /dev/null +++ b/5_of_hearts.svg @@ -0,0 +1,336 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 + + + + + + + + +5 + + + + + + + + diff --git a/5_of_spades.svg b/5_of_spades.svg new file mode 100644 index 00000000..d9492ba4 --- /dev/null +++ b/5_of_spades.svg @@ -0,0 +1,170 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 + + + + +5 + + + diff --git a/6_of_clubs.svg b/6_of_clubs.svg new file mode 100644 index 00000000..306754ea --- /dev/null +++ b/6_of_clubs.svg @@ -0,0 +1,244 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +6 + + + + + + + +6 + + + + + + diff --git a/6_of_diamonds.svg b/6_of_diamonds.svg new file mode 100644 index 00000000..6f12a53c --- /dev/null +++ b/6_of_diamonds.svg @@ -0,0 +1,340 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +6 + + + + + + + + +6 + + + + + + + + diff --git a/6_of_hearts.svg b/6_of_hearts.svg new file mode 100644 index 00000000..9c319ad1 --- /dev/null +++ b/6_of_hearts.svg @@ -0,0 +1,344 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +6 + + + + + + + + +6 + + + + + + + + diff --git a/6_of_spades.svg b/6_of_spades.svg new file mode 100644 index 00000000..83e8feb0 --- /dev/null +++ b/6_of_spades.svg @@ -0,0 +1,177 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +6 + + + + +6 + + + diff --git a/7_of_clubs.svg b/7_of_clubs.svg new file mode 100644 index 00000000..11329b17 --- /dev/null +++ b/7_of_clubs.svg @@ -0,0 +1,252 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 + + + + + + + + +7 + + + + + + + diff --git a/7_of_diamonds.svg b/7_of_diamonds.svg new file mode 100644 index 00000000..d8483a72 --- /dev/null +++ b/7_of_diamonds.svg @@ -0,0 +1,349 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 + + + + + + + + + +7 + + + + + + + + + diff --git a/7_of_hearts.svg b/7_of_hearts.svg new file mode 100644 index 00000000..8d5fd98a --- /dev/null +++ b/7_of_hearts.svg @@ -0,0 +1,356 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 + + + + + + + + + + +7 + + + + + + + + + + diff --git a/7_of_spades.svg b/7_of_spades.svg new file mode 100644 index 00000000..3146b440 --- /dev/null +++ b/7_of_spades.svg @@ -0,0 +1,186 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 + + + + + +7 + + + + diff --git a/8_of_clubs.svg b/8_of_clubs.svg new file mode 100644 index 00000000..28ae6fb6 --- /dev/null +++ b/8_of_clubs.svg @@ -0,0 +1,260 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +8 + + + + + + + + + +8 + + + + + + + + diff --git a/8_of_diamonds.svg b/8_of_diamonds.svg new file mode 100644 index 00000000..d6d1b0eb --- /dev/null +++ b/8_of_diamonds.svg @@ -0,0 +1,358 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +8 + + + + + + + + + + +8 + + + + + + + + + + diff --git a/8_of_hearts.svg b/8_of_hearts.svg new file mode 100644 index 00000000..ac8d5ba2 --- /dev/null +++ b/8_of_hearts.svg @@ -0,0 +1,364 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +8 + + + + + + + + + + +8 + + + + + + + + + + diff --git a/8_of_spades.svg b/8_of_spades.svg new file mode 100644 index 00000000..0e5bd890 --- /dev/null +++ b/8_of_spades.svg @@ -0,0 +1,195 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +8 + + + + + + +8 + + + + + diff --git a/9_of_clubs.svg b/9_of_clubs.svg new file mode 100644 index 00000000..85cde356 --- /dev/null +++ b/9_of_clubs.svg @@ -0,0 +1,254 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +9 + + + + + + + + + + + + +9 + + + + + + + + + + + diff --git a/9_of_diamonds.svg b/9_of_diamonds.svg new file mode 100644 index 00000000..05292f2e --- /dev/null +++ b/9_of_diamonds.svg @@ -0,0 +1,367 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +9 + + + + + + + + + + + +9 + + + + + + + + + + + diff --git a/9_of_hearts.svg b/9_of_hearts.svg new file mode 100644 index 00000000..0f6a2115 --- /dev/null +++ b/9_of_hearts.svg @@ -0,0 +1,378 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +9 + + + +9 + diff --git a/9_of_spades.svg b/9_of_spades.svg new file mode 100644 index 00000000..2359db59 --- /dev/null +++ b/9_of_spades.svg @@ -0,0 +1,198 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +9 + + + + +9 + + + diff --git a/A_of_clubs.svg b/A_of_clubs.svg new file mode 100644 index 00000000..be74fe02 --- /dev/null +++ b/A_of_clubs.svg @@ -0,0 +1,258 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +A + + +A + diff --git a/A_of_diamonds.svg b/A_of_diamonds.svg new file mode 100644 index 00000000..e5636a4a --- /dev/null +++ b/A_of_diamonds.svg @@ -0,0 +1,311 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +A + + +A + + diff --git a/A_of_hearts.svg b/A_of_hearts.svg new file mode 100644 index 00000000..24702e27 --- /dev/null +++ b/A_of_hearts.svg @@ -0,0 +1,324 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +A + +A + diff --git a/A_of_spades.svg b/A_of_spades.svg new file mode 100644 index 00000000..f95b248d --- /dev/null +++ b/A_of_spades.svg @@ -0,0 +1,279 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +A + +A + + diff --git a/Card-flip-sound-effect.mp3 b/Card-flip-sound-effect.mp3 new file mode 100644 index 00000000..484c5b5d Binary files /dev/null and b/Card-flip-sound-effect.mp3 differ diff --git a/Card_back_05a.svg b/Card_back_05a.svg new file mode 100644 index 00000000..f5d3cfc5 --- /dev/null +++ b/Card_back_05a.svg @@ -0,0 +1,663 @@ + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Insert-coin-sound.mp3 b/Insert-coin-sound.mp3 new file mode 100644 index 00000000..a3519639 Binary files /dev/null and b/Insert-coin-sound.mp3 differ diff --git a/J_of_clubs.svg b/J_of_clubs.svg new file mode 100644 index 00000000..a3503059 --- /dev/null +++ b/J_of_clubs.svg @@ -0,0 +1,224 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +J + + + +J + + + + diff --git a/J_of_diamonds.svg b/J_of_diamonds.svg new file mode 100644 index 00000000..d5315413 --- /dev/null +++ b/J_of_diamonds.svg @@ -0,0 +1,338 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +J + + + + + + + + + + + + + + + + +J + + + + diff --git a/J_of_hearts.svg b/J_of_hearts.svg new file mode 100644 index 00000000..dc95ce1d --- /dev/null +++ b/J_of_hearts.svg @@ -0,0 +1,330 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +J + + + + + + + + + + + + +J + + + + diff --git a/J_of_spades.svg b/J_of_spades.svg new file mode 100644 index 00000000..281113fb --- /dev/null +++ b/J_of_spades.svg @@ -0,0 +1,336 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +J + + + + + + +J + + + + diff --git a/K_of_clubs.svg b/K_of_clubs.svg new file mode 100644 index 00000000..fe6e6769 --- /dev/null +++ b/K_of_clubs.svg @@ -0,0 +1,254 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +K + + + + + +K + + + + diff --git a/K_of_diamonds.svg b/K_of_diamonds.svg new file mode 100644 index 00000000..f983c6a3 --- /dev/null +++ b/K_of_diamonds.svg @@ -0,0 +1,351 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +K + + + + + + + + + + + + + + + + + + +K + + + + diff --git a/K_of_hearts.svg b/K_of_hearts.svg new file mode 100644 index 00000000..7250745d --- /dev/null +++ b/K_of_hearts.svg @@ -0,0 +1,337 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +K + + + + + + + + + + + + + + +K + + + + diff --git a/K_of_spades.svg b/K_of_spades.svg new file mode 100644 index 00000000..ac4338d9 --- /dev/null +++ b/K_of_spades.svg @@ -0,0 +1,329 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +K + + + + + + + + +K + + + + diff --git a/MODE7GX3.TTF b/MODE7GX3.TTF new file mode 100644 index 00000000..c9678aed Binary files /dev/null and b/MODE7GX3.TTF differ diff --git a/Q_of_clubs.svg b/Q_of_clubs.svg new file mode 100644 index 00000000..6a636f74 --- /dev/null +++ b/Q_of_clubs.svg @@ -0,0 +1,250 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Q + + + + + +Q + + + + diff --git a/Q_of_diamonds.svg b/Q_of_diamonds.svg new file mode 100644 index 00000000..76b62db0 --- /dev/null +++ b/Q_of_diamonds.svg @@ -0,0 +1,339 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Q + + + + + + + + + + + + + + + + + + +Q + + + + diff --git a/Q_of_hearts.svg b/Q_of_hearts.svg new file mode 100644 index 00000000..90ede784 --- /dev/null +++ b/Q_of_hearts.svg @@ -0,0 +1,331 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Q + + + + + + + + + + + + + + + +Q + + + + + diff --git a/Q_of_spades.svg b/Q_of_spades.svg new file mode 100644 index 00000000..8dc5540b --- /dev/null +++ b/Q_of_spades.svg @@ -0,0 +1,324 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Q + + + + + + + +Q + + + diff --git a/README.md b/README.md index 1d3a8a65..03f7ed25 100644 --- a/README.md +++ b/README.md @@ -1 +1,41 @@ # Rocket Academy Coding Bootcamp: Video Poker + +Technical Review +"Technical" refers to software logic and syntax. +What went well? Please share a link to the specific code. + +- Animations, sounds, click events working ok +- calcHandScore and probability logic + +What were the biggest challenges you faced? Please share a link to the specific code. + +- Scoring table was hard coded with HTML. Probably could have used CSS Grid and some javascript to propagate the score patterns +- Making the layout responsive. The large score table looks to be making the layout off center in mobile view +- App hangs when it runs loop with too many iterations. Unexpected behaviour when user clicks around while loop is running. There will be some "click event backlog" + +What would you do differently next time? + +- Separate UI code and game logic code into different files +- Use CSS grid or flexbox +- Optimise the probability calculation algo + +Process Review +"Process" refers to app development steps and strategy. +What went well? + +- The advice to use test hands to make calcHandScore working first. Helps to focus on cleaning up possible edge cases for calcHandScore +- Build the probability logic in chunks. Have clear pseudo code first +- Container divs for each section was done up first and outputting correctly. Design was done later. + +What could have been better? + +- Not sure if UI layout and colour combinations are the best + +What would you do differently next time? + +- Learn about new features like "click to popup" to show table or prob table separately in mobile layout +- or hamburger menu for user to toggle between features + +https://github.com/rocketacademy/video-poker-bootcamp/pull/44 + +##End diff --git a/Slot-machine-jackpot-sound-effect.mp3 b/Slot-machine-jackpot-sound-effect.mp3 new file mode 100644 index 00000000..d77b8d70 Binary files /dev/null and b/Slot-machine-jackpot-sound-effect.mp3 differ diff --git a/Whomp-whomp.mp3 b/Whomp-whomp.mp3 new file mode 100644 index 00000000..a041313c Binary files /dev/null and b/Whomp-whomp.mp3 differ diff --git a/black_joker.svg b/black_joker.svg new file mode 100644 index 00000000..f4ebef43 --- /dev/null +++ b/black_joker.svg @@ -0,0 +1,278 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +J + + + + + + + + + +o + + + +k + + + +e + + + +r + + + + + + + + + + + + + +J + +o + +k + +e + +r + + diff --git a/index.html b/index.html new file mode 100644 index 00000000..ec9d4fba --- /dev/null +++ b/index.html @@ -0,0 +1,98 @@ + + + + + Video Poker + + + + +

Video Poker

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PLAY 1 TO 5 COINS
ROYAL FLUSH25050075010004000
STRAIGHT FLUSH50100150200250
4 OF A KIND255075100125
FULL HOUSE918273645
FLUSH612182430
STRAIGHT48121620
3 OF A KIND3691215
2 PAIRS246810
PAIR OF JACKS (OR BETTER)12345
+ + + + + + diff --git a/red_joker.svg b/red_joker.svg new file mode 100644 index 00000000..f9492277 --- /dev/null +++ b/red_joker.svg @@ -0,0 +1,288 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + +J + + + + + + + + + + +o + + + + +k + + + + +e + + + + +r + + + + + + + + + + + + + + +J + + +o + + +k + + +e + + +r + + + diff --git a/script.js b/script.js new file mode 100644 index 00000000..c2c4e6e2 --- /dev/null +++ b/script.js @@ -0,0 +1,678 @@ +// Get a random index ranging from 0 (inclusive) to max (exclusive). +const getRandomIndex = (max) => Math.floor(Math.random() * max); + +// Shuffle an array of cards +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; +}; + +const makeDeck = () => { + // Initialise an empty deck array + const newDeck = []; + // Initialise an array of the 4 suits in our deck. We will loop over this array. + const suits = ["hearts", "diamonds", "clubs", "spades"]; + const suitSymbols = ["♥", "♦", "♣", "♠"]; + const suitColours = ["red", "red", "black", "black"]; + + // Loop over the suits array + for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) { + // Store the current suit in a variable + const currentSuit = suits[suitIndex]; + const cardSymbol = suitSymbols[suitIndex]; + const cardColour = suitColours[suitIndex]; + + // Loop from 1 to 13 to create all cards for a given suit + // Notice rankCounter starts at 1 and not 0, and ends at 13 and not 12. + // This is an example of a loop without an array. + for (let rankCounter = 1; rankCounter <= 13; rankCounter += 1) { + // By default, the card name is the same as rankCounter + let cardName = `${rankCounter}`; + + // If rank is 1, 11, 12, or 13, set cardName to the ace or face card's name + if (cardName === "1") { + cardName = "A"; + } else if (cardName === "11") { + cardName = "J"; + } else if (cardName === "12") { + cardName = "Q"; + } else if (cardName === "13") { + cardName = "K"; + } + + // Create a new card with the current name, suit, and rank + const card = { + suitSymbol: cardSymbol, + name: cardName, + suit: currentSuit, + rank: rankCounter, + displayName: cardName, + colour: cardColour, + }; + + // Add the new card to the deck + newDeck.push(card); + } + } + + // Return the completed card deck + return newDeck; +}; +/** + * @param cardInfo {object} card object + * @param tracker {list} user's keep or replace decision + * @return {html element} image of the dealt card + */ +const createCard = (cardInfo, tracker) => { + let img = document.createElement("img"); + img.className = "card"; + if (tracker === REPLACE) { + cardAudio.play(); + img.classList.add("card-animate"); + } + img.src = `./${cardInfo.name}_of_${cardInfo.suit}.svg`; + + return img; +}; +//display a row of 5 card backs +const showCardBacks = () => { + cardContainer.innerHTML = ""; + const handElement = document.createElement("div"); + for (let i = 0; i < 5; i += 1) { + let img = document.createElement("img"); + img.className = "card"; + img.classList.add("card-animate"); + img.src = "./Card_back_05a.svg"; + const cardElement = img; + handElement.appendChild(cardElement); + } + cardContainer.appendChild(handElement); +}; +//push 5 random cards into hand, set decision tracker to all replace +const dealFirstHands = () => { + hand = []; + handClickTracker = [REPLACE, REPLACE, REPLACE, REPLACE, REPLACE]; + deck = shuffleCards(makeDeck()); + for (let i = 0; i < 5; i += 1) { + let card = deck.pop(); + hand.push(card); + } +}; + +const calcHandScore = (hand) => { + const isFlush = (cardSuitTally) => { + for (const suit in cardSuitTally) { + if (cardSuitTally[suit] === 5) { + return true; + } + } + }; + + const isStraight = (hand) => { + let rankList = []; + for (let i = 0; i < hand.length; i += 1) { + rankList.push(hand[i].rank); + } + rankList.sort(function (a, b) { + return a - b; + }); + let isStraightCheck = 0; + for (let j = 1; j < rankList.length; j += 1) { + if (rankList[j] - j === rankList[0]) { + isStraightCheck += 1; + } + } + if ( + rankList[0] === 1 && + rankList[1] === 10 && + rankList[2] === 11 && + rankList[3] === 12 && + rankList[4] === 13 + ) { + return "BROADWAY"; + } + if (isStraightCheck === 4) { + return "STRAIGHT"; + } + }; + + const isFourOfKind = (cardNameTally) => { + for (const name in cardNameTally) { + if (cardNameTally[name] === 4) { + return true; + } + } + }; + + const isThreeOfKind = (cardNameTally) => { + for (const name in cardNameTally) { + if (cardNameTally[name] === 3) { + return true; + } + } + }; + + const numPairs = (cardNameTally) => { + let pairsCount = 0; + for (const name in cardNameTally) { + if (cardNameTally[name] === 2) { + pairsCount += 1; + } + } + + if (pairsCount === 1) { + for (const name in cardNameTally) { + if ( + cardNameTally[name] === 2 && + !(name === "J" || name === "Q" || name === "K" || name === "A") + ) { + pairsCount = 0.5; + } + } + } + return pairsCount; + }; + + const cardNameTally = {}; + for (let i = 0; i < hand.length; i += 1) { + var cardName = hand[i].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; + } + } + + const cardSuitTally = {}; + for (let i = 0; i < hand.length; i += 1) { + var cardSuit = hand[i].suit; + // If we have seen the card name before, increment its count + if (cardSuit in cardSuitTally) { + cardSuitTally[cardSuit] += 1; + } + // Else, initialise count of this card name to 1 + else { + cardSuitTally[cardSuit] = 1; + } + } + + if (isFlush(cardSuitTally) && isStraight(hand) === "BROADWAY") { + return "ROYAL FLUSH"; + } + + if (isFlush(cardSuitTally) && isStraight(hand)) { + return "STRAIGHT FLUSH"; + } + + if (isFourOfKind(cardNameTally)) { + return "4 OF A KIND"; + } + + if ( + isThreeOfKind(cardNameTally) && + (numPairs(cardNameTally) === 1 || numPairs(cardNameTally) === 0.5) + ) { + return "FULL HOUSE"; + } + + if (isFlush(cardSuitTally)) { + return "FLUSH"; + } + + if (isStraight(hand) === "BROADWAY" || isStraight(hand) === "STRAIGHT") { + return "STRAIGHT"; + } + + if (isThreeOfKind(cardNameTally)) { + return "3 OF A KIND"; + } + + if (numPairs(cardNameTally) === 2) { + return "2 PAIRS"; + } + + if (numPairs(cardNameTally) === 1) { + return "PAIR OF JACKS"; + } + + return "NIL"; +}; +//display user's keep or replace decision +const printDecision = () => { + decisionContainer.innerHTML = ""; + for (let i = 0; i < 5; i += 1) { + const decision = document.createElement("div"); + decision.innerText = handClickTracker[i]; + decision.className = "decision"; + decisionContainer.appendChild(decision); + } +}; +//display advice to user which to keep or replace +const revealAdvice = (decisionTracker) => { + probContainer.innerHTML = ""; + for (let i = 0; i < 5; i += 1) { + const decision = document.createElement("div"); + decision.innerText = decisionTracker[i]; + decision.className = "decision"; + probContainer.appendChild(decision); + } +}; + +const printResultHand = () => { + //deal random cards into card positions where user chose to replace + for (let i = 0; i < 5; i += 1) { + if (handClickTracker[i] === REPLACE) { + let newCard = deck.pop(); + hand[i] = newCard; + } + } + cardContainer.innerHTML = ""; + const handElement = document.createElement("div"); + //display the result dealt hand + for (let i = 0; i < 5; i += 1) { + const cardElement = createCard(hand[i], handClickTracker[i]); + handElement.appendChild(cardElement); + } + cardContainer.appendChild(handElement); +}; + +const findPayout = (result) => { + let payAmount = 0; + if (result === "ROYAL FLUSH") { + payAmount = 250; + if (betAmount === 5) { + payAmount = 800; + } + } + + if (result === "STRAIGHT FLUSH") { + payAmount = 50; + } + + if (result === "4 OF A KIND") { + payAmount = 25; + } + if (result === "FULL HOUSE") { + payAmount = 9; + } + if (result === "FLUSH") { + payAmount = 6; + } + if (result === "STRAIGHT") { + payAmount = 4; + } + if (result === "3 OF A KIND") { + payAmount = 3; + } + if (result === "2 PAIRS") { + payAmount = 2; + } + if (result === "PAIR OF JACKS") { + payAmount = 1; + } + payAmount *= betAmount; + + return payAmount; +}; + +const givePayout = (payAmount) => { + credits += payAmount; +}; + +const cardClick = (cardElement, i) => { + if (handClickTracker[i] === REPLACE && gameMode != "end-round") { + cardElement.classList.add("selected-card"); + handClickTracker[i] = KEEP; + printDecision(); + return; + } + + if (handClickTracker[i] === KEEP && gameMode != "end-round") { + cardElement.classList.remove("selected-card"); + handClickTracker[i] = REPLACE; + printDecision(); + return; + } +}; +/** + * function that returns all possible ways to pick X elements from a list of size Y + * @param numToReplace {number} X no of indices I want to pick from a given list + * @param listLength {number} expected length Y of a list + * @return {list} each element is a list of possible chosen indices + */ +const indexPossibilities = (numToReplace, listLength) => { + let combis = []; + if (numToReplace === 1) { + for (let i = 0; i < listLength; i += 1) { + combis.push([i]); + } + } + if (numToReplace === 2) { + for (let i = 0; i < listLength; i += 1) { + for (let j = i + 1; j < listLength; j += 1) { + combis.push([i, j]); + } + } + } + if (numToReplace === 3) { + for (let i = 0; i < listLength; i += 1) { + for (let j = i + 1; j < listLength; j += 1) { + for (let k = j + 1; k < listLength; k += 1) { + combis.push([i, j, k]); + } + } + } + } + if (numToReplace === 4) { + for (let i = 0; i < listLength; i += 1) { + for (let j = i + 1; j < listLength; j += 1) { + for (let k = j + 1; k < listLength; k += 1) { + for (let l = k + 1; l < listLength; l += 1) { + combis.push([i, j, k, l]); + } + } + } + } + } + if (numToReplace === 5) { + for (let i = 0; i < listLength; i += 1) { + for (let j = i + 1; j < listLength; j += 1) { + for (let k = j + 1; k < listLength; k += 1) { + for (let l = k + 1; l < listLength; l += 1) { + for (let m = l + 1; m < listLength; m += 1) { + combis.push([i, j, k, l, m]); + } + } + } + } + } + } + return combis; +}; + +const findProbabilities = (decisionTracker) => { + let numToReplace = 0; + let indexToReplace = []; + for (let i = 0; i < 5; i += 1) { + if (decisionTracker[i] === REPLACE) { + indexToReplace.push(i); + numToReplace += 1; + } + } + let deckIndices = indexPossibilities(numToReplace, 47); + let allPossibleHands = []; + if (numToReplace === 0) { + allPossibleHands.push(hand); + } + for (let i = 0; i < deckIndices.length; i += 1) { + let possibleHand = [...hand]; + for (let j = 0; j < indexToReplace.length; j += 1) { + possibleHand[indexToReplace[j]] = deck[deckIndices[i][j]]; + } + allPossibleHands.push(possibleHand); + } + const resultsList = [ + "ROYAL FLUSH", + "STRAIGHT FLUSH", + "4 OF A KIND", + "FULL HOUSE", + "FLUSH", + "STRAIGHT", + "3 OF A KIND", + "2 PAIRS", + "PAIR OF JACKS", + "NIL", + ]; + let winningHandsTally = {}; + winningHandsTally["TOTAL"] = allPossibleHands.length; + + for (let i = 0; i < resultsList.length; i += 1) { + winningHandsTally[resultsList[i]] = 0; + } + for (let i = 0; i < allPossibleHands.length; i += 1) { + let result = calcHandScore(allPossibleHands[i]); + winningHandsTally[result] += 1; + } + + return winningHandsTally; +}; + +const statsOutput = (probTally) => { + const total = probTally["TOTAL"]; + let expectedPayout = 0; + let outputString = `TOTAL POSSIBLE HAND COMBIS: ${total}

`; + const resultsList = [ + "ROYAL FLUSH", + "STRAIGHT FLUSH", + "4 OF A KIND", + "FULL HOUSE", + "FLUSH", + "STRAIGHT", + "3 OF A KIND", + "2 PAIRS", + "PAIR OF JACKS", + "NIL", + ]; + for (let i = 0; i < resultsList.length; i += 1) { + let probPct = (100 * probTally[resultsList[i]]) / total; + expectedPayout += (probPct * findPayout(resultsList[i])) / 100; + outputString += `${resultsList[i]}: ${probPct.toFixed(5)}%
`; + } + outputString += `
EXPECTED PAYOUT: ${expectedPayout.toFixed(5)}`; + + return [outputString, expectedPayout]; +}; + +const giveSelectionAdvice = () => { + let expectedPayoutList = []; + const sampleSelection = [REPLACE, REPLACE, REPLACE, REPLACE, REPLACE]; + let sampleSelectionList = []; + sampleSelectionList.push(sampleSelection); + for (let i = 1; i <= 5; i += 1) { + let indexToKeep = indexPossibilities(i, 5); + + for (let j = 0; j < indexToKeep.length; j += 1) { + let possibleSelection = [...sampleSelection]; + for (let k = 0; k < indexToKeep[j].length; k += 1) { + possibleSelection[indexToKeep[j][k]] = KEEP; + } + sampleSelectionList.push(possibleSelection); + } + } + for (let i = 0; i < sampleSelectionList.length; i += 1) { + expectedPayoutList.push({ + choices: sampleSelectionList[i], + value: statsOutput(findProbabilities(sampleSelectionList[i]))[1], + }); + } + + expectedPayoutList.sort(function (a, b) { + return b.value - a.value; + }); + + return expectedPayoutList[0].choices; +}; + +//1. Game info message +let gameInfo = document.createElement("div"); +gameInfo.innerText = "Place bet and click deal to start"; +gameInfo.className = "game-info"; +document.body.appendChild(gameInfo); + +//2. Card container +let cardContainer = document.createElement("div"); +cardContainer.classList.add("card-container"); +cardContainer.classList.add("gradient-border"); +document.body.appendChild(cardContainer); + +//3. Tracks the keep or replace decisions +let decisionContainer = document.createElement("div"); +decisionContainer.classList.add("decision-container"); +document.body.appendChild(decisionContainer); + +//4. Credits tracker container +let creditsInfo = document.createElement("div"); +creditsInfo.innerText = "BET: 0 CREDITS: 100"; +creditsInfo.className = "credits-tracker"; +document.body.appendChild(creditsInfo); + +//5. Buttons +let buttonsContainer = document.createElement("div"); +buttonsContainer.classList.add("buttons-container"); +let dealButton = document.createElement("button"); +dealButton.innerText = "DEAL"; + +let betButton = document.createElement("button"); +betButton.innerText = `INSERT COIN`; + +let probButton = document.createElement("button"); +probButton.innerText = "CALC PROBS"; +probButton.classList.add("disabled-button"); + +let adviceButton = document.createElement("button"); +adviceButton.innerText = "ADVISE ME"; +adviceButton.classList.add("disabled-button"); + +buttonsContainer.appendChild(betButton); +buttonsContainer.appendChild(dealButton); +buttonsContainer.appendChild(probButton); +buttonsContainer.appendChild(adviceButton); +document.body.appendChild(buttonsContainer); + +let probContainer = document.createElement("div"); +probContainer.classList.add("game-info"); +document.body.appendChild(probContainer); + +//start of game logic +const KEEP = "KEEP"; +const REPLACE = "REPLACE"; +let betAmount = 0; +let credits = 100; +let deck; +let hand; +let handClickTracker = [REPLACE, REPLACE, REPLACE, REPLACE, REPLACE]; +let gameMode = "first-draw"; // "calc-score" //"end-round" +let adviceResult = 0; + +let coinAudio = new Audio("./Insert-coin-sound.mp3"); +let cardAudio = new Audio("./Card-flip-sound-effect.mp3"); +let winAudio = new Audio("./Slot-machine-jackpot-sound-effect.mp3"); +let loseAudio = new Audio("./Whomp-whomp.mp3"); + +showCardBacks(); +betButton.addEventListener("click", () => { + if (betAmount < 5 && gameMode === "first-draw" && credits > 0) { + coinAudio.play(); + betAmount += 1; + credits -= 1; + creditsInfo.innerText = `BET: ${betAmount} CREDITS: ${credits}`; + } + + if (betAmount === 5 || credits === 0) { + betButton.classList.add("disabled-button"); + } +}); + +probButton.addEventListener("click", () => { + if (gameMode === "calc-score") { + probContainer.innerHTML = `Calculating...`; + + setTimeout(() => { + let outputList = statsOutput(findProbabilities(handClickTracker)); + let outputString = outputList[0]; + probContainer.innerHTML = outputString; + }, 1); + } +}); + +dealButton.addEventListener("click", () => { + if (gameMode === "first-draw" && betAmount > 0) { + betButton.classList.add("disabled-button"); + probButton.classList.remove("disabled-button"); + adviceButton.classList.remove("disabled-button"); + dealFirstHands(); + gameInfo.innerText = "Select cards you want to keep then deal again"; + cardContainer.innerHTML = ""; + const handElement = document.createElement("div"); + for (let i = 0; i < 5; i += 1) { + const cardElement = createCard(hand[i], handClickTracker[i]); + cardElement.addEventListener("click", (event) => { + cardClick(event.currentTarget, i); + }); + handElement.appendChild(cardElement); + } + cardContainer.appendChild(handElement); + gameMode = "calc-score"; + return; + } + if (gameMode === "calc-score") { + decisionContainer.innerHTML = ""; + probButton.classList.add("disabled-button"); + adviceButton.classList.add("disabled-button"); + dealButton.classList.add("disabled-button"); + gameMode = "end-round"; + //FOR TEST HANDS + // hand = testrf; + // handClickTracker = [KEEP, KEEP, KEEP, KEEP, KEEP]; + printResultHand(); + let handResult = calcHandScore(hand); + givePayout(findPayout(handResult)); + + setTimeout(() => { + gameInfo.innerText = handResult; + if (handResult === "NIL") { + loseAudio.play(); + gameInfo.innerText = "Oops, no luck :("; + } else { + winAudio.play(); + gameInfo.classList.add("blinking"); + } + }, 1000); + + betAmount = 0; + + setTimeout(() => { + gameInfo.innerText = "Place bet and click deal to start"; + creditsInfo.innerText = `BET: ${betAmount} CREDIT: ${credits}`; + probContainer.innerHTML = ""; + showCardBacks(); + gameMode = "first-draw"; + betButton.classList.remove("disabled-button"); + dealButton.classList.remove("disabled-button"); + gameInfo.classList.remove("blinking"); + adviceResult = 0; + }, 5000); + + return; + } +}); + +adviceButton.addEventListener("click", () => { + if (gameMode === "calc-score") { + probContainer.innerHTML = `Thinking...`; + + setTimeout(() => { + if (adviceResult === 0) { + adviceResult = giveSelectionAdvice(); + revealAdvice(adviceResult); + } else { + revealAdvice(adviceResult); + } + }, 1); + } +}); diff --git a/styles.css b/styles.css new file mode 100644 index 00000000..4ad9376f --- /dev/null +++ b/styles.css @@ -0,0 +1,158 @@ +@font-face { + font-family: Mode7; + src: url("MODE7GX3.TTF"); +} +body { + background-color: #e5c484; +} + +h1 { + text-align: center; + font-family: Mode7, monospace, courier, fixed; +} + +.score-table { + background-color: #554435; + margin: 0 auto; + font-family: Mode7, monospace, courier, fixed; + border-radius: 8px; +} + +thead { + background-color: #333; + color: #e5c484; +} + +td { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 30px; + padding-right: 40px; + color: yellow; + text-align: center; +} + +.game-info { + background-color: none; + margin: 0px auto; + margin-top: 5px; + /* padding: 20px; */ + max-width: 900px; + font-family: Mode7, monospace, courier, fixed; + + text-align: center; + padding: 10px 50px; +} +.card-container { + margin: 0px auto; + + max-width: 900px; + min-height: 250px; + + /* width: 300px; + height: 2000px; */ + text-align: center; + + background-color: #a0be47; + border-radius: 8px; + border: solid 5px #554435; +} + +.card { + margin: 20px 10px; + padding: 10px; + background-color: white; + width: 150px; + border-radius: 8px; + display: inline-block; + box-sizing: border-box; +} + +.card-animate { + animation: cardflip 1s; +} + +@keyframes cardflip { + 0% { + transform: rotateY(90deg); + } +} + +.selected-card { + background-color: #e5c484; +} + +.decision-container { + margin: 0 auto; + max-width: 900px; + min-height: 20px; + text-align: center; +} + +.decision { + margin: 0px 10px 0px 10px; + padding: 0px 10px 0px 10px; + width: 150px; + text-align: center; + display: inline-block; + box-sizing: border-box; + font-family: Mode7, monospace, courier, fixed; +} + +.credits-tracker { + background-color: none; + margin: 0px auto; + /* padding: 20px; */ + max-width: 700px; + font-family: "Lucida Console", "Courier New", monospace; + text-align: center; + padding: 10px 50px; + font-family: Mode7, monospace, courier, fixed; + font-size: 20px; + color: maroon; + text-shadow: 2px 2px yellow; +} + +.buttons-container { + max-width: 900; + text-align: center; +} + +.buttons-container > button { + /* background-color: yellow; */ + margin: 5px 5px; + padding: 10px 5px; + /* font-family: "Arial Black", sans-serif; */ + font-family: Mode7, monospace, courier, fixed; + font-weight: bold; + color: #554435; + border: 2px solid #554435; + border-radius: 25px; +} + +.disabled-button { + background-color: #b79e7d; +} + +.blinking { + font-size: 20px; + text-shadow: 2px 2px yellow; + animation: blinkingText 0.5s infinite; +} +@keyframes blinkingText { + 0% { + color: red; + } + 49% { + color: red; + } + 60% { + color: transparent; + } + 99% { + color: transparent; + } + 100% { + color: red; + } +} diff --git a/testHands.js b/testHands.js new file mode 100644 index 00000000..ebef621b --- /dev/null +++ b/testHands.js @@ -0,0 +1,160 @@ +const makeDeckTest = () => { + // Initialise an empty deck array + const newDeck = []; + // Initialise an array of the 4 suits in our deck. We will loop over this array. + const suits = ["hearts", "diamonds", "clubs", "spades"]; + const suitSymbols = ["♥", "♦", "♣", "♠"]; + const suitColours = ["red", "red", "black", "black"]; + + // Loop over the suits array + for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) { + // Store the current suit in a variable + const currentSuit = suits[suitIndex]; + const cardSymbol = suitSymbols[suitIndex]; + const cardColour = suitColours[suitIndex]; + + // Loop from 1 to 13 to create all cards for a given suit + // Notice rankCounter starts at 1 and not 0, and ends at 13 and not 12. + // This is an example of a loop without an array. + for (let rankCounter = 1; rankCounter <= 13; rankCounter += 1) { + // By default, the card name is the same as rankCounter + let cardName = `${rankCounter}`; + + // If rank is 1, 11, 12, or 13, set cardName to the ace or face card's name + if (cardName === "1") { + cardName = "A"; + } else if (cardName === "11") { + cardName = "J"; + } else if (cardName === "12") { + cardName = "Q"; + } else if (cardName === "13") { + cardName = "K"; + } + + // Create a new card with the current name, suit, and rank + const card = { + suitSymbol: cardSymbol, + name: cardName, + suit: currentSuit, + rank: rankCounter, + displayName: cardName, + colour: cardColour, + }; + + // Add the new card to the deck + newDeck.push(card); + } + } + + // Return the completed card deck + return newDeck; +}; + +const testDeck = makeDeckTest(); + +const isStraightTest = (hand) => { + let rankList = []; + for (let i = 0; i < hand.length; i += 1) { + rankList.push(hand[i].rank); + } + rankList.sort(function (a, b) { + return a - b; + }); + let isStraightCheck = 0; + for (let j = 1; j < rankList.length; j += 1) { + if (rankList[j] - j === rankList[0]) { + isStraightCheck += 1; + } + } + if (isStraightCheck == 4) { + return true; + } else return false; +}; + +const testsf = [ + testDeck[32], + testDeck[33], + testDeck[34], + testDeck[35], + testDeck[36], +]; + +const testrf = [ + testDeck[9], + testDeck[11], + testDeck[12], + testDeck[10], + testDeck[0], +]; + +const testfourk = [ + testDeck[14], + testDeck[4], + testDeck[17], + testDeck[30], + testDeck[43], +]; + +const testfhse = [ + testDeck[5], + testDeck[18], + testDeck[31], + testDeck[12], + testDeck[25], +]; + +const testfhse2 = [ + testDeck[6], + testDeck[18], + testDeck[31], + testDeck[7], + testDeck[21], +]; + +const testflush = [ + testDeck[23], + testDeck[21], + testDeck[20], + testDeck[16], + testDeck[15], +]; + +const teststraight = [ + testDeck[1], + testDeck[15], + testDeck[29], + testDeck[43], + testDeck[44], +]; + +const testthreek = [ + testDeck[11], + testDeck[24], + testDeck[37], + testDeck[46], + testDeck[26], +]; + +const testHand_twopair = [ + testDeck[9], + testDeck[22], + testDeck[27], + testDeck[40], + testDeck[4], +]; + +const testHand_onepair = [ + testDeck[4], + testDeck[14], + testDeck[2], + testDeck[3], + testDeck[1], +]; + +const testHand_onepair_king = [ + testDeck[4], + testDeck[0], + testDeck[2], + testDeck[3], + testDeck[13], +];