Agnor's HQ

Aula 09 - Enumerações e Estruturas

Conceitos-Chave:

- enumerações, como forma de atribuir um sentido lógico ao código
- estruturas, como um conjunto de propriedades de uma variável

Enumerações

As enumerações servem para ajudar a fazer um código mais lógico. Imaginemos que temos uma função que recebe o parâmetro:

int cor;

Decidíamos, para representar cores em números inteiros, convencionar o valor do azul como 1, o do vermelho como 2 e o do verde como 3. Assim, para representar a cor azul faríamos algo do tipo:

cor = 1;

Teríamos então que memorizar uma tabela com as cores, ou andar sempre com uma quando programamos... Felizmente, existem as enumerações:

#include <iostream>
using namespace std;

enum CORES { AZUL = 1, VERMELHO = 2, VERDE = 3 };   
//não se esqueçam das chavetas, NEM DO PONTO E VÍRGULA

int VerificarCor(CORES cor_a_ver);  //função para verificar qual a cor

int main()
{
    CORES cor;  //vejam! CORES é um tipo de variável

    cor = AZUL;

    VerificarCor(cor);

    cor = VERMELHO;

    VerificarCor(cor);

    VerificarCor(VERDE);

    cout << AZUL << " " << VERMELHO << " " << VERDE << " " << cor << endl;

    cin.get();
    return 0;
}

int VerificarCor(CORES cor_a_ver)
{
    if (cor_a_ver == AZUL)
    {
        cout << "A Cor que escolheu foi Azul" << endl;
    }

    else if (cor_a_ver == VERMELHO)
    {
        cout << "A Cor que escolheu foi Vermelho" << endl;
    }

    else if (cor_a_ver == VERDE)
    {
        cout << "A Cor que escolheu foi Verde" << endl;
    }
}

Exemplo 9.1 - Enumerações: Cores

Acho simples de perceber, afinal as enumerações existem para simplificar a escrita (e posterior leitura) do código.
Resta só dizer que uma enumeração é uma variável constante, ou seja, o valor de AZUL, VERMELHO e VERDE não poderá ser alterada.
Não se esqueçam que, se fizerem cout << AZUL; irá aparecer '1' e não "AZUL", mas isso é obvio...

Dica:

No exemplo acima fizemos:

enum CORES { AZUL = 1, VERMELHO = 2, VERDE = 3 };

Mas poderíamos ter feito:

enum CORES { AZUL = 1, VERMELHO, VERDE};

Que faz rigorosamente o mesmo efeito, pois basta atribuir valor a uma variável, que as outras são incrementadas ( += 1)
Também poderíamos fazer:

enum CORES { AZUL, VERMELHO, VERDE};

Mas desta vez AZUL seria igual a 0 e não a 1

Uso de enumerações em jogos

Dentro de programação de jogos existem vários usos para enumerações. Por exemplo, é comum usar enumerações para representar o teclado, uma vez que, em algumas bibliotecas, o valor da tecla premida pelo utilizador está expresso em números (em alguns casos em hexadecimal). Assim:

enum Teclas
{ ... KEY_LEFT = 112, KEY_RIGHT = 113, ... };

Teclas t;
if(t == KEY_LEFT)
{ moverNaveEsquerda(); }

Os valores são inventados, mas processa-se algo semelhante nos jogos. Em vez de fazermos if(t == 112) podemos fazer if(t == KEY_LEFT) que é muito mais simples.

Outro uso para enumerações dentro dos jogos é no ciclo de jogo. São criados vários estados (CORRER, PARADO, NOVO_JOGO, MENU_JOGO, por exemplo) e sempre que quisermos mudar de um estado para o outro, bastaria modificar a variável que guarda os valores. Veremos isto mais adiante, quando criarmos o primeiro jogo em 2D.

Estruturas

Uma estrutura pode ser considerada como um esboço das propriedades de uma determinada variável. Imaginemos que temos 3 personagens num jogo: Nillight, Laveius e Nysker. Cada personagem tem as seguintes variáveis: int hp (Health Points = Pontos de Saúde), int mp (Magic Points = Pontos de Magia) e

Criaremos então uma estrutura chamada Personagem:

#include <iostream>
using namespace std;

struct Personagem
{
    int hp, mp; //podem fazer isto; explicação abaixo.

};  //Olhem o ponto e vírgula ; !!!!!!!

