PRG29003: Introdução a C++

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar

Próxima aula


Apresentação

Programas precisam armazenar e organizar dados de forma eficiente, o que depende do tipo de problema a ser resolvido, da quantidade de dados a serem manipulados, e da forma com que dados são representados. Para isso existe o conceito de estruturas de dados, que são justamente formas de armazenar e organizar dados. Algumas estruturas de dados corriqueiras são:

  • Filas
  • Pilhas
  • Listas
  • Tabelas de dispersão (hash)
  • Árvores

... porém há muitas outras (faça uma pesquisa se ficou curioso).

Em PRG2 serão estudadas as estruturas de dados acima listadas, as quais são de uso comum em programas em geral. O estudo será orientado a pequenos projetos, com a intenção de mostrar possíveis usos dessas estruturas.

  • Projeto 1: (fila e pilha)
  • Projeto 2: (lista)
  • Projeto 3: (árvore)
  • Projeto 4: (tabela hash)

O estudo dessas estruturas será dividido em duas etapas:

  1. Uso das estruturas de dados: as estruturas de dados são apresentadas, destacando-se suas características, operações e aplicações. Os projetos serão desenvolvidos usando estruturas de dados já existentes.
  2. Implementação das estruturas de dados: As estruturas de dados serão implementadas, de forma a funcionarem como as estruturas usadas na etapa 1. Como resultado, cada equipe terá ao final criado uma biblioteca de programação contendo suas estruturas de dados. Os projetos criados na etapa 1 devem ser compilados e funcionar usando essa biblioteca, sem necessitar qualquer modificação.

Aquecimento: revisão sobre PRG1

Antes de iniciar com PRG2, uma pequena atividade deve ser feita para revisar algumas coisas vistas em PRG1. Nada melhor que um pequeno problema feito em partes

  1. Escreva um programa que leia uma frase pelo teclado, e informe a posição da primeira ocorrência da letra A ou a nessa frase.
  2. Modifique o programa para que mostre as posições de todas as ocorrências da letra A ou a.
  3. Modifique o programa para que leia o conteúdo de um arquivo ao invés de ler somente uma frase pelo teclado.
  4. Modifique o programa para que mostre as posições de todas as ocorrências de cada uma das letras do alfabeto (a até z). Letras que não aparecem na frase devem ser ignoradas. O resultado a ser mostrado deve ser primeiro as posições da letra a, depois da letra b, e assim por diante até letra z.

A linguagem C++

A linguagem de programação a ser usada se chama C++. Como indica o nome, essa linguagem é uma extensão à linguagem C, de forma a aderir ao paradigma de orientação a objetos. Como esse assunto será visto em profundidade na 4a fase, na disciplina de POO (Programação Orientada a Objetos), faremos um uso mais superficial dessa linguagem. Quer dizer, usaremos algumas de suas construções, mas não nos deteremos em seus aspectos teóricos. O objetivo de usar C++ é introduzir essa linguagem, que será usada em próximas disciplinas.


Mas o que tem de especial a linguagem C++ ? Muita coisa, se comparada à linguagem C. Veja este exemplo sobre string em ambas linguagens:

Linguagem C Linguagem C++
#include <stdio.h>
#include <string.h>

int main() {
  char nome[32], sobrenome[32];
  char nomeCompleto[64];

  printf("Nome: ");
  scanf("%32s", nome);
  printf("Sobrenome: ");
  scanf("%32s", sobrenome);
  
  strcpy(nomeCompleto, nome);
  strcat(nomeCompleto, " ");
  strcat(nomeCompleto, sobrenome);

  printf("Nome completo: %s\n", nomeCompleto);

  return 0;
}
#include <iostream>
#include <string>

using namespace std;

int main() {
  string nome, sobrenome, nomeCompleto;

  cout << "Nome: ";
  cin >> nome;
  cout << "Sobrenome: ";
  cin >> sobrenome;

  nomeCompleto = nome + " " + sobrenome;

  cout << "Nome completo: " << nomeCompleto << endl;
}


Obs: para compilar o programa C++, grave-o em um arquivo com extensão .cpp ou .cc e compile-o assim (supondo que o arquivo se chame main.cpp):

