When I first started, I was only going to build just the multi-player aspect of the game. You start the game, join a lobby, and join a room already in play, or create your own room for others to join.
However, this wouldn’t really be too much involved (even for a simple multi-player game), if I don’t flex my muscles, and include user accounts + authentication.
As a player, you’ll be able to create an account by signing up using an e-mail and password. You can also setup your own user avatar icon for display. Should you forget password or want to change it, you’ll be able to reset or modify it as well. The game will also use an emailing system to aid you in the process of resetting or changing your password. Finally, you will also be able to delete your account altogether.
This means a database will be used on the back-end to store user accounts. The back-end will then effectively use the four basic operations of data persistence, or CRUD.
CRUD stands for create, read, update, and delete. Think of it this way:
Create – Creating a new account and signing up; a new user is added to the database. Read – When a user logs in, their credentials are checked against the existing users in the database. Update – A user changes their e-mail, password, or avatar image, or the number of credits they hold changes as they play poker, updating their entry in the database. Delete – A user deletes their account, also deleting their entry from the database altogether.
If interested, you can learn more about CRUD here.
In addition to the technologies listed from the prelude article of this series, I’ve decided to use the following technologies:
Ahem, actually, the Mongoose I’m talkin’ ’bout is an Object Data Modeling (ODM) library that allows Node.js and MongoDB to talk to each other. Long story short, with Mongoose, you easily define how your data is structured in your database, and write code that correctly manipulates that data so that the structure is maintained (and thus, the integrity of your data).
MongoDB stores data as JSON objects, and the formatting is arbitrary. One of the things Mongoose does is allow you to define a structure of how the data will be stored, and it will enforce the rules of that structure to the code you write.
If you like, you can learn more about Mongoose from this article.
This Node.js middleware is used for authenticating your users when they log into your system, as well as performing other tasks that you want to to secure. You can use this along with JSON Web Tokens (JWTs) to validate the user when they make requests to your Express app.
This library allows you to manage your JWTs. When a user logs in, the server will generate a JWT and return to the client. The server then acknowledges the user as “being logged in”, and the user’s client must send this token back to the server for each subsequent request.
A token is a credential that is digitally signed using a secret key (though you can use public / private keys also, but I’m using the secret key here). The signature is performed behind the scenes using an HMAC algorithm.
Although these details go beyond the scope of this article, you can learn more about JSON Web Tokens here and here.
This library is used for securely hashing passwords. Even in the database, the actual plaintext password is not stored in the database. Instead, an encrypted version of the password is stored instead.
So, even if you forgot your password, I cannot look up your user in the database and tell you what it is, because, I don’t know, either! 🙃
Cookies are small pieces of data that the server sends to the client. When the user performs certain actions (usually requiring authentication or validating data sent back to the server in our case), this cookie is sent with the request.
You can get a quick overview on how to use cookie-parser here.
You can use this Node.js module for sending e-mails from your server to your users. You can use this to send plain text or HTML messages, include attachments, along with many other features.
For this poker game, I’m using it to send e-mails when the user forgets their password, as well as notifications if they changed their e-mail address password (to make it was them who requested the change!), as a few other account-based notifications.
It would be a pain to have to manually setup your e-mail messaging system for the various types of messages you want to send to your users (as well as litter your code with lots of string interpolation). This is where Pug comes to the rescue.
This is an e-mail templates system, and it allows you to define templates. While it has it’s own scripting language, you can set up your templates and preview how they will look when sent to the user.
You can have a look at Pug2HTML, an online conversion and previewer. Of course, you’d still need to learn the Pug syntax itself.
dotenv
When using sensitive data like your JWT secrets and e-mail credentials for Nodemailer, you’ll want to store these in some place that’s not hard-coded in any of your files. That’s where dotenv comes into play.
You can use this to store this type of data in a separate file (often called .env), and Node will load these as environment variables. A good practice is to not share this .env file, but instead, each person on your team generates their own .env file.
That’s a lot more added onto this tech stack!
It took quite a while to implement all of these and get them to play nice together. Of course, the client side also has to be able to respond, but all of these tools are used on the server side.
And I’ll admit – at first, I didn’t want to do any back-end user authentication. But then I realized that the value of an app that can perform user authentication is much more valuable than one that can’t. So I went through all the steps.
But I didn’t do it alone… hell no! I had help. Mainly help from this amazing course over on Zenva called called the MMORPG Academy.
With Scott Westover as your instructor, this course is a conglomerate of smaller courses to build a (relatively) simple multi-player MMORPG type game using all the techs mentioned above, as well as Phaser 3 on the client side.
I found this course invaluable on getting me started.
And I’m not quite done with it yet! Still to come is deploying the poker game onto a live web server (or in this case, onto the cloud using Heroku). Excited, and looking forward to finally getting this game done, hopefully within first quarter of 2022!
As I work on the game, I’ll post noteworthy updates in future articles. And you can play the work-in-progress versions of the game as I make playable updates, before the game is released to the public!
Sign up using this form to get on my mailing list:
Thanks for reading, and I hope you continue to stay tuned!
Continuing the series of building a multiplayer poker game, I’ve decided to make a big turn in how the game will be built.
I’ve decided to give Arian’s latest version, Phaser Editor v3, a try.
Why? All my previous projects were deep in v1 or v2. However, I haven’t gotten very far into this Poker project, so it was easy to switch it from v2 to v3 sooner rather than later. Plus, after comparing its functionality with that of previous versions, it made sense to at least give it a try. And so far, it’s working out well!
Now, the biggest attraction, at least for me, was the fact that prefabs were back, which we haven’t seen since v1. Using factories in v2, while they took a bit of work to get them the way that I wanted, allowed me to learn a lot about how custom factories work in Phaser.
At the time of this article, v3 doesn’t yet supply an animations editor, or texture atlas editor. But that’s ok!
For animations, you can use a tool called Animator. You can learn more about animations in v3 here. I haven’t needed to use animations for my Poker game (at least not so far), so I can’t vouch for this tool. However, it is an option.
For texture atlases, you can use Texture Packer, which I’ve enjoyed using quite a bit over the years. To learn more about atlas editor usage in v3, as well as other options, check here.
Since this version now works in your browser (which also significantly reduces its download size), you start it up using your command prompt. So I made a simple batch file which starts the editor with the -desktop option since I work with a local server. My projects workspace is also in a location different than the default workspace, so I use the -ws option. For a full list of options, see this page.
As I’m learning the rules for Poker, the interactive tutorial on this page has been very helpful. Also, playing this game has also been useful. (No, I haven’t been screwing around, getting sucked into playing! Nope. Not me.)
I got a good chuckle from this scene from The Avengers.
That’s all for now. I’ll continue to keep you updated as I make progress.
Finally, sign up using the form below to receive updates to playable builds (or at least interactable builds) as I make noteworthy progress.
Getting started with building a multiplayer Poker game, I’m first setting up the development environment.
After setting up webpack, ESLint, Babel, and Typescript (getting them to all work together and the way I want was a challenge), I’ve started on building a the game’s main display using Phaser Editor.
Building The Game Layout
I decided to go with allowing up to six players, and the layout will look like this:
Just a very simple layout here. Nothing fancy. #ImNotAGameDesigner
Phaser Editor supports Typescript, which is awesome. However, the code the Phaser Editor compiler generates doesn’t make ESLint happy.
As you can see here, we have some lines of code that ESLint is nit-picking us about:
There are sections in the code where you can put whatever you want, and it won’t be overwritten by the Phaser Editor compiler. In this case, I’d surround the generated code to temporarily disable ESLint. /* eslint-disable */ and /* eslint-enable */
NOTE: Since you cannot directly control the generated code, disabling ESLint is fine in these situations.
Since I’m using modules, at the bottom of Scene files generated by Phaser Editor, you can export the Scene class, by doing so at the bottom of the file. Code placed here will not be affected by Phaser Editor (the editor will mark the file with comments, telling you where you can write your own code). At the bottom, you can write something like this:
/* END OF COMPILED CODE */
// You can write more code here
export default [NameOfYourSceneClass];
Setting Up A Factory For The Card Images
Still building the layout, I want the card images to be set up as their own factory in Phaser. When I recently converted the Flash game Blasteroids to HTML5, I used JavaScript. However, for this project, I’m using TypeScript and the code is being linted by ESLint.
First let’s create a class that will display the card image. I won’t go into full details for this class, but the setup could look like this:
NOTE: You can then create properties to store the suit and value of the card, as well as whether or not the card is face up or face down. Note that if you change the face up/down property, you’d need to update the card’s image as well.
Next, let’s create a factory file. The name of my factory would be cardImage, and the looks something like this:
import CardImage from './CardImage';
Phaser.GameObjects.GameObjectFactory.register('cardImage',
function foo(this: Phaser.GameObjects.GameObjectFactory,
x: number, y: number, texture: string, frame?: string | integer): CardImage {
const scene = this.scene;
const sprite = new CardImage(scene, x, y, texture, frame);
scene.sys.displayList.add(sprite);
// scene.sys.updateList.add(sprite);
return sprite;
});
NOTE: The CardImage class extends Phaser.GameObjects.Image. If your class extends Phaser.GameObjects.Sprite, you’d also need to uncomment line 11 as well.
When setting card images in the scene to use cardImage as the factory, then saving the scene file, and viewing the source code, you’ll see there are some issues:
NOTE: I’ve spent a day or so trying to figure out how to resolve this issue. The scene class was originally a TypeScript, and I was originally using the TypeScript version of scenes in Phaser Editor. Unfortunately, I’ve had trouble getting namespaces and modules to work together. My research eventually led me to trying Declaration Merging, and looking at declaration files (.d.ts). And while setting up factories with TypeScript came closest (actually, this resource did work) to helping me solve my issue, I was still unable to resolve error ts(2339) by VS Code in the above image.
Long story short: I’m using JavaScript for scenes that use factories to avoid these issues.
After changing Phaser Editor to use JavaScript instead of TypeScript for this scene, VS Code no longer reports issues, and the code still compiles and runs with no issues! 😎
Now, I can continue to build the game’s main display, and code the functionality for dealing and flipping cards, presenting chips, and building the buttons, call, check, etc. There are still the game logic for the rules of Poker itself, as well as the multiplayer aspect of the game, which will be the game’s main draw (and an excellent experience for me in developing a turn-based, real-time multiplayer game).
That’s it for now!
If you’d like to get on my e-mail list and receive updates are the progress continues, sign up using the form below.
Now that the Flash game Blasteroids has been converted to HTML5, the next game I’m working on is a multiplayer Poker game.
Now, this won’t be a conversion, but a game originally built using Phaser 3, JavaScript, and Phaser Editor.
Building this game will be a bit of a challenge for me for these two reasons:
One, this will be my first attempt at developing a complete multiplayer, turn-based game.
An MP game is much more challenging to build than a single-player one, believe you-me. I once tried making a real-time MP in the past using PlayerIO, but… let’s just say that didn’t pan out so well.
And two, I’m learning a bit about the JavaScript ecosystem. I took previous course on Zenva called MMORPG Academy. The course showed you how to make a simple multiplayer MMO game using Phaser, Express and SocketIO. It also introduced me to the following tools, which I will also be using for this game.
Node.js is a server-side platform built on Google Chrome’s V8 JavaScript Engine. It can be used for developing server-side and networking applications. I’ll use it as part of the back-end for this game.
npm is a very large software repository. It’s a package manager for JavaScript, and you can use it to download and install many third-party packages into your projects. It comes with Node.js, and it can be used to install most of the tools listed below.
This is a web framework that allows your web application to handle requests that are sent to a specific URL. Both Node.js and Express will be used together to create the web server.
Among many other things, webpack can bundle all your modular JavaScript code and packages together into a single file that can be understood by your web browser.
It’s much more convenient to write JS code in the latest/modern version. However, older versions of web browsers can’t understand these versions. This is where Babel comes in. It can transpile your modern code to earlier versions that can be understood those older browsers, increasing the available of your web apps to more people.
This tool examines your code for syntactical errors, or other issues where the code may not adhere to a certain standard or set of styling rules. Essentially, “linting”, helps you write cleaner code.
Some other tools not discussed in the Zenva course that I will be using in Poker are:
I much prefer Typescript over JavaScript. Typescript allows you extra features, and for me, that means static typing and support for interfaces. Of course, I’m sure I’ll learn more as I dive deeper into Typescript.
Note: My plan is to write the code using TypeScript (which both Phaser and Phaser Editor also support), use Babel (with Typescript support) to transpile the code, and bundle it all together in a single JavaScript file using webpack. This is for the client-side portion of the game. The back-end server-side code will not be run in a web-browser, so it will not use this process.
Poker Game Multiplayer Development Plan
First thing’s first: the game’s design, and layout will need to be created. While I’m not a game designer (my service currently only includes programming), this version of Texas Holdem Poker I’ll be making will have a relatively simple enough mechanic. Nothing fancy here. And the game is mainly to add to my portfolio.
I’ll need to find some assets (graphics and sounds). I’ll use the same assets I used from my Thunderjack! game.
Because this is a multi-player game using a client-server model, where the server has the authority and maintains the game’s state.
The client apps (what the players will use) act as visual agents, showing the state of the game server. They also accept input (keyboard, mouse, touch, etc.) from each player, send them to the server, then the server with validate that input. The validation is to make sure the state stays clean, and to prevent cheating.
Because this will be a turn-based game and not a real-time game, it doesn’t need to rely heavily on advanced concepts like client-side prediction or entity interpolation and prediction.
Next, there are the rules of Poker. Because the server maintains the stage, all the game logic will be written on the server. And of course, I’ll need to get the rules down as well. 🙃
And finally, I want the game to be able to use bots that can fill in if no other real players are available. So building an AI will be a challenge all its own, though I’m sure I can research this for help.
Where and How will I Host the Game Server?
The final component to this game is determining where and how I’ll host the game server, so you can play this game online with other real people. The client-side app will be hosted here on my site here, but it’s the game server that needs to be hosted elsewhere.
The multi-player game that the Zenva course helps you to create uses Heroku to host the game project, so I’ll use that again. The course covers just enough for you to set up a simple game, as any more, I believe, would go beyond the scope of the project, but there’s enough there to get started.
As I work on the game, I’ll post noteworthy updates in future articles. And you can play the work-in-progress versions of the game as I make playable updates, before the game is released to the public!
Sign up using this form to get on my mailing list:
Whew! That’s it for now, and this will be quite a challenge. I’m sure this will take me a while to complete. And I hope you stick with me on this journey! I got this! 💪🏾
It’s been pretty quiet lately here on GameplayCoder, but I’ve also been busy behind the scenes learning new skills for more games to add to my portfolio.
Poker Game
Having finished up the card-matching and hand-comparing techniques for poker, the next project will involve coding an actual poker (Texas Hold’em) game.
As for implementing the rules for poker itself, I found a useful article on 888poker that goes over basics, terminology, and flow of the game. There is also this game available from 24/7 Free Poker, which I’ve been playing to help further understand the game/
But I want it to be a multiplayer game (as well as single-player vs AI), and it’s the multiplayer functionality that will prove most challenging.
So, I’ve been taking a course over on Zenva called MMORPG Academy, which teaches you how to build a multiplayer game using various technologies, and middlewares, including but not limited to:
The only tool in this list I did not use was Docker, because it requires virtualization to run, and if your operating system is Windows 10 Home, you’re pretty much outta luck. Of all the suggestions I’ve tried around the net, none of them worked, and I wasn’t about to upgrade to Pro just for Docker. Besides, you don’t really need it to complete this course anyway.
Everything except Phaser and JavaScript on that list was completely new to me. 🙃 So, I’m taking in a lot of new material in this course. But as Tony Stark himself said,
Flash To HTML5 Game Conversion
According to my data, an article I wrote, Converting a Flash Game To HTML5, by far, has received the most views.
After looking at these numbers, I’m like:
So I will be revisiting this topic by converting another Flash game I coded for a previous client, called Blasteroids. This is a remake of Atari’s Asteroids.
If you’d like to play the Flash game I coded, you can play it on my old portfolio site here. Otherwise, if you can’t (or won’t) be bothered with Flash, you can watch this video of my gameplay – and epic fails. 😅
Thanks for being a reader of this blog, and stay tuned. There’s more to come!
When you have two poker hands, and both are straight flushes, this article will show you the code that compares them to find which one wins.
A previous article for poker hands demonstrated how to compare a hand to determine if it was straight flush (the article also covered a royal flush as well). A straight flush is a hand where all the cards are in sequential order, and they all have the same suit. This hand is a straight flush:
Setup
Note: The first stages of the setup can be found on the introduction page to comparing poker hands, here.
There aren’t any other specific preparations we need before we begin.
Writing The Code For Comparing Fours Of Kinds
When two hands that are both a straight flush, the GetWinningHand function will call the FindWinnerStraightFlush function that compares the two hands.
Note: As it turns out, comparing two straight flush hands is the same as comparing two straight hands! The only addition is that you have to make sure all the cards are the same suit.
The only code featured in this article are the functions specific to comparing straight flushes. To see the concepts and code for comparing two straights, see this article.
FindWinnerStraightFlush
FindWinnerStraightFlush = function(hand1, hand2) {
SET workingHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1);
SET hand1Info to an empty object { }
CardMatchUtils.AreCardsStraight(workingHand1, hand1Info)
SET workingHand1 = WildsAssumeValues(workingHand1, hand1Info)
SET sortedHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2);
SET hand2Info to an empty object { }
CardMatchUtils.AreCardsStraight(workingHand2, hand2Info)
SET workingHand2 = WildsAssumeValues(workingHand2, hand2Info)
SET winningPlayerIndex = CardMatchUtils.CompareHands(workingHand1, workingHand2)
RETURN winningPlayerIndex
}
WildsAssumeValues
WildsAssumeValues = function(hand, info) {
SET index to 0
WHILE index IS LESS THAN number of cards in the hand (for example, "hand.length")
SET card = hand[index] (get the nth card in hand)
IF the card is a wild (card.value EQUALS CardValues.wild)
SET the card value to the last value in the info.cardValues array
REMOVE the last card value from the info.cardValues array (info.cardValues.pop())
END
SET index = index + 1
END
SET sortedHand to CardMatchUtils.SortCardsByDescendingValue(hand)
RETURN sortedHand
}
Compare Your Own Hands
You can use the controls below to build your own hands and compare fours of kinds. Have fun playing around with it!
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
When you have two poker hands, and both are a four of a kind, how can you determine which one ranks higher? In this article, you’ll learn how to code a solution.
A previous article for poker hands demonstrated how to compare a hand to determine if it was four of a kind. A four of a kind is hand where four of the cards are the same value, and the remaining card is a different value. It’s like a three of a kind, but instead of matching three cards, it matches four. Here’s an example of a four of a kind:
Also, the comparison process is very similar to a comparing threes of kinds:
Compare the values of the quadruplet (the four cards that have the same value).
If those values are equal, compare the values of other the kickers, which is the card that has the other value.
If no kicker breaks the tie, and all cards have been compared, then both hands are equal.
Let’s look at some examples:
Hand 1
Hand 2
Hand 1 has a quad value of 5, while hand 2 has a quad value of 3. Since 5 is greater than 3, hand 1 is the higher four of a kind.
If the quad values of both hands are the same, then you compare the kicker card. Check this out:
Hand 1
Hand 2
Both hands had a quad value of queen. Hand 1 has a kicker value of king, while hand 2’s kicker value is ace. Ace beats king, so hand 2 is the winner here.
And one more thing before we get into the code – the wild cards (:
But handling wild cards in comparing a four of a kind is similar to that of a three of a kind. Take these hands:
Hand 1
Hand 2
In hand 1, the wild card is swapped for a 2 to form a four of a kind. The kicker value is a queen. For hand 2, it already has a four of a kind from the twos, so you can use the wild card to substitute the highest possible value, an ace.
When comparing both hands, hand 2 wins, because it has the higher kicker value (ace winning over queen).
Note: In hand 1, you could’ve substituted also the wild with the highest possible value, ace. But then, it would no not form a four of a kind, but a three of a kind. You also could’ve substituted it with another queen to form a full house, twos over queens, but a full house ranks lower than a four of a kind. So, substituting the wild for as a two produces the highest possible hand.
On a side note, in hand 2, you could’ve substituted the wild as a two, forming a five of a kind, which ranks higher than a four of a kind. However, we won’t be covering fives of kinds in this series. I’ll leave it as a challenge to you, should you accept it (: If you’re interested, you can learn a little more about a five of a kind here.
Setup
Note: The first stages of the setup can be found on the introduction page to comparing poker hands, here.
There aren’t any other specific preparations we need before we begin.
Writing The Code For Comparing Fours Of Kinds
When two hands are both a three of a kind, the GetWinningHand function will call a function that compares two hands of said poker hand.
In this case, GetWinningHand function will eventually call FindWinnerFourOfAKind (shown below) to compare the hands. This function accepts two parameters, the hand for both players, and it’ll return the ID of the player who has the winning hand. If both hands are equal, it’ll return 0 (which we’ll use to indicate a draw). The pseudocode below starts by comparing the values of the pairs first, then comparing the kickers if necessary.
FindWinnerFourOfAKind
FindWinnerFourOfAKind = function(hand1, hand2) {
sortedHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1);
SET hand1Info to an empty object { }
CardMatchUtils.DoCardsHaveSameValue(hand1, 4, hand1Info);
sortedHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2);
SET hand2Info to an empty object { }
CardMatchUtils.DoCardsHaveSameValue(hand2, 4, hand2Info);
SET winningIndex = CompareQuads(hand1, hand1Info, hand2, hand2Info);
IF (winningIndex NOT EQUAL TO -1)
RETURN winningIndex (one hand's quad outranks the other hand's, and no further checking is necessary)
END
(both hands have the same ranking quad, now compare the kickers of both hands)
SET winningIndex = CompareKickers(hand1, hand1Info, hand2, hand2Info);
RETURN winningIndex;
}
Like most poker hand matching and comparing functions, you’ll need to first sort the cards in descending order of value (highest to lowest) before processing. This helps tremendously in the code. Yeah, you and I could just “look” at a couple hands and see the winner, but code? Not so much. 🙃
If you already read the article for comparing threes of kinds, this function looks very similar to FindWinnerThreeKind!
(Psst, here’s the big secret! 🐱👤 You catch a break with comparing fours of kinds. It’s mostly a copy-paste job, changing threes to fours, and replacing “trios” with “quads”)
Comparing The Quadruplets
In the FindWinnerFourOfAKind function, the code above sets the hands up for comparing their quadruplets. It then sorts the cards or descending order by card value. Next, it uses the DoCardsHaveSameValue function to get the four cards in the hand that make the quad, as well as determine the quad’s value.
CompareQuads
CompareQuads = function(hand1, hand1Info, hand2, hand2Info) {
SET hand1WorkingQuadValue = hand1Info.cardValues[0]
IF (CardMatchUtils.CountCardsByValue(hand1, WILD_VALUE) GREATER OR EQUALS 4)
hand1WorkingPairValue = ACE_VALUE
END
SET hand2WorkingQuadValue = hand2Info.cardValues[0]
IF (CardMatchUtils.CountCardsByValue(hand2, WILD_VALUE) GREATER OR EQUALS 4)
hand2WorkingQuadValue = ACE_VALUE
END
IF (hand1WorkingQuadValue > hand2WorkingQuadValue)
RETURN 0 (hand 1 has the higher ranking quad)
ELSE IF (hand1WorkingQuadValue < hand2WorkingQuadValue)
RETURN 1 (hand 2 has the higher ranking quad)
END
RETURN -1 (both hands' quads have the same value)
}
This function is very similar to the CompareTrios function in our recent article for comparing threes of kinds, except instead of dealing with three cards, we’re dealing with four. If you’d like details on the workings of that function, please check here.
Comparing The Kickers
If the quads of both hands have the same value, then you’ll need to compare the final card in each hand, its kicker.
Like you did when comparing the kickers with previous poker hands, when comparing the kickers, you first remove the quads from both hands so you’re left with the remaining kicker. You can use the CardMatchUtils.BuildHandExcludingValues function to remove the quad.
GetKickers
GetKickers = function(hand, info) {
(get the value of the cards that form the quad)
SET quadCardValue = info.cardValues[0]
(count the number of cards in the hand that match the quad card value)
SET numQuadValueCards = CardMatchUtils.CountCardsByValue(hand, quadCardValue)
(if there are at least as many quad value cards as there are non-kicker cards, specify the quad card value to the values of cards to exclude)
SET numNonKickerCards = 4
IF numQuadValueCards >= numNonKickerCards
SET valuesToExclude = quadCardValue
ELSE {
(otherwise, if there are at least as many wild cards as there are non-kicker cards, add the wild card value to the values of cards to exclude)
SET numWildCards = CardMatchUtils.CountCardsByValue(hand, CardValues.WILD)
IF numWildCards >= numNonKickerCards
SET valuesToExclude = CardValues.WILD
ELSE
(finally, specify BOTH, the quad card value and the wild card value as the values of cards to exclude)
SET valuesToExclude = [ CardValues.WILD, quadCardValue ]
END
}
(create the temporary kickers hand by excluding the specified values and returning the rest)
SET handOfKickers = CardMatchUtils.BuildHandExcludingValues(hand, valuesToExclude, numNonKickerCards)
(finally, sort the kickers hand in descending order, with wilds as the highest value)
handOfKickers = CardMatchUtils.SortCardsByDescendingValueHighWilds(handOfKickers)
RETURN handOfKickers
}
In the GetKickers above, the info object is the same one used in FindWinnerFourKind. It’s either the hand1Info or hand2Info object, depending on which hand you’re getting the kickers from.
There are three situations in GetKickers that determine which values of cards to exclude as kickers.
The first is the simplest. It’s the quad card value used to form the four of a kind. Cards of this value obviously can’t be the kickers. This means they’ll be excluded, leaving the remaining card as the kicker.
The second situation is a hand that contains at least four wilds cards. These cards can assume the highest non-wild value, which is an ace. So the four wilds would form the four of a kind, using an ace as the quad card value. So the wild card value itself would be excluded from the hand of kickers.
Finally, the hand doesn’t have four cards with the same value, but it does contain one of the following combinations:
One wild and a triplet
Two wilds and a pair
Three wilds and the higher non-kicker of the remaining two cards
Note: When excluding cards, you’re always excluding exactly four cards (the number of non-kicker cards).
Those wilds will assume the value of the whatever the quad value is, forming the four of a kind. In this situation, you want to exclude both values of both, the wild card, and the quad card value.
The GetKickers function from above helps with this.
CompareKickers
CompareKickers = function(hand1, hand1Info, hand2, hand2Info) {
SET hand1Kickers = GetKickers(hand1, hand1Info)
SET hand2Kickers = GetKickers(hand2, hand2Info)
SET winningPlayerIndex = CardMatchUtils.CompareHands(hand1Kickers, hand2Kickers)
RETURN winningPlayerIndex
}
The CardMatchUtils.CompareHands function is the same one we used here.
The CompareKickers will return 0 if hand1 has the better kickers, 1 if hand2 has the better kickers, or -1 if both hands are the same rank.
That’s pretty much it! 😎
Compare Your Own Hands
You can use the controls below to build your own hands and compare fours of kinds. Have fun playing around with it!
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
Continuing the series of comparing poker hands of the same rank, this article will show you how to write code to compare two hands that are both a full house.
In a previous article for poker hands, you learned how to write code that checks if a hand is a full house. That is, the hand contains three cards of one value, and two of another, and the suits are not all the same.
Three cards are nines, two cards are fours, and their suits are not uniform.
Comparing a full house looks like this:
Compare the triplets of both hands. Highest triplet wins.
If they are both the same, compare the pairs of both hands. Highest pair wins.
Both hands have equal triplets and pairs. They’re tied.
Getting Triplet And Pair Values
Before we can compare triplets and pairs, we need to get the values of the cards that make up the triplets and pairs.
Let’s first have a look at the cards in hand, because after being sorted in descending value, they’ll have one of two orders.
Note: Make sure that the cards are sorted by card rank in descending order (highest to lowest) first.
First order: You could have – what we’ll call a “3-2” full house – where the higher value is the triplet and the lower value is the pair, as in:
The value of the triplet is 10, and the value of the pair is 3.
Second order: You could have a “2-3” full house, where the pair is the higher value and the triplet is lower.
This time they’re switched. The value of the pair is 10, and the value of the triplet is 3.
To determine the triplet and pair values, compare the values of second and third card of the hand. 💡
In the 3-2 full house, 10♦ 10♣ 10♠ 3♥ 3♦, the values of the second and third card will be the same. In this case, they’re both 10. That means the value pf the triplet is 3. From this, the pair starts on the fourth card, so the value of the pair is the value of that fourth card (in this case, 2).
In the 2-3 full house, 10♦ 10♣ 3♥ 3♦ 3♠, the values of the second and third card will be different. Here, the value of the triplet is 2, and the value of the pair is 10.
Now that you know the values of the triplets, you can compare them. In the example we’ve been using 10 > 3, so the 3-2 hand wins over the 2-3 hand.
And if the values of the triplets were the same, then you’d compare the values of the pairs to determine the higher hand. And if the pairs were the same, both hands are of equal rank.
Setup
Note: The first stages of the setup can be found on the introduction page to comparing poker hands, here.
There aren’t any other specific preparations we need before we begin.
Writing The Code For Comparing Two Full Houses
When both hands are full houses, the GetWinningPlayerId function will eventually call a the FindWinnerFullHouse function that compares them to determine which one wins.
FindWinnerFullHouse
FindWinnerFullHouse = FUNCTION(hand1, hand2)
SET workingHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1)
SET workingHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2)
SET trioPairValues1 = GetTrioPairValues(workingHand1)
SET trioPairValues2 = GetTrioPairValues(workingHand2)
SET trioValue1 = trioPairValues1[0]
SET trioValue2 = trioPairValues2[0]
IF (trioValue1 > trioValue2)
RETURN 0
ELSE IF (trioValue1 < trioValue2)
RETURN 1
END
SET pairValue1 = trioPairValues1[1]
SET pairValue2 = trioPairValues2[1]
IF (pairValue1 > pairValue2)
RETURN 0
ELSE IF (pairValue1 < pairValue2)
RETURN 1
END
RETURN -1
END
GetTrioPairValues
GetTrioPairValues = FUNCTION(hand)
SET secondCardValue = hand[1].value;
SET thirdCardValue = hand[2].value;
IF secondCardValue EQUALS thirdCardValue
SET fourthCardValue = hand[3].value;
RETURN [ secondCardValue, fourthCardValue ]
END
RETURN [ thirdCardValue, secondCardValue ]
END
In the code above, first we sort both hands by card rank in descending order. Next, we call a new function, GetTrioPairValues, which will tell us the values of the pairs and triplets of both hands. The value that GetTrioPairValues returns is an array that contains two elements: first is the value of the triplet, second is the value of the pair.
Next, the code compares the values of the triplets. If a winner is found, it returns the winning player index (0 for the hand 1, or 1 for hand 2). Otherwise, it compare pairs, and again returning the winning player index if a winner is found. And finally, if the pairs are equal, it returns -1, meaning both hands are evenly matched.
That’s it! This one was easy! 😁
.. Whooaaa, hold on a minute chief. What about the wild cards? 😒
Ugh! Them damn wild cards again! Shit! 😅 Well, we’ll handle those next.
Comparing Two Full House Hands With Wild Cards
If a hand has wild cards, the would assume values that would create the best full house possible. If one or more wild cards are in the hand, the above logic, about comparing the second and third cards in the hand, will not work, because the hand won’t have both a triplet and a pair.
We can restore that logic by first replacing the wilds with actual card values. The first step to this is using our handy CardMatchUtils.DoCardsHaveSameValue function.
We’ve used this function many times before. It will tell us if a card with a certain value appears in the hand a specified number of times. Also, if wild cards are in the hand, they can assume said card’s value in order to help satisfy the count. The function returns true if the card was found in the hand the specified number of times. Lastly, the function tracks the values of those cards that match the specified count.
We’ve made some updates to the function since it was first introduced. And we’ll make some new changes here to accommodate wild cards.
DoCardsHaveSameValue
CardMatchUtils.DoCardsHaveSameValue = FUNCTION(sortedHand, numToMatch, wildsInfo)
SET numWilds to 0
SET startIndex to 0
SET cardValues to empty array []
IF wildsInfo is specified
SET numWilds to wildsInfo.numWilds
IF numWilds is 0
count the number of wild cards in the hand, and set this value to numWilds
END
SET startIndex to wildsInfo.startIndex
SET cardValues to wildsInfo.cardValues
ELSE
count the number of wild cards in the hand, and set this value to numWilds
END
SET maxIndex to sortedHand.length - numWilds - 1
SET baseCardValue to 0
SET numMatched to 0
LOOP through each card in the sortedHand array, starting at index startIndex
IF it's the first card in the loop
IF the card is a wild card
//first card is a wild card - the only way the first card would be a wild is if all cards
// starting at the start index are wilds (assuming cards are already sorted in descending
// value order, with wilds at the end)
//the hand must contain at least as many wilds as the requested number of cards to match
IF (u_numWilds LESS THAN u_numToMatch)
RETURN FALSE
END
IF wildsInfo is specified
SET PROPERTY wildsInfo.numWilds to numWilds - numToMatch
SET PROPERTY wildsInfo.startIndex to [index of card within loop] + numToMatch;
ADD card's value into cardValues array
SET PROPERTY wildsInfo.cardValues to cardValues
END
RETURN TRUE
ELSE
//first card starts off the number of matches with a base card value
SET baseCardValue to the card's value
END
SET numMatched to 1
CONTINUE with next card in the loop
END
IF the baseCardValue EQUALS the card's value
//this card's value matches the base card value
ADD 1 to the current value of numMatched
IF numMatched EQUALS numToMatch
//total number of matched cards found - success
IF wildsInfo is specified
SET PROPERTY wildsInfo.numWilds to numWilds
SET PROPERTY wildsInfo.startIndex to the current loop index + 1
ADD card's value into cardValues array
SET PROPERTY wildsInfo.cardValues to cardValues
END
RETURN TRUE
END
//still need to match more cards for the base card value
CONTINUE with next card in the loop
END
//This card's value does not match the base card value. Check if there are enough wilds that can satisfy the match.
IF numMatched + numWilds is GREATER THAN OR EQUALS numToMatch
//there are enough wilds that can satisfy the base card value - success
//deduct the number of wilds used to satisfy the base card value from the current number of wild cards
SET numberOfWildsToDeduct to numToMatch - numMatched
DEDUCT numberOfWildsToDeduct from numWilds
//update the wilds info
IF wildsInfo is specified
SET PROPERTY wildsInfo.numWilds to numWilds
SET PROPERTY wildsInfo.startIndex to the current loop index
ADD baseCardValue into cardValues array
SET PROPERTY wildsInfo.cardValues to cardValues
END
RETURN TRUE
END
//If we arrive here, there are not enough wild cards to satisfy the base card value.
//start a new base card value with the current card that did not match
SET baseCardValue to the value of the card
IF the card is a wild card
//the base card value can't be a wild card - abort the for loop
END LOOP
END
SET numMatched to 1
END LOOP
//unable to satisfy a match - however, one last attempt, if there are remaining wilds, check if number of matched cards on the last loop + num wilds satify
IF numMatched + numWilds GREATER THAN OR EQUALS numToMatch
//there are enough wilds that can satisfy the base card value - success!
//deduct the number of wilds used to satisfy the base card value from the current number of wild cards
SET numberOfWildsToDeduct to numToMatch - numMatched
DEDUCT numberOfWildsToDeduct from numWilds
//update the wilds info
IF wildsInfo is specified
SET PROPERTY wildsInfo.numWilds to numWilds
SET PROPERTY wildsInfo.startIndex to the current loop index
IF baseCardValue NOT EQUAL 0
ADD baseCardValue value into cardValues array
ELSE
ADD wild card value (CardValues.wild) into cardValues array
END
SET PROPERTY wildsInfo.cardValues to cardValues
END
RETURN TRUE
END
//if we arrive here, we were unable to satisfy a match
RETURN FALSE
END
In a nutshell, this function now handles what happens if it encounters a wild card as the first card it checks, and that if only wild cards were processed, the cardValues array will specify the wild card value to let us know.
Note: Just like when you determined if a card was a full house, you’ll need to call the CardMatchUtils.DoCardsHaveSameValue function twice, once to look for the triplet, and again for the pair, as in a 3-2 full house. If you don’t get successful calls both times, you’ll then need to check for a 2-3 full house. You can find details of this on the original full house-matching article here.
If you’re checking for a 3-2 full house, you’d write something like this:
SET info to an empty object { };
IF CardMatchUtils.DoCardsHaveSameValue(hand, 3, info) AND CardMatchUtils.DoCardsHaveSameValue(hand, 2, info))
(we have a 3-2 full house)
END
And for a 2-3 full house:
SET info to an empty object { };
IF CardMatchUtils.DoCardsHaveSameValue(hand, 2, info) AND CardMatchUtils.DoCardsHaveSameValue(hand, 3, info))
(we have a 2-3 full house)
END
Here are five examples of some hands encountered what the cardValues array will include, and the intended resulting hands are.
Example 1 Hand: 8-8-7-7-w (“w” is a wild card, and suits don’t matter in a full house) Becomes: 8-8-(8)-7-7 The cardValues array would be [8, 7] This would end up being a 3-2 full house, as the wild assumes the third eight.
Example 2 Hand: 8-8-7-w-w Becomes: 8-8-(8)-7-(7) cardValues: [8, 7] he first DoCardsHaveSameValue call will substitute one of the wilds as the eight, satisfying the triplet. On the second call, the other wild is used to satisfy a pair of sevens, qualifying as a 3-2 full house.
Example 3 Hand: 8-7-w-w-w Becomes: 8-(8)-(8)-7-(7) cardValues: [8, 7] imilar to the last example, but the first DoCardsHaveSameValue substituted two eights to satisfy the triplet.
Example 4 Hand: 8-w-w-w-w Becomes: (A)-(A)-(A)-8-(8) cardValues: [8, w] A little tricky one here (: Normally, this hand would become 8-(8)-(8)-(A)-(A), because the eight was encountered first, so and there are enough wilds to satisfy the triplet for a 3-2. However, 8-8-8-A-A is not the best hand that can be formed, because we also have enough wilds to form triple aces (which is the highest triplet possible).
That’s where having the DoCardsHaveSameValue function put a “wild card value” in the cardValues array, as you can see in the second call. Later on in this article, we’ll deal with this when we start replacing wilds with actual card values. Hang tight for now 😉
Example 5 Hand: w-w-w-w-w Becomes: (A)-(A)-(A)-(K)-(K) cardValues: [w, w] Wow! 😮 The DoCardsHaveSameValue function gives us two wild card values in its cardValues array for a 3-2. With all wilds, we substitute the highest cards possible: a trio of aces and a pair of kings. Like the last example, there’s a bit of substitution going on here, in both the hand, and the card values, which I’ll show you how to handle in this article.
Setting Up The cardValues For Substitutions Of Wilds
Now that we have a triplet and pair value in the cardValues array, we can begin handling the situations where wilds are in the hand.
But first, if the cardValues array itself contains wild cards, as in examples 4 and 5, we must first replace those with non-wild card values before we can replace those in the hand.
There are two steps to do this:
Start with the highest value card, ace, and replace one wild in the cardValues with that.
If the other value in the array is also a wild, replace that one with a king.
Sort the contents of the new cardValues in descending order of value.
So, let’s have a look at example 4. cardValues: [8, w] We’d replace the wild with an ace, and the array looks like: [8, A] Then after sorting in descending order of value it now looks like: [A, 8]
In example 5, we had cardValues: [w, w] We’d replace the wild with an ace, and the array looks like: [A, w] Then, replace the second wild with a king to get [A, K] They are already properly sorted.
Some code for this function, looks like:
WildsAssumeInfoCardValues
WildsAssumeInfoCardValues = FUNCTION(cardValues)
SET replaceValue to CardValues.ace
IF cardValues[0] EQUALS CardValues.wild
SET cardValues[0] to replaceValue
SET replaceValue to CardValues.king (or subtract 1)
END
IF cardValues[1] EQUALS CardValues.wild
SET cardValues[1] to replaceValue
END
sort cardValues in descending order
END
What this WildsAssumeInfoCardValues does is start with a “replacing value” of ace. Then, every time it encounters a wild value in the cardValues array, it replaces that value with the value of replaceValue. If it’s the first card in the array, it also sets the replacing value to king, so that if the second card is also a wild, it would be replaced with a king instead of an ace.
Replacing Wilds In The Hand
Nooooww!
We’re finally ready to replace the wilds in the hand with values from the cardValues array!
What we’re doing here is first starting with the first value in the cardValues array (triplet), and replace, up to the number of replacements necessary, wilds with that card value.
Then, we do the same for the second value in the cardValues array for the pair.
Let’s dive in. 😏
WildsAssumeCardValues
WildsAssumeCardValues = FUNCTION(hand, cardValues)
SET numWilds TO CardMatchUtils.CountCardsByValue(hand, CardValues.wild)
(handle triplet)
SET cardValue TO cardValues[0]
SET numCardsWithValue TO CardMatchUtils.CountCardsByValue(hand, cardValue)
SET numCardsToMatch TO 3
SET numWildsToReplace TO numCardsToMatch - numCardsWithValue
IF numWildsToReplace LESS THAN OR EQUAL TO 0
(skip the rest of handling triplet and move on to "handle pair"
END
SET cards TO (make a copy of the cards in the hand)
FOR EACH card IN cards
IF the card is a wild card
replace that value of the card with cardValue
decrease numWilds by 1
IF numWilds EQUALS 0
RETURN (we're done; no more wilds to replace)
END
END
END
(handle pair)
SET cardValue TO cardValues[1]
SET numCardsWithValue TO CardMatchUtils.CountCardsByValue(hand, cardValue)
SET numCardsToMatch TO 2
SET numWildsToReplace TO numCardsToMatch - numCardsWithValue
IF numWildsToReplace LESS THAN OR EQUAL TO 0
RETURN (we're done; no wilds to replace)
END
SET cards TO (make a copy of the cards in the hand)
FOR EACH card IN cards
IF the card is a wild card
replace that value of the card with cardValue
decrease numWilds by 1
IF numWilds EQUALS 0
RETURN (we're done; no mre wilds to replace)
END
END
END
sort cards by in order of descending card value
RETURN cards
END
This function replaces wilds in the hand with values specified in the cardValues array, until it runs out of wilds in the hand. Triplets are handled first, getting the higher value of the cardValues array. Then if there are any wilds left, the pair is handled.
Coming Full Circle
If you’re still with me, than great job getting this far! (muscle arm emote)
Now that we’ve removed all wilds in the hand, you can go back and use the GetTrioPairValues to get the values of the triplets and pairs, and finally compare triplets and pairs to determine which full house pair wins.
You’ve reached the end for comparing full houses! No, for real this time, that’s it. 😐
Compare Your Own Hands
You can use the controls below to build your own hands and compare full houses. Have fun playing around with it!
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
If you’re an avid poker player, or even if you’re just starting out, I invite you to check out the poker odds calculator for Texas Hold ’em. With this tool, you can calculate your odds for winning any game. I found a very polished calculator that is available here.
Basic operation of a calculator is adding the cards to your hand and community. It then determines the odds your hand has of winning.
In this article, I’ll cover how you can code a simple poker odds calculator. First, let’s go over how the calculator stores the cards in your hand and the community.
Setup Card Data
A card is the basic data block we’ll be using. We’ll create a simple Card object, that will store the suit and value of each card. You can write it as:
A player’s hand is stored as an array of Card objects. The array has two elements, one for each card. You’d setup that up like this:
Note: If you’d like to see, in detail, the setup for card values, suits, Card objects, and hands, please see this link to an earlier article.
Setup Player and Community Data
The player’s hand and community cards are both defined as arrays, and will contain several Card objects:
var playerHand = [];
var communityCards = [];
Adding Player And Community Cards To Be Played
To add a card to the player’s hand, construct a new Card object, set its value and suit, then add it to the playerHand array. Say you want to add the 4♣. You’d write:
var card = new Card(CardValues.four, CardSuits.clubs);
var playerHand = allPlayerHands[0];
playerHand.push(card);
Adding a community card is similar. To add a Q♦:
var card = new Card(CardValues.queen, CardSuits.diamonds);
communityCards.push(card);
Evaluating Odds
Now that you have set up the players and cards, you can begin calculating odds.
First, create the scenario you want to evaluate. In the following example, we’ll use four community cards from the flop and turn. Let’s say your hand is 4♣ 9♣, and the community cards are 7♦, 5♣ , K♥, 8♣. You’d code this as:
Then, determine the best possible hand for the player using the cards in the player’s hand, and the community cards. You do this by finding how many “outs” you have. An out is an unknown card (in this case, the final river card) that, when added, will give you the best hand.
Next, determine which potential river cards would give you a strong or winning hand (a flush or straight): any 6 (four cards), or 2♣, 3♣, 7♣, 10♣, J♣, Q♣, K♣, and A♣. So, there are a total of 12 outs.
Note: Writing code to determine the outs themselves, or compare odds for multiple players both go beyond the scope of this article. I may cover them in future articles.
When matching and comparing poker hands, you may find it easier to use a “temporary hand” (a new array) when evaluating numerous combinations of the player’s cards with the community cards. For example, consider this:
var workingHand = [
playerHand[1],
communityCards[0],
communityCards[1],
communityCards[2],
communityCards[3]
];
The above code gives you a working hand of 9♣, 7♦, 5♣, K♥, 8♣. You could then perform the various card matching actions on this array, using functions from previous articles, such as sorting ( CardMatchUtils.SortCardsByDescendingValue ), or determining if a hand is a straight ( CardMatchUtils.AreCardsStraight ).
To calculate the percentage you have of getting one of these out cards, you need to factor in the remaining number of cards in the deck, which is 46. A breakdown is:
const MAX_NUM_CARDS_IN_DECK = 52;
var numCardsInPlayerHand = playerHand.length; //2
var numCommunityCards = communityCards.length; //4
var numberOfCardsRemaining = MAX_NUM_CARDS_IN_DECK - numCardsInPlayerHand - numCommunityCards; //52 - 4 - 2 = 46
Of those 46 cards, 12 of them (the outs we found earlier) will give you a strong or winning hand. You can find the percentage of getting one of them with this:
var percentage = 1 - (numberOfCardsRemaining - numOuts) / numberOfCardsRemaining;
In our example, this is 1 – (46 – 12) / 46 = 0.26, or a 26% chance.
If you want to go further and represent this in odds notation (“x to y”), do this calculation:
var odds = 1 / percentage - 1;
Which yields, 1 / 0.26 – 1 = 2.8, or “2.8 : 1”. This means for about every 3 games, you might get a flush or straight.
That’s it for this article! I’ll talk to you next time. Thanks and take care 🙂
Continuing the series of comparing poker hands of the same rank, this article will show you how to write code to compare two flushes to see which ranks higher.
In a previous article for poker hands, you saw how to check a hand to determine if a it’s a flush. That is, all five of its cards are the same suit, and their values are not in sequential order.
Each card is diamonds, and they are not all in sequential order.
Comparing two flush hands is a bit easier than the others we’ve covered so far. You need to perform these three steps:
Temporarily replace all wilds with aces.
Sort cards in hand by descending value.
Compare cards in both hands.
And we’ve performed these tasks before, so let’s get started!
Setup
Note: The first stages of the setup can be found on the introduction page to comparing poker hands, here.
There aren’t any other specific preparations we need before we begin.
Writing The Code For Comparing Two Flushes
When both hands are flushes, the GetWinningPlayerId function will eventually call a the FindWinnerFlush function that compares them to determine which one wins.
Let’s have a look at that function.
FindWinnerFlush
FindWinnerFlush = function(hand1, hand2) {
SET workingHand1 = CopyHand(hand1)
ReplaceWildsWithAces(workingHand1)
SET workingHand1 = CardMatchUtils.SortCardsByDescendingValue(workingHand1)
SET workingHand2 = CopyHand(hand2)
ReplaceWildsWithAces(workingHand2)
SET workingHand2 = CardMatchUtils.SortCardsByDescendingValue(workingHand2)
SET winningPlayerIndex = CardMatchUtils.CompareHands(workingHand1, workingHand2)
RETURN winningPlayerIndex
}
Let’s go over the three steps in more detail.
STEP 1: Temporarily Replace All Wilds With Aces
First, you want to replace any wild cards in the hand with aces. Although a Flush is a hand where all cards are the same suit, if we’re comparing two flushes, the cards’ values now play a factor. So wilds can be replaced with aces to give the highest possible hand value. Also remember, wilds can assume any suit as well as any value, so the condition of the flush is still met.
Say, you had this hand:
That one wild card would be replaced with an ace:
Note: Wilds, as covered in this series, and for the sake of keeping the pseudo code relatively simple when wilds are involved, have no restrictions on the actual card suits and values they can replace. As you can see in the substitution in the above image, it contains two ad cards. If you’d like more official rulings on wilds, please have a look at this Wiki.
Since the card values are being altered, we don’t want to modify the original hands (hand1 and hand2 from above). So, first, you need to make a copy of the hand. You’ll then do all your work and comparing on this “working hand”.
CopyHand
CopyHand = function(hand) {
SET copyHand = new Array()
FOR EACH card in hand
(create a copy of the card)
SET copyCard = new Card(card.value, card.suit)
(add the copied card to the copy hand)
copyHand.push(copyCard)
END
RETURN copyHand
}
Now that you have a copy of all cards in the hand, let’s have a look at the psuedo code that replaces wilds with aces.
ReplaceWildsWithAces
ReplaceWildsWithAces = function(hand) {
FOR EACH card in hand
IF (card.value EQUALS CardValues.wild)
card.value = CardValues.ace
END
END
}
STEP 2: Sort Cards In Hand By Descending Value
Next, after all the wilds have been replaced with aces, sort the cards in the working hand in order of descending value (highest to lowest). We turn to our hero, CardMatchUtils.SortCardsByDescendingValue! We’ve used this guy many times now… where would we be without him? I don’t know about you, but I don’t wanna find out! 😆
Step 3: Compare Cards In Both Hands
The final step is comparing the cards in both hands.
Once again, we turn to a highly used function, CardMatchUtils.CompareHands. This function will compare two hands, both are assumed to already be sorted by descending card value. It accepts two parameters, hand1 and hand2. If hand1 has the higher hand, the function returns 0. If hand2 is higher, 1 is returned. Otherwise, -1 is return if both hands are equal.
So compared to other hand-comparing topics, comparing two flush hands is relatively easy. We’ve already written most of the functions used comparing flushes.
Example
Let’s have one example, using the two hands featured at the top of this article. Which one wins? Let’s find out! ⚔
Hand 2
Hand 2
First, let replace all wilds with aces. Hand 1 has one wild in it, so it now looks like:
The wild assumes both value and suit, and becomes an ace of diamonds.
Hand 2 has no wilds, so we’re done with step 1.
Next, we sort the cards in each hand by value in descending order. The hands now look like:
Hand 1
Hand 2
Finally, compare the cards, starting with the first card in each hand. Both hands have an ace, so move on to the second card.
Hand 1 has a jack, while hand 2 hand a queen. The queen outranks the jack, so hand 2 is the winning flush hand. 🙂
That’s it for comparing flushes! Below is a set of controls you can play with to creating and compare your own flush hands.
Compare Your Own Hands
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.