Tutorial: Programando um jogo da memória – Parte 2: Embaralhando as cartas

Começamos a desenvolver um novo game nesse início de ano.

Criamos o projeto de um jogo da memória e vimos como ele ficará na tela.

Daremos continuidade no desenvolvimento incluindo a funcionalidade de embaralhamento das cartas.

Criamos no último tutorial o projeto do nosso jogo no Cocos2d-x. Fizemos algumas modificações no código de forma que seis cartas com logos de diferentes empresas de desenvolvimento de jogos fossem mostradas na tela. Cada carta era representada por um sprite. Eu peguei as imagens das cartas na Internet e os sprite sheets eu mesmo criei para vocês utilizarem. Caso vocês queiram saber como criar sprite sheets, deem uma olhada nesse tutorial.

Implementaremos nesse tutorial o sistema de embaralhamento das peças, para que diferentes cartas estejam dispostas em diversos locais a cada início de jogo. Para que isso realmente aconteça, precisaremos de um vetor de seis posições com valores inteiros que armazena quais cartas estão em quais lugares. Também precisaremos de um vetor de strings (variáveis de texto) que determina qual valor numérico corresponde a qual logo. Com o valor numérico zero, por exemplo, temos a carta virada. Dessa forma, abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

static char nomes[7][16];

int valorCartas[6];

logo abaixo dessa:

cocos2d::CCSprite* cartas[6];

Salve o arquivo “HelloWorldScene.h”. Acabamos de criar um vetor nomeado “valorCartas”, que armazena em forma de valor inteiro qual é a logo que está em cada posição. Criamos também um vetor de strings, chamado “nomes”, que armazena os nomes dos sprite frames que representa cada valor numérico inserido em “valorCartas”. Note que ainda não demos valores a nenhum dos dois vetores. Primeiramente, vamos inicializar o vetor “nomes”. Abra o arquivo “HelloWorldScene.cpp” e adicione as seguintes linhas de código:

char HelloWorld::nomes[7][16] = {

    “CartaVirada.png”,

    “Atari.png”,

    “Blizzard.png”,

    “EAGames.png”,

    “Konami.png”,

    “Ubisoft.png”,

    “Valve.png”

};

logo abaixo dessa:

using namespace CocosDenshion;

Do jeito que criamos o vetor “nomes”, o valor numérico 0 corresponde ao sprite frame da carta virada, o valor 1 corresponde ao sprite frame da logo da Atari e assim por diante. Agora implementaremos o sistema de embaralhamento com a escolha aleatória de três empresas que aparecerão no jogo e com o preenchimento do vetor “valorCartas” com valores numéricos que representam as três empresas escolhidas. Adicione as seguintes linhas de código:

int empresas[3],i,j,aux,aux1,aux2;

long num = time(NULL);

for(i=0;i<3;i++) {

    srand(num);

    num = rand();

    empresas[i] = num%6 + 1;

    for(j=0;j<i;j++)

        if(empresas[j]==empresas[i]) {

            i–;

            break;

        }

}

for(i=0;i<5;i=i+2) {

    HelloWorld::valorCartas[i] = empresas[i/2];

    HelloWorld::valorCartas[i+1] = empresas[i/2];

}

logo abaixo dessa:

CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(“SpriteSheet.plist”);

Note que, no primeiro “for”, nós escolhemos aleatoriamente três empresas distintas das seis disponíveis no sprite sheet. Caso seja escolhida, por coincidência, uma empresa já sorteada, o algoritmo sorteia novamente outra empresa. Isso fará com que o jogo mostre somente empresas distintas. Os valores numéricos das três empresas distintas são armazenadas no vetor temporário nomeado “empresas”. No último “for”, nós preenchemos o vetor “valorCartas” com os valores numéricos das três empresas escolhidas aleatoriamente. Esse preenchimento é realizado de forma que as duas primeiras cartas sejam a primeira empresa sorteada, as duas próximas cartas sejam a próxima empresa sorteada e assim por diante. Obviamente, isso não é um conjunto de cartas embaralhado. Para embaralhar as cartas no vetor “valorCartas”, adicione as seguintes linhas de código logo abaixo dessas adicionadas anteriormente:

