Aeca

Capítulo 11 — Quando existem alternativas

Série: Do zero ao jogo comercial com C++ e SFML

Capítulo 11 — Quando existem alternativas
aeca

Nosso programa já sabe perguntar. Agora ele precisa escolher entre dois caminhos diferentes.

No capítulo anterior nosso programa finalmente começou a tomar decisões.

Aprendemos a utilizar:

  if

para executar um bloco somente quando uma condição fosse verdadeira.

Por exemplo:

  if (playerCoins >= itemPrice)
{
    playerCoins -= itemPrice;

    std::cout << "Item purchased." << std::endl;
}

Essa regra já resolve metade do problema.

Se o jogador possuir moedas suficientes:

  playerCoins >= itemPrice
↓
true
↓
realizar compra

Mas e se não possuir?

Atualmente nosso programa simplesmente continua.

Nenhuma mensagem.

Nenhuma reação.

Nenhuma ação alternativa.

Queremos representar:

  Possui moedas suficientes?
│
├── SIM → comprar o item
│
└── NÃO → informar que faltam moedas

Agora existem duas alternativas.

E é exatamente esse problema que nos leva ao:

  else

1. Relembrando a limitação do if

Considere:

  int playerCoins = 30;
int itemPrice = 50;

if (playerCoins >= itemPrice)
{
    playerCoins -= itemPrice;

    std::cout << "Item purchased." << std::endl;
}

A condição:

  playerCoins >= itemPrice

é avaliada como:

  30 >= 50
↓
false

Então o bloco não executa.

O programa simplesmente segue adiante.

Mas talvez nossa regra exija uma resposta diferente quando a condição for falsa.


2. Precisamos representar o outro caminho

Queremos algo conceitualmente assim:

  SE playerCoins >= itemPrice

    comprar

SENÃO

    informar que faltam moedas

Em C++, essa segunda alternativa pode ser representada com:

  else

A estrutura básica fica:

  if (condition)
{
    // executado quando a condição é verdadeira
}
else
{
    // executado quando a condição é falsa
}

Agora nosso programa possui dois caminhos possíveis.


3. Nosso primeiro if com else

  #include <iostream>

int main()
{
    int playerCoins = 30;
    int itemPrice = 50;

    if (playerCoins >= itemPrice)
    {
        std::cout << "Item purchased." << std::endl;
    }
    else
    {
        std::cout << "Not enough coins." << std::endl;
    }

    return 0;
}

Como:

  30 >= 50

é falso, o resultado será:

  Not enough coins.

Se alterarmos:

  int playerCoins = 80;

teremos:

  80 >= 50
↓
true

Então:

  Item purchased.

4. Apenas um dos dois blocos será executado

Essa é a principal diferença em relação a dois if independentes.

Com:

  if (condition)
{
    // caminho A
}
else
{
    // caminho B
}

temos:

  condition
   │
   ├── true
   │    ↓
   │  bloco do if
   │
   └── false
        ↓
      bloco do else

Uma condição.

Dois caminhos.

Apenas um deles é escolhido.


5. else não possui uma nova condição

Observe:

  if (playerCoins >= itemPrice)
{
}
else
{
}

O else não precisa escrever:

  playerCoins < itemPrice

Ele significa:

execute este bloco quando a condição do if anterior for falsa.

Portanto:

  if
↓
condição verdadeira

else
↓
a mesma condição foi falsa

6. Transformando a compra em uma regra completa

Agora podemos escrever:

  #include <iostream>

int main()
{
    int playerCoins = 80;
    int itemPrice = 50;

    std::cout << "Coins Before Purchase: " << playerCoins << std::endl;

    if (playerCoins >= itemPrice)
    {
        playerCoins -= itemPrice;

        std::cout << "Item purchased." << std::endl;
    }
    else
    {
        std::cout << "Not enough coins." << std::endl;
    }

    std::cout << "Coins After Purchase: " << playerCoins << std::endl;

    return 0;
}

Resultado:

  Coins Before Purchase: 80
Item purchased.
Coins After Purchase: 30

Agora altere:

  int playerCoins = 30;

Resultado:

  Coins Before Purchase: 30
Not enough coins.
Coins After Purchase: 30

Temos dois cenários completos.


7. O estado muda apenas no caminho correto

Observe:

  if (playerCoins >= itemPrice)
{
    playerCoins -= itemPrice;
}
else
{
    std::cout << "Not enough coins." << std::endl;
}

