Mandar um cafézinho para o programador:


Me ajude a transformar café em código!
Mostrando postagens com marcador Função. Mostrar todas as postagens
Mostrando postagens com marcador Função. Mostrar todas as postagens

Structs e Funções em C++

 Agora que já aprendemos como declarar e usar structs no tutorial passado, vamos ver neste como usar as estruturas de dados com as funções.

Structs em Parâmetros e Argumentos de uma Função

Quando explicamos que as structs e suas instâncias funcionam como variáveis (mas variáveis especiais, que você mesmo criou), isso vale também para funções.

Por exemplo, uma função que vai receber e retornar um inteiro, tem o seguinte cabeçalho:

  • int myFunction(int num);

Ou seja, especificamos o tipo de dado que a função vai receber. Até o momento trabalhamos com int, double, float, char, ponteiros...agora vamos usar o tipo de dado...que nós mesmos vamos criar!

Por exemplo, uma função que vai receber a struct Student, do tutorial anterior, e exibir seus elementos, tem o seguinte cabeçalho:

  • void showStudent(Student alumn);

Por exemplo, o programa abaixo exibe os dados de uma struct de nome 'alumn', do tipo 'Student':

#include <iostream>
using namespace std;

struct Student
{
   char name[50];
   float math,
         physics,
         science;
};

void showStudent(Student alumn)
{
    cout<<"\nDados:"<<endl;
    cout<<"Nome      : "<<alumn.name<<endl;
    cout<<"Matemática: "<<alumn.math<<endl;
    cout<<"Física    : "<<alumn.physics<<endl;
    cout<<"Ciência   : "<<alumn.science<<endl;
}

int main()
{
    Student Alex;

    cout<<"Nome: ";
    cin.get(Alex.name,50);

    cout<<"Nota em Matemática: ";
    cin >> Alex.math;

    cout<<"Nota em Física: ";
    cin >> Alex.physics;

    cout<<"Nota em Ciências: ";
    cin >> Alex.science;

    showStudent(Alex);

    return 0;
}

Só para dizer que não é exatamente igual como fizemos com outras variáveis, note que nossa função usar a struct Student...ou seja, ela já deve EXISTIR antes de declararmos a função, por isso colocamos a declaração da struct ANTES da função que vai usar ela, entendido?

Retornando uma Struct de uma Função

Assim como as funções servem para receber informações e performar tarefas específicas, elas também servem para retornar informações. Até o momento, fizemos retorno com int, double, char, void...mas as funções podem retornar qualquer tipo de dado, desde que a sua struct tenha sido declarada antes.

A função getStudent() não recebe nenhum parâmetro/argumento, mas retorna uma variável do tipo Student, e é usada para retornar uma struct preenchida, veja como funciona:

#include <iostream>
using namespace std;

struct Student
{
   char name[50];
   float math,
         physics,
         science;
};

void showStudent(Student alumn)
{
    cout<<"\nDados:"<<endl;
    cout<<"Nome      : "<<alumn.name<<endl;
    cout<<"Matemática: "<<alumn.math<<endl;
    cout<<"Física    : "<<alumn.physics<<endl;
    cout<<"Ciência   : "<<alumn.science<<endl;
}

Student getStudent()
{
    Student alumn;

    cout<<"Nome: ";
    cin.get(alumn.name,50);

    cout<<"Nota em Matemática: ";
    cin >> alumn.math;

    cout<<"Nota em Física: ";
    cin >> alumn.physics;

    cout<<"Nota em Ciências: ";
    cin >> alumn.science;

    return alumn;
}

int main()
{
    Student Geddy = getStudent();
    showStudent(Geddy);

    return 0;
}

Veja como nossa main() ficou enxuta, apenas declaramos um aluno, fazemos ele receber os dados da função getStudent(), e catapimbas, exibimos o seu conteúdo, tá feito.

Passagem por Valor e por Referência de Structs

Vamos criar uma função, chamada fillStudent() que tem como argumento uma instancia da struct Student, nessa função, vamos solicitar ao usuário os dados do aluno.

Nosso código fica:

#include <iostream>
using namespace std;

struct Student
{
   char name[50];
   float math,
         physics,
         science;
};

void showStudent(Student alumn)
{
    cout<<"\nDados:"<<endl;
    cout<<"Nome      : "<<alumn.name<<endl;
    cout<<"Matemática: "<<alumn.math<<endl;
    cout<<"Física    : "<<alumn.physics<<endl;
    cout<<"Ciência   : "<<alumn.science<<endl;
}

