Buscar

Trabalho implementar um jogo em C especificação

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 16 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 16 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 16 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Universidade de Brasília
Departamento de Ciência da Computação/IE
Semestre: 2/2015
Disciplina: Algoritmos e Programação de Computadores
Trabalho Prático 1
O objetivo desta primeira etapa é que o aluno aprenda a utilizar estrututas condicionais, laços de 
repetição, funções, arquivos de texto e variáveis globais em algoritmos e a implementá-los em 
programas que executem corretamente no computador.
Especificação da primeira etapa:
Problema: IMPLEMENTAR A ESTRUTURA INICIAL DE UM PROGRAMA QUE 
(POSTERIORMENTE) DEVERÁ EXECUTAR UMA VERSÃO DO JOGO “EliminaLetras”.
Neste trabalho, você deve implementar a estrutura inicial de um programa que (posteriormente) deverá 
executar uma versão do jogo “EliminaLetras”. Este jogo é basicamente uma matriz de caracteres 
preenchida com diferentes símbolos, da qual o jogador deve selecionar posições para eliminar um 
elemento e todos os vizinhos (consecutivos) que contiverem o mesmo símbolo daquele elemento. 
Quanto maior a vizinhança eliminada de uma vez, maior a pontuação obtida na jogada. Para esta 
primeira etapa, você deve implementar o menu principal, mensagens iniciais e finais de apresentação e 
um menu de configurações do jogo. As configurações devem ser persistidas num arquivo de texto.
Detalhamento do problema:
1) Hello, world! - Inicialmente, o programa deve mostrar uma mensagem de boas-vindas e solicitar ao 
usuário que pressione ENTER, como na imagem à seguir:
2) Menu principal - Em seguida, o programa deve entrar em um laço (loop) para o menu principal. Os 
passos dentro deste laço (loop) devem ser basicamente mostrar a tela do menu, ler a opção do usuário e 
executar a opção selecionada. A condição de parada para este laço (loop) é que o usuário selecione a 
última opção do menu: sair. Veja um exemplo de tela:
3) Detalhamento do menu principal
3.1) A primeira opção do menu principal deve ser a opção de jogar a versão implementada do 
“EliminaLetras”. Esta opção deverá ser posteriormente implementada no Trabalho Prático 2 – parte 1. 
Coloque apenas um aviso temporário de “em construção”.
3.2) A segunda opção do menu principal deve ser a opção de visualizar o ranking de partidas que já 
aconteceram, persistido em um arquivo binário. Esta opção deverá ser posteriormente implementada no 
Trabalho Prático 2 – parte 2. Coloque apenas um aviso temporário de “em construção”.
3.3) A terceira opção do menu principal deve fazer o programa entrar em mais um laço (loop): o menu 
de configurações do jogo. As quatro primeiras opções deste menu devem servir para alterar 
respectivamente cada uma das quatro variáveis de configuração do jogo. São elas:
– 1. string com os caracteres que serão utilizados para preencher a matriz do jogo,
– 2. quantidade de linhas da matriz, 
– 3. quantidade de colunas da matriz e
– 4. a base da pontuação. 
Após ler o novo valor de alguma configuração, o programa deve perguntar ao usuário se a mudança 
deve realmente ser efetuada, ou seja, confirmar o alteração. A última opção deve encerrar o laço (loop) 
do menu de configurações, finalizando a execução da terceira opção do menu principal. Veja alguns 
exemplos:
3.4) A última opção do menu principal deve encerrar o laço (loop). Ao verificar que o usuário solicitou 
esta opção, o programa deve sair do laço (loop), mostrar uma mensagem de até logo, solicitar que o 
usuário pressione ENTER e encerrar o programa, como na seguinte imagem:
4) Variáveis globais - Neste trabalho, você deverá utilizar variáveis globais. Este recurso deve ser 
utilizado com bastante cuidado, portanto, é sugerido fortemente que você leia o apêndice referente para 
entender a maneira correta de escolher quais variáveis deverão ser globais ao criar um programa.
Neste programa, as variáveis globais deverão ser apenas as seguintes:
char caracteres[11]; /* caracteres para preencher a matriz do jogo */
int linhas, colunas; /* dimensoes da matriz */
float base_pontos; /* base para a pontuacao no jogo */
5) Validação de entrada
5.1) Ao receber uma opção de menu inválida, o programa deve mostrar uma mensagem de erro e 
solicitar que o usuário entre com a opção novamente. Veja um exemplo:
5.2) Dentro da terceira opção no menu principal, ao ler uma das quatro configurações do jogo, o 
programa deve realizar as verificações/validações a seguir:
5.2.1) O tamanho da string de caracteres deve ser no mínimo 3 e no máximo 10. ATENÇÃO: Não é 
necessário realizar nenhum outro teste de consistência com a string.
5.2.2) A quantidade de linhas da matriz deve ser no mínimo 3 e no máximo 9.
5.2.3) A quantidade de colunas da matriz deve ser no mínimo 3 e no máximo 9.
5.2.4) A base da pontuação deve ser maior que 1 e menor ou igual a 2. Este número servirá para 
calcular o pontos recebidos por jogada. Será utilizado no Trabalho Prático 2.
6) Arquivo de texto – A maneira de armazenar as configurações do jogo será através de um arquivo de 
texto. Desta forma, o usuário pode alterar as configurações através do programa, ou editando 
diretamente o arquivo. O formato do arquivo deverá ser o seguinte:
- A primeira linha deverá conter a string com as letras que serão utilizadas no jogo;
- A segunda linha deverá conter a quantidade de linhas da matriz do jogo;
- A terceira linha deverá conter a quantidade de colunas da matriz do jogo;
- A quarta e última linha deverá conter a base da pontuação.
O nome do arquivo de texto deve ser: EliminaLetras_settings.txt
A seguir é dada uma sugestão de funções a serem criadas para implementar o trabalho. Duas delas 
manipulam diretamente o arquivo de texto.
WriteSettings()
Esta função deve simplesmente escrever os valores das variáveis globais no arquivo de texto, seguindo 
o formato especificado.
readSettings()
Esta função deve ler o arquivo de texto com as configurações do jogo para preencher as variáveis 
globais. A lógica desta função deve ser a seguinte:
- Tentar abrir o arquivo. Se não conseguir, preencher as variáveis globais com valores padrão: 
string=OZXM, linhas=6, colunas=9, base=1.5;
- Se for possível abrir o arquivo, ler os valores do arquivo para preencher as variáveis globais e atribuir 
valores padrão para as configurações com valores eventualmente inválidos (caso o usuário tenha 
editado o arquivo de texto diretamente); 
- Por fim, chamar a função writeSettings() para o caso de não ter sido possível abrir o arquivo, 
ou para o caso de algum valor do arquivo recém lido ser inválido.
A correção do trabalho irá testar a leitura de arquivos com valores inválidos, mas sempre no formato 
correto.
Importante: Sempre que uma das quatro configurações for alterada, através do menu de configurações, 
todo o arquivo deve ser escrito novamente, ou seja, a função writeSettings() deve ser chamada.
7) Funções sugeridas – Para implementar o trabalho, você deve criar as funções abaixo. Os 
nomes das funções são apenas sugestões.
int main(); /* implementa o loop do menu principal */
void helloworld(); /* mostra a mensagem inicial do programa */
MenuMainOpt menuMain(); /* exibe a tela do menu principal, le uma 
opcao e retorna o valor escolhido */
void play(); /* sera implementada no trab2 */
void ranking(); /* sera implementada no trab2 */
void settings(); /* implementa o loop do menu de configuracoes */
MenuSettingsOpt menuSettings(); /* exibe a tela do menu de 
configuracoes, le uma opcao e retorna o valor escolhido */
void changeChars(); /* primeira opcao do menu de configuracoes */
void changeRows(); /* segunda opcao do menu de configuracoes */
void changeCols(); /* terceira opcao do menu de configuracoes */
void changeScoreBase(); /* quarta opcao do menu de configuracoes */
void readSettings(); /* funcao para ler o arquivo de texto */
void writeSettings(); /* funcao para escrever o arquivo de texto */
bool invalidChars(); /* valida a string */
bool invalidRows(); /* valida a quantidade de linhas */
boolinvalidCols(); /* valida a quantidade de colunas */
bool invalidScoreBase(); /* valida a base da pontuacao */
void quit(); /* exibe a tela de ate logo */
Apêndice
A) Pré-processador – Os comandos colocados no código-fonte de um programa que se iniciam com o 
caractere '#' (cerquilha) são comandos para o pré-processador de código. Esta é uma ferramenta que o 
próprio compilador passa em um código antes de compilá-lo de fato. Instruções deste tipo servem para 
modificar de alguma maneira o código-fonte que está prestes a ser compilado. Utilizando uma diretiva 
#include, o pré-processador modifica o código-fonte incluindo, naquela linha onde a diretiva foi 
colocada, um arquivo inteiro, que é especificado na própria diretiva, exemplo: #include 
<stdio.h>. Utilizando uma diretiva #define, o pré-processador modifica o código-fonte 
substituindo toda ocorrência da macro definida pelo respectivo valor de expansão, exemplo: #define 
VALOR_PADRAO 50. É possível combinar diretivas utilizando diretivas condicionais, exemplo:
#ifdef _WIN32
#define CLEAR “cls”
#else
#define CLEAR “clear”
#endif
As diretivas acima definem uma macro com um comando utilizado para limpar a tela, de acordo com o 
sistema operacional em que o código-fonte for compilado. Quando um compilador está sendo 
executado no Windows, a macro _WIN32 fica definida no ambiente e pode ser utilizada em diretivas 
do pré-processador. O trecho acima exemplifica uma maneira de escrever código que compila e executa 
corretamente em diferentes sistemas operacionais.
Observação: No Windows, o comando de terminal “cls” de fato limpa todo o terminal. No Linux, o 
comando equivalente “clear” apenas coloca algumas quebras de linha e sobe a tela.
B) typedef enum
O comando typedef é utilizado para definir sintaticamente novos tipos, ou seja, algo como int, ou 
float. Pode ser utilizado em combinação com diversas estruturas da linguagem C para criar novos 
tipos.
Uma estrutura frequentemente utilizada em C é o comando enum. Este comando serve para criar 
palavras que expandem para valores numéricos durante a compilação. A diferença para um #define, 
é que uma enumeração é expandida pelo próprio compilador, após a expansão do pré-processador, além 
de só serem aceitos valores inteiros.
Em combinação, estes dois comandos podem ser utilizados para criar tipos integrais de uma maneira 
extremamente conveniente. Toda variável em C possui tipo e valor. Além disso, para cada diferente 
tipo existe um conjunto de possíveis valores. Exemplos: int → [ −231 , 231−1 ]; char → 
símbolos da tabela Ascii. Utilizando a combinação typedef enum, é possível criar novos tipos e novos 
valores. Um exemplo comum é incluir o cabeçalho da biblioteca padrão do C “stdbool.h”. Este 
cabeçalho define o tipo bool e seus dois únicos valores: true e false. Este tipo e valores só 
existem de fato na gramática de C++, mas podem ser implementados em C utilizando a forma sugerida 
– que não necessariamente é a forma utilizada no cabeçalho “stdbool.h”. Exemplos:
typedef enum {
 false = 0, /* 0 */
 true /* 1 */
} bool;
typedef enum {
 MENUMAIN_NA = 0, /* 0 */
 MENUMAIN_PLAY, /* 1 */
 MENUMAIN_RANKING, /* 2 */
 MENUMAIN_SETTINGS, /* 3 */
 MENUMAIN_QUIT /* 4 */
} MenuMainOpt;
typedef enum {
 PONTO_CORSA = 200, /* 200 */
 PONTO_GOL, /* 201 */
 PONTO_CELTA, /* 202 */
 PONTO_UNO = 350, /* 350 */
 PONTO_PALIO, /* 351 */
 PONTO_FIT = 198, /* 198 */
 PONTO_CIVIC, /* 199 */
 PONTO_CITY, /* 200 */
 PONTO_FOCUS, /* 201 */
 PONTO_KA /* 202 */
} PontuacaoPorCarro;
bool flag = true;
if (flag == true)
 flag = false;