Quando existem moedas suficientes:

  80 - 50
=
30

Quando não existem:

  30
↓
continua 30

Isso representa uma regra muito mais adequada.

Não apenas mostramos uma mensagem diferente.

Também impedimos uma alteração inválida de estado.


8. O else representa uma alternativa, não um erro

É importante não pensar em else como:

  algo deu errado

Ele apenas representa:

  a condição anterior foi falsa

Por exemplo:

  if (playerHealth > 0)
{
    std::cout << "Player is alive." << std::endl;
}
else
{
    std::cout << "Player is defeated." << std::endl;
}

Nenhum dos dois caminhos é tecnicamente um "erro".

São apenas estados diferentes.


9. Um exemplo com vida

  #include <iostream>

int main()
{
    int playerHealth = 25;

    if (playerHealth > 0)
    {
        std::cout << "Player is alive." << std::endl;
    }
    else
    {
        std::cout << "Player is defeated." << std::endl;
    }

    return 0;
}

Com:

  Health = 25

resultado:

  Player is alive.

Agora:

  int playerHealth = 0;

Resultado:

  Player is defeated.

10. A regra precisa estar bem definida

Observe:

  if (playerHealth > 0)

Isso implica que qualquer valor:

  <= 0

cairá no else.

Então:

  0
-1
-50

todos produziriam:

  Player is defeated.

Talvez isso seja adequado.

Talvez não.

O ponto importante é:

o else cobre tudo que não satisfaz a condição do if.

Por isso a condição precisa representar corretamente a regra.


11. Duas alternativas precisam ser realmente complementares

Considere:

  if (playerCoins >= itemPrice)
{
    // pode comprar
}
else
{
    // não pode comprar
}

Aqui temos uma divisão clara:

  playerCoins >= itemPrice

ou:

  não playerCoins >= itemPrice

Para números neste contexto, o segundo caminho corresponde ao caso em que as moedas são insuficientes.

Isso torna if/else uma boa representação.


12. Dois if independentes não significam a mesma coisa

Compare:

  if (playerCoins >= itemPrice)
{
    std::cout << "Item purchased." << std::endl;
}

if (playerCoins < itemPrice)
{
    std::cout << "Not enough coins." << std::endl;
}

com:

  if (playerCoins >= itemPrice)
{
    std::cout << "Item purchased." << std::endl;
}
else
{
    std::cout << "Not enough coins." << std::endl;
}

Nosso segundo código expressa melhor a intenção:

existem duas alternativas para a mesma decisão.

No primeiro, temos duas decisões independentes.


13. Por que isso importa?

Quando escrevemos:

  if (condition)
{
}
else
{
}

a própria estrutura comunica:

  um caminho ou o outro

Isso ajuda quem lê o código a compreender que os dois blocos pertencem à mesma decisão.

Estrutura de código também comunica intenção.


14. Calculando quanto falta para comprar

Já podemos fazer uma pequena melhoria.

Quando o jogador não possui moedas suficientes:

  else
{
    std::cout << "Not enough coins." << std::endl;
}

podemos calcular:

  int missingCoins = itemPrice - playerCoins;

Então:

  else
{
    int missingCoins = itemPrice - playerCoins;

    std::cout << "Not enough coins." << std::endl;
    std::cout << "Missing Coins: " << missingCoins << std::endl;
}

Se:

  playerCoins = 30
itemPrice = 50

temos:

  50 - 30 = 20

Resultado:

  Not enough coins.
Missing Coins: 20

15. O cálculo pertence ao caminho em que faz sentido

Observe onde colocamos:

  int missingCoins = itemPrice - playerCoins;

Ele está dentro do:

  else

Isso é interessante.

Só precisamos calcular missingCoins quando realmente faltam moedas.

Estamos começando a perceber que blocos diferentes podem possuir trabalho diferente.


16. Variáveis dentro de blocos

Considere:

  else
{
    int missingCoins = itemPrice - playerCoins;

    std::cout << missingCoins << std::endl;
}

A variável:

  missingCoins

é criada dentro daquele bloco.

Ainda teremos um capítulo específico sobre escopo.

Então não aprofundaremos isso agora.

Por enquanto, observe apenas:

declaramos a variável perto do lugar onde ela é necessária.

Essa decisão já melhora a leitura.


17. Não vamos antecipar o capítulo de escopo