int main()
{
    //diferentes maneiras de preencher as variáveis:
    Personagem Nillight = { 30, //HP
                            10, //MP
                            };
    Personagem Laveius = { 50, 7 };

    Personagem Nysker;

    Nysker.hp = 20; //dá para fazer isto
    Nysker.mp = 60;

    cout << "HP de Nillight e de " << Nillight.hp << " e o MP e de " << Nillight.mp << endl;
    cout << "HP de Laveius e de " << Laveius.hp << " e o MP e de " << Laveius.mp << endl;
    cout << "HP de Nysker e de " << Nysker.hp << " e o MP e de " << Nysker.mp << endl;

    cin.get();
    return 0;
}

Exemplo 9.2 - Estrutura Personagem

Uma estrutura define-se da seguinte forma:

struct nome_da_estrutura {
  //...variáveis
};

Aviso:

Nunca se esqueçam do ';' depois de fecharem as chavetas '{}'.

Para podermos aceder às variáveis que estão dentro da estrutura, utilizamos um ponto a separar a variável "estruturada" e a propriedade:

Personagem teste;
teste.hp = 0;
cout << teste.hp;

Podemos criar estruturas para praticamente tudo. No exemplo seguinte vou representar uma estrutura de um quadrado (figura geométrica):

#include <iostream>
using namespace std;

struct Quadrado
{
    int lado;
    int area;
};

int calcularArea(Quadrado quadrado)
{
    return (quadrado.lado * quadrado.lado);
}

int main()
{
    Quadrado square;
    square.lado = 4;

    square.area = calcularArea(square);

    cout << "Area do Quadrado: " << square.area << endl;

    cin.get();
    return 0;
}

Exemplo 9.3 - Estrutura Quadrado - Mostrar a área de um quadrado

Para trabalho de casa, podem criar funções para alterar ou mostrar facilmente os vários atributos. Assim o protótipo da função para visualizar o HP de uma personagem seria:

int getHP(Personagem personagem);

E para modificar o valor seria:

void setHP(int hp, Personagem personagem);

Jogo - Hall of Monsters

É um jogo simples, criado por mim, baseado nas aventuras em modo de texto (estilo MUD). Pode-se dizer que é um resumo das aulas até agora:

/*
 *  Exemplo 9.4 - Hall of Monsters
 *  Propriedade de http://agnor.gamedev-pt.net
 *
 *  Autor :	João Portela aka Agnor
 *  Data  :	20/02/2004 a 21/02/2004
 *  Desc  : Hall of Monsters - jogo-tutorial
 *
 */

#include <iostream>
#include <windows.h> //para usar o GetTickCount();
using namespace std;

/************************************
**************ESTRUTURAS*************
************************************/

struct Personagem
{
    int hp; //os pontos de vida
	int mp; //Pontos de Mana
	int max_hp; // vai ser usada para recuperar o personagem no fim de cada partida
	int max_mp; // como dito em cima.....
	int forca; // a forca do personagem
};

struct Monstro
{

	int hp; // HP do monstro
	int forca; //forca do monstro
	//monstros não necessitam de MP
	char *nome; // necessário para podermos alterar o valor do nome sempre que quisermos...
	//será explicado na aula 11 - referências e apontadores
};

/////////////////////////////////////
///////////Variáveis/////////////////
/////////////////////////////////////

Personagem player = {50, 7, 50, 7, 5};
Monstro ORC = { 40, 10, "Orc" };
Monstro LIZARD = { 60, 15, "Lizard" };
Monstro SHADOW = { 100, 23, "Shadow" };
Monstro BAHAMUT = { 140, 31, "Bahamut" };
Monstro ULTIMA = { 1000, 100, "Ultima" }; // tentem matar este :P

/*							*
	Declarações das funções
*							*/

int menuJogo();
int chamarBatalha(Monstro monstro);
int menuBatalha(Monstro monstro);
int MonstroIA(Monstro monstro);
int ganhou();
int perdeu();
int getRandom(int de,  int ate);

//que main pequeno não é?

int main()
{

	menuJogo();

	cin.get();
	return 0;
}

/* chamarBatalha(monstro);
Desc: chama uma Batalha para um determinado monstro ( ex: chamarBatalha(SHADOW); )
*/

int chamarBatalha (Monstro monstro)
{
	cout << "\n\nApareceu um " << monstro.nome << endl;
	menuBatalha(monstro);
	return 0;
}