g++ -std=c++11 -o exemplo main.cpp


Algumas características básicas de C++ podem ser identificadas:

  • A estrutura de um programa em linguagem C é muito parecida em C++: assim como na linguagem C, em C++ um programa possui a função main. A execução do programa inicia nessa função. Argumentos de linha de comando podem ser passados pelos parâmetros argc e argv. Outras funções podem existir no programa, sendo declaradas e implementadas como se faria em C.
  • Declaram-se variáveis em C++ da mesma forma que em C: variáveis são declaradas precedidas pelo seu tipo, como neste exemplo:
    int x;
    float y;
    bool ok;
    
    Os tipos nativos da linguagem C são os mesmos em C++ (int, char, double, float, short, long), porém em C++ há também o tipo bool, que aceita os valores true e false. Outro detalhe: em C++ variáveis podem ser declaradas em qualquer linha de uma função, e não apenas no início de funções ou bloco de sentenças (aquelas contidas entre chaves).
  • As estruturas de controle da linguagem C são as mesmas em C++: estruturas de controle if, while, do {} while, e for são usadas em C++ da mesma forma que em C. Existem algumas facilidades no uso de for em C++, que serão mostradas no momento apropriado.
  • Entrada e saída pode ser feita como em C, ou no estilo C++: as funções de entrada e saída da biblioteca C padrão podem ser usadas em um programa C++ (printf, fprintf, scanf, fscanf, fgets, e outras). No entanto, em C++ existe uma outra forma de entrada e saída denominada streams. Em alguns casos o uso de streams é mais simples que as funções da biblioteca C, mas há situações em que o estilo C é mais prático. A escolha de qual forma de entrada e saída usar fica por gosto e experiência do programador (para enxergar quando uma ou outra é melhor ;-). No estilo C++:
    • A leitura de dados do console (entrada padrão) se faz por meio da variável predefinida cin (console input). Essa variável cin funciona como um arquivo somente leitura, e é similar a stdin da biblioteca C padrão. O exemplo a seguir mostra como ler um valor por meio do operador >> (operador leitura), o qual converte os caracteres lidos para o tipo de dados da variável onde será armazenado o valor.
      int ano;
      
      cin >> ano;
      
      Outras formas de ler dados serão vistas mais adiante na disciplina.
    • A escrita de dados no console (saída padrão) se faz por meio da variável predefinida cout (console output). Essa variável também funciona como um arquivo, porém somente escrita, e é similar a stdout da biblioteca C padrão. A escrita formatada de dados se faz por meio do operador << (operador escrita).
      int n = 3;
      double pi = 3.1416;
      
      cout << "Após " << n << "voltas ";
      cout << " o ângulo é " << 2*n*pi << endl;
      
      Outras formas de escrever dados serão vistas mais adiante
  • Cadeias de caracteres (string) em C++ são MUITO mais simples que em C: em C++ existe um novo tipo de dados para representar strings, tornando desnecessário (na maiorias das vezes) o uso de vetores de caracteres. Na verdade, string em C++ é mais que um tipo de dados, pois oferece não somente uma representação de sequência de caracteres, como também um conjunto de operações que podem ser feitas sobre uma sequência. Em C++, string é um exemplo de uma classe (análoga ao tipo de dados, porém conceitualmente muito mais ampla), e suas variáveis são chamadas de objetos. Em princípio isso pode ser deixado de lado, usando-se string como mais um tipo de dados. O exemplo a seguir mostra uma concatenação de strings, feita de forma muito mais simples que em C:
    string nome = "Dmitri";
    string sobrenome = "Ivanovich Nekhlyudov";
    
    string nome_completo = nome + ' ' + sobrenome;
    
    count << nome_completo << endl;
    
    Mais informações sobre string


Há mais detalhes que diferem as linguagens C e C++, mas a principal diferença entre elas reside no paradigma de programação com que foram concebidas. A linguagem C segue o paradigma de programação estruturada, e C++ segue o paradigma de orientação a objetos. Em C++, um programa é pensado como um conjunto de objetos que se relacionam com o objetivo de apresentar a solução imaginada.


Em uma aula posterior teremos um primeiro contato com classes e objetos.

Uso do IDE CLion