PontuacaoPorCarro pts;
pts = PONTO_KA;
if (pts == PONTO_FIT)
 /* faca algo */
Apesar de ser possível criar novos tipos e novos valores, estes tipos e valores não estão amarrados. Na 
verdade, tipos criados com a combinação typedef enum não passam de um apelido para o tipo 
int. Isto significa que valores definidos dentro de qualquer enumeração podem ser atribuídos a 
qualquer variável do tipo int, ou de qualquer tipo criado com typedef enum. No entanto, uma boa 
prática de programação e forma de comunicação entre programadores é respeitar as definições das 
enumerações, como forma de programação segura. Um programador deixa uma mensagem implícita 
para outro programador que futuramente coloque as mãos em seu código, dizendo que não é seguro 
atribuir qualquer valor à uma dada variável inteira que utilize uma enumeração: apenas os valores da 
enumeração são seguros. Outros valores inteiros não especificados podem causar mal-funcionamento 
no software.
Além disso, utilizar uma enumeração é uma maneira de criar valores mnemônicos, evitando a 
necessidade de colocar comentários no código para indicar o significado de um valor, o que deixa a 
programação inclusive mais intuitiva.
C) switch – Uma estrutura condicional extremamente recomendada para a implementação de MENUS 
é a estrutura switch. Esta estrutura é apenas uma maneira simplificada de escrever uma sequência 
if-else if-else if-...-else if-else, com a diferença de que o teste condicional 
realizado apenas verifica se um valor inteiro bate com uma das constantes selecionadas. Exemplo para 
o menu principal do seu jogo:
switch (menuMain()) {
 case MENUMAIN_PLAY: play(); break;
 case MENUMAIN_RANKING: ranking(); break;
 case MENUMAIN_SETTINGS: settings(); break;
 case MENUMAIN_QUIT: quit(); break;
 default:
 exit(EXIT_FAILURE);
}
Uma sequência equivalente seria:
MenuMainOpt opt = menuMain();
if (opt == MENUMAIN_PLAY)
 play();