/* Cria o menu de Batalha ( utilizada por chamarBatalha(monstro); )
*/

int menuBatalha (Monstro monstro)
{
	int escolha;
	cout << "\n\nSeu HP: " << player.hp << '/' << player.max_hp << endl;
 	cout << "Seu MP: " << player.mp << '/' << player.max_mp << endl;
	cout << "Escolha um ataque:" << endl;
	cout << "\n1 - Ataque normal" << endl;
	cout << "2 - Fogo" << endl;
	cin >> escolha;

 	switch (escolha)	{

 	case 1:
  		monstro.hp -= player.forca * 7;
  		cout << "\nVoce atacou!" << endl;
  		break;

	case 2:
		monstro.hp -= player.forca * 10;

		player.mp -= 7;
  		cout << "\nVoce usou o fogo!" << endl;
    	break;

  	default:
 		cout << "\nComando nao conhecido..." << endl;
 		menuBatalha(monstro); 
 		//estamos a utilizar recursividade nas funções: o menu vai ser chamado de novo
 		break;
	}

	if ( monstro.hp <= 0 )
		ganhou(); //se só tiver uma instrução, um if não precisa de ter chavetas { ... }
	else
		MonstroIA(monstro);
	return 0;
}

// A intelegência artificial do Monstro. Para dar mais hipoteses aos jogadores
// só há 25% do Monstro utilizar o ataque especial

int MonstroIA(Monstro monstro)
{
	int random;
	random = getRandom(1, 4);
	switch (random)
	{
		case 1:
		case 2:
		case 3:
			cout << "\n\n" << monstro.nome << " atacou!" << endl;
			player.hp -= monstro.forca;
			break;
		case 4:
			cout << "\n\n" << monstro.nome << " usou o seu ataque especial" << endl;
			player.hp -= monstro.forca * 2;
			break;
	}

	if (player.hp <= 0)
	perdeu();

 	else
 	menuBatalha(monstro);

	return 0;
}

//a popular função getRandom

int getRandom(int de,  int ate) {

    srand(GetTickCount());
    int random = ( rand() % ate ) + de;
    return random;
}

// perdeu :(((((

int perdeu()
{
	cout << "\nPerdeu... Na proxima vez vais ter mais sorte :(" << endl;
	menuJogo();
	return 0;
}

//ganhou... e também subiu de nível :PPPP

int ganhou()
{
	cout << "\n\n\nWee ganhou!!!!! e subiu de nivel :P" << endl;
	player.forca += 2; //as modificações para "subir de nivel"
  	player.max_hp += 10;
   	player.max_mp += 7;
   	player.hp = player.max_hp; //recuperar a energia
   	player.mp = player.max_mp;

	//esperar.....
 	cin.get();

	menuJogo();

 	return 0;
}

// o menu do jogo

int menuJogo()
{
	int escolha;

 	cout << "\nEscolha um adversario:" << endl;
 	cout << "\n1 - Orc" << endl;
  	cout << "\n2 - Lizard" << endl;
   	cout << "\n3 - Shadow" << endl;
    cout << "\n4 - Bahamut" << endl;
    cout << "\n5 - ULTIMA" << endl;

    cin >> escolha;

    switch (escolha)
    {
    	case 1:
     		chamarBatalha(ORC);
       		break;
        case 2:
        	chamarBatalha(LIZARD);
       		break;
         case 3:
         	chamarBatalha(SHADOW);
       		break;
         case 4:
         	chamarBatalha(BAHAMUT);
       		break;
         case 5:
         	chamarBatalha(ULTIMA);
       		break;
		default:
  			cout << "Comando nao conhecido.... tente outra vez\n\n" << endl;
  			menuJogo();
  			break;
    }

     return 0;
}

Exemplo 9.4 - Hall of Monsters

É um jogo bastante simples e com alguns bugs (erros lógicos), mas demonstra tudo o que aprendemos.

Experimentem fazer uma modificação do programa, adicionando mais monstros, corrigindo bugs, adicionando ataques.

Podem usar o email rpgplus@iol.pt para me mandarem o jogo para corrigir (e quem sabe publicar no site as modificações :)

Final da aula 09 de C++:

Próxima aula -> C++ 10 - Alcance e Tempo de Vida de Variáveis

Fazer o download do código fonte dos exemplos da aula WinZip
Fazer o download da aula em PDF (Brevemente)

Ir para o topo da página

Aulas de C++

Anúncios