Na disciplina recomenda-se usar o ambiente integrado de desenvolvimento (IDE - Integrated Development Environment) CLion. Esse software auxilia na escrita de programas, pois integra um editor de texto, um gerenciador de projetos, compilador e depurador, além de ajuda on-line e outras facilidades. Os exemplos durante a disciplina serão disponibilizados como projetos do CLion, mas não é obrigado utilizá-lo - pode-se trabalhar diretamente com outro IDE (NetBeans, https://www.eclipse.org/downloads/ Eclipse], ...), ou mesmo um editor de textos (ex: gedit, pluma) e o compilador C++ (g++) e depurador (gdb), porém essa última opção é um pouco mais trabalhosa ...

Para instalar o CLion siga estes passos:

  1. Crie uma conta de estudante no site da empresa Jet-Brains, a qual fornece o CLion. Ali você deverá informar seu email. A empresa enviará então uma mensagem para esse email com instruções para criação da conta. Essa conta será necessária para obter uma licença de uso acadêmico do CLion.
  2. Instale os programas necessários para compilação C e C++:
    sudo apt update
    sudo apt install build-essential
    
  3. Faça o download do instalador do CLion (ele tem cerca de 480 MB):
  4. Descompacte o instalador em algum subdiretório (ex: sua pasta pessoal). Em seguida, execute um terminal de texto (no Ubuntu, clique em Atividades e, em seguida, digite terminal).
  5. No terminal, entre na pasta do CLion e ali execute o programa de instalação:
    cd clion-2019.2
    bin/clion.sh
    
    ... e siga as instruções. Não são necessários plugins adicionais (isso é sugerido durante a instalação).


Exercícios

Resolva estes exercícios para experimentar a linguagem C++:

  1. Escreva um programa que calcula a área de um triângulo, apresentando o resultado na tela. Qualquer valor que o programa precisar para o cálculo deve ser obtido pelo teclado.
  2. Escreva um programa capaz de descobrir o valor de um número que você tenha imaginado. O programa deve interagir sucessivamente com você, até descobrir o número. Ao final, ele deve informar quantas tentativas precisou para descobrir o número. OBS: o número deve ser um inteiro entre 0 e 100.
    Dica: é possível descobrir o número em no máximo 7 tentativas se for usada uma busca binária.
  3. Escreva um programa que teste se um número é primo. Ao final, seu programa deve informar se o número é primo ou não.
  4. Escreva um programa que fatore um número inteiro. Esse programa deve mostrar todos os números primos que dividem o número a ser fatorado.
  5. Escreva um programa que calcule a integral definida aproximada de uma curva, cujos pontos estão contidos em um arquivo cujo nome é informado como primeiro argumento de linha de comando. Cada linha desse arquivo contém as coordenadas de um ponto em um espaço bidimensional, como neste exemplo:
    0 3
    0.5 1.25
    1.0 0.0
    1.5 -0.75
    2.0 -1.0
    2.5 -0.75
    3.0 0.0
    3.5 1.25
    4.0 3.0
    
    ... sendo a primeira coluna a abscissa, e a segunda coluna a ordenada. Seu programa deve calcular a área entre a curva e o eixo da abscissa (i.e. a integral definida dessa curva).
Esqueleto de uma solução

Classes e objetos


Uma classe se assemelha a um tipo de dados, do ponto de vista da declaração de variáveis. A rigor existem diferenças conceituais relevantes, mas, para ajudar a compreensão, perdoa-se essa grande simplificação. Em exercícios anteriores se usou a classe string, que é bastante corriqueira em C++. O exemplo a seguir relembra a declaração e uso de uma variável string:

string nome, sobrenome, nome_completo;

cout << "Digite o nome: ";
cin >> nome;
cout << "Digite o sobrenome: ";
cin >> sobrenome;

nome_completo = nome + ' ' + sobrenome;

cout << "Nome completo: " << nome_completo;

Nesse exemplo, as variáveis nome, sobrenome e nome_completo são da classe string, e por isso são chamadas de objetos. Cada classe possui atributos, que representam valores internos, e operações que podem ser realizadas. Isso é mais fácil de entender observando o que se pode fazer com objetos string. Em um objeto, os atributos da classe string (os quais não precisamos saber quais são !) armazenam a cadeia de caracteres contida nesse objeto. As operações, por outro lado, devem ser conhecidas para que possam ser utilizadas.

#include <string>
#include <iostream>

using namespace std;

int main() {
  string titulo = "The Shawshank Redemption";

  cout << "Filme: " << titulo << endl << endl;
  cout << "Nome do filme tem " << titulo.size() << " caracteres" << endl;
  cout << "Primeira letra do título é: " << titulo[0] << endl;

  while (true) {
    int pos = titulo.find(' ');
    cout << "Palavra do título: " << titulo.substr(0, pos) << endl;
    if (pos == string::npos) break;
    titulo.erase(0, pos+1);
  }

}

O programa acima, após ser compilado e executado, apresenta este resultado na tela:

Filme: The Shawshank Redemption

Nome do filme tem 24 caracteres
Primeira letra do título é: T
Palavra do título: The
Palavra do título: Shawshank
Palavra do título: Redemption

A novidade nesse pequeno programa reside no uso de operações de string. Cada operação é invocada por meio de um método da classe string, o qual funciona de forma muito parecida com uma função (tanto que em C++ também é chamado de função-membro). No exemplo, o primeiro método usado se chama size(), e informa o comprimento da string. Os parênteses vazios após seu nome indicam que não são necessários parâmetros. A seguir destaca-se o uso do método size() (ver linha 10 do exemplo):

  titulo.size()

Deve-se observar que um método de uma classe é invocado por meio de um objeto dessa classe. Por isso é necessário prefixar o nome do método com o nome do objeto em questão. O significado disso é que as ações realizadas pelo método irão afetar esse objeto em particular. No exemplo, pode-se dizer: chama-se o método size() no objeto titulo para se obter o comprimento da string contida em titulo. O resultado desse método é um número inteiro, que é devolvido pelo método da mesma forma que uma função devolve um resultado.

Outros métodos foram mostrados no exemplo, tais como:


O importante a observar é a coesão que essas operações trazem ao uso de strings. As operações elementares sobre strings estão já embutidas na própria definição do que é uma string (no caso, a classe tem esse papel). Outro ponto importante é a simplificação quanto aos detalhes sobre como de fato os caracteres são armazenados na string, pois isso não precisa ser conhecido. Basta saber que o conteúdo da string pode ser acessado e modificado por meio dos métodos.

Mais exercícios

Estes novos exercícios incluem uma novidade: a possibilidade de testar as soluções automaticamente (técnica conhecida como teste de unidade). Um teste de unidade possibilita verificar automaticamente se uma parte de um programa, o que se chama uma unidade, funciona como esperado. Nos nossos exercícios, a unidade a ser testada pode ser uma função ou mesmo um programa como um todo (no caso de programas pequenos). Daqui em diante, todos os exercícios propostos (inclusive questões de avaliações !) incluirão seus testes de unidade. Com isso, vocês saberão se conseguiram resolver plenamente o que se pede no exercício.

O teste de unidade é executado dentro do IDE CLion. Para cada exercício, um arquivo de projeto do CLion é fornecido, o qual contém seu teste de unidade. A execução do teste depende do tipo de exercício:

  • Exercícios que envolvem escrever funções (i.e. não existe a função main):
    1. No seletor de configurações de execução, selecione runTest
    2. Para executar o teste, clique na seta verde que fica ao lado do seletor de configurações
  • Exercícios que envolvem a escrita de programas (i.e. que contếm a função main):
    1. No seletor de configurações de execução, selecione a configuração do programa a ser compilado. Usualmente ela tem o nome do tema do exercício.
    2. Pressione CTRL F9 para compilar o programa, ou selecione o menu Build->Build nome_do_programa
    3. Em seguida, no seletor de configurações de execução, selecione runTerm
    4. Para executar o teste, clique na seta verde que fica ao lado do seletor de configurações

OBS: descompacte o arquivo de projeto dentro da pasta CLionProjects, que reside em sua pasta pessoal. Em seguida, abra esse projeto por meio do menu File->Open, selecionando ali a pasta do novo projeto.


  1. Escreva um programa que leia uma string do teclado, e inverta a ordem de seus caracteres. Ao final, a string invertida deve ser apresentada na tela. Apenas uma variável string pode ser usada pelo seu programa. (projeto CLion)
  2. Escreva um programa que leia uma string do teclado e conte quantas palavras existem nessa string. Ao final, a contagem de palavras deve ser mostrada na tela. As palavras são delimitadas por espaços. (projeto CLion). Dica: use a função getline para ler uma linha completa do teclado, como neste exemplo
      string linha;
    
      // lê caracteres a partir de cin, e guarda-os na string "linha",
      // até encontrar um caractere newline (quebra-de-linha, ou \n)
      getline(cin, linha);
      cout << "Você digitou esta linha: " << linha << endl;
    
  3. Escreva uma função que procure uma substring dentro de uma string, e a substitua por outra string (projeto CLion). Por exemplo, se a string for correr, e a substring a ser procurada for rre for subsituída por pia, o resultado deve ser copiar. Essa função deve ser declarada assim:
    // Parâmetros:
    //   texto: a string a ser modificada
    //   sub: a substring a ser pcourada dentro de texto
    //   outra: a string a substituir a outra string
    // Resultado:
    //  a função devolve como resultado o valor de "texto" com a substituição efetuada
    string substitui(string texto, string sub, string outra) {
      // implementação da função
    }
    
    OBS: se sub não existir dentro de texto, texto não deve ser modificado.

Um exemplo sobre classes usando números complexos

O próximo exemplo sobre classes e objetos visa criar números complexos, que são compostos por uma parte real e outra imaginária. Eles possuem grande aplicação na Física e Engenharias, incluindo Telecomunicações (como vocês verão). No entanto, as linguagens de programação não costumam definir um tipo de dados para números complexos (Python é uma exceção !, e, pra falar a verdade, C++ também oferece um tipo de dados rudimentar). Para o propósito do exemplo, um número complexo tem partes real e imaginária do tipo double, e apresenta operações para calcular o módulo e ângulo para forma polar. A seguir se mostram definições para esse novo tipo em C e C++.


Linguagem C Linguagem C++
#include <math.h>

struct Complexo {
  double r, i;
};

double modulo(struct Complexo * z) {
  return sqrt(z->r*z->r + z->i*z->i);
}

double angulo(struct Complexo * z) {
  return atan(z->i / z->r);
}
#include <math.h>

class Complexo {
 // os atributos de um número complexo: suas partes real e imaginária
 private:
  double r, i; // partes real e imaginária

 public:
  // construtor: método para criação de um número complexo
  Complexo(double rr, double ii) {
    r = rr;
    i = ii;
  }

  // métodos para obter cópias dos valores dos atributos do número complexo
  double real() const { return r;}
  double imaginario() const { return i;}

  // métodos para obter módulo e ângulo da forma polar
  double modulo() const {
    return sqrt(r*r + i*i);
  }

  double angulo() const {
    return atan(i/r);
  }
};


Uma vez tendo declarado a classe Complexo, podem-se criar objetos dessa classe e usá-los em programas:


Linguagem C Linguagem C++
#include <stdio.h>
#include "complexo.h"

int main() {
  struct Complexo z = {1, 1};

  printf("Parte real: %lg\n", z.r);
  printf("Parte imaginaria: %lg\n", z.i);
  printf("Forma polar: modulo=%lg, angulo=%lg\n", modulo(&z), angulo(&z));
}
#include <iostream>
#include "complexo.h"

using namespace std;

int main() {
  Complexo z(1,1); // "z" é um objeto da classe Complexo

  cout << "Parte real: " << z.real() << endl;
  cout << "Parte imaginaria: " << z.imaginario() << endl;
  cout << "Forma polar: modulo=" << z.modulo();
  cout << ", angulo=" << z.angulo() << endl;
}


Compile os exemplos e execute-os para vê-los em funcionamento. Em seguida, experimente fazer pequenas modificações na versão em C++. Por exemplo, tente acessar diretamente os atributos do objeto z (tente acessar z.r ou z.i).


O exemplo é muito simples, e pode-se questionar o que se ganha escrevendo-o usando classe e objetos. Essa questão poderá ser retomada quando os programas forem um pouco maiores ou mais complexos ... O próximo exemplo também é simples, mas possui alguns requisitos a mais. Afinal, ele faz alguma coisa aparentemente útil ;-)