void fillStudent(Student alumn)
{
    cout<<"Nome: ";
    cin.get(alumn.name,50);

    cout<<"Nota em Matemática: ";
    cin >> alumn.math;

    cout<<"Nota em Física: ";
    cin >> alumn.physics;

    cout<<"Nota em Ciências: ";
    cin >> alumn.science;
}

int main()
{
    Student Geddy;
    fillStudent(Geddy);
    showStudent(Geddy);

    return 0;
}

Na main(), criamos o estudante 'Geddy' e enviamos para a fillStudent() para seus dados serem preenchidos. Porém, quando invocamos a função showStudent(), ela exibe o seguinte resultado:

Dados:
Nome      : Ћ���
Matemática: 3.0844e-41
Física    : 6.11017e-29
Ciência   : 3.0844e-41

Ou seja, os membros da struct 'Geddy' não foram preenchidos! O motivo disso é que a passagem de structs foi feita por valor!

Quando fazemos fillStudent(Geddy), a função pega essa instância, cria uma cópia internamente na função, e altera os valores nessa cópia, e não na struct original.

E como fazer para essa função alterar, de fato, os membros da struct? Simples, basta fazer uma passagem por referência, da struct:

#include <iostream>
using namespace std;

struct Student
{
   char name[50];
   float math,
         physics,
         science;
};

void showStudent(Student alumn)
{
    cout<<"\nDados:"<<endl;
    cout<<"Nome      : "<<alumn.name<<endl;
    cout<<"Matemática: "<<alumn.math<<endl;
    cout<<"Física    : "<<alumn.physics<<endl;
    cout<<"Ciência   : "<<alumn.science<<endl;
}

void fillStudent(Student &alumn)
{
    cout<<"Nome: ";
    cin.get(alumn.name,50);

    cout<<"Nota em Matemática: ";
    cin >> alumn.math;

    cout<<"Nota em Física: ";
    cin >> alumn.physics;

    cout<<"Nota em Ciências: ";
    cin >> alumn.science;
}

int main()
{
    Student Geddy;
    fillStudent(Geddy);
    showStudent(Geddy);

    return 0;
}

Apenas adicionamos & ao parâmetro 'alumn'. Agora, toda struct que mandarmos para a função fillStudent() será alterada.

Sobrecarga (overload) de Função Construtora

Neste tutorial de nossa apostila C++ Progressivo, vamos aprender sobre overloading, ou sobrecarga, da função constructor.

Sobrecarga de funções construtoras

Várias funções construtoras

Você foi contratado por uma universidade para criar um sistema para ajudar os professores, principalmente para trabalhar com as notas dos alunos.

Como você fez o curso C++ Progressivo, vai criar um sistema fantástico, com diversas classes e objetos comendo solto.
Mas vamos com calma.

Vamos criar uma classe de matemática, chamada Math. Pra simplificar, ela vai fazer apenas uma operação: fazer a média de duas notas, de um aluno, só isso.

A função construtor vai dizer logo de cara a média do aluno.
Veja como fica nosso código:

#include <iostream>
using namespace std;

class Math
{
    public:
        Math(double, double);
};


Math::Math(double g1, double g2)
{
    cout<<"Media: "<<(g1+g2)/2<<endl;
}


int main()
{
    Math ze(10, 8);

    return 0;
}

Resultado deu 9 certinho, tudo bonito e legal, e o aluno Zé ficou com uma ótima média.

E falando de experiência de mercado, é MUUUUUUITO comum os clientes ficarem pedindo alterações, novas funcionalidades etc. Se acostume, é sempre pedidos e reclamações.

Nesse caso, a universidade agora quer que você calcule a média de 3 notas.

Hora, é muito simples, só adicionar mais um parâmetro na lista da função construtor, criar o objeto com as 3 notas e mandar bala, já era, nosso código fica assim:

#include <iostream>
using namespace std;

class Math
{
    public:
        Math(double, double, double);
};


Math::Math(double g1, double g2, double g3)
{
    cout<<"Media: "<<(g1+g2+g3)/3<<endl;
}


int main()
{
    Math ana(10, 9, 10);

    return 0;
}

Tudo certinho e a Ana com média quase perfeita.

Mas aí chega sua universidade e diz: olha, tem aluno que vai fazer duas cadeiras e alunos que vai fazer três cadeiras, ou seja, seu sistema tem que calcular a média em ambos casos.

