Departamento de Ciência da Computação IME-USP MAC 110 Introdução à Computação para BM, BE, BMA IME Primeiro Semestre de 2011 1 Introdução Primeiro Exercício-Programa (EP1) O Jogo da Velha Dançarina Prazo máximo para entrega: 4/4/2011 versão 1.0 30 de março de 2011 Todo mundo conhece o jogo da velha. Ele começa com o tabuleiro Os jogadores se alternam, preenchendo os espaços com X e O, até que uma das marcas complete uma fileira horizontal, vertical ou diagonal, como neste exemplo que vai ser mencionado depois como o exemplo padrão: X X O Quem completou a fileira ganha o jogo. Se ninguém completar uma fileira e o tabuleiro ficar cheio, o jogo termina empatado. Como todos aprenderam com uns 6 anos de idade, esse jogo sempre termina empatado se os dois jogadores jogarem a sério, ou seja, só tem graça jogar se sua idade for < 6. Para ele ficar mais interessante, vamos introduzir dois movimentos extras (na verdade, são 10), e ver no que dá. Antes disso, vamos adotar uma numeração para as casas do tabuleiro: O primeiro desses movimentos é um pequeno giro no sentido horário. Pense nas marcas como sendo fichas; a do centro não se move, o canto superior esquerdo vai para a posição à direita, e o resto acompanha. Mais precisamente, seguindo o esquema abaixo (note o que acontece com o exemplo-padrão): 4 1 2 7 5 3 8 9 6 O X X X O Ou seja, a peça que estava na posição i vai para a nova posição marcada com i. 1
A segunda é um deslizamento. Ele usa um tamanho k que é um inteiro entre 1 e 9. O efeito é o seguinte: a marca na posição 1 desliza k posições, até a k + 1; a 2 vai para a posição seguinte e assim por diante; a primeira marca que quer sair do tabuleiro (a da posição 10 k) vai para a posição 1, e o resto segue. Nos exemplos abaixo, aparecem as posições após deslizar 1, 3 e 5 a partir da configuração inicial, seguido dos efeitos correspondentes no exemplo-padrão. 9 1 2 3 4 5 6 7 8 5 6 7 8 9 1 2 3 4 O X X X O X X X O Com essas jogadas possíveis, o jogo fica um pouco mais interessante e supreendente (por algum tempo). Uma coisa curiosa que pode acontecer é que após uma jogada os dois jogadores ganhem ao mesmo tempo! Veja que agora a velha desliza e gira, e é daí que vem o nome do jogo. O objetivo do EP é programar um tabuleiro deste jogo, conforme as instruções abaixo. 2 Especificação Em linhas gerais, o programa deve: Ler e imprimir o tabuleiro inicial Aí, repetidamente (enquanto o jogo não acabar) Pedir uma jogada Atualizar e imprimir o tabuleiro Verificar se alguém ganhou o jogo ou se houve empate (ou seja, se o tabuleiro ficou cheio), e neste caso terminar o jogo com uma mensagem informativa. Para isso, vai ser preciso respeitar uma série de convenções quanto à entrada e à saída: Os jogadores são conhecidos como 1 e 2, e em vez de marcarem as casas com X e O, marcam com 1 e 2. Casas vazias são preenchidas com 0. A leitura do tabuleiro deve seguir a seguinte regra: o tabuleiro é dado como um número inteiro não negativo de 9 dígitos, composto só dos dígitos 0, 1, 2; as posições dos dígitos no tabuleiro vão da esquerda para a direita, ou seja, o dígito mais à direita (unidade) vai para a posição 9, o dígito da dezena vai para a posição 8, e assim em diante. Por exemplo, uma entrada 1122101 corresponde ao tabuleiro da esquerda, que no formato tradicional seria o da direita: 0 0 1 1 2 2 1 0 1 X X O O X X Note que como o número tinha menos que 9 dígitos, foi completado com zeros à esquerda. 2
Ainda sobre a leitura: ela deve obrigatoriamente ser feita em uma variável inteira chamada tabuleiro, com o comando scanf("%d", &tabuleiro); A impressão de um tabuleiro deve seguir o modelo abaixo: 0 0 1 ---+---+--- 1 2 2 ---+---+--- 1 0 1 As jogadas Ao pedir uma jogada, o programa deve ler um único número, que deve ser interpretado assim: 0 significa um giro. Um dígito positivo k significa um deslizamento de tamanho k. Um inteiro 10 de dois dígitos deve ser interpretados como linha e coluna a preencher. Assim, a jogada 31 corresponde à linha 3 e coluna 1, ou seja à posição 7. Seu programa não precisa verificar se o número digitado representa uma jogada válida ou não. Considere apenas os casos acima. A única exceção a ser tratada explicitamente é a tentativa de jogar numa casa já ocupada: neste caso o jogador perde a vez, e seu programa deve imprimir uma mensagem correspondente. As várias mensagens, pedindo dados e informando o resultado, devem ser copiadas literalmente do executável, descrito na seção seguinte. Aliás, para facilitar isto, colocamos as mensagens neste arquivo, de onde podem ser copiadas. Observe que a mensagem de empate só deve ser impressa quando o tabuleiro ficou cheio sem que houvesse um ganhador na jogada anterior. Algumas observações sobre a leitura do tabuleiro: A entrada do tabuleiro é um número de (até) 9 dígitos contendo apenas os dígitos 0, 1 e 2. Se aparecer algum outro dígito, seu programa pode fazer o que quiser (parar, explodir, chorar,...); nós não testaremos seu programa com dados desse tipo. O tabuleiro de entrada pode ser algo que normalmente não ocorreria num jogo da velha: poderia ter três 1 s e um 2, por exemplo. Não faz mal, o importante é seguir a partir daí; o primeiro a jogar é sempre o jogador 1. Claro que o tabuleiro inicial pode já ter uma linha ganhadora; não tem importância, peça a primeira jogada antes de conferir isso. Por outro lado, se o tabuleiro inicial já estiver cheio, pare o jogo sem pedir nova jogada. Nesse caso, como não houve jogada anterior, imprima a mensagem de empate, independentemente de haver linha vencedora. 3 Dicas Esta seção contém algumas dicas para facilitar a sua vida. Recomendamos que você tente encontrar sozinho soluções para os diversos passos da implementação, e só depois, se der curiosidade ou se faltar mesmo qualquer ideia de solução, tomar emprestado algumas ideias daqui. 3
Posições do tabuleiro: o formato de representação do tabuleiro em um inteiro de 9 dígitos, adotado pela convenção da entrada, é bastante conveniente para uma série de tarefas. Se você quiser acessar (ler ou modificar) o conteúdo de uma casa, poderá encontrar uma potência de 10 adequada para isso, que pode ser calculada facilmente a partir da linha e da coluna correspondente. Por exemplo você pode acrescentar uma jogada do jogador 2 na linha 1 coluna 2 somando 2*10000000 ao tabuleiro. Deslizamento: esta operação poderia ser chatíssima de implementar se não fosse a representação do tabuleiro como um inteiro de 9 dígitos. Experimente um pouco com a representação numérica do tabuleiro antes e depois de um deslizamento. Deve dar para ver que o número se quebra em dois pedaços que são juntados ao contrário. Esses pedaços podem ser calculados usando divisão por potências de 10. Giro: esta operação, ao contrário das duas anteriores, não possui uma descrição algébrica trivial. A solução neste caso é fazer a alteração numa representação do tabuleiro em 9 variáveis separadas, uma para cada casa do tabuleiro, e girar as peças usando trocas entre as variáveis que participam do giro. 4 Colaboração Como informado no folheto de informações gerais, todos os EPs devem ser feitos individualmente, e isso é absolutamente obrigatório. No entanto, como esta é a nossa primeira experiência de programação, será admitida a colaboração em duplas para o desenvolvimento deste EP. Isto significa que cada aluno poderá contar com um colega para tirar dúvidas, discutir detalhes de implementação, etc. É essencial que cada aluno indique no cabeçalho do programa quem é o outro aluno da dupla, para evitar que os dois trabalhos sejam tratados como casos de cola ou plágio. 5 Executáveis Programas já compilados que solucionam este exercício programa podem ser encontrados na página do EP1 no PACA. Caso você tenha dúvidas sobre qual deve ser o comportamento do seu programa em alguma situação, veja como se comporta este executável. Um detalhe que deve estar visível nos exemplos e no executável é que as mensagens estão sem acentos. Isto é porque a apresentação correta de letras acentuadas na tela depende de configurações às vezes complicadas; senão, um texto que aparece corretamente num computador pode aparecer confuso em outro. Para simplificar o programa, deixamos os acentos de lado. 6 Consistência dos dados Os dados lidos pelo seu programa são todos números inteiros não negativos. Você deve se preocupar apenas em tratar corretamente as jogadas válidas. Os monitores não testarão seu programa com entradas inválidas. Se na hora em que os dados são pedidos alguém digitar um número inválido, um texto ou qualquer outra coisa, seu programa pode reagir como quiser. Isto significa que se, por exemplo, um número com casas decimais ou um número negativo for digitado como entrada para o programa, ou uma letra, um cifrão, uma arroba, o seu programa pode travar o computador ou explodir sem ficar envergonhado. Por outro lado, se alguém fornecer valores válidos ao seu programa, está explicado acima direitinho como ele deve reagir. 4
7 Informações sobre entrega do EP Todo exercício programa deve seguir as observações contidas na página de informações sobre entrega de EPs, onde estão descritas as diretrizes para forma de entrega do exercício, aspectos importantes na avaliação etc. 5