Um outro exemplo: representando horários

A classe Horario representa um horário do dia com resolução de segundos. Objetos dessa classe representam horários, e com eles se podem saber a hora, minuto ou segundo do dia. Esses objetos podem ser criados especificando-se exatamente um horário, ou a partir do relógio do computador. A declaração dessa classe está apresentada a seguir.

Classe Horario
#include <string>
#include <cstdlib>
#include <time.h>

using namespace std;

class Horario {
 public:
  // construtor sem parâmetros: cria um objeto a partir do relógio do computador
  Horario();

  // construtor com parâmetros: cria um objeto com o horário informado
  Horario(int hh, int mm, int ss);

  // estes métodos possibilitam obter os valores de hora, minuto e segundo

  int hora();

  int minuto();

  int segundo();

  // este método retorna uma string que representa o horário, no formato HH:MM:SS
  string str();

  // este método modifica o horário a partir do relógio do computador
  void recarrega();

  // este método calcula a diferença de tempo entre este Horario e outro Horario
  // o resultado é a quantidade de segundos entre os dois Horarios
  int delta(const Horario & outro);

 private:
  // os atributos do Horario (hora, minuto, segundo)
  int h, m, s;

  // um método privativo para uso interno da classe
  string dois_digitos(int x);
};

Arquivo Horario.h
#include "Horario.h"