Talvez você tente utilizar:

  missingCoins

fora do bloco e encontre um erro.

Isso acontece porque a existência e a visibilidade de variáveis dependem do escopo.

Esse assunto será estudado formalmente no Capítulo 20.

Por enquanto, mantenha:

  missingCoins

dentro do bloco em que ela é utilizada.


18. Aplicando dano com dois resultados

Imagine:

  int playerHealth = 25;
int damage = 40;

Primeiro:

  int newHealth = playerHealth - damage;

Teremos:

  25 - 40 = -15

Podemos utilizar:

  if (newHealth > 0)
{
    playerHealth = newHealth;

    std::cout << "Player survived." << std::endl;
}
else
{
    playerHealth = 0;

    std::cout << "Player defeated." << std::endl;
}

Agora existem duas alternativas claras.


19. Implementação do cenário

  #include <iostream>

int main()
{
    int playerHealth = 25;
    int damage = 40;

    int newHealth = playerHealth - damage;

    if (newHealth > 0)
    {
        playerHealth = newHealth;

        std::cout << "Player survived." << std::endl;
    }
    else
    {
        playerHealth = 0;

        std::cout << "Player defeated." << std::endl;
    }

    std::cout << "Health: " << playerHealth << std::endl;

    return 0;
}

Resultado:

  Player defeated.
Health: 0

Agora altere:

  int damage = 10;

Resultado:

  Player survived.
Health: 15

Dois caminhos.

Um único resultado final coerente.


20. Cuidado com a regra de vida igual a zero

Na condição:

  if (newHealth > 0)

se:

  newHealth = 0

o resultado será falso.

Então o jogador será considerado derrotado.

Isso corresponde à regra:

  Health > 0 → vivo

Health <= 0 → derrotado

Se nosso Game Design fosse diferente, a condição também precisaria ser diferente.

Código e regra precisam concordar.


21. else depende imediatamente do if

A estrutura é:

  if (condition)
{
}
else
{
}

O else pertence ao if correspondente.

Não podemos simplesmente escrever:

  else
{
}

sozinho.

Ele representa a alternativa de uma decisão anterior.


22. Erro proposital — else sem if

Experimente:

  #include <iostream>

int main()
{
    else
    {
        std::cout << "Alternative." << std::endl;
    }

    return 0;
}

Faça Build.

O compilador não conseguirá interpretar esse else corretamente porque não existe um if associado.

Use nossa metodologia:

  erro
↓
linha
↓
estrutura esperada
↓
estrutura existente
↓
correção

Depois restaure:

  if (true)
{
}
else
{
}

O exemplo acima é apenas para demonstrar a estrutura; não precisamos preservar um if (true) no código real.


23. Erro proposital — ponto e vírgula continua perigoso

Considere:

  if (playerCoins >= itemPrice);
{
    std::cout << "Item purchased." << std::endl;
}
else
{
    std::cout << "Not enough coins." << std::endl;
}

Esse código não representa nossa intenção e pode inclusive gerar erro de compilação devido à forma como o else passa a se associar.

O problema começa aqui:

  if (playerCoins >= itemPrice);

Aquele:

  ;

encerra a instrução controlada pelo if.

Não coloque ; após a condição.


24. O formato que adotaremos

Sempre:

  if (condition)
{
    // caminho verdadeiro
}
else
{
    // caminho falso
}

Chaves presentes.

Indentação consistente.

Nenhuma tentativa de comprimir tudo em uma linha.


25. Não faremos isto

Mesmo sendo possível encontrar:

  if (playerCoins >= itemPrice)
    playerCoins -= itemPrice;
else
    std::cout << "Not enough coins." << std::endl;

em nosso projeto preferiremos:

  if (playerCoins >= itemPrice)
{
    playerCoins -= itemPrice;
}
else
{
    std::cout << "Not enough coins." << std::endl;
}

O custo de algumas linhas extras é pequeno.

O ganho de estrutura visual é grande.


26. Também não precisamos repetir a condição inversa

Evite escrever algo como:

  if (playerCoins >= itemPrice)
{
    std::cout << "Can buy." << std::endl;
}
else
{
    if (playerCoins < itemPrice)
    {
        std::cout << "Cannot buy." << std::endl;
    }
}

Esse segundo teste é redundante.

Se chegamos ao else, já sabemos que:

  playerCoins >= itemPrice

foi falso.

