possible to dry up code without the use of functions

Write a command line game that plays a simplified version of blackjack where we don’t worry about aces and face cards. The program should generate a random number between 1 and 10 each time the player gets a card. It should display a running total of the players cards, and ask the player whether or not it should deal another card. If the player goes over 21, your program should tell the player he is bust. At the end of the hand, your program should ask the player if he would like to play again.

Here's my completed code, but I was wondering if there's any possible way I can dry up my code without using functions. Or if you have any suggestions on improving my code, please let me know. I

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main(){
        int total=0, firstCard, secondCard, anotherRandomCard;
        char anotherCard = 'y', playAgain = 'y';

        do {
                // seed the random number generator
                srand(time(0));

                // generate a random number between 1 and 10 each time the player gets a card
                cout << "First cards: ";
                firstCard = 1+(rand()%10);
                secondCard = 1+(rand()%10);
                cout << firstCard << ", " << secondCard << endl;
                total = firstCard + secondCard;
                cout << "Total: " << total << endl;
                cout << "Do you want another card? (y/n): ";
                cin >> anotherCard;
                while (anotherCard == 'y')
                {
                        anotherRandomCard = 1+(rand()%10);
                        cout << "Card: " << anotherRandomCard << endl;
                        total += anotherRandomCard;
                        cout << "Total: " << total << endl;
                        if(total > 21)
                        {
                                cout << "Bust!" << endl;
                                cout << "Would you like to play again(y/n): ";
                                cin >> playAgain;
                                if (playAgain == 'y')
                                {
                                        anotherCard = 'n';
                                }
                                else
                                {
                                        break;
                                }
                        }
                        else if(total == 21)
                        {
                                cout << "Blackjack!" << endl;
                                cout << "Would you like to play again(y/n): ";
                                cin >> playAgain;
                                if (playAgain == 'y')
                                {
                                        anotherCard = 'n';
                                }
                                else
                                {
                                        break;
                                }
                        }
                        else {
                                cout << "Do you want another card? (y/n): ";
                                cin >> anotherCard;
                        }

                }
        } while (playAgain == 'y');
        return 0;
}
Assuming that "dry up code" means 'write the code in a more compact manner',
and assuming that "without the use of functions" implies both
a. 'functions defined by the standard library are allowed' and b. 'closures are not allowed':

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cctype>

int main() {

    // avoid magic numbers
    constexpr int MAX_CARD_VALUE = 10 ;
    constexpr int MAX_SCORE = 21 ;

    // see: http://en.cppreference.com/w/cpp/numeric/random In addition to
    // the engines and distributions described above, the functions and constants
    // from the C random library are also available though not recommended
    std::srand( std::time(nullptr) ) ; // once, at the start of the program

    char again ;
    do { // pick any one brace/indentation style and then use it consistently
         // https://en.wikipedia.org/wiki/1_true_brace_style
         // classic K&R and Allman (aka BSD) styles are popular

        const int first = std::rand() % MAX_CARD_VALUE + 1 ;
        const int second = std::rand() % MAX_CARD_VALUE + 1 ;

        int score = first + second ;
        std::cout << "\nfirst two cards are: " << first << ", " << second
                  << ", total: " << score << '\n' ;

        char one_more ;
        while( score < MAX_SCORE && std::cout << "deal another card? " &&
               std::cin >> one_more && std::toupper(one_more) == 'Y' ) {

            const int next_card = std::rand() % MAX_CARD_VALUE + 1 ;
            score += next_card ;
            std::cout << "next card: " << next_card << ", total: " << score << '\n' ;
        }

        if( score > MAX_SCORE ) std::cout << "bust!\n" ;
        else if( score == MAX_SCORE ) std::cout << "blackjack!\n" ;
        else std::cout << "total: " << score << '\n' ;

    } while( std::cout << "play again (y/n)? " && std::cin >> again &&
             std::toupper(again) == 'Y' ) ;
}
"dry up"
I think this is in reference to "Don't Repeat Yourself"
https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
Last edited on
Yes. Thank you!

