You can see an index of all the posts in this series: go to index.
I want to consolidate the skills introduced so far by creating an entire game. In this challenge project I will convert the BASIC game, Acey Ducey to a Command Line program written in C.
Acey Ducey is a simple card game in which two cards are dealt face up from a shuffled deck, and the player then bets on whether the next card drawn will have a value that falls between the first two cards.
If you want the original source code, here it is: aceyducy.bas. It’s all explained in this post however.
Here’s the original BASIC listing in full:
10 PRINT TAB(26);"ACEY DUCEY CARD GAME" 20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" 21 PRINT 22 PRINT 23 PRINT 30 PRINT "ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER " 40 PRINT "THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP" 50 PRINT "YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING" 60 PRINT "ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE" 70 PRINT "A VALUE BETWEEN THE FIRST TWO." 80 PRINT "IF YOU DO NOT WANT TO BET, INPUT A 0" 100 N=100 110 Q=100 120 PRINT "YOU NOW HAVE";Q;"DOLLARS." 130 PRINT 140 GOTO 260 210 Q=Q+M 220 GOTO 120 240 Q=Q-M 250 GOTO 120 260 PRINT "HERE ARE YOUR NEXT TWO CARDS " 270 A=INT(14*RND(1))+2 280 IF A<2 THEN 270 290 IF A>14 THEN 270 300 B=INT(14*RND(1))+2 310 IF B<2 THEN 300 320 IF B>14 THEN 300 330 IF A>=B THEN 270 350 IF A<11 THEN 400 360 IF A=11 THEN 420 370 IF A=12 THEN 440 380 IF A=13 THEN 460 390 IF A=14 THEN 480 400 PRINT A 410 GOTO 500 420 PRINT "JACK" 430 GOTO 500 440 PRINT "QUEEN" 450 GOTO 500 460 PRINT "KING" 470 GOTO 500 480 PRINT "ACE" 500 IF B<11 THEN 550 510 IF B=11 THEN 570 520 IF B=12 THEN 590 530 IF B=13 THEN 610 540 IF B=14 THEN 630 550 PRINT B 560 GOTO 650 570 PRINT "JACK" 580 GOTO 650 590 PRINT "QUEEN" 600 GOTO 650 610 PRINT "KING" 620 GOTO 650 630 PRINT "ACE" 640 PRINT 650 PRINT 660 INPUT "WHAT IS YOUR BET";M 670 IF M<>0 THEN 680 675 PRINT "CHICKEN!!" 676 PRINT 677 GOTO 260 680 IF M<=Q THEN 730 690 PRINT "SORRY, MY FRIEND, BUT YOU BET TOO MUCH." 700 PRINT "YOU HAVE ONLY ";Q;" DOLLARS TO BET." 710 GOTO 650 730 C=INT(14*RND(1))+2 740 IF C<2 THEN 730 750 IF C>14 THEN 730 760 IF C<11 THEN 810 770 IF C=11 THEN 830 780 IF C=12 THEN 850 790 IF C=13 THEN 870 800 IF C=14 THEN 890 810 PRINT C 820 GOTO 910 830 PRINT "JACK" 840 GOTO 910 850 PRINT "QUEEN" 860 GOTO 910 870 PRINT "KING" 880 GOTO 910 890 PRINT "ACE" 900 PRINT 910 IF C>A THEN 930 920 GOTO 970 930 IF C>=B THEN 970 950 PRINT "YOU WIN!!!" 960 GOTO 210 970 PRINT "SORRY, YOU LOSE" 980 IF M<Q THEN 240 990 PRINT 1000 PRINT 1010 PRINT "SORRY, FRIEND, BUT YOU BLEW YOUR WAD." 1020 INPUT"TRY AGAIN (YES OR NO)";A$ 1030 IF A$="YES" THEN 110 1040 PRINT "OK HOPE YOU HAD FUN!" 1050 END
Let’s break this down, bit by bit, starting with lines 10 to 80.
10 PRINT TAB(26);"ACEY DUCEY CARD GAME" 20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" 21 PRINT 22 PRINT 23 PRINT 30 PRINT "ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER " 40 PRINT "THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP" 50 PRINT "YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING" 60 PRINT "ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE" 70 PRINT "A VALUE BETWEEN THE FIRST TWO." 80 PRINT "IF YOU DO NOT WANT TO BET, INPUT A 0"
This section shouldn’t present any real challenge to me, it simply displays instructions to the user. I’ll keep my text left-aligned, so I won’t worry about the TAB instructions in lines 10 and 20. Remember that a PRINT instruction on its own, e.g. line 21, simply moves the print position to the next line. Here’s how that looks:
Now for lines 100 and 110.
100 N=100 110 Q=100
These lines initialise two variables. N holds the amount of the player’s bet, while Q holds the amount of money the player has available. Remember that C doesn’t have the single letter variable name restriction that BASIC does, so I can give my variables more self-explanatory names.
120 PRINT "YOU NOW HAVE";Q;"DOLLARS." 130 PRINT 140 GOTO 260
This short section of code simply displays the amount of money the player has remaining before moving on to the code at 260 (which is the code for displaying the cards). It looks like this:
260 PRINT "HERE ARE YOUR NEXT TWO CARDS " 270 A=INT(14*RND(1))+2 280 IF A<2 THEN 270 290 IF A>14 THEN 270 300 B=INT(14*RND(1))+2 310 IF B<2 THEN 300 320 IF B>14 THEN 300 330 IF A>=B THEN 270 350 IF A<11 THEN 400 360 IF A=11 THEN 420 370 IF A=12 THEN 440 380 IF A=13 THEN 460 390 IF A=14 THEN 480 400 PRINT A 410 GOTO 500 420 PRINT "JACK" 430 GOTO 500 440 PRINT "QUEEN" 450 GOTO 500 460 PRINT "KING" 470 GOTO 500 480 PRINT "ACE" 500 IF B<11 THEN 550 510 IF B=11 THEN 570 520 IF B=12 THEN 590 530 IF B=13 THEN 610 540 IF B=14 THEN 630 550 PRINT B 560 GOTO 650 570 PRINT "JACK" 580 GOTO 650 590 PRINT "QUEEN" 600 GOTO 650 610 PRINT "KING" 620 GOTO 650 630 PRINT "ACE" 640 PRINT
This section picks two cards at random and displays them to the player. Lines 270 and 300 are used to pick the cards and store them in the variables A and B. Notice that the range for the random numbers is 2 to 14, with 2 to 10 being the number cards, 11 for a Jack, 12 for a Queen, 13 for a King and 14 for an Ace (Aces are high in this game).
The code in lines 280 to 290 and 310 to 320 ensures the random number is constrained within the range 2 to 14. I should be able to write my random number generation in such a way that this additional code is unnecessary.
Line 330 checks to see if the first card has the same value or a higher value than the second card. If it does, control is returned to line 270 so two new cards can be chosen.
Lines 350 to 390 go to an appropriate PRINT command based on the value of the card. Cards with a value below 11 are printed as the numbers 2 to 10 in line 400. Lines 420, 440, 460 and 480 display the word “JACK”, “QUEEN”, “KING” or “ACE” respectively. Once the card value has been displayed, control is passed to line 500.
Note that lines 500 to 630 are almost identical to lines 350 to 480 except they use the card in variable B rather than the card in variable A. The limitations of this early dialect of BASIC often forced programmers into using this sort of brute force approach to a problem. I should be able to think of a more elegant and efficient way of doing this. Maybe a function could help here? Here’s what this code displays:
650 PRINT 660 INPUT "WHAT IS YOUR BET";M 670 IF M<>0 THEN 680 675 PRINT "CHICKEN!!" 676 PRINT 677 GOTO 260 680 IF M<=Q THEN 730 690 PRINT "SORRY, MY FRIEND, BUT YOU BET TOO MUCH." 700 PRINT "YOU HAVE ONLY ";Q;" DOLLARS TO BET." 710 GOTO 650
Line 660 displays a prompt and then gets the amount of the player’s bet into the variable M. I could do this in a couple of ways. I can use the input technique you have already seen to get the player’s bet, but I will have to use a different conversion specifier. Alternatively, is there a function I used when interpreting command line arguments that might be useful here?
In line 670 the amount of the player’s bet is checked to see if it is anything other than zero. If it is zero, then a suitably derisory response is displayed on line 675. Control is then returned to the code that displays the cards on line 260.
If the player has entered something other than zero, control is passed to line 680, which checks that the player hasn’t tried to bet more money than they have available.
If the player has bet too much they are warned in line 690 and reminded of the amount remaining in line 700. Control is then returned to line 650, where the player is asked to enter a new bet.
730 C=INT(14*RND(1))+2 740 IF C<2 THEN 730 750 IF C>14 THEN 730 760 IF C<11 THEN 810 770 IF C=11 THEN 830 780 IF C=12 THEN 850 790 IF C=13 THEN 870 800 IF C=14 THEN 890 810 PRINT C 820 GOTO 910 830 PRINT "JACK" 840 GOTO 910 850 PRINT "QUEEN" 860 GOTO 910 870 PRINT "KING" 880 GOTO 910 890 PRINT "ACE" 900 PRINT
Line 730 chooses the third card. This line and the lines that follow it are identical to the routines for the other two cards, except that the card is stored in the variable C. Again, I should be looking for ways I can achieve this more efficiently.
910 IF C>A THEN 930 920 GOTO 970 930 IF C>=B THEN 970 950 PRINT "YOU WIN!!!" 960 GOTO 210 970 PRINT "SORRY, YOU LOSE" 980 IF M<Q THEN 240 990 PRINT 1000 PRINT 1010 PRINT "SORRY, FRIEND, BUT YOU BLEW YOUR WAD." 1020 INPUT"TRY AGAIN (YES OR NO)";A$ 1030 IF A$="YES" THEN 110 1040 PRINT "OK HOPE YOU HAD FUN!" 1050 END
Line 910 checks if the third card is higher than the first card. If it is, it moves on to the next check in 930. If it is isn’t, control is passed to the lose routine on 970.
Line 930 checks if the third card is equal to or higher than the second card. If it is then control is passed to the lose routine on 970.
If the third card is between the first and second cards then line 950 displays a win message. Control is then passed back to line 210, which adds the player’s winnings to their total.
Line 970 is the start of the lose routine. It displays a lose message. Line 980 then checks that the amount to be deducted is less than the player’s remaining money. If it is then control passes back to line 240, which deducts the loss. If it isn’t then a broke message is shown on line 1010.
Line 1020 prompts the player to indicate if they want to play again. The answer is checked in line 1030, and if the player answered “YES”, control is passed back to line 110, which resets the player’s cash to the starting amount.
If the player answers anything other than “YES”, a farewell message is displayed on line 1040 and the program ends.
Reading a word rather than a single character from the player’s input is a bit trickier, but I’ll try and find a way to do this.
210 Q=Q+M 220 GOTO 120 240 Q=Q-M 250 GOTO 120
The last few lines you haven’t yet seen are these. Line 210 adds the amount of the player’s bet to their total and then control returns to line 120, which prints the remaining amount of money. Correspondingly, line 240 subtracts the amount of the player’s bet from their total before passing control back to line 120.
Here’s a flowchart for Acey Ducey:
While I’m working on my solution, I will refer to the documentation for the commands and functions I am using. The GNU C Reference Manual describes the fundamental features of the C language. The GNU C Library Reference describes library functions and sorts them based on type of activity.
I’ll show and explain my solution in the next post.
Be First to Comment