Simple game using pointers01

From GPWiki
Jump to: navigation, search

About this page

This code was originally developed to be an example of a "real" application where the power of pointers can be seen. Unfortunately, the code ended up being longer than desired, but it can still be easily understood after some time. Other parts of the code can be useful to beginners as well.

This is what I wrote several years ago, when I made this example. A lot of time has passed since, and I'm programming a little better now. anyway, the problem is that now I realize how bad this example is. It's really bad. I don't have the time to properly fix it now, but I believe that the only real use of this piece of code is to exercise how many errors you can spot in the code. So be careful when studying it.

Source

#include <string.h>
#include <math.h>
#include <iostream>
 
struct Unit
{
    int health;
    int attack;
    int defense;
    char name[12];	  
} gameunits[6];
 
// this function will print all the units names on screen, if they are alive.
// It will also separate them in player one and two. Note that the separation is
// done based on the unit position in the array (the array elements 0, 1 and 2
// belong to player one, and 3, 4 and 5 to player 2)
void PrintUnits() 
{
	std::cout <<"Player 1\n";
    for(int i = 0;i < 6;i++)
    {
    	if(i == 3)std::cout <<"\nPlayer 2\n";
    	std::cout << i + 1 << " - ";
    	if (gameunits[i].health > 0) std::cout << gameunits[i].name; 
    	else std::cout << "DEAD"; 
        std::cout <<"\n";	
    }
    	std::cout <<"\n";
}
 
// This function will calculate the damage a unit should recieve based on that
// unit's defense value and the attack value of the ATTACKER. No matter the
// values passed, the damage will aways be at least 1, to prevent some possible
// problems with while() structures
int damageTaken(int attack, int defense)
{
	float damageFactor = 1;
	damageFactor = pow(1.2, (attack - defense)); // pow() is the same as 1.2^x
	if(damageFactor <= 0.125f) damageFactor = 0.125f; // just to make shure that
                          //there will aways be damage done. note that 0.125 * 8 = 1
	return 8 * damageFactor; // 8 was choosed just to make values range between
        // 1 and 8 when the defense value is bigger than attack value
}
 
// This funtion will make the two units figth until one of them (or in rare cases
// both of them) is dead. Note that the units are passed by reference, using
// pointers. this is because this way the function can update the unit health by
// itself
void FightUnits(Unit* attacker, Unit* defender)
{
        // this loop will go on until one or both units are dead. It will compute
        // each unit's damage (the attacker and the defender) based on unit's values
        // note that it doesen't matter who is the attacker and who is the defender,
        // they will both use the same formula.
        // Also, note that damageTaken() function will aways return at least 1. This
        // way, this loop will aways come to an end, no matter what the values where.
	while (attacker->health > 0 & defender->health > 0)
	{
		defender->health -= damageTaken(attacker->attack, defender->defense);
		attacker->health -= damageTaken(defender->attack, attacker->defense);
	}
 
        if (attacker->health <= 0 & defender->health<=0)
        {
            std::cout << "Whoa! Both units got killed!\n";
		}
		else
		{
            if (attacker->health <= 0) std::cout << attacker->name << " was killed\n";	
            if (defender->health <= 0) std::cout << defender->name << " was killed\n";
        }     
}
 
// This function will check if the player is alive or not. If he isn't then we
// must close the program to avoid any errors.
bool playerlives(int player)
{
    bool UnitLives = false;
	if (player == 1)
	{
		for (int i = 0;i < 3;i++)
		{
            if(gameunits[i].health > 0) UnitLives = true;
		}
	}
	if (player == 2)
	{
		for (int i = 3;i < 6;i++)
		{
            if(gameunits[i].health > 0) UnitLives = true;
		}
	}
	return UnitLives;
	//well, sorry for that little code hack. What is
	// happening here is that the UnitLives variable will keep track of the life
	// of the player units. So, if at least one of the units is alive, then
	// UnitLives = true. If some units are alive, then the player is alive, and
	// therefore, we must return true. Only when no unit is alive, then UnitLives
	// will remain false, and the function will return false
}
 
// This is our core funtion for the game, it will be called by an loop in the
// program int main() funtion.
int engine()
{
    Unit* attacker = &gameunits[0];   // some initals values to prevent errors
    Unit* defender = &gameunits[3];   // some initals values to prevent errors
    PrintUnits();
    if (playerlives(1)&playerlives(2))
    {
        std::cout <<"Type 1, 2 or 3 to choose the attacker: ";
        int number;
        std::cin >> number;
        if (number > 0 & number < 4)
        {
        	attacker = &gameunits[number - 1];
        	if (attacker->health <=0)
        	{
        	std::cout << "This unit is Dead!\n";
        	return 0;        		
            }
        }
        else
        {
        	std::cout << "Bad number!!\n";
        	return 0;
        }
        std::cout <<"Type 4, 5 or 6 to choose the target: ";
        std::cin >> number;
        if (number > 3 & number < 7)
        {
        	defender = &gameunits[number - 1];
        	if (defender->health <=0)
        	{
        	std::cout << "This unit is Dead!\n";
        	return 0;        		
            }
        }
        else
        {
        	std::cout << "Bad number!!\n";
        	return 0;
        }
        defender = &gameunits[number - 1];
        FightUnits(attacker, defender);
	}
 
}
 
int main()
{
    { // this block will create all units and their data.
    gameunits[0].health = 250; gameunits[0].attack = 8;
    gameunits[0].defense = 8;  strcpy(gameunits[0].name,"Wyvern");
 
    gameunits[1].health = 60; gameunits[1].attack = 4;
    gameunits[1].defense = 3; strcpy(gameunits[1].name,"Swordman");
 
    gameunits[2].health = 80; gameunits[2].attack = 7;
    gameunits[2].defense = 8; strcpy(gameunits[2].name,"Knight");
 
    gameunits[3].health = 160; gameunits[3].attack = 8;
    gameunits[3].defense = 10; strcpy(gameunits[3].name,"Stone Golem");
 
    gameunits[4].health = 130; gameunits[4].attack = 6;
    gameunits[4].defense = 5;  strcpy(gameunits[4].name,"Troll");
 
    gameunits[5].health = 100; gameunits[5].attack = 6;
    gameunits[5].defense = 3; strcpy(gameunits[5].name,"Orc");
    }
 
    while (playerlives(1)&playerlives(2)) // while both players are alive, the game goes on
	{
		engine();
	}
 
    if(playerlives(1)) std::cout << "CONGRATULATIONS! you have killed stuff!\n";
    // if player 1 is alive, he won! so we congratulate him
    else std::cout << "You Die!! Looks like you need better strategy!\n";
    // else: this means he is not alive...
 
    system("pause"); // sometimes, when the program closes, windows will close the
    // console with it, so we need this line to prevent that
	return 0;
}