else if (opt == MENUMAIN_RANKING)
 ranking();
else if (opt == MENUMAIN_SETTINGS)
 settings();
else if (opt == MENUMAIN_QUIT)
 quit();
else
 exit(EXIT_FAILURE);
D) Variáveis globais
Neste trabalho, você deve aprender a utilizar variáveis globais de forma correta. Variável global é 
aquela que é declarada no escopo global, ou seja, no mesmo nível em que funções são criadas. Em 
outras palavras, para criar uma variável global você deve declarar uma variável fora de todas as 
funções, no início do arquivo fonte. Ou seja, uma variável global deve possuir o mesmo nível de 
indentação de declarações de funções: nenhum!
A escolha de quais variáveis devem ser globais em um programa deve ser feita com cuidado. 
Normalmente, variáveis que contêm dados ou apontam para regiões de memória que precisam ser 
manipuladas por diversas funções do programa são globais. Isto não quer dizer que, por exemplo, 
variáveis contadoras de laços (loops) devem ser globais. Não é porque diversas funções utilizam 
contadores de laços, que você deve declarar um inteiro global chamado “i”. Se você tentar utilizar um 
contador de laço global, você irá notar que o comportamento do programa será totalmente incorreto, se, 
por exemplo, existir um laço “para” que utiliza esta variável global para realizar a contagem e dentro 
deste laço há uma chamada à uma função que possui outro laço “para” que utiliza a mesma variável 
global “i”. Após a função retornar, a variável “i” estará com o último valor do laço desta função, o que 
muito provavelmente irá provocar o mal funcionamento do laço que chamou a função. Outro exemplo, 
são variáveis utilizadas para realizar troca de valores entre variáveis. Se você utilizar um inteiro global 
“aux” para realizar uma troca de valores entre duas variáveis em diversas funções, muito 
provavelmente o programa irá funcionar de maneira incorreta. Mais um exemplo, são variáveis 
acumuladoras. Não é porque você precisa somar uma série de valores em diversas funções, que você 
deve utilizar uma variável global “total” como acumulador.
Por outro lado, as configurações de um jogo, por exemplo, precisam estar em apenas um lugar da 
memória, durante toda a execução de uma partida deste jogo. A pontuação do jogador é um dado cujo 
valor irá mudar durante a execução da partida, diferentemente dasconfigurações. No entanto, este dado 
também só precisa estar em um lugar da memória. Por acaso, pontuação é uma variável de acumulação, 
ou seja, sempre há exceções a considerar.
Contudo, perceba que é possível implementar um programa que utiliza apenas variáveis locais, por 
mais que muitas destas variáveis possam ser globais. A vantagem em declarar variáveis como globais, 
as que podem ter este privilégio, está em simplificar a interface de diversas funções. Não é necessário, 
por exemplo, que uma variável de pontuação de um jogador precise ser passada como argumento de 
uma função, que repassa esta mesma pontuação como argumento de outra função e assim por diante. 
Todas as variáveis globais são acessíveis dentro de qualquer função. Outra vantagem, do ponto de vista 
de desempenho, tanto temporal quanto espacial, é que o compilador não precisa gerar instruções de 
máquina para empilhar argumentos. O computador não perde tempo colocando argumentos na pilha de 
chamada/registradores e não perde espaço criando cópias e mais cópias de uma mesma variável.
Concluindo, chegamos ao seguinte princípio: uma variável deve ser local, até que hajam razões 
suficientes para que na verdade ela seja global; e não o contrário. Ou seja, não é normal declarar 
inicialmente uma variável como global e somente mover sua declaração para dentro do corpo de uma 
função (tornando-a uma variável local) se aparecerem boas razões para isto. A mudança natural do 
escopo de uma variável é mudar de escopo local para escopo global, quando surgem fortes razões. O 
contrário pode acontecer, mas não é comum.
E) Função system() - Uma sugestão interessante para o trabalho é utilizar a função system() do 
cabeçalho “stdlib.h” para limpar o terminal, a cada vez que o programa for exibir uma nova tela. 
Utilizando a dica do item A do apêndice, basta realizar a chamada system(CLEAR);
Observações gerais:
1. Incluir cabeçalho como comentário (ou seja, entre /* */), no programa fonte, de acordo com os 
critérios de avaliação dos trabalhos (Disponível no Moodle).
2. A data de entrega do programa é: 19/10/2015 (2a-feira) até às 23:55 hs, via moodle. 
3. O arquivo fonte deve ser compactado em um arquivo .zip ou .rar, seguindo as regras de 
nomenclatura especificadas na guia do aluno.
4. Sigam as determinações quanto às entradas e saídas do programa. Serão descontados pontos de 
programas que tiverem de ter a entrada e/ou a saída corrigidas. Se tiverem alguma dúvida quanto à 
formatação de entrada e de saída, entrem em contato com os monitores com antecedência em relação 
ao prazo de entrega do trabalho.
Universidade de Brasília
Departamento de Ciência da Computação/IE
Semestre: 2015-2
Disciplina: Algoritmos e Programação de Computadores
Trabalho Prático 2
O objetivo desta segunda etapa é que o aluno aprenda a utilizar vetores/strings, matrizes (primeira 
parte), registros e arquivos binários (segunda parte) em algoritmos e a implementá-los em programas 
que executem corretamente no computador.
Especificação da primeira etapa:
Problema: IMPLEMENTAR O JOGO “EliminaLetras”.
Neste trabalho, você deve implementar a parte restante do programa proposto na primeira etapa, ou 
seja, implementar o jogo propriamente dito e um ranking que utiliza arquivo binário para registrar as 
maiores pontuações obtidas no jogo. O jogo “EliminaLetras” é basicamente uma matriz de caracteres 
preenchida com diferentes símbolos, da qual o jogador deve selecionar posições para eliminar um 
elemento e todos os vizinhos laterais que contiverem o mesmo símbolo daquele elemento. Quanto 
maior a vizinhança eliminada de uma vez, maior a pontuação obtida na jogada.
Detalhamento do problema:
Parte 1
1) Opção 1 do menu principal – Ao escolher a opção de jogar uma partida, o programa deve 
perguntar ao usuário um apelido (por exemplo: char nick[21]), que servirá como identificação ao 
gravar pontuações no ranking. Esta solicitação deve ser repetida até que o usuário digite um apelido 
com no mínimo 3 e no máximo 20 caracteres. Exemplo:
2) Partida – Ao receber um apelido válido, o programa deve iniciar uma partida. A lógica de uma 
partida deve ser a seguinte:
2.1) Inicialização – A primeira coisa a ser feita é chamar a função implementada na primeira etapa 
responsável por ler o arquivo de texto com as configurações do jogo. Em seguida, deve-se inicializar a 
matriz. Será necessário declarar uma variável global, por exemplo, char matriz[9][10] (veja o 
item 3 desta especificação), cujas dimensões de fato utilizadas na partida são determinadas pelas 
variáveis globais de configuração criadas anteriormente (int linhas, colunas). O programa 
deve passar por cada elemento da parte utilizada da matriz, atribuindo um caractere sorteado a partir da 
string global de configuração também criada anteriormente: char caracteres[11]. Para sortear 
um caractere da string, utilize a função rand(), declarada no cabeçalho stdlib.h (leia o item do 
apêndice sobre geração de números pseudo-aleatórios). É necessário também declarar uma variável 
global, por exemplo, int pontos, e atribuir a ela o valor zero, para realizar a contagem de pontos da 
partida.
2.2) Grande laço – Após a inicialização da partida, o programa deve entrar em um laço cuja condição 
de parada é que todos os elementos da matriz tenham sido eliminados. A sequência de passos que deve 
ocorrer dentro deste laço é a seguinte: limpar a tela; mostrar a matriz; ler o movimento do jogador até 
que ele seja válido (linha e coluna de um elemento não-vazio da matriz); marcar o elemento e sua 
vizinhança com o caractere especial '*' (veja o item 4 desta especificação); limpar a tela; mostrar a 
matriz; mostrar uma mensagem com a pontuação daquela jogada (veja o item 5 desta especificação); 
perguntar ao jogador se ele confirma a jogada; caso o jogador confirme, executar a jogada eliminando 
os elementos marcados com '*' e fazendo com que os elementos restantes caiam sobre as posições 
vazias; caso o jogador desconfirme a jogada, desmarcar a área marcada com '*', atribuindo o caractere 
original. Exemplo de uma iteração do laço:
2.3) Finalização da partida – Ao término de uma partida, uma nova tela deve mostrar os pontos 
obtidos pelo jogador e deve ser feita uma chamada a uma função que realize a atualização do arquivo 
binário do ranking (esta função será implementada na parte 2 deste trabalho prático). Exemplo:
3) Matriz – A matriz deve possuir o tamanho máximo permitido pelas configurações do jogo: 9 linhas 
por 9 colunas. No entanto, ela deve ser declarada com uma coluna a mais para armazenar o caractere 
delimitador '\0'. Isto irá facilitar a impressão da matriz: basta fazer um laço que imprima cada linha 
como se fosse uma string. Lembre-se também de que a inicialização da partida deve criar a coluna de 
caracteres '\0' na posição correta, de acordo com as configurações! Ao criar a função de mostrar a 
matriz, mostre também a pontuação atual e a string bônus (veja o item 6 desta especificação), como nas 
imagens de exemplos do item 2.2.
4) Marcação da vizinhança – O problema da marcação de vizinhança é naturalmente recursivo. Você 
deve criar uma função (void markCell(int linha, int coluna)) que implemente a 
seguinte lógica: verificar se o elemento descrito pelos parâmetros de entrada está nos limites da parte 
utilizada da matriz; caso esteja fora, a função deve ser retornada (condição de parada da recursão); caso 
esteja dentro, verificar se o caractere da matriz naquela posição é igual ao caractere do elemento 
selecionado na jogada do usuário; caso seja diferente, a função deve ser retornada (condição de parada 
da recursão); caso seja igual, marcar o elemento com '*', incrementar um contador global de elementos 
na vizinhança (por exemplo: int elementos) e realizar chamadas recursivas à markCell() para 
os quatro vizinhos laterais (e não diagonais) do elemento de entrada.Lembre-se de que o contador 
global de elementos na vizinhança sempre deve ser zerado antes da marcação do elemento inicial da 
jogada escolhida pelo usuário.
5) Pontuação – A pontuação de uma jogada deve ser calculada com a seguinte expressão:
(int)ceil(pow(base_pontos, elementos))
Para isto, será necessário incluir o cabeçalho math.h e utilizar a opção -lm na compilação.
6) Pontuação bônus – Sempre que uma jogada for executada, isto é, o jogador confirmar o movimento 
selecionado, o caractere da jogada deve ser concatenado em uma string global (por exemplo: char 
bonus[10]). Assim que o tamanho desta string global for igual à quantidade de colunas da matriz 
utilizadas na partida, o programa deve realizar um laço que percorre cada linha da matriz, verificando 
se a string é igual a aquela linha. Para cada linha que for igual a string global, o programa deve 
acumular a seguinte expressão em uma variável temporária:
(int)ceil(pow(2*base_pontos, colunas))
Ao final do laço, adicione o valor da variável temporária à pontuação total da partida, imprima uma 
mensagem avisando ao jogador da pontuação bônus recebida e esvazie a string global.
7) Variáveis globais – A seguir estão as variáveis globais sugeridas nesta primeira parte da 
especificação. Além delas, você pode incluir outras que achar necessárias para a sua solução, mas 
lembre-se de que a utilização correta de variáveis globais será avaliada na correção do trabalho!
char nick[21]; /* apelido do jogador */
char matriz[9][10]; /* matriz de caracteres do jogo */
int pontos; /* pontuacao da partida */
int elementos; /* contagem de elementos na funcao recursiva */
8) Funções sugeridas – Para implementar a primeira parte do trabalho, você deve criar as funções 
abaixo. Os nomes, parâmetros e tipos de retorno utilizados são apenas sugestões, você pode modificar o 
que achar necessário.
void play(); /* funcao para o grande laco de uma partida */
void setupMatch(); /* inicializacao para uma nova partida */
void setupMatrix(); /* inicializacao da matriz em uma nova partida */
void showMatrix(); /* limpa a tela e mostra a matriz */
void readMove(); /* le uma jogada */
void markArea(); /* inicializa a var. elementos e chama markCell() */
void markCell(int linha, int coluna); /* funcao descrita no item 4 */
void unmarkArea(); /* funcao para desmarcar a vizinhanca marcada */
void execMove(); /* implementa a logica de execucao de uma jogada */
void processCol(int coluna); /* “cai” os elementos de uma coluna */
void registerMatch(); /* atualiza o ranking (2a parte) */
void showScore(); /* limpa a tela e mostra o resultado da partida */
void ranking(); /* exibe o ranking (2a parte) */
Parte 2
9) Registro de uma partida no ranking – A função sugerida registerMatch() deve servir para 
registrar a pontuação obtida durante a partida no arquivo binário com as informações de ranking. Para 
implementar esta função, será necessário definir o seguinte tipo:
typedef struct {
char nick[21];
int score;
} Player;
O nome do arquivo binário de ranking deve ser: Eliminaletras_ranking.bin
Utilizando o tipo definido, crie a função registerMatch() com a seguinte lógica: tentar abrir o 
arquivo para leitura (opção “rb”); caso não seja possível, abrir o arquivo para escrita (opção “wb”) e 
gravar um vetor de 10 posições do tipo Player, em que o primeiro elemento descreve o resultado da 
partida que acabou de terminar e os próximos 9 elementos devem possuir a string nick vazia, ou seja, 
com '\0' na primeira posição, e encerrar a função; caso seja possível, utilizar o arquivo aberto para ler 
um vetor de 10 posições do tipo Player; após ler o vetor, a função deve procurar uma posição para 
inserir um registro com o resultado da partida que acabou de terminar; se foi possível inserir o registro, 
abrir o arquivo para escrita e escrever o novo vetor de 10 posições.
Para encontrar a posição do novo registro, basta olhar o valor da pontuação em cada registro. O vetor 
deve sempre permanecer ordenado da maior pontuação para a menor. Ao encontrar uma posição para o 
novo registro, o resto do vetor deve ser deslocado para frente e o último elemento deve ser descartado. 
Caso o laço encontre um registro com pontuação igual a pontuação do novo registro, o novo registro 
deve ser inserido antes, ou seja, em uma classificação mais próxima do topo do ranking.
10) Opção 2 do menu principal – Ao escolher a opção de visualizar o ranking, o programa deve exibir 
uma tela com as informações contidas no arquivo binário e perguntar se o usuário deseja remover o 
arquivo atual com a função int remove ( const char * filename ) declarada no 
cabeçalho stdio.h. Caso não seja possível abrir o arquivo binário, mostrar uma mensagem dizendo 
que o ranking está vazio. Exemplos:
Apêndice
A) Função time()
No cabeçalho padrão time.h está declarada a função time_t time (time_t* timer), que 
retorna o número de segundos que já se passaram desde 00:00, Jan 1, 1970 UTC. O tipo time_t é 
apenas um apelido para um outro tipo integral nativo. Caso o ponteiro passado como argumento para a 
função seja diferente de NULL, a função irá gravar o valor que ela retorna no endereço apontado.
B) Geração de números pseudo-aleatórios
Muitas vezes queremos introduzir coisas aleatórias em nossos programas. A biblioteca padrão do C nos 
fornece funções para gerar sequências de números pseudo-aleatórias, isto é, a sequência gerada não é 
de fato aleatória, é previsível, mas é muito próxima de aleatória, pois a dificuldade para prever as 
sequências é bem grande.
As funções estão declaradas no cabeçalho stdlib.h e são as seguintes:
void srand (unsigned int seed);
Esta função atribui o valor do parâmetro de entrada seed a uma variável global interna da biblioteca.
int rand (void);
Esta função utiliza o valor atual da variável global interna da biblioteca para calcular o valor retornado 
e atribui um novo valor à variável global interna. Os valores retornados por esta função costumam ser 
bem grandes. Calculando o resto da divisão destes valores retornados por algum número N, obtemos 
números inteiros no intervalo [0, N – 1].
Observe que dada uma semente qualquer, a sequência de números gerada pela função rand() é 
sempre a mesma. Por isso, uma boa semente para a função srand() são os valores retornados pela 
função time() (veja o item do apêndice relacionado). Portanto, antes de realizar chamadas à função 
rand(), faça a seguinte chamada:
srand(time(NULL));
Observações gerais:
1. Incluir cabeçalho como comentário (ou seja, entre /* */), no programa fonte, de acordo com os 
critérios de avaliação dos trabalhos (Disponível no Moodle).
2. A data de entrega do trabalho 2 será dividida em 2 partes com datas diferentes.
PARTE 1: entrega dia 03/12/2015 (5a) até às 23:55 hs, via moodle. Enviar o programa 
completo incluindo o que já foi implementado no Trabalho 1.
PARTE 2: entrega dia 10/12/2015 (5a) até às 23:55 hs, via moodle. Enviar o programa 
completo incluindo o que já foi implementado no Trabalho 1 e na parte 1 do Trabalho 2.
3. O arquivo fonte deve ser compactado em um arquivo .zip ou .rar, seguindo as regras de 
nomenclatura especificadas na guia do aluno.
4. Sigam as determinações quanto às entradas e saídas do programa. Serão descontados pontos de 
programas que tiverem de ter a entrada e/ou a saída corrigidas. Se tiverem alguma dúvida quanto à 
formatação de entrada e de saída, entrem em contato com os monitores com antecedência em relação 
ao prazo de entrega do trabalho.

Continue navegando