C Números Aleatórios (rand)
Jogos jogam dados, sorteios escolhem um ganhador, quizzes embaralham as perguntas. Em todos eles o programa precisa de números que não dá para prever. O C tem duas funções para isso, no <stdlib.h>: rand, que sorteia, e srand, que "embaralha" o sorteio. Nesta aula você vai entender por que o computador, que só sabe fazer contas, consegue parecer sortudo, por que o seu programa sorteia sempre os mesmos números (e como consertar), como sortear dentro de um intervalo e os erros mais comuns.
- O que o
rand()devolve e o que é oRAND_MAX. - Como transformar o resultado num dado de 1 a 6, ou em qualquer intervalo.
- O que é a semente, por que usar
srand(time(NULL))e por que chamá-lo uma vez só. - Quando uma semente fixa é útil.
- Como sortear números com vírgula e embaralhar uma lista.
- Os limites do
rand: o viés do resto e por que ele não serve para senhas.
Todos os programas foram compilados com o gcc 15.2 na máquina fictícia da Ana (usuária ana, computador notebook), na pasta ~/c, com gcc -std=c23 -Wall -Wextra arquivo.c -o programa.
O C diz o que o rand faz, mas não qual conta ele usa. Cada biblioteca C escolhe a sua. Os terminais da aula mostram a do Linux (glibc). O editor do guia usa outra biblioteca (a wasi-libc), e por isso sorteia outros números, mesmo com a mesma semente. Os dois estão certos. As missões desta aula conferem o que vale em qualquer computador (o intervalo, por exemplo), nunca os números sorteados.
A ideia: o caderno de números
Imagine que a professora da Ana tem um caderno com milhões de números escritos em sequência, sem nenhum padrão que se perceba: 1804289383, 846930886, 1681692777… Quando alguém pede "um número aleatório", ela lê o próximo número do caderno.
- Para quem recebe, os números parecem sorte.
- Mas se ela começar sempre da primeira página, a turma de amanhã recebe os mesmos números, na mesma ordem.
- Para cada aula ser diferente, ela precisa abrir o caderno numa página diferente. O número da página é a semente.
O rand funciona assim. Os números não são sorte de verdade: são o resultado de uma conta, feita a partir do número anterior. Por isso se chamam pseudoaleatórios ("falsos aleatórios"). A conta é escolhida para que eles pareçam aleatórios, e para jogos e sorteios do dia a dia isso basta.
1. rand() e RAND_MAX
rand() ("random", aleatório) não recebe nada e devolve um int entre 0 e RAND_MAX, uma constante que também vem do <stdlib.h>:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("RAND_MAX = %d\n", RAND_MAX);
for (int i = 0; i < 5; i++) {
printf("%d ", rand());
}
printf("\n");
return 0;
}
- #include <stdlib.h>
- A "standard library", biblioteca padrão: traz
rand,srandeRAND_MAX. - RAND_MAX
- O maior número que o
randpode devolver. O C só garante que ele vale pelo menos 32767; no Linux (e no editor) é 2147483647, o maiorint. - rand()
- Cada chamada devolve o próximo número da sequência.
$ gcc -std=c23 -Wall -Wextra dado.c -o dado $ ./dado RAND_MAX = 2147483647 1804289383 846930886 1681692777 1714636915 1957747793 $ ./dado RAND_MAX = 2147483647 1804289383 846930886 1681692777 1714636915 1957747793 « os mesmos cinco, de novo
Rodou duas vezes e saíram exatamente os mesmos números. É o caderno aberto sempre na primeira página: sem você escolher uma semente, o C usa a semente 1. No editor, a sequência é outra (o primeiro número lá é 0), mas também se repete a cada Rodar.
2. Um dado de 1 a 6
Números de até 2 bilhões não servem para um jogo de tabuleiro. Para trazer o resultado para um intervalo pequeno, usamos o resto da divisão (%, de Operadores Aritméticos): o resto de uma divisão por 6 é sempre um número de 0 a 5.
| Expressão | Resultado possível | Por quê |
|---|---|---|
rand() | de 0 a 2147483647 | Um número grande qualquer. |
rand() % 6 | de 0 a 5 | O resto da divisão por 6 nunca chega a 6. |
rand() % 6 + 1 | de 1 a 6 | Soma 1 nos dois extremos: o 0 vira 1 e o 5 vira 6. |
#include <stdio.h>
#include <stdlib.h>
int main(void) {
for (int i = 0; i < 10; i++) {
int dado = rand() % 6 + 1;
printf("%d ", dado);
}
printf("\n");
return 0;
}
$ gcc -std=c23 -Wall -Wextra dado6.c -o dado6 $ ./dado6 2 5 4 2 6 2 5 1 4 2 $ ./dado6 2 5 4 2 6 2 5 1 4 2
Dez jogadas de dado, todas entre 1 e 6. Mas, de novo, a mesma partida toda vez. A seção 3 resolve isso.
Missão: o programa joga o dado 1000 vezes e conta quantas jogadas ficaram entre 1 e 6. Rode e veja: algumas ficaram de fora, porque rand() % 6 dá de 0 a 5. Conserte a linha do dado para ele dar de 1 a 6.
Dentro de 1 a 6: 1000 de 1000
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int dentro = 0;
for (int i = 0; i < 1000; i++) {
int dado = rand() % 6; // conserte: tem de dar de 1 a 6
if (dado >= 1 && dado <= 6) {
dentro++;
}
}
printf("Dentro de 1 a 6: %d de 1000\n", dentro);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int dentro = 0;
for (int i = 0; i < 1000; i++) {
int dado = rand() % 6 + 1;
if (dado >= 1 && dado <= 6) {
dentro++;
}
}
printf("Dentro de 1 a 6: %d de 1000\n", dentro);
return 0;
}
3. A semente: srand
srand(numero) ("seed random", semear o aleatório) escolhe a página do caderno: a partir dela, o rand segue outra sequência. Para cada execução ser diferente, precisamos de uma semente que mude sozinha. O clássico é o relógio: time(NULL), do <time.h>, devolve quantos segundos se passaram desde 1º de janeiro de 1970, um número que muda a cada segundo.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
for (int i = 0; i < 10; i++) {
printf("%d ", rand() % 6 + 1);
}
printf("\n");
return 0;
}
- #include <time.h>
- Traz a função
time. - time(NULL)
- A hora atual, em segundos. O
NULLquer dizer "só me devolva o número" (veja Ponteiro Nulo, no Nível 2). - srand(time(NULL));
- Usa a hora como semente. Fica no começo do
main, antes do primeirorand(), e roda uma vez só.
$ gcc -std=c23 -Wall -Wextra semente.c -o semente $ ./semente 1 2 6 5 6 6 3 4 3 3 $ sleep 1 « espera um segundo $ ./semente 2 5 5 1 4 6 3 6 4 4 « outra partida
Agora cada execução é uma partida diferente. O sleep 1 está ali porque a semente só muda de um segundo para o outro: dois programas iniciados no mesmo segundo recebem a mesma semente e sorteiam a mesma coisa. Para um jogo, não faz diferença.
Experimente: clique em Rodar várias vezes, esperando um pouco entre uma e outra: as jogadas mudam. Depois apague a linha do srand e rode de novo: a partida volta a ser sempre a mesma.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
for (int i = 0; i < 10; i++) {
printf("%d ", rand() % 6 + 1);
}
printf("\n");
return 0;
}
Semente fixa: repetir o sorteio de propósito
Às vezes a repetição é exatamente o que você quer. Se o jogo tem um defeito que só aparece com certos sorteios, você precisa reproduzir aquela partida para encontrá-lo. Para isso, use uma semente fixa, qualquer número:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
srand(42);
for (int i = 0; i < 10; i++) {
printf("%d ", rand() % 6 + 1);
}
printf("\n");
return 0;
}
$ gcc -std=c23 -Wall -Wextra fixa.c -o fixa $ ./fixa 1 1 6 4 5 5 2 1 6 6 $ ./fixa 1 1 6 4 5 5 2 1 6 6
Com srand(42), a sequência é sempre a mesma neste computador. No editor do guia, a mesma semente dá 3 2 5 1 3 2 5 3 1 3: outra biblioteca, outra conta. Um teste que espera "o primeiro dado é 1" funciona no Linux e falha no editor (ou no Windows, ou no macOS). Use a semente fixa para repetir partidas na mesma máquina, nunca para prometer números exatos.
4. Sortear entre um mínimo e um máximo
O dado foi um caso especial. Para sortear de qualquer min a qualquer max, a conta geral é:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int sortear(int min, int max) {
return rand() % (max - min + 1) + min;
}
int main(void) {
srand(time(NULL));
printf("Dado: %d\n", sortear(1, 6));
printf("Moeda: %s\n", sortear(0, 1) == 0 ? "cara" : "coroa");
printf("Mega-Sena: %d\n", sortear(1, 60));
printf("Mês: %d\n", sortear(1, 12));
printf("Desconto: %d%%\n", sortear(5, 15));
return 0;
}
- max - min + 1
- Quantos números existem no intervalo. De 5 a 15 são 11 números (5, 6, …, 15), e não 10: o
+ 1conta os dois extremos. - rand() % (max - min + 1)
- Um número de 0 a 10 (para o desconto).
- … + min
- Empurra o intervalo para começar no
min: de 0–10 para 5–15. - sortear(0, 1) == 0 ? "cara" : "coroa"
- Uma moeda: sorteia 0 ou 1 e escolhe o texto com o operador ternário.
$ gcc -std=c23 -Wall -Wextra sortear.c -o sortear $ ./sortear Dado: 1 Moeda: coroa Mega-Sena: 10 Mês: 7 Desconto: 13% $ sleep 1 $ ./sortear Dado: 4 Moeda: cara Mega-Sena: 60 Mês: 11 Desconto: 7%
Repare no srand: ele fica no main, e não dentro de sortear. A função é chamada cinco vezes; a semente é plantada uma vez só. (A seção "Quando dá errado" mostra o que acontece se o srand for parar dentro de um laço.)
Todas as faces saem por igual?
Um dado honesto dá cada face mais ou menos 1/6 das vezes. Jogando 6000 vezes, cada face deveria sair perto de 1000:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int contagem[7] = {0};
srand(time(NULL));
for (int i = 0; i < 6000; i++) {
int dado = rand() % 6 + 1;
contagem[dado]++;
}
for (int face = 1; face <= 6; face++) {
printf("face %d: %d vezes\n", face, contagem[face]);
}
return 0;
}
$ gcc -std=c23 -Wall -Wextra frequencia.c -o frequencia $ ./frequencia face 1: 1038 vezes face 2: 1016 vezes face 3: 980 vezes face 4: 934 vezes face 5: 1055 vezes face 6: 977 vezes
O array tem 7 posições para usar o próprio número da face como índice (a posição 0 fica sem uso; veja Arrays). Nenhuma face deu exatamente 1000, e isso é normal: com um dado de verdade também não daria. O importante é que todas ficaram perto.
5. Números com vírgula
Para sortear um double entre 0 e 1, divida o rand() por um número um pouco maior que o maior resultado possível:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
srand(7);
for (int i = 0; i < 4; i++) {
double x = rand() / (RAND_MAX + 1.0);
printf("%.4f\n", x);
}
double preco = 10.0 + rand() / (RAND_MAX + 1.0) * 5.0;
printf("Preço entre 10 e 15: %.2f\n", preco);
return 0;
}
- rand() / (RAND_MAX + 1.0)
- Um número de 0 até quase 1 (o 1 nunca sai, porque o
rand()nunca chega aRAND_MAX + 1). O1.0faz a conta ser com vírgula; com1, seria divisão inteira, e há um problema pior, mostrado logo abaixo. - 10.0 + … * 5.0
- Estica o intervalo de 0–1 para 0–5 e empurra para 10–15.
$ gcc -std=c23 -Wall -Wextra fracao.c -o fracao $ ./fracao 0.4869 0.8680 0.5926 0.2147 Preço entre 10 e 15: 10.05
Com RAND_MAX + 1 (sem o .0), a soma é feita com int, e RAND_MAX já é o maior int. O gcc avisa:
$ gcc -std=c23 -Wall -Wextra fracaoerr.c -o fracaoerr
fracaoerr.c: In function ‘main’:
fracaoerr.c:5:35: warning: integer overflow in expression of type ‘int’ results in ‘-2147483648’ [-Woverflow]
5 | double x = rand() / (RAND_MAX + 1);
| ^
$ ./fracaoerr
0.000000
"Estouro de inteiro na expressão do tipo int, que resulta em −2147483648". O RAND_MAX + 1 deu a volta e virou negativo (Inteiros), e a divisão inteira de um rand() por esse número dá sempre 0. No editor, o Clang avisa: overflow in expression; result is -2'147'483'648 with type 'int' [-Winteger-overflow].
6. Embaralhar uma lista
A turma da Ana tem 8 alunos, numerados de 1 a 8, e a ordem das apresentações tem de ser sorteada. Sortear 8 números de 1 a 8 não funciona: o mesmo aluno poderia sair duas vezes. O certo é embaralhar a lista, como um baralho. O jeito clássico é o embaralhamento de Fisher-Yates: de trás para a frente, troque cada item com um item sorteado entre os que ainda não foram fixados.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void embaralhar(int v[], int n) {
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
int temp = v[i];
v[i] = v[j];
v[j] = temp;
}
}
int main(void) {
int alunos[8] = {1, 2, 3, 4, 5, 6, 7, 8};
srand(time(NULL));
embaralhar(alunos, 8);
printf("Ordem das apresentações:");
for (int i = 0; i < 8; i++) {
printf(" %d", alunos[i]);
}
printf("\n");
return 0;
}
- for (int i = n - 1; i > 0; i--)
- Começa pelo último lugar da fila e vai até o segundo.
- int j = rand() % (i + 1);
- Sorteia uma posição de 0 a
i: qualquer um dos alunos que ainda não ganharam lugar fixo, incluindo o próprioi. - temp, v[i] = v[j], v[j] = temp
- Troca os dois de lugar, com uma variável de apoio. Depois disso, a posição
iestá decidida e não mexe mais. - void embaralhar(int v[], int n)
- A função recebe o array e muda o array do
main(arrays não são copiados; o porquê está em Ponteiros e Arrays).
$ gcc -std=c23 -Wall -Wextra embaralhar.c -o embaralhar $ ./embaralhar Ordem das apresentações: 5 7 2 1 3 6 8 4 $ sleep 1 $ ./embaralhar Ordem das apresentações: 2 8 1 6 7 5 3 4
Cada aluno aparece exatamente uma vez, numa ordem diferente a cada execução. O mesmo código embaralha cartas, perguntas de quiz ou músicas de uma playlist.
Os limites do rand: qual usar
O viés do resto
O % tem um pequeno defeito. Imagine um rand de brinquedo que só sorteia de 0 a 9 (10 números), e você quer de 0 a 2 com % 3:
Resultado de % 3 | Vem de quais sorteios | Chance |
|---|---|---|
| 0 | 0, 3, 6, 9 | 4 em 10 |
| 1 | 1, 4, 7 | 3 em 10 |
| 2 | 2, 5, 8 | 3 em 10 |
Como 10 não se divide por 3, o 0 sai mais. Com o RAND_MAX de 2 bilhões e um intervalo pequeno (um dado, uma Mega-Sena), a diferença é tão pequena que não se percebe. Ela só importa com intervalos enormes, perto do próprio RAND_MAX.
| Para… | Use | Observação |
|---|---|---|
| Jogos, exercícios, simulações simples | srand(time(NULL)) uma vez + rand() % n + min | O que esta aula ensinou |
| Repetir a mesma partida na mesma máquina | srand(numero_fixo) | Os números mudam de biblioteca para biblioteca |
| Número com vírgula | rand() / (RAND_MAX + 1.0) | Com .0, nunca RAND_MAX + 1 |
| Ordem aleatória sem repetir | Embaralhar (Fisher-Yates) | Não sorteie item por item |
| Senhas, códigos de acesso, sorteios valendo dinheiro | Nunca o rand: a fonte segura do sistema (no Linux, getrandom) | Quem descobre a semente (por exemplo, a hora em que o programa rodou) prevê todos os números |
Quando dá errado
O que significa: faltou o srand. Sem ele, a semente é sempre 1, e o programa repete a mesma "sorte" a cada execução.
Como consertar: srand(time(NULL)); no começo do main, com #include <time.h>.
srand dentro do laço
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
for (int i = 0; i < 10; i++) {
srand(time(NULL));
printf("%d ", rand() % 6 + 1);
}
printf("\n");
return 0;
}
$ gcc -std=c23 -Wall -Wextra laco.c -o laco $ ./laco 4 4 4 4 4 4 4 4 4 4
O que aconteceu: o laço inteiro roda em menos de um segundo. A cada volta, o srand planta a mesma semente (a hora não mudou) e o rand recomeça do mesmo ponto: o primeiro número daquela sequência, de novo e de novo. É como abrir o caderno na mesma página antes de cada leitura. O compilador não avisa.
Como consertar: tire o srand do laço (e de dentro de funções chamadas várias vezes). Ele vai uma vez só, no começo do main.
$ ./zeroseis 1 4 3 1 5 1 4 0 3 1 2 1 2 1 5 4 0 0 4 4
O que significa: o código usa rand() % 6, que dá de 0 a 5.
Como consertar: some o mínimo: rand() % 6 + 1. Em geral, rand() % (max - min + 1) + min.
Exceção de ponto flutuante (código 136)
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int premios = 0;
printf("Sorteando...\n");
int sorteado = rand() % premios;
printf("Prêmio %d\n", sorteado);
return 0;
}
$ gcc -std=c23 -Wall -Wextra zero.c -o zero $ ./zero Sorteando... Exceção de ponto flutuante (imagem do núcleo gravada) ./zero $ echo $? 136
O que significa: rand() % 0 é uma divisão inteira por zero, que derruba o programa (apesar do nome, a "exceção de ponto flutuante" acontece com inteiros). Acontece quando o tamanho do intervalo vem de uma variável que, naquele momento, vale 0: uma lista vazia, por exemplo. No editor, o resultado é o mesmo, com código 136.
Como consertar: antes de sortear, confira: if (premios > 0) { … }.
error: implicit declaration of function ‘srand’ (e de time e rand)
$ gcc -std=c23 -Wall -Wextra seminclude.c -o seminclude
seminclude.c: In function ‘main’:
seminclude.c:4:5: error: implicit declaration of function ‘srand’ [-Wimplicit-function-declaration]
4 | srand(time(NULL));
| ^~~~~
seminclude.c:4:11: error: implicit declaration of function ‘time’ [-Wimplicit-function-declaration]
4 | srand(time(NULL));
| ^~~~
seminclude.c:2:1: note: ‘time’ is defined in header ‘<time.h>’; this is probably fixable by adding ‘#include <time.h>’
1 | #include <stdio.h>
+++ |+#include <time.h>
2 |
seminclude.c:5:20: error: implicit declaration of function ‘rand’ [-Wimplicit-function-declaration]
5 | printf("%d\n", rand() % 6 + 1);
| ^~~~
O que significa: faltaram os #include. Para o time, o gcc até diz qual: ‘time’ is defined in header ‘<time.h>’ ("o time está definido no cabeçalho <time.h>"). No editor, o Clang diz use of undeclared identifier 'srand'.
Como consertar: #include <stdlib.h> (para rand e srand) e #include <time.h> (para time).
warning: integer overflow in expression of type ‘int’ results in ‘-2147483648’
O que significa: você escreveu RAND_MAX + 1, uma conta de int que estoura.
Como consertar: RAND_MAX + 1.0, para a conta ser feita com double.
Referência rápida
| Código | O que faz |
|---|---|
#include <stdlib.h> | Traz rand, srand e RAND_MAX |
rand() | Um int de 0 a RAND_MAX, o próximo da sequência |
RAND_MAX | O maior valor do rand() (pelo menos 32767; no Linux, 2147483647) |
srand(time(NULL)); | Semente pela hora: uma sequência nova a cada execução (precisa de <time.h>). Uma vez só, no começo |
srand(42); | Semente fixa: a mesma sequência a cada execução, na mesma biblioteca |
rand() % 6 + 1 | Um dado: de 1 a 6 |
rand() % (max - min + 1) + min | De min a max, incluindo os dois |
rand() / (RAND_MAX + 1.0) | Um double de 0 até quase 1 |
j = rand() % (i + 1) + troca | Um passo do embaralhamento de Fisher-Yates |
Exercícios
1. A semente pela hora
Complete a linha que faz cada execução sortear números diferentes:
2. Uma moeda
Complete para sortear 0 ou 1:
3. Um dado de 20 faces
Complete para sortear de 1 a 20:
4. Quantos números diferentes rand() % (15 - 5 + 1) + 5 pode dar?
5. Um programa chama srand(time(NULL)) dentro de um laço de 10 voltas e sorteia um dado em cada volta. O que costuma acontecer?
6. Para gerar a senha provisória de um site de banco, o rand serve?
Missão final: a rifa da festa junina
Missão: os bilhetes da rifa vão do 10 ao 20. A função sortear(min, max) deveria devolver um número de min a max (incluindo os dois), mas está errada. O main faz 10 000 sorteios e confere: qual foi o menor, qual foi o maior e quantos ficaram fora do intervalo. Conserte a função. A saída tem de ser exatamente esta, sem avisos:
Menor sorteado: 10 Maior sorteado: 20 Fora do intervalo: 0
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int sortear(int min, int max) {
return rand() % max; // conserte: de min a max
}
int main(void) {
srand(time(NULL));
int menor = 1000;
int maior = -1000;
int fora = 0;
for (int i = 0; i < 10000; i++) {
int bilhete = sortear(10, 20);
if (bilhete < menor) {
menor = bilhete;
}
if (bilhete > maior) {
maior = bilhete;
}
if (bilhete < 10 || bilhete > 20) {
fora++;
}
}
printf("Menor sorteado: %d\n", menor);
printf("Maior sorteado: %d\n", maior);
printf("Fora do intervalo: %d\n", fora);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int sortear(int min, int max) {
return rand() % (max - min + 1) + min;
}
int main(void) {
srand(time(NULL));
int menor = 1000;
int maior = -1000;
int fora = 0;
for (int i = 0; i < 10000; i++) {
int bilhete = sortear(10, 20);
if (bilhete < menor) {
menor = bilhete;
}
if (bilhete > maior) {
maior = bilhete;
}
if (bilhete < 10 || bilhete > 20) {
fora++;
}
}
printf("Menor sorteado: %d\n", menor);
printf("Maior sorteado: %d\n", maior);
printf("Fora do intervalo: %d\n", fora);
return 0;
}
Com o código errado, rand() % 20 dá de 0 a 19: o menor sorteado é 0, o 20 nunca sai e quase metade dos bilhetes fica fora. (O aviso unused parameter 'min' também denunciava o erro: a função ignorava o mínimo.) Essa conferência funciona com qualquer semente e em qualquer computador: em 10 000 sorteios de 11 números, todos acabam aparecendo.
Resumo
rand()(do<stdlib.h>) devolve umintde 0 aRAND_MAX. Os números são pseudoaleatórios: saem de uma conta.- Sem semente, a sequência é sempre a mesma.
srand(time(NULL)), uma vez, no começo domain, muda a sequência a cada execução. Dentro de um laço, ele repete o mesmo número. - Uma semente fixa (
srand(42)) repete a partida, útil para achar defeitos. Cada biblioteca C tem a sua conta: o editor sorteia outros números que o Linux. - De
minamax:rand() % (max - min + 1) + min. Com vírgula:rand() / (RAND_MAX + 1.0). Ordem sem repetir: embaralhe (Fisher-Yates). rand() % 0derruba o programa (Exceção de ponto flutuante, 136).- O
randserve para jogos e simulações, nunca para senhas. - Próxima aula, no Nível 2: Memória e Endereços. Para usar tudo isto num jogo completo, veja o Projeto: Jogo de Adivinhação.