Para essa decisão binária simples, basta:

  if (...)
{
}
else
{
}

27. O else reduz duplicação de raciocínio

Compare mentalmente:

  perguntar se pode comprar

depois perguntar novamente se não pode comprar

com:

  perguntar uma vez

se sim → A

senão → B

A segunda estrutura representa diretamente a decisão.

Menos condições desnecessárias também significam menos lugares para cometer erros.


28. Um exemplo com experiência

Considere:

  const int EXPERIENCE_REQUIRED = 100;

int playerExperience = 80;

Podemos escrever:

  if (playerExperience >= EXPERIENCE_REQUIRED)
{
    std::cout << "Experience requirement reached." << std::endl;
}
else
{
    int missingExperience = EXPERIENCE_REQUIRED - playerExperience;

    std::cout << "More experience required." << std::endl;
    std::cout << "Missing Experience: " << missingExperience << std::endl;
}

Resultado:

  More experience required.
Missing Experience: 20

29. Testando o limite exato

Agora:

  int playerExperience = 100;

Temos:

  100 >= 100
↓
true

Então:

  Experience requirement reached.

Essa é uma boa oportunidade para testar valores de fronteira.


30. Valores de fronteira importam

Se a regra é:

  playerExperience >= EXPERIENCE_REQUIRED

devemos testar pelo menos:

  99
100
101

Por quê?

Porque estamos interessados especialmente no ponto onde o comportamento muda.

  99  → falso
100 → verdadeiro
101 → verdadeiro

Essa forma de pensar será muito importante em QA e automação de testes mais adiante.


31. Nosso primeiro pensamento sobre cenários

Para uma condição:

  playerCoins >= itemPrice

podemos testar:

  abaixo do preço
igual ao preço
acima do preço

Por exemplo:

  49
50
51

com:

  itemPrice = 50

Resultados esperados:

  49else
50if
51if

Já estamos pensando em comportamento de fronteira sem precisar de um framework de testes.


32. if/else começa a aproximar código e regra de negócio do jogo

Considere:

  if (playerCoins >= itemPrice)
{
    playerCoins -= itemPrice;
}
else
{
    std::cout << "Not enough coins." << std::endl;
}

Isso representa uma regra.

Não é apenas sintaxe.

Temos:

  pré-condição
↓
moedas suficientes?

caminho válido
↓
realizar compra

caminho inválido
↓
recusar compra

Mais tarde sistemas completos serão formados por regras muito mais sofisticadas.

Mas a base já está aqui.


33. Ainda não precisamos de ShopSystem

Nosso exemplo de compra possui:

  int playerCoins;
int itemPrice;

e uma decisão.

Não precisamos criar:

  ShopSystem
StoreManager
PurchaseService
TransactionProcessor
EconomyEngine

Esse seria exatamente o tipo de abstração prematura que queremos evitar.

Primeiro precisamos entender o comportamento.


34. Ainda não precisamos de funções

O código está começando a repetir padrões:

  condição
↓
ação A
↓
ação B

Isso futuramente contribuirá para o crescimento do main.cpp.

Mas ainda não chegamos ao capítulo de funções.

Por enquanto é útil enxergar esse crescimento.

A necessidade de organização precisa ser sentida antes da abstração aparecer.


35. E se houver três possibilidades?

Agora surge uma pergunta natural.

Imagine Health:

  Health > 70 → estado saudável

Health entre 30 e 70 → estado ferido

Health abaixo de 30 → estado crítico

Temos:

  mais de dois caminhos

Um simples:

  if (...)
{
}
else
{
}

possui apenas dois ramos.

Mas C++ permite construir cadeias de decisões.


36. else if existe

Você provavelmente encontrará:

  if (conditionA)
{
}
else if (conditionB)
{
}
else
{
}

Isso permite representar mais de duas situações.

Mas não vamos aprofundar cadeias complexas neste artigo.

Nosso objetivo central foi entender corretamente a relação:

  if
↕
else

O próximo capítulo abordará o problema de muitas opções, incluindo quando estruturas alternativas começam a ser úteis.


37. Por que não aprofundar tudo agora?

Poderíamos colocar neste mesmo artigo:

  if
else
else if
nested if
logical AND
logical OR
logical NOT
switch
ternary operator

Mas teríamos novamente um capítulo grande demais e uma progressão pior.

Nossa sequência continua deliberadamente incremental.

