My First Game

Hey,

Here is a game I wrote in C++ as a project to teach myself the syntax once and for all. It is a small game, kinda arcade style, but still "fun." Some of you might want to try it :D Anyway, while my syntax is correct, and everything works, there are some things I am not to happy about. You might notice I'm using a lot of "goto"s, and that is because I just didn't know how else to do it. If anyone could tell me a better way to do it, I would be very grateful. Also, if you find anything else you would have done different (probably a lot) then please tell me, and I will do my best to fix it.

Thanks, code to follow:

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <cstdlib>
#include <iostream>
#include <ctime>

using namespace std;
    //ATTACK VARIABLES-----------------------------------
    int kill_count = 0;
    int playerhp = 100;
    int playeratk;
    int enemyvalue = 280;
    int enemyhp = 100;
    int enemyatk;
    char fightorflee;
    int playwp_atk;
    int playwp_def;
    //Money Variables------------------------------------
    int money = 850;
    int playerxp = 0;
    int buywhich;
    //Weapon Variables-----------------------------------
    string weaponID1 = "Sword";
    int weaponID1_atk = 5;
    int weaponID1value = 600;
    string weaponID2 = "Axe";
    int weaponID2_atk = 10;
    int weaponID2value = 1000;
    string weaponID3 = "Shield";
    int weaponID3_def = 3;
    int weaponID3value = 300;
    //Menu Variables-------------------------------------
    int menu_desicion;
    string mainmenu = "Welcome to 'Fight Till You Die' V.1.2.0.  -  Copyright 2009||Cbeppe :)\n\n[MAIN MENU]\nFrom here you can decide whether to fight or to buy a new weapon.\n\n";
   
    //START MAIN FUNCTUION-------------------------------
   
