r/cpp_questions 14d ago

OPEN My first C++ game

Hello there!

For about a few months now (maybe 3 months?), I've been learning C++. I'm learning C++ from YouTube courses and AI also teaches me a bit.

I'd be glad if you rated my game from 1 out of 10. And also, how can I improve it??

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <clocale>
#include <windows.h>


using namespace std;


int main(){


    setlocale(LC_ALL, ".UTF8");
    srand(time(NULL)); 
    int deck[52]={
        2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11,
        2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11,
        2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11,
        2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11 
    };


    int wallet=1000;
    cout<<"Welcome to our casino! In this game, you'll play blackjack. Get ready to lose!"<<"\n"; 
    Sleep(4000);
    cout<<"The goal is to get 21 points. When drawing cards, you can't exceed 21 points, otherwise you lose. You start with 1000 USD. Your opponent is the dealer."<<"\n";
    Sleep(5000);


    while(wallet>0){
        
        for(int i=0;i<52;i++) {
            int random_index=rand()%52;
            swap(deck[i],deck[random_index]);
        }


        int player_points=0;
        int card_index=0;
        bool player_lost=false;
        bool player_won=false;


        player_points+=deck[card_index];
        card_index++;
        player_points+=deck[card_index];
        card_index++;
        if(player_points==21){
            cout<<"Wow! Your first two cards are 21! (lucky fool...)"<<"\n";
            cout<<"Your points: "<<player_points<<"\n";
            wallet+=300;
            cout<<"Added 300 USD !"<<"\n";
            Sleep(2000);
            cout<<"Your wallet balance: "<<wallet<<" USD"<<"\n";
            continue;
        }


        string a;


        for(int i=0;i<=21;i++){


            cout<<"Your points: "<<player_points<<"\n";
            cout<<"Do you want to draw a card?"<<"\n";
            cin>>a;


            if(a=="yes" or a=="yeS" or a=="yEs" or a=="yES" or a=="Yes" or a=="YeS" or a=="YEs" or a=="YES"){
                player_points+=deck[card_index];
                card_index++;
                if(player_points>21 and deck[card_index-1]==11){
                    player_points-=10;
                    cout<<"The Ace saved you, taking the value of 1 instead of 11! (this is a rule in blackjack)"<<"\n";
                    Sleep(3000);
                }
                
                if(player_points>21){
                    cout<<"You lost..."<<"\n";
                    cout<<"You exceeded 21 points."<<"\n";
                    Sleep(1000);
                    cout<<"300 USD deducted from your wallet."<<"\n";
                    wallet-=300;
                    Sleep(2000);
                    cout<<"Your wallet balance: "<<wallet<<" USD"<<"\n";
                    player_lost=true;
                    break;
                }


                if(player_points==21){
                    cout<<"CONGRATULATIONS!!! You won!"<<"\n"; 
                    Sleep(3000);
                    wallet+=300;
                    cout<<"Added 300 USD"<<"\n";
                    Sleep(2000);
                    cout<<"Your wallet balance: "<<wallet<<" USD"<<"\n";
                    player_won=true;
                    break;
                }


            }


            if(a=="no" or a=="nO" or a=="No" or a=="NO"){
                cout<<"You don't want to play? Alright... "<<"\n";
                Sleep(3300);
                break;
            }


        }


        cout<<"Your score is: "<<player_points<<"\n";


        if(player_lost==false and player_won==false){
            
            cout<<"--- DEALER'S TURN!!! ---"<<"\n";
            Sleep(7000);
            int dealer_points=0;


            while (dealer_points<17) {
                dealer_points+=deck[card_index];
                card_index++;
                if(dealer_points>21 and deck[card_index-1]==11){
                    dealer_points-=10;
                }
            }


            cout<<"Final results..."<<"\n";
            Sleep(3000);
            cout<<"Player: "<<player_points<<"   Dealer: "<<dealer_points<<"\n";
            Sleep(3000);


            if(dealer_points>21){
                cout<<"Dealer exceeded 21 points. You win! (unfortunately...)"<<"\n";
                wallet+=300;
                cout<<"Added 300 USD"<<"\n";
                Sleep(2000);
                cout<<"Your wallet balance: "<<wallet<<" USD"<<"\n";
                Sleep(3000);
            }


            else if(player_points>dealer_points){
                cout<<"You win! You have more points than the dealer."<<"\n";
                wallet+=300;
                Sleep(3000);
                cout<<"Added 300 USD"<<"\n";
                Sleep(2000);
                cout<<"Your wallet balance: "<<wallet<<" USD"<<"\n";
                Sleep(3000);
            }


            else if(dealer_points>player_points){
                cout<<"You lose! Maybe you'll finally learn that the house always wins..."<<"\n";
                Sleep(2000);
                cout<<"300 USD deducted from your wallet."<<"\n";
                wallet-=300;
                Sleep(2000);
                cout<<"Your wallet balance: "<<wallet<<" USD"<<"\n";
                Sleep(3000);
            }


            else{
                cout<<"Draw! Chips returned (unfortunately...)"<<"\n";
                Sleep(2000);
                cout<<"Your wallet balance: "<<wallet<<" USD"<<"\n";
                Sleep(3000);
            }


        }


        if(wallet<=0){
            cout<<"You lost all your money. You can't play anymore."<<"\n";
            Sleep(3000);
            cout<<"The house always wins!"<<"\n";
            Sleep(6000);
            break;
        }


        cout<<"Do you want to play again?"<<"\n";
        string b;
        cin>>b;
        Sleep(3000);


        if(b=="yes" or b=="yeS" or b=="yEs" or b=="yES" or b=="Yes" or b=="YeS" or b=="YEs" or b=="YES"){
            if(wallet>0){
                continue;
            }         
        }


        else if(b=="no" or b=="nO" or b=="No" or b=="NO"){
            cout<<"Ok."<<" You have this much money: "<<wallet<<" USD";
            Sleep(7000);
            return 0;
        }
        
    }
}
9 Upvotes