Hoje:

  uma condição
↓
dois caminhos

Depois:

  múltiplas opções

38. Microdesafio — moedas suficientes

Comece:

  int playerCoins = 75;
int itemPrice = 50;

Se puder comprar:

  Item purchased.

Caso contrário:

  Not enough coins.

Uma possível solução:

  if (playerCoins >= itemPrice)
{
    playerCoins -= itemPrice;

    std::cout << "Item purchased." << std::endl;
}
else
{
    std::cout << "Not enough coins." << std::endl;
}

39. Microdesafio — mostrar quanto falta

Agora, no caminho falso:

  int missingCoins = itemPrice - playerCoins;

Mostre:

  Missing Coins: 20

quando:

  playerCoins = 30
itemPrice = 50

40. Microdesafio — vida

Comece:

  int playerHealth = 20;
int damage = 25;

Calcule:

  int newHealth = playerHealth - damage;

Se:

  newHealth > 0

mostre:

  Player survived.

Caso contrário:

  Player defeated.

e defina:

  playerHealth = 0;

quando derrotado.


41. Microdesafio — experiência

Comece:

  const int EXPERIENCE_REQUIRED = 100;
int playerExperience = 70;

Se tiver experiência suficiente:

  Experience requirement reached.

Caso contrário, calcule:

  int missingExperience = EXPERIENCE_REQUIRED - playerExperience;

Resultado esperado:

  More experience required.
Missing Experience: 30

42. Código final do capítulo

Vamos manter um cenário que reúne compra e progressão sem criar sistemas prematuramente:

  #include <iostream>

int main()
{
    const int EXPERIENCE_REQUIRED = 100;

    int playerCoins = 30;
    int itemPrice = 50;
    int playerExperience = 80;

    std::cout << "=== PURCHASE ===" << std::endl;

    if (playerCoins >= itemPrice)
    {
        playerCoins -= itemPrice;

        std::cout << "Item purchased." << std::endl;
        std::cout << "Coins Left: " << playerCoins << std::endl;
    }
    else
    {
        int missingCoins = itemPrice - playerCoins;

        std::cout << "Not enough coins." << std::endl;
        std::cout << "Missing Coins: " << missingCoins << std::endl;
    }

    std::cout << std::endl;
    std::cout << "=== EXPERIENCE ===" << std::endl;

    if (playerExperience >= EXPERIENCE_REQUIRED)
    {
        std::cout << "Experience requirement reached." << std::endl;
    }
    else
    {
        int missingExperience = EXPERIENCE_REQUIRED - playerExperience;

        std::cout << "More experience required." << std::endl;
        std::cout << "Missing Experience: " << missingExperience << std::endl;
    }

    return 0;
}

Resultado:

  === PURCHASE ===
Not enough coins.
Missing Coins: 20

=== EXPERIENCE ===
More experience required.
Missing Experience: 20

43. Agora teste o caminho verdadeiro

Altere:

  int playerCoins = 80;
int playerExperience = 120;

Resultado esperado:

  === PURCHASE ===
Item purchased.
Coins Left: 30

=== EXPERIENCE ===
Experience requirement reached.

O mesmo programa agora percorre caminhos diferentes de acordo com seu estado.


44. Uma entrada, uma decisão, um caminho

Podemos resumir:

  ESTADO
↓
CONDIÇÃO
↓
true / false
↓
ESCOLHA DE CAMINHO
↓
AÇÃO
↓
NOVO ESTADO

Esse padrão aparecerá incontáveis vezes durante o desenvolvimento do jogo.


45. Validando os cenários

Não teste apenas uma combinação.

Para a compra:

  Item Price = 50

teste:

  Coins = 49
Coins = 50
Coins = 51

Esperado:

  49else
50if
51if

Para experiência:

  Required = 100

teste:

  Experience = 99
Experience = 100
Experience = 101

Esperado:

  99else
100if
101if

Testar bordas começa a se tornar um hábito.


46. Erros comuns deste capítulo

Alguns problemas que você deve reconhecer:

Usar = em vez de ==

  if (playerLevel = 2)

quando queria:

  if (playerLevel == 2)

Colocar ; após o if

  if (condition);

Esquecer as chaves

Mesmo quando tecnicamente possível, não seguiremos esse estilo.

Repetir a condição inversa dentro do else

  else
{
    if (...)
    {
    }
}

quando o segundo teste é desnecessário.