int main(int argc, char *argv[], int attack_or_defend )
{
    main:
    int enemy_hp_org;
    enemy_hp_org = enemyhp;
    cout << mainmenu << "KILL STREAK:\nYou have killed " << kill_count << " enemies.\n\n(1)Weapons Store || (2)Play\n";
    cin >> menu_desicion;
    //STORE MENU------------------------------------------
   if(menu_desicion == 1){
                    system("CLS");
                cout << "Here you can buy weapons!\n\nNOTE:\nATTACK VALUES ONLY COUNT WHEN YOU CHOOSE 'ATTACK' DURING BATTLE.\nDEFENSE VALUES ONLY COUNT WHEN CHOOSING 'DEFEND'\n\nThe weapons that are availiable are:\n\n"; 
cout << "(You have " << money << " coins)\n"<< "\n(1) Sword  - Attack: +5  Defense +0  - Cost: 600\n(2) Axe    - Attack: +10 Defense +0  - Cost: 1000\n(3) Shield - Attack: +0  Defense +3  - Cost: 300\n";
                cout << "\n\nOr press (4) to go back to the main menu\n";
                cin >> buywhich;
                switch(buywhich){
                                case 1:
                                     if(money >= weaponID1value){
                                     money -= weaponID1value;
                                     playwp_atk = weaponID1_atk;
                                     cout << "You have bought a " << weaponID1 << "!\nYou have " << money << " coins left.\n\n\n\n\n";
                                     system("PAUSE");
                                     system("CLS");
                                     goto main;
                                     }
                                     else{
                                             cout << "\n\nYou do not have enough money to buy this weapon.\n";
                                             system("PAUSE");
                                             system("CLS");
                                             goto main;
                                             }
                                     break;
                                case 2:
                                     if(money >= weaponID2value){
                                     money -= weaponID2value;
                                     playwp_atk = weaponID2_atk;
                                     cout << "You have bought a " << weaponID2 << "!\nYou have " << money << " coins left.\n\n\n\n\n";
                                     system("PAUSE");
                                     system("CLS");
                                     goto main;
                                     }
                                     else{
                                             cout << "\n\nYou do not have enough money to buy this weapon.\n";
                                             system("PAUSE");
                                             system("CLS");
                                             goto main;
                                             }
                                     break;
                                case 3:
                                     if(money >= weaponID3value){
                                     money -= weaponID3value;
                                     playwp_def = weaponID3_def;
                                     cout << "You have bought a " << weaponID3 << "!\nYou have " << money << " coins left.\n\n\n\n\n";
                                     system("PAUSE");
                                     system("CLS");
                                     goto main;
                                     }
                                     else{
                                             cout << "\n\nYou do not have enough money to buy this weapon.\n";
                                             system("PAUSE");
                                             system("CLS");
                                             goto main;
                                             }
                                     break;
                                default:
                                        cout << "\n\n\n\n";
                                        system("CLS");
                                        goto main;
                                        }
                                       
   }
   //END STORE MENU ------------------------------------------------------
   else{
    cout << "You are under attack! You must fight!\n" << "Your Hitpoints:" << playerhp << "\nEnemy Hitpoints:" << enemyhp;
    //START ATTACK LOOP --------------------------------------------------
while (enemyhp >= 1 && playerhp >= 1){
      cout << "\n\nAttack (1) or Defend (2)\n";
      srand(time(NULL));
      cin >> attack_or_defend;
      system("CLS");
      //ATTACK/DEFEND SWITCH----------------------------------------------
      switch(attack_or_defend){
      case 1:
           if(enemyhp <= 0 || playerhp <= 0){
                      goto dead;}
                      else{
      playeratk = (rand() % 22 + playwp_atk);
      enemyatk = (rand() % 23 + 4);
      enemyhp = enemyhp - playeratk;
      cout << "\n\nYou did " << playeratk << " damage.\nEnemy hitpoints left: " << enemyhp;
      playerhp = playerhp - enemyatk;
      cout << "\n\nYou lost " << enemyatk << " damage. \nYour hitpoints: "<< playerhp << "  \n\n";
      }
      break;
     
      case 2:
           if(enemyhp <= 0 || playerhp <= 0){
                      goto dead;}
                      else{
      playeratk = (rand() % 3 + 1);
      enemyatk = (rand() % (6 - playwp_def) + (3 - playwp_def));
      enemyhp = enemyhp - playeratk;
      cout << "\n\nYou did " << playeratk << " damage.\nEnemy hitpoints left: " << enemyhp;
      playerhp = playerhp - enemyatk;
      cout << "\n\nYou lost " << enemyatk << " damage. \nYour hitpoints: "<< playerhp << "  \n\n";
      }
      break;
     
      default:
      cout << "Press (1) to attack and (2) to defend.";
      }
}
//END ATTACK LOOP -------------- START AFTER FIGHT CALCULATION -----------------------------------
if(playerhp > 0){
            playerxp = playerxp += 25;
            int loot = (enemyvalue + playerxp);                //IF PLAYER WINS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            money = money + loot;
            kill_count++;
           cout << "\n\nYOU WIN!\nCoins Collected from Enemy: " << loot << "\nNew Balance: " << money << " coins\n\n";
           cout << "Your hitpoints have been restored\nYour next enemy will be harder!\n\n\n";
           system("PAUSE");
           }
           else{
                dead:
                playerxp = playerxp -= 10;                     //IF PLAYER LOSES!!!!!!!!!!!!!!!!!!!!!!!!!!!
                kill_count = 0;
                cout << "\n\nYou are dead...\n\nYour health has been restored.\nHopefully, your next enemy will be easier!\n\n\n";
                system("PAUSE");
                }
}
//END AFTER FIGHT CALCULATIONS ----------- START CLEANUP PHASE --------------------------------
enemyhp = enemy_hp_org + playerhp;
playerhp = 100;
system("CLS");
goto main;
//END PROGRAM --------------------------------------------------------------------------------------------
}
Last edited on
Congrats for your first game. :-)
You only need to call srand once, at the start of your program.

all of the other control structures can be used instead of goto, depending on the situation you're using goto in.

If you're using goto to repeatedly loop through the same code, then you could use while or for instead.

If you're using goto to control the flow of code, then you should look at using if and switch statements

Since you're already using all of these control structures, in addition to goto, it's clear you already understand how to use them, so it's just a matter of continuing to apply that knowledge instead of resorting to goto. One other thing you need to start doing to assist in this area is start using functions to clean up your code. This will make it more readable and easier to modify, and make it easier to see the high level program flow, and apply the proper control structures to get the flow you want.