Horario::Horario() {
  recarrega();
}

// construtor com parâmetros: cria um objeto com o horário informado
Horario::Horario(int hh, int mm, int ss) {
  if (hh < 24) h = hh;
  else h = 0;
  if (mm < 60) m = mm;
  else m = 0;
  if (ss < 60) s = ss;
  else s = 0;
}

// estes métodos possibilitam obter os valores de hora, minuto e segundo

int Horario::hora() {
  return h;
}

int Horario::minuto() {
  return m;
}

int Horario::segundo() {
  return s;
}

// este método retorna uma string que representa o horário, no formato HH:MM:SS
string Horario::str() {
  string t;

  t += dois_digitos(h);
  t += ':' + dois_digitos(m);
  t += ':' + dois_digitos(s);
  return t;
}

// este método modifica o horário a partir do relógio do computador
void Horario::recarrega() {
  time_t t;
  struct tm *tmp;
  char buffer[8];

  t = time(NULL);
  tmp = localtime(&t);

  strftime(buffer, 8, "%H", tmp);
  h = stoi(buffer);

  strftime(buffer, 8, "%M", tmp);
  m = stoi(buffer);

  strftime(buffer, 8, "%S", tmp);
  s = stoi(buffer);
}

// um método privativo para uso interno da classe
string Horario::dois_digitos(int x) {
  string r;
  if (x < 10) r += '0';
  r += to_string(x);
  return r;
}