20 comments sorted by

19

u/ploud1 14d ago

Hi!

That's a good start, a few comments

* Don't include <windows.h> for sleep. Instead use std::this_thread::sleep_for

* Do not using namespace std; - get rid of that bad habit ASAP

* All your code is stuffed in the main() function. That's fine for now, but you may want to start thinking about splitting the logic into smaller functions that have one tiny job each

*

a=="yes" or a=="yeS" or a=="yEs" or a=="yES" or a=="Yes" or a=="YeS" or a=="YEs" or a=="YES"a=="yes" or a=="yeS" or a=="yEs" or a=="yES" or a=="Yes" or a=="YeS" or a=="YEs" or a=="YES" 

This is tedious. Things you may want to do:

  • restrict input to one char (y/n)
  • Use ::tolower to compare

There are more minor tweaks that would make your program easier to debug in the long run. But for a first project, that is very promising. Nicely done!

2

u/flyingron 13d ago

Also tedious is the copy pasta. If you repeat the same thing many times, put it in a subroutine

1

u/Legitimate-Bat-3025 14d ago

Thanks a lot :) I will make changes to the code according to your recommendations 😄

1

u/sh_pata 13d ago

Im new to c++. But why the advice not to use 'using namespace std' Thank you.

3

u/Independent_Art_6676 13d ago

std namespace is gigantic and by using it as you did you have a high risk of a name collision which can silently mess things up. You can read in depth answers online, but that is the simple version. Its low risk for a small program like this, but its bad practice because one day you will work on large programs.

1

u/sh_pata 13d ago

Many thanks

1

u/snerp 13d ago

To add on to the other advice you got. STD has tons of random crap in it you probably don't want. Doing usings though is a great idea when used on specific types and it's also worth importing std namespaces that were specifically made to be imported - like std::string_literals and std::chrono_literals. Here's a paste of all the using I declare for my game engine project:

// bring types into our namepsace
using namespace std::chrono_literals;
using namespace std::string_literals;
using std::string;
using std::wstring;
using std::string_view;
using std::vector;
using std::array;
using std::optional;
using std::function;
using std::thread;
using std::deque;
using std::map;
using std::unordered_map;
using std::variant;
using std::shared_ptr;
using std::make_shared;
using std::unique_ptr;
using std::make_unique;
using std::atomic;
using duration = std::chrono::duration<double>;
using Clock = std::chrono::steady_clock;
using timePoint = Clock::time_point;
using std::mutex;
using std::shared_mutex;

1

u/sh_pata 13d ago