for(i=0;i<15;i++) {

    srand(num);

    num = rand();

    aux1 = num%6;

    srand(num);

    num = rand();

    aux2 = num%6;

    aux = HelloWorld::valorCartas[aux1];

    HelloWorld::valorCartas[aux1] = HelloWorld::valorCartas[aux2];

    HelloWorld::valorCartas[aux2] = aux;

}

Com o vetor “valorCartas” devidamente preenchido, nós embaralhamos os valores nele contidos com a escolha de dois valores inteiros aleatórios entre 0 e 5. Esses valores sorteados correspondem às posições do vetor que terão seus valores numéricos trocados. Se realizarmos consecutivas trocas de valores dentro do vetor, teremos, no final, um vetor embaralhado. Note que fizemos um total de 15 trocas, o que já é mais do que o suficiente.

Para finalizar, criaremos os sprites que correspondem a cada carta na tela com o sprite frame representado por um valor numérico existente em cada posição do vetor “valorCartas”. Dessa forma, modifique a seguinte linha de código:

HelloWorld::cartas[0] = CCSprite::createWithSpriteFrameName(“Atari.png”);

por essa:

HelloWorld::cartas[0] = CCSprite::createWithSpriteFrameName

  (HelloWorld::nomes[HelloWorld::valorCartas[0]]);

, a seguinte linha de código:

HelloWorld::cartas[1] = CCSprite::createWithSpriteFrameName(“CartaVirada.png”);

por essa:

HelloWorld::cartas[1] = CCSprite::createWithSpriteFrameName

  (HelloWorld::nomes[HelloWorld::valorCartas[1]]);

, a seguinte linha de código:

HelloWorld::cartas[2] = CCSprite::createWithSpriteFrameName(“Blizzard.png”);

por essa:

HelloWorld::cartas[2] = CCSprite::createWithSpriteFrameName

  (HelloWorld::nomes[HelloWorld::valorCartas[2]]);

, a seguinte linha de código:

HelloWorld::cartas[3] = CCSprite::createWithSpriteFrameName(“CartaVirada.png”);

por essa:

HelloWorld::cartas[3] = CCSprite::createWithSpriteFrameName

  (HelloWorld::nomes[HelloWorld::valorCartas[3]]);

, a seguinte linha de código:

HelloWorld::cartas[4] = CCSprite::createWithSpriteFrameName(“EAGames.png”);

por essa:

HelloWorld::cartas[4] = CCSprite::createWithSpriteFrameName

  (HelloWorld::nomes[HelloWorld::valorCartas[4]]);

e a seguinte linha de código:

HelloWorld::cartas[5] = CCSprite::createWithSpriteFrameName(“CartaVirada.png”);

por essa:

HelloWorld::cartas[5] = CCSprite::createWithSpriteFrameName

  (HelloWorld::nomes[HelloWorld::valorCartas[5]]);

Se você salvar as modificações que realizamos no código e o compilar, perceberá que, a cada nova execução do jogo, uma nova sequência de empresas será mostrada na tela. Para os curiosos de plantão, a Figura 1 mostra a execução do jogo na sua versão atual, com a escolha aleatória de três empresas e o embaralhamento das cartas.

Figura 1 - Jogo executando

Figura 1 – Jogo executando

Vimos nesse tutorial como programar o sistema de embaralhamento das cartas. Para isso, criamos um vetor de valores inteiros que armazena a sequência de logos existentes nas cartas a serem mostradas. Cada valor inteiro corresponde a uma empresa e vimos que precisávamos sortear três empresas a serem inseridas no jogo. Logo após, nós preenchemos o vetor com os valores numéricos que representam as três empresas sorteadas.

Por último, embaralhamos os valores contidos no vetor com a escolha de duas posições aleatórias para a troca dos valores contidos nelas. Com quinze trocas seguidas, nós temos o vetor devidamente embaralhado para que seja possível a criação das cartas de forma embaralhada. No próximo tutorial nós implementaremos o sistema de escolha das cartas pelo jogador.

Um grande abraço e até mais.

Santiago Viertel

Santiago Viertel

Formado em Bacharelado em Ciência da Computação (UDESC), mestre e doutorando em Análise de Algoritmos (UFPR). Foi programador da Céu Games por 8 anos. Possui a preferência por jogos de estratégia e de tiro em primeira pessoa. Jogando bastante DotA 2, Left 4 Dead 2 e Age of Empires II HD.

Send this to a friend