Well, don't know how this expression std::rand() % MAX_CARD_VALUE + 1 can be "dried up" without closures/function objects.
My apologies if that came across as snarky. It wasn't intended that way.
I suppose you could use a macro if you really wanted to. But this is a foolish requirement anyways.
Last edited on
> My apologies if that came across as snarky.

No, it didn't. I hadn't heard of the usage 'dry up' in the context of software till now.
hi guys! Sorry I should have been a bit more clear about this. DRY = don't repeat yourself. The code works but I was wondering if there's anyway to refactor my code to make it cleaner that's all.. I was going to use functions but my professor did not want us to use functions for this particular assignment. If you guys have any suggestions on how I can improve my code, please let me know. Thanks!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cctype>
using namespace std;

int main()
{
   char ans;
   bool play = true;
   srand( time( 0 ) );

   while( play )
   {
      int total = 0, numDrawn = 0;
      bool drawAgain = true;
      while ( drawAgain )
      {
         int card = 1 + rand() % 10;
         total += card;
         numDrawn++;
         cout << "Card: " << card << "    Total: " << total << '\n';

         if ( total >= 21 )
         {
            drawAgain = false;
            cout << ( total > 21 ? "Bust!" : "Vingt et un!" ) << '\n';
         }
         else if ( numDrawn >= 2 )
         {
            cout << "Do you want another card (y/n)? ";
            cin >> ans;
            drawAgain = ( tolower( ans ) == 'y' );
         }
      }
         
      cout << "Would you like to play again (y/n)? ";
      cin >> ans;
      play = ( tolower( ans ) == 'y' );
   }
}


Fundamentally, there are two things that you do repetitively:
- play a game
and, within that,
- draw cards

I think that your nested loop structure should reflect that.

Decisions are made (by you or the rules of the game)
- as a response to drawing cards
- as a response to the end of a game

I think that your if blocks should reflect that.


The restriction not to use functions is sad, however:
- it makes the single routine main() quite long;
- it removes the opportunity for the names of functions to indicate what is going on;
- there is still unnecessary repetition (lines 31-33 and 37-39) that could be reduced.

It's a nice exercise in logic, however.
Last edited on
> my professor did not want us to use functions for this particular assignment.

Taking that in the literal sense (lambda expressions are not functions), the earlier code can be made more arid:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cctype>

int main() {

    // avoid magic numbers
    constexpr int MAX_CARD_VALUE = 10 ;
    constexpr int MAX_SCORE = 21 ;

    static const auto draw = [] { return std::rand() % MAX_CARD_VALUE + 1 ; } ;
    static const auto yes = [] { char ans ; return std::cin >> ans && std::toupper(ans) == 'Y' ; } ;

    // see: http://en.cppreference.com/w/cpp/numeric/random In addition to
    // the engines and distributions described above, the functions and constants
    // from the C random library are also available though not recommended
    std::srand( std::time(nullptr) ) ; // once, at the start of the program

    do { // pick any one brace/indentation style and then use it consistently
         // https://en.wikipedia.org/wiki/1_true_brace_style
         // classic K&R and Allman (aka BSD) styles are popular

        int score = draw() ; ;
        std::cout << "\nfirst card: " << score << ", " ;

        do {

            const int next_card = draw() ;
            score += next_card ;
            std::cout << "next card: " << next_card << ", total: " << score << '\n' ;

        } while( score < MAX_SCORE && std::cout << "deal another card? " && yes() ) ;

        if( score > MAX_SCORE ) std::cout << "bust!\n" ;
        else if( score == MAX_SCORE ) std::cout << "blackjack!\n" ;
        else std::cout << "total: " << score << '\n' ;

    } while( std::cout << "play again (y/n)? " && yes() ) ;
}
Topic archived. No new replies allowed.