E agora? Como o construtor vai adivinhar? Uma hora calcula a média dividindo por 2 e no outro exemplo ele dividiu por 3 pois tinha uma variável a mais.

Criar uma classe para cada caso? Claro que não, pois isso é complicação.
Programação foi feito pra tornar o mundo mais fácil! É aí que entra a sobrecarga (overloading) de construidor.


A sobrecarga de Construtores

O C++ tem uma carta na manga: ele te permite criar quantos construtores quiser. Isso mesmo, funções com mesmo nome.
Mas uma coisa tem que ser diferente: a lista de parâmetros.

Exemplo de lista de parâmetros diferentes:

  • Math(double, double)
  • Math(double, int)
  • Math(int, double)
  • Math(double, double, double, float, char, int)
  • ...

Então, no nosso exemplo das médias, basta criar duas funçoes constructors, uma que recebe duas notas e a outra que recebe três notas:

#include <iostream>
using namespace std;

class Math
{
    public:
        Math(double, double);
        Math(double, double, double);
};

Math::Math(double g1, double g2)
{
    cout<<"Media: "<<(g1+g2)/2<<endl;
}

Math::Math(double g1, double g2, double g3)
{
    cout<<"Media: "<<(g1+g2+g3)/3<<endl;
}


int main()
{
    Math ze(10, 8);
    Math ana(10, 9, 10);

    return 0;
}

Veja como o C++ é inteligente. Quando você criou o objeto Zé, só passou dois argumentos, e o objeto invocou a função construidor que só trabalha com dois números.

Quando criou o objeto ana, chamou a outra função construidor, a que trabalha com três valores.
Ou seja, o C++ chama o construtor correto!
Isso é a sobrecarga de construtor.

Agora se você tiver dois construtores com a lista de parâmetros iguais, aí não tem como o C++ adivinhar que função você está querendo invocar, ok?

Vamos aprender um pouco mais sobre sobrecarga quando estudarmos uma classe super especial, a string, que faz loucuras e maravilhas com overloading.

Função Destruidor (destructor) em C++

 Neste tutorial de nosso curso de C++, vamos conhecer e aprender a usar as funções destruidoras.

A função Destruidor (Destructor)

No tutorial passado, falamos sobre a Função Construtor , que existe em toda classe e é executada sempre que um objeto é instanciado.

Analogamente, existe a função destruidor, que é executada apenas quando o objeto é destruído.

Para criarmos uma função destructor, basta definirmos uma função com o mesmo nome da classe, com o símbolo de til ( ~ ) antes. Vamos ver um exemplo, criando uma classe com construtor e destruidor:

#include <iostream>
using namespace std;

class Test
{
    public:
        Test();
        ~Test();
};

Test::Test()
{
    cout << "Constructor" << endl;
}

Test::~Test()
{
    cout << "Destructor" << endl;
}

int main()
{
    Test t;

    return 0;
}

O resultado vai ser as duas palavras na tela. Uma ocorre ao criarmos o objeto e outra ocorre quando o programa se encerra, e o nesse caso o destructor também é invocado.
E assim também como os construtores, toda classe tem destruidor. Mesmo que você não defina um, vai existir um padrão em branco, mas vai existir sempre.

Também não aceitam nenhum argumento, nem lista de parâmetros e não retornam nenhuma informação.

Para que serve a Função Destruidor ?

Basicamente, para fazer coisas que devem ser feitas quando um objeto deixa de existir.
Um exemplo muito comum é liberar memória que foi alocada dentro de um objeto.

No momento, estamos usando objetos bobinhos, pequenos, mas o normal é serem gigantes, com classes com centenas de variáveis e dezenas de funções. E lá dentro, é comum fazer alocação dinâmica de memória, e quando esse objeto deixar de existir, é uma boa prática liberar toda essa memória (principalmente em sistemas mais críticos com pouca memória, como seu relógio ou o sistema digital da sua geladeira).

Vamos supor que você criou um sistema pro banco, e quer sempre fazer um teste: se alguém acessou a classe Bank, instanciando algum objeto. Para isso, você define uma variável de escopo global chamada "spy" com valor inicial 0.

Pra verificar se algum objeto foi criado, faça com que 'spy=1' no destructor, veja:

#include <iostream>
using namespace std;

int spy=0;

class Bank
{
    public:
        ~Bank();
};


