Skip to content

Games programming from the ground up with C: Challenge project 1

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:

Output from the Acey Ducey BASIC program showing how the instructions are displayed.
How the instructions for Acey Ducey are displayed by the original BASIC program

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:

Output from teh Acey Ducey BASIC program showing how the player's remaining money is displayed.
How the Acey Ducey program displays the player’s remaining money
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:

Output from the Acey Ducey BASIC program showing how the first two cards are displayed.
How the Acey Ducey program displays the drawn cards
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.

Output from the Acey Ducey BASIC program showing the "Chicken!!" message that is displayed if the player declines to bet.
How the Acey Ducey program responds to a bet of 0

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.

Output from the Acey Ducey BASIC program showing the message displayed if a player tries to bet more money than they have.
How the Acey Ducey program deals with bets that are too large
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.

Output from the Acey Ducey BASIC program showing the player winning a round, losing a round and running out of money. They are asked if they want to try again and decline, so the program ends.
An example of the final part of an Acey Ducey game
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:

A flowchart describing the function of the Acey Ducey BASIC program.
A flowchart describing the function of the Acey Ducey program

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.

Published inGamesProgramming

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *