TUTORIAL EM 10 PASSOS: Algoritmo simulador da Megasena em C

Trouxe um passo a passo de um algoritmo que gostei de fazer para treinarmos o básico da linguagem C e entendermos um pouco mais de suas estruturas.
Apesar da complexidade que aparenta, é mais simples do que parece - se você já treinou com alguns algoritmos mais fáceis antes (é claro). Começar pelo mais difícil não funciona, acredite. E é claro que existem milhares de maneiras de resolver essa questão e a que vou ensinar a vocês não é a "mais certa" ou quem sabe a mais fácil; afinal, resoluções diferentes não significam resoluções erradas. Antes de fazer, recomendo conhecer o básico de como funciona a Megasena e a linguagem em questão.
O código será na maior parte em imagens, para que você possa escrever o seu também - e aprender.
Bom, vamos começar com o essencial:

     1. Montando a estrutura básica inicial
#include <stdio.h> 
#include <time.h> //biblioteca necessária para não repetir os números no sorteio
#include <stdlib.h>


int main() { 


return 0;
}
Faremos o código dentro da função principal.

     2. Declarando variáveis (inteiras, já que são as únicas que vamos precisar):
(imagem 1)
As variáveis i, j e m serão usadas nos laços for. O inteiro apostas é o contador para o número de apostas do usuário - você também pode perguntar ao usuário no início do programa quantas apostas ele quer fazer (==1 ou <=5) e criar um vetor  para todas as apostas, ou, como vamos fazer, a cada aposta perguntar ao usuário se ele deseja apostar novamente. A matriz todasApostas[5][6] é onde vamos armazenar todas as apostas do usuário para conferir com o resultado depois; onde 5 representa o número de linhas (uma para cada aposta) e 6 cada número do cartão e o vetor result[6] armazenará o resultado. As demais variáveis comentaremos no decorrer do algoritmo.

     3. Zerando matriz de armazenamento das apostas para evitar aproveitamento da memória antiga: 
(imagem 2)
srand(time(NULL)); //comando para a cada iniciação do programa os números sorteados não serem os mesmos

     4. Fazendo as apostas
(imagem 3)
Esse while repete a estrutura de apostas enquanto o usuário ainda quiser fazer uma nova e a quantidade ainda seja menor ou igual a 5. "Mas por que a condição é apostas<=4 se a quantidade máxima é 5?" Boa pergunta e com resposta bem simples, porque no C a contagem começa a partir do 0: 0 1 2 3 4. A variável n, já declarada lá no começo funcionará como um booleano e enquanto essa condição for verdadeira (de fazer uma nova aposta) e apostas<=4, a estrutura se repetirá.

O programa lê a resposta do usuário entre fazer sua própria aposta ou obter um cartão aleatório e enquanto o usuário digitar um número diferente de um e zero, o sistema vai solicitar uma opção válida (como solicitado pela questão).  PS: a resposta fica armazenada em p.

PS: esse }//while uso apenas para me situar sobre qual comando eu estou fechando.

     5. Apostas randômicas
(imagem 4)
Caso o usuário escolha pelo cartão randômico /* if (p==1) */ então o programa vai entrar nessa estrutura para gerar a aposta e imprimi-la.
No printf será mostrado na tela o número do cartão que é apostas+1 porque, como dito antes, a contagem começa do 0 para o sistema, mas para o usuário começa no 1.
Usamos o for 6 vezes para gerar imprimir 6 números aleatórios (cada cartão de aposta deve conter seis números).
A cada vez que se repetir, o do... while nos garantirá que o número sorteado x será sempre >=1 e <= 60.

O segundo for checa se aquele número já foi sorteado antes nessa aposta; ele  vai rodar no vetor da matriz que corresponde a aposta atual /* todasApostas[apostas][j] */ e caso encontre um valor igual ao sorteado /* if(todasApostas[apostas][j] == x) */ , i será decrementado (para que se repita o procedimento na mesma posição) e o sistema sairá do segundo for /* break */ - afinal, se já foi encontrado uma repetição, não é necessário rodar o resto do vetor. 
Caso não encontre depois que rodar todo o vetor, o valor sorteado (x) será atribuído à matriz de apostas e i será incrementado /* for (i=0;i<6;i++) */.

(trecho da imagem 4)
Depois de fazer isso para todos os seis números do primeiro for, o sistema sai também do mesmo. 
O puts(""); é puramente para aparência do programa, para dar uma quebra de linha, portanto, não é algo essencial.

O último for vai imprimir para o usuário seu cartão randômico. E, antes do final do if principal que define a estrutura da aposta randômica, a variável apostas recebe apostas+1.
PS: o comando rand() %60 sorteia um número aleatório >=0 e <=60.

     6. Apostas pelo usuário
(imagem 5)
Caso o usuário opte por fazer sua própria aposta /* if (p==0) */ , então o programa vai entrar nessa estrutura para armazenar os números.
Dentro do for:
Enquanto o usuário digitar um número inválido, o programa solicitará um novo número. 
Quando digitado um número válido, o programa vai avaliar se o número já foi digitado antes (dentro de um segundo for, como fizemos para o cartão randômico):
(trecho da imagem 5)
Para cada número da aposta será repetido o que está dentro do for principal, armazenando um a um na matriz /* todasApostas[apostas][i] = x; */ e depois, apostas recebe apostas+1.

     7. Deseja fazer uma nova aposta?
(imagem 6)
Enquanto o usuário ainda não tiver chegado ao limite de 5 cartões o programa vai perguntar se ainda deseja fazer uma nova aposta; e solicitará uma opção válida enquanto for digitado um número diferente de 1 e 0, então armazenará o número na variável n (aquela usada na condição do while do passo 4), fazendo com que a estrutura de fazer apostas se repita até que a pessoa selecione 0 ou atinja o limite.
E, enfim, fechamos o while do passo 4 e acaba a parte do código referente a fazer as apostas.

     8. Ordenando as cartelas de apostas em ordem crescente e as imprimindo
8.1 ORDENANDO:
(imagem 7)
Estrutura simples de ordenação, a única diferença é que por ser matriz, precisamos de 3 for. Basicamente ele percorre cada número de cada linha e na mesma linha, caso encontre um número menor que o anterior, usa a auxiliar x (aproveitamento de variável) para trocar os valores.

8.2 IMPRIMINDO:
(imagem 8)
Os três ifs são apenas para diferenciar a mensagem de tela, de acordo com a quantidade de apostas feitas pelo usuário, portanto, são opcionais; você pode colocar uma mensagem única se quiser.
Os dois for vão imprimir as apostas da matriz, e a cada cartão, pula uma linha.
A condição é i<apostas-1, porque sem ela, caso o usuário fizesse apenas duas apostas, por exemplo, o programa continuaria a imprimir outras linhas da matriz zeradas.  

     9. Sorteando, ordenando e imprimindo resultado
9.1 SORTEANDO:
(imagem 9)
Mesma estrutura de sorteio para cartões randômicos, a diferença é que o armazenamento agora é em um vetor e não em uma matriz.

9.2 ORDENANDO 
(imagem 10)
Também usamos a mesma estrutura de ordenação que a dos cartões do usuário, dessa vez, no entanto, com apenas dois for, já que é um vetor e não uma matriz. 
OBS: Caso vá copiar e colar, cuidado para não se embolar com as variáveis i, j (e m, no caso de três); é importante conhecer seus comportamentos dentro do código para que isso não aconteça.

9.3 IMPRIMINDO RESULTADO
(imagem 11)
Impressão simples do vetor de resultado já ordenado. PS: Antes do for, use um puts("\n Resultado da Megasena:\n"); para pular uma linha e melhorar a organização antes de imprimir o resultado.

     10. Resultado final: Informando se o usuário ganhou quadra, quina, sena ou nada:
10.1 CHECANDO IGUALDADES
(imagem 12)
O cont vai contar quantos números iguais existem entre cada cartão de aposta e o vetor do resultado. Para cada cartão ele vai checar a quantidade e imprimir para o usuário o que ele ganhou em cada cartão:
10.2 INFORMANDO O QUE O USUÁRIO GANHOU
(imagem 13)
Caso cont for igual a 6 (tendo assim 6 igualdades entre a cartela e o resultado), ele imprimirá que o usuário ganhou uma Sena e sucessivamente, como na imagem. 
O for aberto na imagem 12 fecha na linha com fundo azul e o código termina logo depois dele também, como você pode ver:


Eu disse que era mais simples do que parece. Qualquer dúvida pode deixar aí nos comentários que eu vou tentar responder o quanto antes :)
Espero que tenham gostado e se tiverem sugestões, pode deixar aí também. Quero ver todo mundo fazendo o seu próprio código e treinando! Agora compartilha com teus amigos que estão com dificuldade na matéria! Beijos e até a próxima.

3 comentários:

  1. Porque que você usar outra função dentro do srand? "srand(time(NULL));"?

    ResponderExcluir
    Respostas
    1. Para que a cada sorteio os números não sejam os mesmos, caso não use, todas as vezes que o algoritmo for executado, os valores não mudarão.

      Excluir
  2. Ola, esse fundamento utilizado também pode ser baseado na criação de um simulador de QUINA??

    ResponderExcluir