Bank::~Bank()
{
    spy = 1;
}

int main()
{
    Bank *b;
    b = new Bank;

    delete b;

    cout<<"Spy: " << spy << endl;
    return 0;
}

Vamos supor que seja uma classe gigante, com vários membros, várias coisas acontecendo...você criou um objeto, usou ele, fez tudo direitinho e tal. Então chega a hora de dar um delete nele, e nessa hora a função destructor vai ser executada.

O resultado vai ser 'Spy: 1' ali na main(), indicando que alguém mexeu nessa classe Bank. Ou seja, o destruidor, por sempre ser executado, vai executar a operação 'spy=1'.

Um outro exemplo função destructor, é se você criar um jogo e tiver um personagem (que é um objeto) e ele simplesmente morrer ou sair do jogo. Na sua função destruidor, você deleta o nome, tirar seus pontos, tira ele dos times, tira do ranking.

E etc etc, por ai vai pessoal, quase sempre tem coisas pra se fazer quando um objeto deixa de existir, ok?

Matrizes em Funções

Neste tutorial de nossa apostila de C++, vamos aprender como trabalhar com matrizes e funções, aprendendo a declarar, invocar e usar estes dois importantes tópicos, conjuntamente.

Como Passar Matriz para Função

No estudo de arrays, vimos que existem algumas maneiras de declarar o cabeçalho de funções com arrays como parâmetros, da seguinte maneira:
  • tipo func(tipo *array);
  • tipo func(tipo array[tamanho]);
  • tipo func(tipo array[]);

Ou seja, basta passar o ponteiro (*array - estudaremos mais na frente) ou o só com o par de colchetes em aberto (array[]).

No caso de arrays bidimensionais, precisamos especificar o número de colunas da matriz que estamos enviando:
  • void func(int arr[][COLUMN]);

Veja bem, o número de linhas não é obrigatório (até podemos passar), mas o número de colunas, sim.
Vamos declarar e inicializar uma matriz 2x2 e em seguida enviara para a função show(), que vai simplesmente exibir ela na forma de uma tabela, veja como fica nosso código:
#include <iostream>
using namespace std;

void show(int arr[][2], int row)
{
    for (int i=0 ; i<row ; i++){
        for(int j=0 ; j<2 ; j++)
            cout<<arr[i][j]<<"  ";
        cout<<endl;
    }
}

int main()
{
    int arr[][2]={ {1,2}, {3,4} };
    show(arr, 2);
    return 0;
}
Note algumas coisas importantes, no código acima.

Primeiro, passamos a matriz arr[][2] para a função, com o número de colunas.
Mas e o número de linhas? Como a função vai saber o tanto de linhas, para imprimir a tabela ?
Ela não sabe, por isso passamos outro parâmetro na função, o inteiro 'row'.

Matriz em C++: Passagem por referência

Toda passagem de dados para funções que envolvem arrays, é por referência. Sempre.
Ou seja, passou um array pra uma função? Ela vai acessar diretamente o array e seus dados, direto na memória. Não é uma cópia que vai pra função, não é passagem por valor, ok?

Isso quer dizer uma coisa: cuidado! As funções podem modificar seus arrays, lembre-se sempre disso.

O código abaixo introduz a função 'init', que vai receber um array e inicializar cada elemento dele, perguntando pro usuário:
#include <iostream>
using namespace std;
const int COLS = 3;
const int ROWS = 3;

void init(int arr[][COLS], int ROWS)
{
    for(int i=0 ; i<ROWS ; i++)
        for(int j=0 ; j<COLS ; j++){
            cout << "matrix["<<i+1<<"]["<<j+1<<"]: ";
            cin  >> arr[i][j];
        }
}

void show(int arr[][COLS], int ROWS)
{
    for (int i=0 ; i<ROWS ; i++){
        for(int j=0 ; j<COLS ; j++)
            cout<<arr[i][j]<<"  ";
        cout<<endl;
    }
}

int main()
{
    int arr[ROWS][COLS];
    init(arr, ROWS);
    show(arr, ROWS);
    return 0;
}
Para melhorar a organização, já definimos as linhas (ROWS) e colunas (ROLS) como variáveis globais do tipo constantes, para não ter perigo de ninguém, em algum local do código, alterar seus valores. Isso deixa o código mais claro e seguro, para manutenção.

Array de arrays em C++

Exercício de Matriz em C++