Also look into file access so instead of having all those item/object values hard coded, they're stored in a text file that gets read in. Then you can tweak values, even add new items, without having to modify the code. Modern games use this concept quite heavily, allowing the programmers to focus their time on adding more game features, and allowing non-programmers to focus on adding actual content to the game world itself.
Thank you very much for your replies.

@jRaskell:
About your suggestions, I tried a lot of different combinations with srand() and rand() and this is the one that worked best for me. As far as I can see, I'm only using srand() once, but you might have been referring to the rand() function?

I'm using goto to jump to different places in the code. Mostly, I'm using it in the Store menu, redirecting players back to the Main menu after they are done. My menus are constructed like branches where the goto statement is used at the end of a branch to bring a user back to the "trunk." I am not completely sure, but I think I might have been able to use functions for it. Unfortunately, I'm not sure how.

I actually thought about using files, but decided against it since I have been sending it back and forth to people via IM. If I was making a big game, or working with a team, the idea is definitely a good one.

Again, thank you both for you comments. Very much appreciated ;)
closed account (S6k9GNh0)
Concerning goto statements: People tend not to use goto functions very often you'll soon find out. It usually ends up in buggy and unorganized code. In certain situations, it's simply easier to use a goto statement but that rarely comes across. In your situation, goto statements are confusing and seems to not be needed.

Concerning massive amounts of variables: I don't feel these are neccessary in your game. In MANY MANY games, people avoid the allocation of new variables such as your by defining them with macros and letting the compiler hard code them wherever you use your macro. To add to that, for security (sort of) and clarification, if you want to keep variables, I suggest you make them constant unless they plan to be changed so as to tell anyone who looks at your code including yourself that the variables are for strict hard-coded configuration of your program.

I see an overuse of system();. For the sake of good practice, I really do suggest you not use it for pause or cls and find alternative and faster methods to accomplish these tasks.
Last edited on
@ computerquip:

Thanks for taking the time to read through my code. I already know that using goto statements is a bad practice, but what I need to know is how you would replace them. For example, here in my first switch statement, I use a goto to get back to the main menu, where I was before. How would you elimiate that goto?