int Horario::delta(const Horario & outro) {
  int s1 = h*3600 + m*60 + s;
  int s2 = outro.h*3600 + outro.m*60 + outro.s;

  return s1 - s2;
}
Arquivo Horario.cpp

Experimente criar um programa que use objetos da classe Horario. Para isso faça o seguinte:

  1. Crie o arquivo Horario.h e copie o conteúdo de Horario.h mostrado anteriormente
  2. Crie o arquivo Horario.cpp e copie seu conteúdo
  3. Crie seu arquivo main.cpp, e nele declare a função main.
  4. Implemente seu programa dentro da função main
  5. Abra um terminal e nele compile seu programa com este comando:
    g++ -std=c++11 -o prog main.cpp Horario.cpp
    
  6. Teste seu programa, executando-o no terminal:
    ./prog
    


ALTERNATIVA: crie um projeto no Netbeans para fazer este exercício !

Mais exercícios

  1. Crie uma classe cujos objetos representam números inteiros. As operações dessa classe possibilitam obter representações de um número em binário, octal, hexadecimal ou decimal.
  2. Implemente a classe Semaforo
  3. Implemente a classe Nome
  4. Implemente a classe CPF


... outros exercícios (ver Etapa 0)

Alguns pequenos programas

Jogos clássicos são um bom exemplo de problemas interessantes e relativamente simples de transformar em programas. A seguir são sugeridos programas para alguns desses jogos. Resolva-os se quiser praticar mais !