Crie uma matriz 4x4, onde cada linha representa as notas de um aluno, e cada coluna é uma matéria diferente. Você deve criar uma função que vai preenchendo as notas dos alunos, uma por uma, assinalando qual é a matéria e qual é o aluno.

Em seguida, seu programa deve exibir, de maneira organizada, as notas de cada aluno, bem como a média de cada um, a média da turma para cada matéria, e a média geral, de todos alunos de todas as notas.

Postem sua solução nos comentários.

Como usar Arrays em Funções

Neste tutorial de nossa seção de Arrays em C++, vamos aprender como trabalhar com arrays e funções, aprendendo como passar um array como argumento, como retornar e receber um array, como copiar, comparar e alterar arrays, usando funções.

Arrays como argumentos para Funções

O que diferencia, basicamente, uma variável inteira de um array de inteiros? Vejamos as declarações:
  • int num;
  • int num[2112];

Hora, é o par de colchetes, com um número dentro. Concorda?
Quando passamos um inteiro para uma função, seu protótipo fica:
  • show(int num); ou show(int);

Então, como você pode suspeitar, para passarmos um array como argumento, você pode fazer, no protótipo:
  • show(int num[]); ou show(int []);

Veja bem, você passa só com o par de colchetes, ok? Sem número dentro.
Já no código da função, o cabeçalho é com: show(int num[]);

Vamos dar um exemplo de código de um array que declaramos na main(), de inteiros, passamos pra função show() e ela exibe esses elementos:

Olhe como invocamos a função: show(num);
O nome do array é 'num', ok? Não faça: show(num[]) pra invocar a função.
#include <iostream>
using namespace std;

void show(int []);

int main()
{
    int num[]={10, 20, 30};

    show(num);

    return 0;
}

void show(int num[])
{
    int count;

    for(count=0 ; count<3 ; count++)
        cout<<"Elemento "<<count+1<<": "<<num[count]<<endl;
}
Pegou? Porém, aí tem um problema...a função 'já sabia' de antemão que o array tinha 3 elementos. Mas, ora, as funções não tem bola de cristal. Por isso, é comum e de praxe, passarmos junto com o array, o seu tamanho também, para as funções:
#include <iostream>
using namespace std;

void show(int [], int);

int main()
{
    int num[]={10, 20, 30, 40, 50};
    int size=5;
    show(num, size);

    return 0;
}

void show(int num[], int size)
{
    int count;

    for(count=0 ; count<size ; count++)
        cout<<"Elemento "<<count+1<<": "<<num[count]<<endl;
}

Quando estudarmos a classe vector, em STL, vamos ver tipos mais dinâmicos e poderosos, de arrays, e não precisaremos nos preocupar de informar o tamanho do array, pois será uma informação própria da estrutura que vamos usar.

Retornar Array: Passagem por referência

Vamos criar um array chamado num[], inserir alguns números.
Em seguida, vamos passar para a função doub(), que vai dobrar cada elemento do array, e imprimir ele dobrado.

Em seguida, imprimimos, agora na main(), novamente o array num:
#include <iostream>
using namespace std;

void doub(int [], int);

int main()
{
    int num[]={10, 20, 30, 40, 50};
    int size=5, count;

    doub(num, size);

    for(count=0 ; count<size ; count++)
        cout<<num[count]<<"  ";

    return 0;
}

void doub(int num[], int size)
{
    int count;

    for(count=0 ; count<size ; count++)
        num[count] *= 2;

    for(count=0 ; count<size ; count++)
        cout<<num[count]<<"  ";

    cout<<endl;
}
O resultado é:
20  40  60  80  100
20  40  60  80  100

Ora, veja só! Você passou um array pra função. Dentro dela, ela dobrou.
Quando voltou da função, pra main(), e você imprimiu novamente o array, ele estava dobrado.
Ou seja: sua função mexeu no array.

Embora você tenha passado somente o nome do array, ela alterou o array original. Ou seja: quando passamos um array pra uma função, essa passagem é por referência. Quando passamos o nome do array pra função, o C++ passa o endereço real do array. Assim, a função altera aquela posição da memória, diretamente, e não uma cópia do valor (como ocorre na passagem por valor).

Isso ocorre por questões de eficiência, visto que levaria muito tempo pra fazer uma cópia dos arrays passados para as funções (no dia-a-dia, trabalhamos com arrays muuuito grandes mesmo).
Ok? C++ passa o array por referência, não se esqueça!

Como copiar Arrays

