[Prévia] [Próxima] [Prévia por assunto] [Próxima por assunto]
[Índice cronológico] [Índice de assunto]

Re: Observacoes sobre o EP2



O problema é que um asteróide pode passar por cima do outro e eles não
colidirem...
Isto é, um cruza tão rápido o outro que no momento seguinte eles não caem na
mesma posição, o que o programa não detectaria como colisão.

Nosso grupo pensou nisso. Só não achamos um jeito de resolver tal problema
;-)

Bruno

----- Original Message -----
From: "Nelson Posse Lago" <lago@that.com.br>
To: <kon-211@ime.usp.br>
Sent: Monday, June 17, 2002 7:56 PM
Subject: Observacoes sobre o EP2


> Ola' a todos,
>
> As notas do EP2 (fase 1 do projeto) estao "saindo do forno" e, como da
outra
> vez, gostariamos (eu e o Thiago) de fazer algumas observacoes:
>
> - Eu ja' falei da documentacao da outra vez, e vou repetir:
>    - coloquem uma breve explicacao de como compilar seus programas (de
>      preferencia com um makefile);
>    - deem uma "dica" de como rodar o programa e qual o tipo de saida dele.
Por
>      exemplo, na fase 2, houve grupos que fizeram o programa esperar um
"enter"
>      entre uma tela e outra. Isso e' otimo mas, como nao tinha sido
>      especificado, demorei algum tempo para descobrir por que "./ep |
less" nao
>      estava funcionando. No caso do jogo, voces precisam explicar como
joga-lo,
>      e um exemplo pode ser util;
>    - Tenham do' dos monitores :-) : nao e' facil ler codigo alheio e, se
voces
>      nao fornecem uma explanacao sobre a estrutura do programa (tipo: "os
>      asteroides sao structs assim assado, que ficam numa lista ligada
com/sem
>      cabeca; a tela e' representada por uma matriz assim assada chamada
"Tela";
>      a cada iteracao, o programa executa a funcao "desenha", que desenha a
>      tela, depois a funcao "move", que move os corpos na tela, depois a
funcao
>      "colide", que encontra objetos que estao na mesma coordenada e os
destroi;
>      a deteccao de colisoes e' feita percorrendo a lista ligada varias
vezes,
>      uma vez para cada asteroide" etc. etc.), a coisa fica mais dificil.
Como o
>      EP tambem pedia explicitamente esse tipo de documentacao, falhas
nesse
>      quesito foram descontadas.
>    - facam um relatorio.txt sobre os problemas encontrados e os aspectos
que
>      julgarem mais importantes, por exemplo, ideias aparentemente otimas
que
>      voces tiveram mas que foram rejeitadas por alguma razao, limitacoes
da
>      solucao que voces desenvolveram etc.
>
> - Ja' esta' na hora de voces dominarem o processo de compilacao "em
partes";
>   nao e' muito bom fazer um arquivo "ep.c"  e colocar tudo la' dentro. Em
>   particular nesse EP, em que o enunciado pede explicitamente modularidade
no
>   codigo, isso custou pontos.
>
> - Tambem e' bom voces aprenderem a usar o "make" um pouco melhor; houve
varios
>   makefiles do tipo:
>
> ep:
> gcc -o ep file1.c file2.c file3.c file4.c
>
> Nao descontamos pontos por causa disso, porque e' melhor que nada, mas
usar o
> make assim nao traz nenhuma vantagem em relacao a um script bobo em bash,
por
> exemplo. O certo seria algo do tipo:
>
> ep: file1.o file2.o file3.o file4.o defs.h
> gcc -o ep file1.o file2.o file3.o file4.o
> file1.o:
> gcc -c file1.c
> file2.o:
> gcc -c file2.c
> file3.o: file3.h
> gcc -c file3.c
> file4.o:
> gcc -c file4.c
>
> Esse exemplo, na verdade, esta' bem "1/2 boca", mas cumpre o papel de
permitir
> a compilacao em partes. Ou seja, se voce esta' escrevendo e testando o
arquivo
> file2.c, nao precisa recompilar os outros toda vez.
>
> - os testes nao foram realizados como foi pedido, ou seja, eh preciso ser
mais
>   fiel `a especificacao do projeto.
>
> - Por favor! Houve trabalhos em que 90% do EP se concentra em uma unica
funcao
>   de 10 telas de tamanho. Facam funcoes mais enxutas e melhor
documentadas; uma
>   funcao deve realizar uma tarefa simples e bem definida, e ter um nome
que
>   torne essa tarefa clara. Por exemplo, o "loop" principal do programa
>   obviamente deve consistir em algo como "desenhar a tela", "mover os
objetos"
>   e "eliminar os objetos que colidem" (nao necessariamente nessa ordem).
Entao
>   nao faz sentido fazer uma funcao enorme que executa essas tres tarefas
na
>   sequencia. Melhor seria algo do tipo:
>
> /* inicializa estruturas de dados */
> init();
> /* Desenha tela vazia, so' com a terra e a estacao */
> desenha_tela();
> for (int i = 0; i < 100; i++) {
> cria_asteroides();
> move_asteroides();
> detecta_colisoes();
> if (nave_atingida()) {
> desenha_tela(); // Para o usuario ver o asteroide que bateu na nave
> printf ("Ja' era!\n");
> break;
> } else {
> desenha_tela();
> }
>
> Esse loop e' tao pequeno e claro que pode fazer parte de main(); se tudo
for
> feito direitinho, main() vai ocupar umas 2 telas.
>
> Dependendo da estrutura do programa, talvez nao faca sentido separar
> "move_asteroides" e "detecta_colisoes", mas sim definir uma funcao
> "passa_tempo()" que faca as duas coisas. Mas, nesse caso, voce
provavelmente
> vai encontrar lugares "dentro" de passa_tempo() onde voce pode usar
funcoes
> auxiliares para tornar a funcao mais clara. O importante e' que so' de ler
o
> nome de uma funcao eu ja' saiba qual e' a tarefa que ela desempenha, e so'
de
> dar uma olhada nela (que deve ser CURTA) eu ja' compreenda quais sao os
passos
> que ela usa para desempenhar seu papel.
>
> - A modularizacao do projeto nao pode ser aleatoria. Deve-se definir um
>   criterio mais ou menos logico de separacao do programa. Nao adianta
dividir o
>   programa em 4 arquivos e colocar cada funcao em um deles para o programa
ser
>   "modular". Por exemplo, voce provavelmente precisa manipular o conjunto
dos
>   asteroides do programa quando cria um novo asteroide, quando detecta
colisoes
>   e quando desenha a tela. Se os asteroides estao em uma lista ligada,
voce
>   pode manipula-la diretamente em todos esses lugares (foi o que todos os
que
>   eu corrigi fizeram). Mas seria mais elegante separar as funcoes de
acesso `a
>   lista ligada de asteroides em um modulo `a parte. No primeiro caso, voce
tem
>   que verificar, ao longo do seu programa inteiro, se lembrou de fazer "p
=
>   p->next", se lembro de testar "if (p != NULL)" etc. Se percorrer a lista
e'
>   uma tarefa restrita em um modulo, voce so' precisa "debugar" essas
coisas uma
>   vez. Alem disso, se voce quiser mudar algo na estrutura da lista (por
>   exemplo, passar de uma lista ligada para uma lista duplamente ligada),
voce
>   sabe que todas as alteracoes tem que ser feitas apenas nesse modulo. Nao
>   descontei nada de quem fez isso, porque uma lista ligada realmente e'
simples
>   e nao e' tao ruim manipula-la diretamente. Outro exemplo: alguns EPs
>   detectaram colisoes entre asteroides da seguinte maneira: "move o
asteroide
>   para a sua nova posicao; se a nova posicao contem um '*', '@' ou '!',
houve
>   colisao". Isso e' totalmente nao-modular, porque o algoritmo de deteccao
de
>   colisao depende da representacao das coisas na tela. Se a representacao
>   mudar (como, por exemplo, entre a fase 1 e a fase 2), o algoritmo tem
que ser
>   completamente reescrito. Desse tipo de coisa eu descontei pontos.
>
> - Varias pessoas fizeram diversas "promiscuidades" com os arquivos ".h".
Embora
>   *sintaticamente* um arquivo .h possa conter qualquer tipo de codigo C
valido,
>   *semanticamente* nao e' assim: os arquivos .h existem para exporem para
>   diversos arquivos o mesmo conjunto de declaracoes de funcoes, variaveis
e
>   constantes. Ou seja, normalmente voce nao deve colocar a definicao de
uma
>   funcao dentro de um arquivo ".h", apenas a sua declaracao. Para que?
Para que
>   voce possa definir uma funcao em um arquivo .c e chama-la em outro
arquivo
>   .c; esse segundo arquivo "#includes" o arquivo .h com as declaracoes de
>   funcoes do primeiro. Alem disso, incluir o arquivo .h no arquivo .c
>   correspondente a ele e' util porque permite que voce defina as funcoes
no
>   arquivo em qualquer ordem. Se voce nao fizer isso, ou voce declara os
>   prototipos no inicio do arquivo .c (o que nao e' muito esperto, pois da'
>   muito mais trabalho que incluir o arquivo .h) ou voce precisa ter
certeza de
>   definir as funcoes de maneira que uma funcao sempre faca referencia a
uma
>   funcao definida anteriormente.
>
> - Varias pessoas fizeram isso:
>
> typedef struct blah* pblah;
>
> struct blah {
> int lala;
> pblah next;
> }
>
> E nunca mais usaram o typedef "pblah". Nao esta' errado, mas nao e'
necessario;
> voce pode fazer:
>
> struct blah {
> int lala;
> struct blah* next;
> }
>
> Que da' tudo certo tambem. Outra opcao e':
>
> typedef struct Blah {
> int lala;
> struct Blah* next;
> } blah;
>
> Que me parece mais natural.
>
> Finalmente, uma charada: o algoritmo mais usado para deteccao de colisoes
foi:
> "calcula a nova posicao de todos os asteroides; verifica se dois
asteroides
> estao na mesma posicao; se estiverem, houve colisao". Qual o problema com
esse
> algoritmo (nao, eu nao descontei pontos de quem fez assim)?
>
> Ate' +
> Nelson e Thiago
>