1
2
3
4
5
6
7
8
9
case 1:
      if(money >= weaponID1value){
          money -= weaponID1value;
          playwp_atk = weaponID1_atk;
          cout << "You have bought a " << weaponID1 << "!\nYou have "; 
          cout << money << " coins left.\n\n\n\n\n";
          system("PAUSE");
          system("CLS");
          goto main;



I will be sure to read up on Macros - I'm not really sure how to use them yet, but that will change. About the "System() overuse," do you have any suggestions as to how to replace them? In the beginning I used the "cin >> a;" to wait for the user, but that requires them to press 2 buttons. System("PAUSE") only requires one button press.

Again, thanks for looking into my case.
Last edited on
You're calling srand on line 112, which is inside both your attack loop (while loop) and your main loop (goto loop).
To do your kind of switch and stuff, you would generally do something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
while(true) {
    //get input
    switch(input) {
        case 1:
            shop();
            break;
        case 2:
            fight();
            break;
        default:
            std::cout<<"Not valid input.\n";
    }
}
What did you write your code with? In which text editor? It might pay
to invest in a good one because they can help with neatness as it may
make your code easier to follow.

A few things you may like to try:
* Whenever you enter new level of scope, or open a {, indent your code
until you exit that level of scope, or until you close the code block with };
* Try spacing things out, so if you declare a group of variables, and then
start making function calls put some white space in between them. You
may also like to do this by relevance.
* You may also find it easier to read if you hand warp your code. Although
most text editors have word wrap functionality, not all do (this forum
being one)

some examples of this
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
67
68
69
70
71
bool loop = true;   /* Main loop control variable */

/* 
 * numbers 
 */ 
int num01 = 1;
int num02 = 2;
int num03 = 3;
int num04 = 4;

/* 
 * a long string
 */ 
std::string str = "This is a really long string. \n" +
            "However, instead of just writing it all out on one line" +
            "I am word wrapping it by myself for ease of reading.\n" +
            "I can do this because the line does not end until the compiler" +
            " sees a \";\" character. Until then I can continue appending " +
            "strings together to be assigned to my variable, str.\n\n" +
            "P.S. Notice how I indented the subsequent lines a reasonable " +
            "amount? Because I have done this I can easily see that I " +
            "Have not ended the prvious line. My text editor helped alot.\n\n";
            /* std::string str */

int main()
{

    /*
     * some variables
     */
    int     aNewInt     = 0;
    char    aNewChar    = 'a';
    string  aNewString  = "aNewString";
    float   aNewFloat   = 0f;

    /*
     * player stats
     */
    int     damage      = 4;
    int     hp          = 10;
    int     attack      = 1;

    /*
     * enemy stats
     */
    int     enemy_dam   = 2;
    int     enemy_hp    = 15;
    int     enemy_att   = 2;

    while ( loop == true )
    {
        /*
         * sending strings to stdout
         */
        std::cout << str;
        std::cout << "New string\n";
        std::cout << "A more detailed string\n\n";

        if (...)
        {
            ...
        } /* if (...) */
        else
        {
            ...
        } /* if (...) else */
    } /* while ( loop == true ) */

    return 1;
} /*main() */


With your use of goto, If you changed the main label into a while
loop, close it on line 169 and delete your other goto loops and it
should work in the same way. Because the goto main statments
are the last line of every route of that switch, then if you instead leave
them, it will hit the break statement and move to the end, which is
the end of an if statement. As the rest of the code is in the
else that corresponds to the if statement you will go strait to
the end of the while loop.

Try watching the flow of your code and you may discover that you will get
to where you want to go using a few more if statements. Perhaps in
different places.

One last thing

 
playerxp = playerxp -= 10;  

that was on line 159 and I see you have done it in at least one other spot.

what you want to do is remove 10 from playerxp. To do that all you have to
do is playerxp = playerxp - 10;. The -= operator makes
it easier to do by removing the right hand side from the variable on the left.
So, the following two lines of code are the same.
1
2
playerxp = playerxp - 10;
playerxp -= 10;


What you have done still works, but is essentially assigning -10 to the same
variable twice. Hope that helped a little. Sorry if I seemed a bit condescending.
Last edited on
closed account (S6k9GNh0)
Macros are simple creatures. It basically says, replace x with y whenever you see x. It's completely precompilation which means it's done before compilation and has zero affect on your program. Although macros are known to be buggy and have bad reactions (sort of. It really depends on how you use them.) To accomplish macros, we use preprocessor directives such as #define BUFFERSIZE 255 . For more info, see http://cplusplus.com/doc/tutorial/preprocessor/

For more on why system() is evil: http://www.cplusplus.com/forum/articles/11153/
For ways to clear your screen without system: http://www.cplusplus.com/forum/articles/10515/
For ways to pause the current console program: http://www.cplusplus.com/forum/articles/7312/
Last edited on
doesnt work:(
do we just put it in C++?
what type of project?
if you type exit in console it spams fighting. not sure why but it does.
Here is a way you can bunch your separate menus/tasks into functions and remove the gotos:

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
67
68
69
70
71
72
73
74
#include <cstdlib>
#include <iostream>
#include <ctime>

using namespace std;

// set variables
bool dead(false);

void do_shop()
{
	cout << "Shop Menu" << endl;
	cin >> which;
	buy_weapon(which);
}

void do_attack()
{
	// do stuff
}

void do_defend()
{
	// do stuff
}

void do_play()
{
	cout << "Play Title" << endl;

	while(enemyhp >= 1 && playerhp >= 1)
	{
		cout << "Play Menu" << endl;
		cin >> action;
		
		switch (action)
		{
			case 1:
				do_attack();
				break;
			case 2:
				do_defend();
				break;
			default:
		}
	}

	calculate_fight();
}

int main(int argc, char *argv[], int attack_or_defend)
{
	srand(time(NULL)); // only once

	cout << "Game Title\n";
	
	while(!dead)
	{
		cout << "Main Menu\n";
		cin >> menu_desicion;
		
		switch(menu_desicion)
		{
			case 1:
				do_shop();
				break;
			case 2:
				do_play();
				break;
		}
	}

	return 0;
}

Topic archived. No new replies allowed.