Muitas vezes, queremos fazer algumas coisas com arrays, mas sem alterá-los.
Por exemplo, vamos supor que tenhamos um array 'num' de inteiros, e queiramos um outro array onde cada elemento seja o triplo do valor de cada elemento do array 'num'.

O que podemos fazer é primeiro criar uma cópia de 'num', vamos chapar de 'copy', e pimba, mandamos a 'copy' para uma função que triplica os elementos. Como a passagem é por referência, ela vai alterar os valores da 'copy' e nem vai ficar sabendo da existência de 'num', que fica inalterado.

Para fazer uma função 'copyArray' que faz uma cópia de um array, precisamos passar os dois arrays como argumento para a função, bem como o tamanho deles, que deve ser necessariamente o mesmo. Depois, basta copiar elemento por elemento, com um laço.

Veja como fica nosso código:
#include <iostream>
using namespace std;

void copyArray(int [], int [], int);
void triple(int [], int);

int main()
{
    int num[]={10, 20, 30, 40, 50}, copy[5];
    int size=5, count;

    copyArray(num, copy, size);
    triple(copy, size);

    cout<<"Array original: "<<endl;
    for(count=0 ; count<size ; count++)
        cout<<num[count]<<"  ";

    cout<<"\nArray triplicado: "<<endl;
    for(count=0 ; count<size ; count++)
        cout<<copy[count]<<"  ";

    return 0;
}

void copyArray(int num[], int copy[], int size)
{
    int count;

    for(count=0 ; count<size ; count++)
        copy[count] = num[count];
}

void triple(int copy[], int size)
{
    int count;

    for(count=0 ; count<size ; count++)
        copy[count] *= 3;

}
Resultado:
Array original:
10  20  30  40  50 
Array triplicado:
30  60  90  120  150

Se você realmente quiser preservar o array original 'num' e quiser mesmo garantir que ele não seja alterado, pode declará-lo e usá-lo como sendo do tipo const:
No cabeçalho: void copyArray(const int [], int [], int);
Na declaração da função: void copyArray(const int num[], int copy[], int size) {...}
No declaração do array: const int num[]={10, 20, 30, 40, 50};

Jogo em C++: Adivinhe o número sorteado

Neste tutorial, vamos resolver um exercício de nossa lista de funções.

Game em C++: Adivinhe o número sorteado

Crie um jogo onde o  computador sorteie um número de 1 até 100. A cada vez que você chutar um número, ele deve dizer se você chutou abaixo do valor real, acima ou se acertou. Ao final, diz o número de tentativas que você teve e se bateu o record ou não. Ah, ao final de cada rodada, o programa pergunta se você quer jogar novamente ou não, exibindo o record atual.

Código comentado do jogo em C++

Bem, vamos lá, vamos com calma e cuidado, que hoje vamos passar das 100 linhas de código.
Mas não se assuste, um grande programa nada mais é que vários pequenos programinhas divididos, entre outras coisas, entre funções que fazem coisas específicas.

Inicialmente, declaramos a variável record, que vai armazenar o número record de tentativas que o usuário acertou em uma rodada. Ela inicia em 0. Já já você vai entender o motivo.

Em seguida, criamos a função limpa(), que vai limpar a tela a cada rodada.

A função gerar() faz com que o computador gere um número aleatório, de 1 até 100, e retorna ele.

A função palpite() vai servir para receber o palpite do usuário. Ela recebe um inteiro, o número de tentativas que o usuário já realizou, pra exibir: "tentativa 1", "tentativa 2", "tentativa 3"...

A função checa() vai comparar o número que você chutou com o número gerado pelo computador.
Se você acertar, ele retorna 1, se errar retorna 0.

A função dica() vai receber o seu palpite e o número gerado, e vai te dar a dica, se o seu palpite foi maior, menor ou igual ao gerado pelo computador.

A função encerra() exibe as informações finais do jogo.
Ela pega o número de tentativas que você realizou, e diz se você bateu o record ou não. Inicialmente, se a variável record for igual 0, essa variável vai pegar o número de tentativas que você levou pra acertar, no seu primeiro jogo. Depois, ela avalia se suas tentativas foram menores que o valor de 'record', se for, ela diz que você bateu o record e esse é o novo valor da variável record. Se não, mostra o record.

Por fim, a função continuar() pergunta se você deseja jogar de novo ou não.