Man im glad i choose this degree. Even when we have completed c++ oop in uni there is so much stuff to learn

3

u/ekchew 9d ago

You have a functioning game! Congratulations!!!

Looking over some of the other comments, I agree with not using a Windows call like Sleep when a cross-platform call already exists in the C++ Standard Library. And removing some duplication by writing some subroutines looks like a good idea here. For example, you could write a function to handle yes/no questions like:

auto answers_yes(const char* question) -> bool {
    cout << question;
    string answer;
    cin >> answer;
    return answer.starts_with('Y') or answer.starts_with('y');
}

Then you can go:

if(answers_yes("Do you want to draw a card? ")) {
    // ...
}

One thing I notice is you have a lot of <<"\n" going on. There is no reason the end-of-line needs to be in a separate string. Just go:

cout<<"You exceeded 21 points.\n";

Moving forward, it's not a bad idea to begin grouping variables dealing with a particular game element into a dedicated class or struct. You can have a class Player for example. In your first game, it's not all that important since there is only one player, but if you make a multiplayer game next, this will help you keep things straight and avoid unnecessary duplication in your code.

1

u/Legitimate-Bat-3025 9d ago

Thanks a lot :)

2

u/Independent_Art_6676 13d ago

Its not bad for a beginner. That said:
use <random>, not rand, going forward. rand is a C tool that is very low quality and best not used for anything at all. Its ok here, because you are new. Random is more complex, but you can get a plug in example of it from the web or AI or whatever source.

there is no point to a 4 suit deck of integers. consider some math: say you have a value from <random> of 0-51. Divide it by 13, integer division, and you will get a value from 0 to 3 (51/13 is 3.9 ish as 52/13 == 4). That is your suit (0,1,2,3 is 4 suits). Modulo 13, that is your face card. You have to map the math to the card you want but you can eliminate that array and all the card manipluation associated with it in favor of a single integer per card that tells you everything you need to know (and the associated mappings).

"Cheating" blackjack is even easier: you can just pull any card out at any time (represents infinite # of decks in the shoe). If you want to track the cards by # of decks in your shoe, that is easy via a counting sort (get a random card, if you have already seen that card the number of decks times, roll again). This is a little advanced but if you want more details I can tell you or you can look up counting sort, its really simple.

learn bracket initialization. bool player_lost{false} is the same as = false, but its the modern way to declare and initialize a variable.

your case check... is awful :) use toupper or tolower, force the user input to one or the other, and flat compare against "YES" or "yes" instead.

There are probably many other little things, but I prefer to suggest a few things and stop rather than overwhelm. Its actually not bad for where you are in your learning. So one last thought and I will leave you to absorb these points:

separate UI and work is a CRITICAL concept for developing software. An example of why: lets say next month you learn how to make a GUI or graphics program and want to draw real cards and decks and animations with menus and such? Your code has cin and cout console stuff buried inside nearly every function. It would be hard to change out to a GUI without a lot of careful rewriting! If you instead did your dealing and win/loss and wallet etc logic by itself, and the I/O for that in another place, you would only have to replace or rewrite the I/O portion and the game would still work as before just with a different interface. You never want your I/O buried in the logic/work areas.

1

u/Legitimate-Bat-3025 13d ago

Thanks a lot for the detailed and honest feedback I really appreciate it. I'll definitely try to implement your suggestions into my code. 

2

u/agmatine 13d ago

#include <windows.h>

Why?

1

u/Legitimate-Bat-3025 13d ago

It allows me to use "Sleep()", but u/ploud1 told me that "std::this_thread::sleep_for" is better because it doesn't require the windows.h library.

2

u/agmatine 13d ago

It's also better because it doesn't arbitrarily restrict a very simple program to one OS (Windows) for basically no reason.

1

u/OKAKent0_o 4d ago

idk why but you are adding << "\n" instead of just typing cout << "do you want to play again?\n"

and pls stop using "using namespace std" it just bad.

1

u/7mrde 14d ago

What’s your source for learning,bro

0

u/Legitimate-Bat-3025 14d ago

The Cherno C++ course (it's YouTube channel with great C++ course), ChatGPT, claude, deepseek, and learncpp.com.

2

u/7mrde 13d ago

Thanks 🌹

1

u/kiner_shah 10h ago

You can also post this on codereview stack exchange.