Welcome to the fifth entry in the Intermediate ColdFusion Contest. The earlier entries may be found at the end of this post. Today's entry is from Behrang Noroozinia. Before reading on, please check his application here. You can download his code from the download link at the bottom. Please respect the copyright of the creator.
The first thing I noticed about this application was how simple it looked. That is not a complaint. I like simplicity. I like how it defaulted the 10 dollar bet. As I mentioned in an earlier entry, I'm lazy, so I have preferred the entries that didn't make me type in an amount each time.
I tried to break the bet entry box, but it seems like he handled validation very well. I tried Apple, -10, and other things, and they all worked. This entry too accepted 9.9999999999, and I eventually ended up with 0.009999999 cents in my account. I'd probably suggest updating the validation to check the cents value. This could be done easily enough with string functions. To get the cents, you could do:
<cfif listLen(bet, ".") is 2 and len(listLast(bet,".")) gte 3>
.....
</cfif>
The absolute coolest thing in this game is the history function. This shows you every hand, who won, and how much money was won or lost. Darn nice little feature there.
Now let's dig into his code a bit. The first thing I found was a lack of var scoping in his showHands UDF. I'm sure everyone is tired of hearing me harp on var scoping... well... sorry, I'm not going to stop. Skipping the var scope can lead to very hard to debug issues. I'm going to keep bugging people about it till they pry my dead hangs from the keyboard (hopefully many, many years from now).
He uses CFCs to handle most of the game logic. I noticed quite a bit of try/catch pairs in his index.cfm file, and looking into his CFCs, I see he uses cfthrow to be very particular about user actions. In other words, if you try to hit when you aren't supposed to, the game logic will know it. It seems like he went over the top with his validation, which I think is a good thing.
A minor nit - in his methods that return void, he included a <cfreturn> tag. I normally don't include any <cfreturn> tag, and I believe that would be the generally accepted practice. (At least IMHO.)
I liked how his Deck.cfc was set up, especially the way cards are handed out. Here is the code:
<cffunction name="nextCard" access="public" output="false" returntype="Card">
<cfif variables.nextIndex gt arrayLen(variables.cards)>
<cfset shuffle()>
</cfif>
<cfset variables.nextIndex = variables.nextIndex + 1>
<cfreturn variables.cards[variables.nextIndex - 1]>
</cffunction>
Notice how he returns a Card component - and automatically handles reshuffling if he runs out of cards. This would handle a case where, by some miracle, enough cards were dealt out to empty the deck. While this would/should never happen in a 2 person BJ game, he could easily move his Deck.cfc, and Card.cfc to a Poker game.
I noticed that in Card.cfc, he used the This scope. I'm guessing he did this to make it easier to output the card values. While I still would have used a get/set method, I can see his reasoning for this.
Earlier Entries:
Archived Comments
The title of this blog post say contest entry 4. Should it not be 5? :)
Seems to be a bit of an issue with black jacks.
I had A & J and Dealer had A & J. The game said I won.
Also, I had A & Q and dealer had 2 & 8. It stopped the game and said I won. While I love to win :). The dealer is suppose to win in ties. It did not give the computer a chance to get 21.
Overall, without looking at the code the game looks, simple but good. UI was not the issue in this so the looks really do not matter.
Oh and yes that history thing is very nice!
Jason:
As far as the computer not getting a chance to get to 21, this is actually the first one that I believe i've seen done 'right'.
If a player (either the human player or the dealer) get a blackjack (defined as the first 2 cards totalling 21), the hand should end.
Maybe the original specs didn't call for it (don't have time to look 'em up right now), but that's the way mine is set up too. If a player gets dealt a 21, game's over, player wins. If the dealer gets dealt a 21, game's over, dealer wins. If both get dealt 21, dealer wins (the push).
I also like the history very much. I kept a running tally of the number of hands each player has won...but not to that level of detail. I like the fact that not only does it keep the history of wins/losses, but actually shows you the cards for each hand. VERY nice touch IMO.
I've not had a chance to look at the code yet, but looking forward to doing so. Liked this entry a lot.
while I am no expert on BlackJack I'm pretty sure, via my times in Vegas, that the rules are a little off (though this might not have been part of the contest.
1. On a Push the player keeps their money but doesn't win anything either.
2. On a blackjack (21 with 2 cards) the player is paid 1.5x their bet. I remeber hitting Black Jack at the casino, before the dealer even got her second card, they would pay me so I am not sure it even matters if it is a push.
One small comment about the game itself. I didn't actually look at the source code - but from a presentation angle it would have been nice if all messages that would appear/disappear were to come below the cards this way the table holding the cards wouldn't have shifted up/down as the messages visiblity toggled.
Also, it would be nice if the "bet" box remembered your last bet and didn't return to a 10 default every time.
Bill, if you check the original specs, I specifically said these were not Vegas rules. I wanted to keep things a bit simpler. :)
Here's a quick UI thing. It is a bit confusing having the 'Hit' button under my hand, and the 'Stay' button under the dealers hand.
Thanks everyone for your feedbacks.
- Ray
About checking for cents, you're right and I forget to check for cents!
And about var scoping in showHands UDF, I first created that section of code inside index.cfm and then wanted to used that in history, so I just copy/pasted it and forgot to var scope "i" variable.
- Jason
I have never played blackjack before. However, we have a game called "21" which is similar to blackjack, and in that game when you have 21 (with no limit to card counts), you win immediately. So I think I was thinking about "21" when developing that part.
- Bill
I agree with you about messages. In fact I have done this for the top message area which shows status messages like "New game started", But I forgot this in the game table! And your are right, about game remembering the last bet.
- Scott
I chose this design, because I thought that it shows where the next card would arrive! Just a design decision.
I tried to use CFC's in this game, and this is one of my first OO apps. I would appriciate if anyone comments on my OO design and suggests improvments. Thanks.
Yeah I guess I was not thinking correct about the rules. If the player gets black jack and and dealer does not the hand is over and the player wins. A natural black jack beats a dealers 21 with more than 2 cards. So I guess the only issue that remains is when I had A & J and Dealer had A & J. The game said I won. That should be a push.
I wish I would have known the correct rules b/c my game lets the dealer try to match the players blackjack....oops. So I already have one mistake and my game has not been evaluated yet :).
This contest has been a good learning experience so far. I know I will learn even more when my app is evaluated. :).
Thanks