Funções explicadas, vamos pra lógica do jogo, na main().
Inicialmente, declaramos 3 variáveis, a que vai armazenar o número de tentativas em cada rodada, a que vai armazenar o número gerado em cada rodada e a que vai armazenar os palpites do usuário.

No primeiro DO WHILE, vamos controlar as rodadas que serão jogadas. Ao fim de cada iteração, chamamos a função continuar() dentro do WHILE, pra saber se devemos começar outra rodada ou não.

Dentro de cada rodada, primeiro limpamos a tela.
Em seguida, zeramos o número de tentativas, afinal, é uma nova rodada.

Exibimos o record atual, através da variável 'record'. E aviamos que geramos o número a ser adivinhado.

Agora, vamos ficar em um looping: pergunta um chute, diz se errou ou acertou, dá a dica...pede outro chute, avisa se acertou ou não, dá dica...pede outro número...até a pessoa acertar.

Para isso, vamos usar outro laço DO WHILE. Esse vai rodar sempre que a pessoa errar. Errou? Roda de novo. Quem controla isso é a função checa(). 

Dentro desse DO WHILE interno, primeiro incrementamos o número de tentativas.
Pegamos o palpite do usuário, então damos a dica (que também avisa quando ganha).

Por fim, vai pra função checa(), que retorna 1 se a pessoa acerta (termina o looping) ou 0 se ela erra (roda de novo).

Encerrado esse looping interno, chamamos a função encerra(), que vai dizer em quantas tentativas você acertou, se bateu o record ou não.

Depois disso, vai no while externo, que vai perguntar se você deseja jogar de novo ou não.
Simples, não?

Código do Jogo em C++

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int record=0;

void limpa();       // Limpa a tela
int gerar();        // Gera o número aleatório
int palpite(int);   // Pega o palpite do usuário
int checa(int, int);// Checa se errou ou ganhou
void dica(int, int);// Da a dica se é maior ou menor
void encerra(int);  // Exibe informações da partida
int continuar();    // Pergunta se quer jogar de novo

int main()
{
    int tentativas,
        gerado,
        palp;

    do{
        limpa();
        tentativas=0;
        cout<<"Record até o momento: "<< record <<" tentativas!"<<endl;
        gerado = gerar();
        cout<<"\nNúmero sorteado! "<<endl;

        do{
            tentativas++;
            palp = palpite(tentativas);
            dica(gerado, palp);
        }while(checa(gerado, palp) != 1);

        encerra(tentativas);
    }while( continuar() );
    return 0;
}
void limpa()
{
    if(system("CLS")) system("clear");
    //int n;
    //for(n=1 ; n<10 ; n++)
      //  cout<<endl;
}
int gerar()
{
    unsigned seed = time(0);
    srand(seed);

    return 1+rand()%100;
}

int palpite(int tent)
{
    int palp;
    cout<<"\nTente adivinhar o número de 1 até 100."<<endl;
    cout<<"Tentativa "<<tent<<":"<<endl;
    cin >> palp;

    if(palp>0 && palp<=100)
        return palp;
    else
        cout<<"Só vale números de 1 até 100"<<endl;
}

int checa(int gerado, int palp)
{
    if(gerado == palp)
        return 1;
    else
        return 0;
}

void dica(int gerado, int palp)
{
    if(palp<gerado)
        cout<<"ERROU! Seu palpite foi MENOR que o número sorteado!"<<endl;
    else
        if(palp>gerado)
            cout<<"ERROU! Seu palpite foi MAIOR que o número sorteado!"<<endl;
        else
            cout<<"Ahhhhh muleeeeque!"<<endl;
}

void encerra(int tent)
{
    cout<<"\nVocê acertou em "<<tent<<" tentativa(s)!"<<endl;

    if(record==0)
        record = tent;

    if(tent<=record){
        cout<<"Parabéns! O record é seu!"<<endl;
        record = tent;
    }
    else
        cout<<"O record ainda é de "<<record<<" tentativa(s)"<<endl;
}

int continuar()
{
    int cont=1;

    cout<<"\nJogar de novo?"<<endl;
    cout<<"0. Sair"<<endl;
    cout<<"1. De novo!"<<endl;
    cin >> cont;

    return cont;
}

Ajude o C++ Progressivo

Que tal apoiar e fazer crescer o ensino da programação no Brasil ?

Ajudar nosso país a crescer e se desenvolver cada vez mais, tecnologicamente?

Clica abaixo pra saber mais!

Apoiar o Projeto Progressivo