Alterar estado no caminho errado

Por exemplo, descontar moedas fora do bloco que validou a compra.


47. Nosso estado arquitetural continua simples

Nada mudou na estrutura:

  CppGameEngine/
└── main.cpp

Adicionamos comportamento.

Não adicionamos infraestrutura.

Essa diferença é importante.

Estamos deixando o software crescer em capacidade, e não apenas em quantidade de arquivos.


48. Git

Depois de validar todos os cenários:

  git status

Adicione:

  git add CppGameEngine/main.cpp

Ajuste o caminho se necessário.

Commit sugerido:

  git commit -m "feat: add alternative gameplay decision paths"

A mudança representa:

nossas decisões agora podem executar caminhos diferentes para condições verdadeiras e falsas.


49. Atualizando o CHANGELOG

Em [Unreleased]:

  ### Added

- Added alternative decision paths using `if` and `else`.
- Added purchase feedback for successful and insufficient coin scenarios.
- Added missing coin calculation for failed purchases.
- Added experience requirement feedback for both decision outcomes.
- Added boundary scenario validation for conditional rules.

Depois:

  git add CHANGELOG.md
git commit -m "docs: update changelog with alternative decision paths"

Não precisamos atualizar o ROADMAP técnico neste capítulo.


50. O que aprendemos?

No Capítulo 10 nosso programa aprendeu:

  SE condição for verdadeira → execute

Agora evoluímos para:

  SE condição for verdadeira → execute A

SENÃO → execute B

Conhecemos:

  if (condition)
{
}
else
{
}

e aprendemos que:

  • o if representa o caminho verdadeiro;

  • o else representa o caminho quando a condição é falsa;

  • apenas um dos dois blocos é executado;

  • else não precisa repetir a condição inversa;

  • dois if independentes não comunicam necessariamente a mesma intenção que if/else;

  • estado deve ser modificado apenas no caminho que representa uma operação válida;

  • regras de fronteira precisam ser testadas;

  • valores imediatamente abaixo, iguais e acima de um limite são particularmente importantes;

  • blocos diferentes podem possuir cálculos específicos de cada caminho;

  • não precisamos criar sistemas, funções ou classes prematuramente.


Conclusão

Nosso programa já conseguia perguntar:

  Player possui Coins suficientes?

Antes ele sabia apenas:

  SIM → comprar

Agora sabe representar:

  SIM → comprar

NÃO → informar que faltam moedas

Isso parece simples, mas muda bastante nosso modelo de execução.

Agora temos:

  estado
↓
condição
↓
escolha
├── caminho A
└── caminho B
↓
resultado

Jogos são formados por escolhas desse tipo o tempo inteiro.

  Existe espaço no inventário?
├── sim → coletar
└── não → recusar

Jogador possui a chave?
├── sim → abrir
└── não → manter fechado

Crop está madura?
├── sim → colher
└── não → continuar crescendo

Mas nem toda situação possui apenas duas alternativas.

Imagine um menu:

  1 → New Game
2 → Load Game
3 → Settings
4 → Exit

Ou um estado:

  SPRING
SUMMER
AUTUMN
WINTER

Ou uma seleção:

  Sword
Axe
Pickaxe
Hoe
Watering Can

Poderíamos criar uma longa sequência de decisões.

Mas talvez exista uma estrutura mais apropriada quando um único valor precisa ser comparado contra várias opções.

Esse será nosso próximo problema.


Próximo capítulo

Capítulo 12 — Muitas opções: quando switch ajuda

Série: Do zero ao jogo comercial com C++ e SFML

No próximo artigo partiremos de um problema como:

  opção == 1?
opção == 2?
opção == 3?
opção == 4?

e analisaremos o que acontece quando começamos a empilhar várias decisões para representar opções discretas.

Só então conheceremos:

  switch

e conceitos como:

  case
break
default

Também veremos algo essencial:

switch não substitui if.

Ele resolve melhor alguns tipos específicos de problema.

Nosso programa já sabe escolher entre dois caminhos.

No próximo capítulo ele aprenderá a lidar com muitas opções de maneira mais organizada.

Subscreve "Aeca" para receber atualizações diretamente na tua caixa de entrada
aeca

Subscreve aeca para reagir

Subscrever

Comentários

Ainda não há comentários. Sê o primeiro a comentar!

Subscreve Aeca para receber atualizações diretamente na tua caixa de entrada