Jogo da Forca


O jogo da Forca é um jogo em que se tenta adivinhar uma palavra letra a letra. Um jogador escolhe uma palavra, e informa quantas letras ela possui. Outro jogador tenta descobrir a palavra, informando sucessivamente letras que imagina pertencer à palavra. Cada letra que não exista na palavra implica uma penalidade, acrescentando uma parte do corpo à forca, como ilustrado na figura a seguir. Se o corpo na forca ficar completo, o desafiador perde a partida.

Prg2-forca.gif


Esse jogo pode ser facilmente implementado como um programa. Basicamente ele trata de manipulação de string e caracteres. Sendo assim, implemente esse jogo em linguagem C++.


Um bom ponto de partida é primeiro definir um protótipo que seja o mais simples possível, porém que contenha as características essenciais do jogo.


Jogo da Senha

O jogo da Senha é um jogo clássico entre dois jogadores. Um jogador escolhe uma senha, composta por uma combinação de quatro peças coloridas, e a esconde usando um pequeno anteparo. O outro jogador deve então tentar descobrir a combinação de peças, limitado por dez tentativas. A cada tentativa, o dono da senha usa uma combinação de peças brancas e pretas para informar ao desafiante quantas peças ele acertou. Cada peça preta informa que uma peça tem a cor certa e está na posição correta. Cada peça branca informa que uma peça com cor certa está em posição errada. Assim, usando raciocínio lógico, o desafiante deve ser capaz de descobrir a combinação correta de peças coloridas. A figura a seguir mostra o tabuleiro desse jogo.


PRG2-Jogo-senha.jpg


Um programa para esse jogo poderia usar números no lugar de cores. O programa sortearia inicialmente uma combinação de cores, e em seguida pediria ao jogador para tentar combinações sucessivamente, até que se descubra a combinação correta. A cada tentativa, o programa informaria ao jogador quantas cores estão em posição correta e quantas estão em posição errada. Por exemplo, o jogo poderia interagir com o jogador desta forma:

A cada tentativa, digite os códigos de cores separados por espaços: 
Cores: valores entre 1 e 8

Cores: 1 1 2 2
Cores em posições corretas: 0
Cores em posições erradas: 0

Cores: 3 3 4 4
Cores em posições corretas: 1
Cores em posições erradas: 1

Cores: 3 3 5 5
Cores em posições corretas: 0
Cores em posições erradas: 0

Cores: 4 6 6 4
Cores em posições corretas: 3
Cores em posições erradas: 0

Cores: 4 6 7 4
Você descobriu as cores na sequência correta !


Tente criar um programa para esse jogo !

Jogo Craps


Um jogo de dados popular em cassinos se chama craps. Ele aparece em muitos filmes ambientados em cassinos, e a figura a seguir mostra a mesa do jogo. Nesse jogo se usam dois dados, que devem ser lançados em rodadas. Uma rodada é composta por jogadas sucessivas, sendo dividida em duas etapas: come-out e point. Apostas podem ser feitas com base nas categorias de resultados possíveis.


Prg2-Craps.jpg


Uma rodada inicia com uma ou mais jogadas até que se atinja o estado de come-out. Basicamente, os dados devem somar um dentre os valores 4, 5, 6, 8, 9 ou 10 para que se passe à etapa seguinte, chamada point. O valor obtido ao final de come-out é chamado também de point, e o objetivo é repeti-lo na próxima etapa. O jogador lança os dados até obter novamente o point, quando então ganha a rodada, ou aparecer o valor 7, quando a perde.

As apostas são do tipo pass ou dont pass, que é o oposto da primeira. A aposta pass vence se:

  • A rodada na etapa point terminar conseguindo-se obter o valor point com os dados
  • Durante a etapa come-out, os valores 7 ou 11 aparecerem nos dados.

... e perde se:

  • A rodada na etapa point terminar com o valor 7.
  • Durante a etapa come-out, os valores 2, 3 ou 12 aparecerem nos dados.


O jogo parece razoavelmente simples. Como seria um programa que o implementasse ?