Você está na página 1de 126

Programao em Python e Introduo ao Pygame

Kaya Sumire Abe kaya.sumire@gmail.com

Cmpus Curitiba  2012 Verso 0.1

ii

Copyright

c draft version Kaya Sumire Abe 2012.

Verso rascunho, 0.1. Colaboradores: Bianca Alessandra Visineski Alberton, Diego de Faria do Nascimento Alguns direitos reservados. Este documento uma obra derivada de Invent Your Own Games with Python, de Al Sweigart, e est sob a licena Creative Commons 3.0 de atribuio, uso no-comercial e compartilhamento pela mesma licena. Este trabalho foi confeccionado como material de suporte para as atividades do grupo PET Computando Culturas em Equidade.

Voc pode:

Compartilhar: copiar, distribuir Produzir obras derivadas.


Com as seguintes condies:

e utilizar o trabalho

Atribuio: voc dever atribuir o trabalho da forma especicada pelo autor. Uso no-comercial: voc no poder utilizar este trabalho para ns comerciais. Compartilhamento pela mesma licena: se voc alterar, transformar ou ampliar esta obra,
dever distribuir o trabalho em uma licena semelhante a esta. Em caso de dvidas sobre esta licena, visite o link

http://creativecommons.org/licenses/

by-nc-sa/3.0/legalcode.

Sumrio
1 The Hard Way - o jeito mais difcil
1.1 O que queremos dizer com o jeito mais difcil? 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2 . . . . . . . . . . . . . . . . . . . . . Leitura e Escrita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ateno aos detalhes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Localizar diferenas No copie e cole Prtica e persistncia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1
1 1 1 1 2 2 2

Voc pode treinar em casa

2 Terminal interativo do Python


2.1 2.2 2.3 2.4 2.5 2.6 Matemtica 2.1.1 2.2.1 2.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nmeros inteiros e de ponto utuante . . . . . . . . . . . . . . . . . . . . . . . Expresses dentro de expresses Resolvendo expresses

3
3 3 4 4 4 6 7 8 8

Armazenando valores em variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sobreencrevendo valores das variveis Usando mais de uma varivel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Strings
3.1 3.2 3.3 Strings 3.1.1 3.2.1 3.3.1 3.3.2 3.3.3 3.4 3.5 3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Concatenao de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hello World! Comentrios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Escrevendo o primeiro script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Como o programa Hello World funciona . . . . . . . . . . . . . . . . . . . . . . . . . Funes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Finalizando o programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9
9 9 10 10 11 11 11 12 13 13 13

Nome de variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 Adivinhe o nmero
4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 O jogo adivinhe o nmero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modelo de execuo do adivinhe o nmero A sentena A funo 4.5.1 Cdigo-fonte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14
14 14 14 15 16 17 17 18 18 18 19 19 19 20 20 20 21 22

import . . . . . . . random.randint()

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Chamando funes que pertencem a mdulos . . . . . . . . . . . . . . . . . . .

Passando argumentos para funes Laos de repetio (loops ) Blocos

Saudando o jogador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Dado booleano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operadores de comparao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Condies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loops com sentenas

while

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

As tentativas do jogador

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.14.1 4.14.2 4.15

Convertendo strings para inteiros . . . . . . . . . . . . . . . . . . . . . . . . . . Incrementando variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Sentenas

if

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii

iv

SUMRIO

4.16 4.17 4.18 4.19

Saindo de

loops com o comando

break

. . . . . . . . . . . . . . . . . . . . . . . . . .

22 22 23 23 24

Vericar se o jogador venceu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vericar se o jogador perdeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resumo: o que exatamente programao?

4.17.1

Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5 O Reino do Drago
5.1 5.2 5.3 5.4 Introduo funes 5.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Como jogar O Reino do Drago Cdigo-fonte do programa 5.4.1 5.4.2 5.4.3 5.4.4 5.4.5 5.4.6 5.4.7 5.4.8 5.4.9 5.4.10 5.4.11 5.4.12 5.4.13 5.5 5.6 5.7 Denindo funes Tabelas-verdade Modelo de sada do jogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

25
25 25 25 26 27 27 27 28 28 29 29 29 30 30 30 31 31 31 31 32 33

Como o programa funciona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operadores booleanos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obtendo a entrada do jogador Escopo de variveis Denindo a funo

Retorno de valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

checkCave(chosenCave)

. . . . . . . . . . . . . . . . .

Onde denir funes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mostrando o resultado do jogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Decidindo em que caverna est o drago amigvel Onde o programa realmente comea Chamando funes no programa

. . . . . . . . . . . . . . . . . . . . . . . . . .

Perguntando se o jogador quer jogar novamente

Projetando um programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6 Jogo da forca
6.1 6.2 6.3 6.4 6.5 Modelo de sada do jogo de forca Arte ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projetando um programa atravs de um uxograma . . . . . . . . . . . . . . . . . . . Cdigo-fonte do jogo de forca 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.5.8 6.6 6.7 6.6.1 6.7.1 6.7.2 6.7.3 6.7.4 6.7.5 6.7.6 6.8 6.8.1 6.8.2 6.9 6.10 Strings de vrias linhas Constantes Listas O operador Como funcionam algumas coisas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34
35 36 37 38 40 41 41 42 43 43 44 44 45 46 46 46 47 47 48 49 50 51 51 52 52 53 53

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

in

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Removendo itens de listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Listas de listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mtodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Os mtodos de lista O mtodo de lista

reverse()

append()

. . . . . . . . . . . . . . . . . .

A diferena entre mtodos e funes . . . . . . . . . . . . . . . . . . . . . . . . . . . .

split()

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

Como o cdigo funciona As funes Loops

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e

Mostrando a ilustrao para o jogador . . . . . . . . . . . . . . . . . . . . . . .

range()

list()

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

for

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Mostrando os espaos para as letras da palavra secreta

Substituindo sublinhados por letras adivinhadas corretamente

Obtendo os palpites do jogador . . . . . . . . . . . . . . . . . . . . . . . . . . .

Sentenas

elif (else if)

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Ter certeza que o jogador deu um palpite vlido

Perguntando se o jogador deseja jogar novamente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Reviso das funes criadas para este jogo Cdigo principal do jogo

SUMRIO

6.10.1 6.10.2 6.10.3 6.10.4 6.11 6.12

Mostrando a ilustrao ao jogador secreta

. . . . . . . . . . . . . . . . . . . . . . . . .

53 54 54 54 55 55

Permitindo o jogador a fazer um palpite e vericando se o palpite est na palavra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vericar se o jogador venceu ou perdeu o jogo

Iniciando uma nova rodada . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 Jogo da velha
7.1 7.2 7.3 7.4 7.5 7.6 Modelo de sada do jogo da velha Cdigo-fonte do jogo da velha Representando o tabuleiro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projetando o programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Raciocnio do jogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Como o programa funciona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.6.1 7.6.2 7.6.3 7.6.4 7.6.5 7.7 7.8 7.9 7.10 7.11 7.12 7.13 Imprimindo o tabuleiro na tela . . . . . . . . . . . . . . . . . . . . . . . . . . . Permitindo o jogador a escolher o smbolo desejado . . . . . . . . . . . . . . . Decidindo quem inicia o jogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . Perguntando se o jogador deseja jogar novamente . . . . . . . . . . . . . . . . . Mostrando a jogada no tabuleiro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56
56 58 61 61 62 63 63 63 64 64 64 64 65 65 65 65 65 65 66 66 66 66 66 66 67 67 67 67

Referncias de lista

Vericar se o jogador venceu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Duplicando o tabuleiro Vericando se um espao no tabuleiro est livre Permitindo que o jogador entre com a sua jogada Escolhendo um movimento da lista de movimentos O valor

7.12.1 7.13.1 7.13.2 7.13.3 7.14 7.15

None

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Criando a inteligncia articial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O computador verica se pode vencer em um movimento O computador verica se o jogador pode vencer em uma jogada

Vericando os cantos, o centro e os lados (nesta ordem) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Vericando se o tabuleiro est cheio . . . . . . . . . . . . . . . . . . . . . . . . . . . . O incio do jogo Rodando a vez do jogador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rodando a vez do computador Finalizando o jogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.15.1 7.15.2 7.15.3 7.16

Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8 Bagels
8.1 8.2 8.3 8.4 Modelo de execuo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cdigo-fonte do jogo Projeto do jogo 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

68
68 69 70 71 71 71 71 71 71 72 72 72

Como o programa funciona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operadores compostos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Retornando a dica ao jogador . . . . . . . . . . . . . . . . . . . . . . . . . . . . O mtodo de lista O mtodo de

sort() . string join()

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Vericando se a string possui apenas nmeros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interpolao de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utilizando as funes descritas e vericando a vitria do jogador . . . . . . . .

Incio do jogo

9 O Criptograma de Csar
9.1 9.2 9.3 9.4 9.5 Criptograa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A encriptao de Csar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ASCII, utilizando nmeros para localizar letras As funes

74
74 74 74 75 75

chr() ord()

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Modelo de execuo do programa

vi

SUMRIO

9.6 9.7

Cdigo-fonte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Como o cdigo funciona 9.7.1 9.7.2 9.7.3 9.7.4 9.7.5 9.7.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Decidindo se o usurio quer encriptar ou desencriptar uma mensagem

76 77 77 77 77 77 77 78 78 78 78 78 79

Obtendo a mensagem do jogador . . . . . . . . . . . . . . . . . . . . . . . . . . Obtendo a chave do jogador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Encriptando ou desencriptando a mensagem com a chave dada . . . . . . . . . Encriptando e desencriptando cada letra . . . . . . . . . . . . . . . . . . . . . . O incio do programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e

9.8 9.9 9.10 9.11

O mtodo de string Os mtodos de Fora Bruta 9.10.1

isalpha() . string isupper()

islower()

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Adicionando um mtodo de fora bruta ao programa . . . . . . . . . . . . . . .

Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10 Introduo Grcos e Animao (parte 1)


10.1 10.2 10.3 10.4 10.5 Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cdigo-fonte do Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Importando o mdulo Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funes e mtodos do programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

80
80 80 81 82 83 83 83 83 83 83 83 84 84 85 85 86 86 86 86 87 87 87 87 88 88 88

10.5.1 10.5.2 10.6 10.7 10.8

pygame.init()

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

pygame.display.set_mode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Referncias de objetos Fontes O

Cores em Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A funo

10.8.1 10.8.2 10.9 10.11 10.12

pygame.font.SysFont() . . mtodo render() para objetos Font

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Atributos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.10 Mtodos

get_rect() para os objetos pygame.font.Font e pygame.Surface Funo construtor e type() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O mtodo fill() para objetos Surface . . . . . . . . . . . . . . . . . . . . . . . pygame.draw.poligon()

10.13 Mais funes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.13.1 10.13.2 10.14.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Desenhos genricos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O mtodo

10.14 O tipo de dado 10.15 A funo 10.16.1 10.16.2

pygame.PixelArray . . . . . . blit() para objetos Surface pygame.display.update() . . . . . pygame.event.get() pygame.quit() . . . .

10.16 Eventos e loop do jogo A funo A funo

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.17 Exerccios Complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11 Introduo Grcos e Animao (parte 2


11.1 11.2 11.3 Cdigo-fonte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Como o programa funciona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Movendo e rebatendo os blocos . . . . . . . . . . . . . . . . . . . . . . . . . . . Criando a janela principal e iniciando o Pygame Rodando o loop principal . . . . . . . . . . . . . . . . . Como o programa funciona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Iniciando as estruturas de dados dos blocos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Movendo cada bloco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vericando se o bloco foi rebatido Mudando a direo do bloco rebatido 11.2.1 11.3.1 11.3.2 11.3.3 11.3.4 11.3.5 11.3.6 11.3.7 11.4

90
90 91 91 92 92 93 93 93 93 94 94 94

Desenhando os blocos em suas novas posies . . . . . . . . . . . . . . . . . . .

Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12 Deteco de colises
12.1 Cdigo fonte: coliso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

95
95

SUMRIO

vii

12.2

Como o programa funciona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A funo de deteco de coliso O objeto . . . . . . . . . . . . . . . . . . . . . . . . . . e o mtodo Determinando se um ponto est dentro de um retngulo . . . . . . . . . . . . .

97 97 98 98 98 99 99 99 99 101 101 101 102 102 102

12.2.1 12.2.2 12.2.3 12.2.4 12.2.5 12.2.6 12.2.7 12.3 12.3.1 12.3.2 12.3.3 12.3.4 12.3.5 12.4

pygame.time.Clock

tick()

. . . . . . . . . . . . . .

Colidindo com os quadrados verdes . . . . . . . . . . . . . . . . . . . . . . . . . No adicione ou remova itens de uma lista enquanto houver iteraes sobre ela Removendo os quadrados verdes . . . . . . . . . . . . . . . . . . . . . . . . . . Desenhando os quadrados verdes na tela . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Iniciando os movimentos O evento

Cdigo-fonte: entrada do usurio

Lidando com as variveis do teclado . . . . . . . . . . . . . . . . . . . . . . . .

MOUSEBUTTONUP colliderect()

Movendo o jogador pela tela O mtodo

Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13 Dodger
13.1 13.2 13.3 Reviso dos tipos bsicos de dados do Pygame . . . . . . . . . . . . . . . . . . . . . . Cdigo-fonte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Como o programa funciona e recursos adicionais . . . . . . . . . . . . . . . . . . . . . Importando os mdulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Explorando o uso de constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . Explorando o uso de funes Modo fullscreen O mtodo A funo . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cursor do mouse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . para objetos Mostrando a tela inicial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

103
103 104 108 108 108 108 108 108 108 109 109 109 110 110

13.3.1 13.3.2 13.3.3 13.3.4 13.3.5 13.3.6 13.3.7 13.3.8 13.3.9 13.3.10 13.4

move_ip()

Rect

e evento de movimento do mouse

Movendo a personagem do jogador . . . . . . . . . . . . . . . . . . . . . . . . .

pygame.mouse.set_pos()

. . . . . . . . . . . . . . . . . . . . . .

Desenhando o placar do jogo

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

Finalizando o projeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

A Fluxogramas
A.1 Criando um Fluxograma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

111
111

Referncias Bibliogrcas

116

Lista de Figuras
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Uma expresso construda com valores e operadores. Variveis so como caixas que podem guardar valores. As variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 5 7 18 21 22 27 32 37 45 61 62 62 63 70 74 82 84 92 92 98 107 111 112 112 113 113 114 115

fizz

eggs
loop

ilustradas. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Blocos e indentao. Sentenas

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Funcionamento de um

while.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

if

while. .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Partes de uma denio de funo no Python. . . . . . . . . . . . . . . . . . . . . . . . Fluxograma para o jogo O Reino do Drago. . . . . . . . . . . . . . . . . . . . . . . . Fluxograma para o jogo da forca. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ndices em uma lista que contm outras listas. . . . . . . . . . . . . . . . . . . . . . . . Fluxograma para o jogo da velha. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Representao do tabuleiro para o jogo da velha. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Representao do tabuleiro do jogo da velha para o computador.

Expanso do passo Obter o movimento do computador no uxograma. . . . . . . . . Fluxograma para o jogo Bagels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alfabeto substitudo por caracteres 3 casas frente. Tcnica de . . . . . . . . . . . . . . . . . . . Resultado da execuo do cdigo 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

anti-aliasing aplicada a uma reta. . . . . . . . . . . . . . . . . . . . . . . .

Resultado da execuo do cdigo 9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formas de coliso possveis neste programa. . . . . . . . . . . . . . . . . . . . . . . . . Resultado da execuo do cdigo 10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Execuo do programa Dodger. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comeando seu uxograma com as caixas incio e m. Ramicando o uxograma. . . . . . . . . . . . . . . . . . . Desenhando os trs primeiros passos do Fluxograma. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Criando os laos no uxograma. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alterando o segundo comando e adicionando a nova caixa. . . . . . . . . . . . . . . . . Incluindo as novas caixas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fluxograma completo: Incluindo a nova caixa e o novo lao. . . . . . . . . . . . . . . .

viii

Lista de Tabelas
1 2 3 4 5 6 7 8 9 10 Operaes matemticas bsicas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comandos para caracteres especiais. Operadores de comparao. Tabela-verdade do operador Tabela-verdade do operador Tabela-verdade do operador Tabela ASCII. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 12 19 28 28 28 75 84 85 109

and or . not

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Cores RGB. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Atributos dos objetos

Rect.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Constantes de evento para as teclas pressionadas. . . . . . . . . . . . . . . . . . . . . .

ix

Lista de Cdigos
1 2 3 4 5 6 7 8 9 10 11 12 Primeiro script. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jogo adivinhe o nmero. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O Reino do Drago. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jogo de forca. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jogo da velha. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bagels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Criptograma de Csar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hello World grco. Animaes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 15 26 38 58 69 76 81 90 95 99 104

Deteco de colises. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deteco de entrada do usurio. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jogo Dodger. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 The Hard Way - o jeito mais difcil


Voc deve pensar o qu? Vamos aprender algo do jeito mais difcil? No quero mais este curso!. Acalme-se. O jeito mais difcil, na verdade, o mais fcil!

1.1

O que queremos dizer com o jeito mais difcil?


No vamos abordar todos conceitos para depois colocar a mo na massa . Isso torna qualquer

coisa desinteressante! O que vamos fazer aqui o seguinte: 1. Analisar cada exerccio 2. Digit-los cuidadosamente 3. Fazer cada um deles funcionar corretamente Provavelmente, seguir estes passos com sucesso pode ser difcil, inicialmente. Comearemos

com programas simples, para rever ou aprender conceitos bsicos de programao. Durante as aulas, avanaremos nos conceitos e direcionaremos o que j foi apresentado para aplicaes em jogos simples, mas que so o incio para o desenvolvimento das aplicaes mais sosticadas do mercado. As principais habilidades que necessitaro ser desenvolvidas neste curso so: leitura e escrita, ateno aos detalhes e localizar diferenas. Entretanto, ainda h outras recomendaes a serem seguidas para uma boa prtica da programao.

1.1.1

Leitura e Escrita
Pode parecer bvio, mas se voc possui problemas em digitao, voc ter problemas em apren-

der a programar, principalmente se voc tem problemas com caracteres especiais, comuns em programao, como chaves, colchetes, dois-pontos, etc. Digitar os cdigos apresentados e faz-los funcionar, o ajudar a desenvolver esta habilidade.

1.1.2

Ateno aos detalhes


A habilidade que diferencia os bons programadores dos ruins a ateno aos detalhes. Alis,

isto o que diferencia o prossional bom do ruim em qualquer prosso. Sem prestar ateno nos mnimos detalhes do seu trabalho, voc pode deixar passar elementos-chave das suas criaes. Em programao, isto resulta em

bugs e sistemas difceis de utilizar.

Durante o curso, voc copiar os cdigos exatamente do jeito que eles forem apresentados. Isto far com que voc preste ateno nos detalhes.

1.1.3

Localizar diferenas
Uma habilidade muito importante, que programadores desenvolvem com a prtica, notar

diferenas entre coisas, em especial, programas. Um programador experiente encontra diferenas entre cdigos similares muito facilmente. H ferramentas que fazem este servio para os programadores, mas no utilizaremos nenhuma delas neste curso. Assim que treinarmos o crebro, poderemos usar as ferramentas. Enquanto voc zer os exerccios, digitando cada um, sem trapacear, haver erros. inevitvel, mesmo programadores experientes os cometem. Seu trabalho notar onde esto as diferenas entre o seu cdigo e aquele que voc estiver copiando. Fazendo isso, voc treinar a si mesmo a identicar erros,

bugs e outros problemas. Mais tarde, a tarefa ser encontrar os erros nos seus prprios cdigos,

sem ter o que comparar.

1 Mas

vamos apresentar os conceitos fundamentais para construir qualquer programa!

1.

THE HARD WAY - O JEITO MAIS DIFCIL

1.1.4

No copie e cole
Esquea o

Ctrl + C e o Ctrl + V. Voc deve

DIGITAR

todos os exerccios. Do contrrio,

voc estar enganando a si mesmo.

O objetivo desta prtica treinar sua digitao de programas

(que no to trivial quanto digitar um texto) e sua mente para ler, escrever e vericar um cdigo.

1.1.5

Prtica e persistncia
Lembre-se que tudo que vale a pena, se algo que voc realmente quer, requer um certo

esforo. Qualquer que seja o motivo por querer desistir, desista deste motivo. Force a si mesmo. Se voc chegar em um exerccio que no consegue resolver, esquea-o por um momento e volte a resolv-lo posteriormente. Traga suas dvidas para a aula. Programao no to satisfatrio no incio, mas, depois, pode ser algo realmente prazeiroso. Talvez, no incio, voc no entenda muita coisa, como se estivesse aprendendo qualquer idioma que voc no conhece. Voc se atrapalhar com as palavras, smbolos, etc., e, de repente, ocorrer um estalo e tudo estar claro. Mas isto depende da persistncia de cada um. Se voc sempre zer os exerccios e continuar tentando entend-los, uma hora voc os entender.

1.2

Voc pode treinar em casa


Se voc tem um computador em casa, nada lhe impede que voc pratique os exerccios! Aqui, no vamos ensin-lo a instalar ou congurar o Python em seu computador. H inmeras

pginas

web que explicam cada etapa de instalao, em qualquer sistema operacional, e temos certeza

de que voc sucientemente hbil para realizar esta tarefa.

2 Terminal interativo do Python


Tpicos abordados neste captulo:

Nmeros inteiros e de ponto utuante Expresses Valores e operadores Resoluo de expresses Armazenamento de valores em variveis Antes de iniciarmos com os jogos, aprenderemos alguns conceitos bsicos relacionados ao Python, tais como valores, operadores, expresses e variveis. do Python. No comearemos, de fato, a programar neste captulo, mas aprenderemos a utilizar uma poderosa ferramenta: o terminal interativo

2.1

Matemtica
Abra o terminal do Python de acordo com as orientaes do instrutor. Em seu computador,

voc poder fazer as operaes aqui apresentadas atravs do terminal interativo de acordo com o sistema operacional utilizado. Observe que h um cursor esperando para receber comandos. De incio, digite como uma calculadora.
Tabela 1: Operaes matemticas bsicas.

2 + 2.

Conse-

quentemente, observe a resposta. Ou seja, tambm possivel utilizar o terminal interativo do Python

2+2 2-2 2*2 2/2

adio subtrao multiplicao diviso

2.1.1

Nmeros inteiros e de ponto utuante


Em programao, assim como na matemtica, h os nmeros inteiros (tais como 6, 79, 22, -3,

0), tambm conhecidos como nmeros sem vrgula. Nmeros fracionrios ou com vrgula, no so inteiros, como 3,2 e -7,89. No Python, 5 um nmero inteiro, mas, se voc deni-lo como 5.0 , ele deixar de ser tratado como um inteiro, diferentemente da matemtica convencional. Nmeros com um ponto decimal so denominados

nmeros de ponto utuante.

Em programao, o computador

considera qualquer nmero com ponto decimal como um no-inteiro. Digite alguns destes problemas matemticos no terminal interativo e pressione de cada um deles. Observe os resultados.

Enter

depois

2+2+2+2+2 86 10 5 + 6 2
Estes problemas so denominados por

expresses. Computadores podem resolver milhares de ope-

raes em tempo muito pequeno. Expresses so construdas com

operadores (sinais matemticos).

valores (os nmeros) e conectadas

Vamos analisar o que estes valores e operadores so.

2 Observe
ponto.

que, em programao, a vrgula que utilizamos para denir nmeros fracionrios representada por um

2.

TERMINAL INTERATIVO DO PYTHON

Figura 1: Uma expresso construda com valores e operadores.

Como pode ser visto na ltima expresso da lista de exemplos anterior, possivel colocar qualquer quantidade de espaos entre os inteiros e os operadores. (Entretanto, esteja certo de que no h espaos antes do incio da expresso.) Nmeros so um tipo de valor enquanto os inteiros so tipos de nmeros. Porm, embora os inteiros sejam nmeros, nem todos os nmeros so inteiros (por exemplo, 2.5) . A seguir, veremos como trabalhar com texto em expresses. O Python no limitado apenas a nmeros, muito mais que apenas uma calculadora!

2.2

Resolvendo expresses
Quando um computador resolve a expresso

10 + 5

e resulta em 15, dizemos que ele resolveu

a expresso. Ou seja, a expresso reduzida a um valor nico, igual a resoluo de um problema em matemtica, reduzindo-o para um nico nmero: a resposta. Expresses como

10 + 5

10 + 3 + 2

possuem o mesmo valor, pois ambas resultam no mesmo

resultado. Mesmo valores nicos so considerados expresses: a expresso Entretanto, se voc digitar apenas erro:

15

resulta no valor

15.

5+,

no terminal interativo, voc obter uma mensagem de

>>> 5 + SyntaxError: invalid syntax


Este erro ocorre porque operadores, e

5+

no uma expresso. Expresses contm valores conectados por

um operador que espera dois itens a serem conectados no Python. Como apenas

denimos um valor, a mensagem de erro apareceu. Um erro de sintaxe (syntax

error)

signica

que o computador no entendeu a instruo dada, por ter sido digitada incorretamente. O Python sempre mostrar uma mensagem de erro caso ele no consiga entender alguma expresso. Isto pode no parecer to importante, inicialmente. Contudo, programao no apenas

ao computador o que fazer:

dizer

corretamente

dizer
Do

o que um computador deve fazer.

contrrio, como esperado, ele no executar as ordens corretamente.

2.2.1

Expresses dentro de expresses


Expresses tambm podem conter expresses. Por exemplo, na expresso

2 + 5 + 8,  2 + 5

tambm uma expresso. ento, se torna

2+5

resolvido pelo Python, gerando o valor 7 e a expresso original,

7 + 8,

nalmente gerando o resultado 15.

2.3

Armazenando valores em variveis


Quando programamos, frequentemente queremos armazenar valores, gerados pelas expresses

ou no, para utiliz-los posteriormente no programa. Podemos armazenar valores em

variveis.

a mesma analogia de que gatos so animais, mas nem todos os animais so gatos.

2.3.

ARMAZENANDO VALORES EM VARIVEIS

Pense em variveis como caixas que podem guardar valores. Voc pode armazenar valores em variveis utilizando o sinal valor 15 na varivel

=,

denominado

sinal de atribuio.
no terminal.

Por exemplo, para armazenar o

spam,

entre com

spam = 15

>>> spam = 15
Continuando com a analogia da caixa, conforme ilustrado na gura 2, como a caixa nomeada) e o valor um pequeno item guardado na caixa.

spam

a etiqueta (ou

Figura 2: Variveis so como caixas que podem guardar valores.

Quando

Enter for pressionado, no haver nada a ser respondido, ao contrrio do que acontecia
Isto quer dizer que a

com os resultados das operaes anteriores. Se no houver mensagens de erro, aparecer apenas uma linha em branco.

instruo

foi executada com sucesso.

O prximo

>>>

aparecer para que a prxima instruo seja digitada. Esta instruo, denominada 15 nela.

sentena de atribuio, cria a varivel spam e armazena o valor

Diferente das expresses, sentenas so instrues que no chegam a valores nais (como

resultados dos problemas matemticos), motivo pelo qual o terminal no mostra valores na linha seguinte a elas. Pode parecer confuso entender qual a diferena entre sentena e expresso. O segredo : se uma instruo gera um valor nal, ento uma expresso. Seno, ento uma sentena. Uma sentena de atribuio gerada por um nome para a varivel, seguido de um sinal anteriormente podem ser armazenadas em variveis. Lembre-se que variveis armazenam valores, no expresses. For exemplo, se houver a instruo

= seguido

por uma expresso. O valor que a expresso gera armazenado na varivel. Logo, as expresses vistas

spam = 10 + 5, a expresso 10+5 ser resolvida e o resultado 15 ser armazenado na varivel spam. Para vericar se a varivel foi criada corretamente, digite o spam no terminal. O resultado
esperado o seguinte:

>>> spam = 15 >>> spam 15


Agora,

o resultado de

spam retorna o valor dentro da varivel, spam + 5.

15. Aqui h uma interessante mistura: observe

>>> spam = 15 >>> spam 15 >>> spam + 5 20 >>>


Isto pode parecer estranho, mas faz sentido ao lembrarmos que o valor de

spam

15. Devido

spam ter 15 + 5.

este valor armazenado, executar

spam + 5

naturalmente resulta em 20, como a expresso

Se voc no tiver criado uma varivel antes de utiliz-la, o Python retornar uma mensagem de erro, pois a varivel em questo no existe. Isto tambm acontece se voc digitar o nome de uma varivel incorretamente.

2.

TERMINAL INTERATIVO DO PYTHON

possvel mudar o valor armazenado em uma varivel entrando com uma nova sentena de atribuio. Por exemplo, tente o seguinte:

>>> >>> 20 >>> >>> 8 >>>

spam = 15 spam + 5 spam = 3 spam + 5

A primeira expresso resulta em 20, pois armazenamos o valor 15 em com

spam.

Ento, entramos

spam = 3,

e o valor 15 substitudo pelo valor 3. Agora, se entrarmos novamente com

spam

+ 5,

o valor ser outro, no caso, 8, pois

spam

agora vale 3.

Para descobrir qual o valor de uma varivel, apenas digite o nome da varivel no terminal, como feito anteriormente. Agora, algo interessante: devido uma varivel ser apenas um escrever expresses como:

nome para um valor, podemos

>>> spam = 15 >>> spam + spam 30 >>> spam - spam 0 >>>


Estas expresses usam a varivel

spam duas vezes cada.

Voc pode usar variveis quantas vezes

quiser, ou for necessrio. Lembre-se que o Python calcular as expresses com os valores armazenados nelas, cada vez que uma varivel for utilizada. Desta forma, podemos usar o valor de uma varivel para atribuir um novo valor a ela mesma. Observe.

>>> spam = 15 >>> spam = spam + 5 20 >>>


A sentena de atribuio

spam = spam + 5

o mesmo que o novo valor da varivel

spam

o valor atual mais 5. Lembre-se que a varivel do lado esquerdo do sinal jeito e quantas vezes quisermos.

armazenar o valor que a

expresso, do lado direito do sinal, vale. Assim, podemos continuar aumentando o valor de

spam

do

>>> >>> >>> >>> >>> 30 >>>

spam spam spam spam spam

= = = =

15 spam + 5 spam + 5 spam + 5

2.3.1

Sobreencrevendo valores das variveis


Mudar o valor de uma varivel fcil: basta formular outra sentena de atribuio com a mesma

varivel. Veja o que acontece com o seguinte cdigo dado como entrada no terminal:

>>> spam = 42 >>> print(spam) 42 >>> spam = Hello

2.4.

USANDO MAIS DE UMA VARIVEL

>>> print(spam) Hello >>>


Inicialmente,

spam

recebe o valor 42.

Esta a forma com que o primeiro comando

print

imprime 42. Mas, quando

spam = Hello

executado, o valor 42 esquecido pela varivel e o

Hello

ca no lugar do valor anterior na varivel

spam.

Substituir um valor em uma varivel frequentemente denominado tal valor futuramente, dena uma nova varivel para receb-lo.

sobreescrev-lo.

im-

portante salientar que o valor antigo da varivel perdido permanentemente. Se for necessrio utilizar

>>> spam = 42 >>> print(spam) 42 >>> oldSpam = spam >>> spam = Hello >>> print(spam) Hello >>> print(oldSpam) 42
No exemplo anterior, antes de sobrescrevermos o valor de uma varivel chamada

spam, armazenamos o valor atual em

oldSpam.

2.4

Usando mais de uma varivel


Quando os programas tomarem forma mais complexa do que estes do terminal interativo do

Python, no conveniente que haja limitao para o uso de apenas uma varivel, certo? Logo, veremos como lidar com mais de uma varivel. Por exemplo, vamos declarar duas variveis:

>>> fizz = 10 >>> eggs = 15


Agora,

fizz

possui o valor 10 e

eggs,

o valor 15.

Figura 3: As variveis

fizz

eggs

ilustradas.

Sem mudar o valor da varivel

spam,

vamos atribuir um novo valor a ela. Entre com

spam

= fizz + eggs
resultado?

no terminal e depois verique o valor de

spam.

Voc consegue imaginar qual o

>>> >>> >>> >>> 25 >>>

fizz = 10 eggs = 15 spam = fizz + eggs spam

O valor de nados em

fizz

e em

spam agora 25, porque somamos fizz e eggs, eggs, e armazenamos o resultado em spam.

logo, somamos os valores armaze-

2.

TERMINAL INTERATIVO DO PYTHON

2.5

Resumo
Neste captulo, foi apresentado o bsico sobre instrues do Python. necessrio que seja

dito exatamente o que deve ser feito, porque computadores no possuem senso comum e apenas entendem instrues muito simples. Voc aprendeu que o Python pode resolver expresses (isto , reduzir uma expresso a um valor nico) e que expresses so valores combinados com operadores (como

+ ou ).

Voc tambm aprendeu que possvel armazenar valores em variveis para utiliz-las

posteriormente. No prximo captulo, veremos mais conceitos fundamentais e estaremos prontos para programar!

2.6

Exerccios complementares

1. Usando o terminal interativo faa: (a) Atribua quatro notas a quatro variveis diferentes (nota1, atribua a mdia desses valores varivel (b) Atribua o valor de

(3,1415...)

aps calcule o comprimento da

nota2, nota3 e nota4), media, e imprima o resultado na tela. variavel pi e um valor positivo qualquer varivel raio, 2 circunferncia (2R) e a rea do circulo (R )

3 Strings
Tpicos abordados neste captulo:

Ordem de execuo Strings Concatenao de strings Tipos de dados Funo Funo

print input

Comentrios Nomear variveis adequadamente Case-sensitivity Sobreescrevendo variveis Comandos para caracteres especiais J vimos o suciente sobre nmeros no captulo anterior. Python mais do que uma simples

calculadora.

Agora, vamos ver o que possvel fazer com textos.

Neste captulo, aprenderemos Muitos dos programas que

a armazenar texto em variveis, combinar textos e mostr-los na tela. com algum texto atravs do teclado. interativo.

veremos usaro textos para serem mostrados na tela para o jogador/usurio e o mesmo dever entrar Tambm construiremos o primeiro cdigo fora do terminal

3.1

Strings
No Python(e talvez em todas as linguagens de programao), denominamos pequenos trechos de

texto como

strings.

Podemos armazenar valores

string da mesma forma que armazenamos nmeros.

Quando digitamos strings, elas devero estar entre aspas simples ('), como o seguinte:

>>> spam = hello >>>


As aspas simples servem para informar o computador onde a string comea e termina e no faz parte do valor da string. Se voc digitar (no caso anterior, a string 'hello'). Strings podem ter (quase) quaisquer caracteres ou sinais, assim como espaos e nmeros:

spam

no terminal, voc ver o contedo da varivel

spam

hello Hi there! Albert KITTENS 7 apples, 14 oranges, 3 lemons A long time ago in a galaxy far, far away... O*&#wY\%*&OCfsdYO*&gfC\%YO*&\%3yc8r2

3.1.1

Concatenao de strings
Voc pode ligar uma string a outra utilizando o operador

+,

o que chamado de concatenao

de strings. Observe:

>>> Hello + World! HelloWorld! >>>


Uma alternativa para manter as strings separadas adicionar um espao depois de `Hello': 9

10

3.

STRINGS

>>> Hello + World! Hello World! >>>


Strings e inteiros so diferentes O tipo de valor de

tipos de dados.

Todos os valores possuem um tipo denido.

Hello

string, enquanto o tipo de 5 inteiro.

3.2

Escrevendo o primeiro script


Em Python, geralmente chamamos os programas fora do terminal interativo de

scripts, apenas

por convenincia. Voc pode utilizar qualquer editor de texto que no adote formatao ao salvar um arquivo para escrever um script. E voc pode escrever o script no terminal tambm, entretanto no confortvel sempre escrever o mesmo programa linha a linha, se ele for muito longo. Por exemplo, voc pode usar o bloco de notas do Windows ou o gedit, no Ubuntu. Basta salvar o arquivo com a extenso .py. Se voc est em dvida ou no sabe por onde comear, esteja atento s instrues em sala de aula ou pesquise sobre isso em casa.

3.2.1

Hello World!
Tradicionalmente, quando aprendemos uma nova linguagem, o primeiro programa feito mos-

trar a saudao Hello World!

4 na tela. Criaremos o nosso prprio programa Hello World! agora.

Quando voc entrar com o programa, no digite os nmeros do lado esquerdo do cdigo. Eles servem apenas para que possamos nos localizar mais facilmente em um cdigo e no fazem parte dele como um todo. de Digite o texto a seguir no editor de sua preferncia. Chamamos este texto

cdigo fonte do programa, pois ele contm as instrues que o Python seguir para determinar o
Certique-se que estar usando a verso Python 3, ou o programa no funcionar.
Cdigo 1: Primeiro script.

comportamento do programa.

# Este programa me cumprimenta e pede o meu nome. print(Hello world!) print(What is your name?) myName = input() print(It is good to meet you, + myName)
Se o programa no funcionar, leia o erro e tente consert-lo, se for um erro de sintaxe. Caso

obtenha uma mensagem similar a:

Hello world! What is your name? Albert Traceback (most recent call last): File "C:/Python26/test1.py", line 4, in <module> myName = input() File "<string>", line 1, in <module> NameError: name Albert is not defined
Quer dizer que a verso que voc est utilizando, do Python, no a correta para a execuo deste programa. Verique a compatibilidade do Python 2 em relao ao Python 3 e conserte o que for necessrio, ou certique-se que est usando a verso 3.

Tarefa 3.1
Pesquise sobre as diferenas entre as verses 2 e 3 do Python e faa as alteraes necessrias para o cdigo 1 funcionar no Python 2.

4 Ol,

mundo!

3.3.

COMO O PROGRAMA HELLO WORLD FUNCIONA

11

3.3

Como o programa Hello World funciona


Como este programa funciona? Cada linha em que demos entrada uma instruo ao comUm programa de

putador que interpretada pelo Python, de forma que o computador entenda. computador como uma receita de bolo:

primeiro passo, segundo passo, e assim por diante, at

chegar ao m. Cada instruo seguida em sequncia, do incio ao m do programa. O passo-a-passo de um programa chamado de para simplicar. Agora vamos analisar minuciosamente este programa.

ordem de execuo

ou apenas

execuo,

3.3.1

Comentrios

# Este programa me cumprimenta e pede o meu nome.


Esta linha um

comentrio.

Qualquer texto seguido por um sinal de sustenido (#) um

comentrio.

Comentrios no so para o computador, mas para o programador; o computador os

ignora. Eles so utilizados para lembrar ao programador ou inform-lo sobre o que o cdigo faz.

3.3.2

Funes
Uma

funo

como se fosse um mini-programa dentro do seu programa, contm linhas de

cdigo que so executadas do incio ao m. O Python fornece algumas funes prontas para facilitar a prtica da programao. A vantagem disso que no precisamos saber dos passos que a funo toma para executar determinada ao, apenas como utiliz-la para obter um resultado. Uma

chamada de funo

um trecho de cdigo que informa ao programa para executar o

cdigo dentro da funo. Por exemplo, o seu programa pode chamar a funo voc quiser mostrar algum texto na tela.

print()

sempre que

A funo print()

print(Hello world!) print(What is your name?)


Estas linhas chamam a funo

print(),

com a string a ser impressa dentro dos parnteses. Analogamente,

Adicionamos parnteses no m dos nomes das funes para deixar claro que estamos nos referindo a funes e no a variveis que possam ter o mesmo nome de uma funo. 42 e no ao inteiro 42. utilizamos aspas para nos referirmos s strings: por exemplo, ao utilizarmos `42' nos referimos string

Comandos para caracteres especiais


Eventualmente, gostaramos de imprimir alguns caracteres que so vistos na programao como caracteres especiais, tais como barras, aspas, apstrofos, etc. Como eles no so caracteres que possam ser impressos normalmente com a funo utiliz-los em modo texto . Outros recursos tambm podem ser utilizados na funo pular linhas ou imprimir tabulaes. Observe a tabela 2.

print(),

ento utilizamos alguns comandos simples para

print()

para

Aspas duplas e aspas simples


Strings no necessitam vir sempre entre aspas simples, no Python. entre aspas duplas tambm, obtendo-se o mesmo efeito. possvel colocar texto

>>> print(Hello world) Hello world >>> print("Hello world") Hello world
5 Em
ingls, chamados de

escape characters

12

3.

STRINGS

Tabela 2: Comandos para caracteres especiais.

Comando
\\ \' \" \n \t

O que impresso
Contra-barra (\) Aspas simples (') Aspas duplas (") Nova linha Tabulao

Entretanto, no se deve misturar aspas simples e duplas.

>>> print(Hello world") SyntaxError: EOL while scanning single-quoted string


Lembre-se que s necessrio utilizar o comando

\'

quando uma string envolvida por aspas

simples. O mesmo serve para as aspas duplas. Observe o exemplo.

>>> print(I asked to borrow Abe\s car for a week. He said, "Sure.") I asked to borrow Abes car for a week. He said, "Sure." >>> print("He said, \"I cant believe you let him borrow your car.\"") He said, "I cant believe you let him borrow your car."

A funo input()

myName = input()
Esta linha possui uma sentena de atribuio uma varivel (myName) e uma chamada de

funo (input()). sada (output). de

Quando a funo

input()

chamada, o programa espera por uma entrada

(input) do usurio com texto. A string que o usurio entra (neste caso, seu nome) torna-se o valor de Como expresses, chamadas de funo resultam em um valor nico. Este resultado chamado Neste caso, o valor de retorno da funo

valor de retorno.

input()

a string dada como

entrada. Apesar do seu nome, a funo em programao, o operador varivel

argumento, que so dados dentro dos parnteses.

input() no necessita de nenhuma entrada, ou, como chamamos

Na ltima linha do programa, temos, novamente, uma funo

print(). Desta vez, utilizamos + para concatenar a string It is good to meet you e a string armazenada na myName, que contm o nome que o usurio deu como entrada ao programa. Esta a forma

com que o programa nos cumprimenta pelo nome.

3.3.3

Finalizando o programa
Uma vez que o programa executa a ltima linha, ele para. Neste ponto, ele

termina o programa

e todas as variveis so esquecidas pelo computador, inclusive a string que armazenamos na varivel

myName.
utilizado.

Se voc tentar executar o programa novamente, com um nome diferente, o novo nome ser

Hello world! What is your name? Carolyn It is good to meet you, Carolyn
Lembre-se que o computador executa exatamente o que for programado para fazer. Computadores so burros. Este programa no se importa com o que voc digitar no lugar do seu nome. Voc pode digitar qualquer coisa e o computador o tratar da mesma forma:

3.4.

NOME DE VARIVEIS

13

Hello world! What is your name? poop It is good to meet you, poop

3.4

Nome de variveis
O computador no se importa com o nome que voc d para as suas variveis. Entretanto, o

recomendado que as variveis possuam nomes que facilitem o seu entendimento. A identicao dos nomes de variveis (assim como qualquer outra coisa no Python) diferenciam maisculas de minsculas (

case-sensitive).

Isso signica que uma varivel com o mesmo nome, mas

com a escrita diferente, entre maisculas e minsculas, no so consideradas a mesma coisa. Assim,

spam, SPAM
diferente.

sPAm

so consideradas diferentes variveis, cada uma podendo carregar um valor

Contudo, no uma boa ideia utilizar variveis com o mesmo nome, para evitar confuses. Por exemplo, uma simples troca de varivel pode fazer com que o resultado no seja o esperado, embora o programa execute corretamente. Este erro frequentemente chamado de das variveis que voc escolher faam sentido. til usar letras maisculas em variveis quando utilizado mais de uma palavra em seu nome. Por exemplo, se voc utilizar

bug

e comum

ocorrerem acidentes deste tipo enquanto construmos programas. Por isso, importante que os nomes

nomeDaVariavel ao invs de nomedavariavel pode tornar o cdigo

mais fcil de ser lido. Esta uma

conveno (ou seja, uma padronizao opcional para se trabalhar)

da programao em Python e em outras linguagens tambm.

3.5

Resumo
Agora que voc aprendeu a lidar com texto, podemos comear a construir programas com os

quais podemos interagir. Isto foi importante porque atravs do texto que o usurio e o computador se comunicaro. Strings so um diferente tipo de dado que utilizaremos em nossos programas. Podemos utilizar o operador

para concatenar strings.

No prximo captulo, vamos aprender mais sobre como lidar com variveis para que o programa utilize os dados e nmeros dados como entrada em um programa. Uma vez que tenhamos aprendido como utilizar texto, nmeros e variveis, estaremos prontos para criar jogos.

3.6

Exerccios complementares

1. Faa um programa (script) que pea dois nmeros ao usurio e imprima a soma. 2. Faa um programa que pea um lado do quadrado, calcule a rea, em seguida mostre o dobro desta rea para o usurio. 3. Faa um programa que pea a temperatura em graus Fahrenheit, transforme e mostre a temperatura em graus Celsius. (C

= (5 (F 32)/9)).

4. Faa um programa que pea 2 nmeros inteiros e um nmero real. Calcule e mostre: (a) O produto do dobro do primeiro com metade do segundo . (b) A soma do triplo do primeiro com o terceiro. (c) O terceiro elevado ao cubo. 5. Faa um programa que pea o tamanho de um arquivo para download (em MB) e a velocidade de um link de Internet (em Mbps), calcule e informe o tempo aproximado de download do arquivo usando este link (em minutos). Obs. 1 MB (megabyte) = 8 Mb(megabit).

4 Adivinhe o nmero
Tpicos abordados neste captulo:

Sentenas Mdulos Argumentos Sentenas Condies Blocos Valores booleanos Operadores de comparao Diferena entre Sentenas

import

while

==

if

break str() e int() A funo random.randint()


A palavra-chave As funes

4.1

O jogo adivinhe o nmero


Atravs do que j vimos, vamos fazer um jogo de adivinhao de nmeros. Neste jogo, o

computador sortear um nmero entre 1 e 20 e pedir ao usurio para adivinhar este nmero. Voc ter 6 chances e o computador o informar se seu palpite maior ou menor que o nmero sorteado. Se voc adivinh-lo dentro de 6 tentativas, voc vence. Este um bom programa de incio, pois utiliza nmeros (pseudo) aleatrios, para diferentes tipos de dados (e o porqu de necessitar este artifcio). Devido a estarmos lidando com jogos, eventualmente chamaremos o usurio de cham-lo de usurio tambm adequado.

loops e entrada do

usurio em um cdigo curto. Assim que voc escrever o programa, voc aprender a converter valores

jogador,

mas

4.2

Modelo de execuo do adivinhe o nmero


desta forma que o jogo aparecer ao jogador assim que o programa rodar.

Hello! What is your name? Albert Well, Albert, I am thinking of a number between 1 and 20. Take a guess. 10 Your guess is too high. Take a guess. 2 Your guess is too low. Take a guess. 4 Good job, Albert! You guessed my number in 3 guesses!

4.3

Cdigo-fonte
Nesta seo voc encontra o cdigo fonte para este jogo. Se voc j sabe um pouco de progra-

mao, atravs do que j foi abordado, voc pode tentar implementar este jogo antes de ver o cdigo. Entretanto, se voc no tem ideia de como comear, digite cuidadosamente o cdigo 2. 14

4.4.

A SENTENA

IMPORT
Cdigo 2: Jogo adivinhe o nmero.

15

# Jogo adivinhe o numero. import random guessesTaken = 0 print(Hello! What is your name?) myName = input() number = random.randint(1, 20) print(Well, + myName + , I am thinking of a number between 1 and 20.) while guessesTaken < 6: print(Take a guess.) guess = input() guess = int(guess) guessesTaken = guessesTaken + 1 if guess < number: print(Your guess is too low.) if guess > number: print(Your guess is too high.) if guess == number: break if guess == number: guessesTaken = str(guessesTaken) print(Good job, + myName + ! You guessed my number in + guessesTaken + guesses!) if guess != number: number = str(number) print(Nope. The number I was thinking of was + number)

Importante!

Tenha certeza de que voc executar o programa com o Python 3.

Se voc

utilizar o Python 2, provavelmente encontrar erros na maioria dos programas.

possvel fazer

algumas alteraes para rodar os programas, mas mais fcil que voc esteja usando a verso correta! Se o programa no funcionar depois de voc t-lo digitado, verique se tudo foi digitado corretamente.

4.4

A sentena

import

Depois da primeira linha de comentrio, que nos informa o que o programa faz, temos uma linha de importao:

import random
Esta uma

sentena de importao.

Sentenas no so funes (observe que nem

import

ou

random

possuem parnteses em seguida). Lembre-se que sentenas so instrues que realizam

alguma ao mas no geram resultado. J discutimos sentenas: sentenas de atribuio armazenam um valor em uma varivel (mas a sentena em si, no gera resultados, como operaes fazem). Enquanto o Python possui muitas funes, algumas delas existem em programas separados, chamados

mdulos.

Mdulos so programas do Python que contm funes adicionais. Utilizamos

funes destes mdulos trazendo-os para os programas com uma sentena estamos importando o mdulo A sentena

import.

Neste caso,

random. import
seguido pelo nome do mdulo

import

construda atravs do comando

desejado. A linha 2 do programa para adivinhar um nmero possui uma sentena destas, que traz o

16

4.

ADIVINHE O NMERO

mdulo

random

que contm vrias funes relacionadas nmeros aleatrios (randmicos). Utiliza-

mos uma de suas funes para gerar o nmero a ser adivinhado.

guessesTaken = 0
Esta linha cria uma nova varivel chamada

guessTaken.

Vamos armazenar o nmero de

tentativas, que o jogador far, nesta varivel.

J que, no incio do programa, no temos nenhuma

tentativa, ento iniciamos esta varivel com o valor 0.

print(Hello! What is your name?) myName = input()


As linhas 6 e 7 so as mesmas que utilizamos no programa anterior, o Hello World, visto

anteriormente.

Programadores frequentemente reutilizam trechos de cdigo de outros programas

quando eles precisam de fazer algo que eles j zeram anteriormente. A linha 6 uma chamada para a funo cdigo dentro da funo

print().

Lembre-se que uma funo como um mini-

programa rodando, e, ento, quando o programa chama uma funo, ele roda este mini-programa. O

print()

mostra a string que lhe foi passada dentro dos parnteses na tela.

Quando estas linhas terminam de executar, a string que for designada como o nome do jogador ser armazenada na varivel

myName.

4.5

A funo

random.randint()

number = random.randint(1, 20)


Na linha 9, chamamos uma nova funo,

randint(),

e ento armazenamos o seu valor em

uma varivel chamada

number.

Lembre-se que chamadas de funes so expresses porque elas geram

resultado. Chamamos este resultado de Devido funo

retorno da funo.

randint()

ser fornecida pelo mdulo

random,

ela precedida pelo nome A funo O nmero para

do mdulo seguindo de um ponto, para sinalizar que a funo pertence a tal mdulo. dos parnteses. Neste caso, fornecemos os nmeros 1 e 20, separados por uma vrgula.

randint() retorna um nmero aleatrio, inteiro, entre e inclusive os nmeros que estipulamos dentro
gerado pela funo armazenado na varivel importar o mdulo

number. import random


para observar o resultado da

Por um momento, vamos voltar ao terminal interativo e entrar com

random.

Entre com

random.randint(1, 20)

chamada da funo. Ela deve retornar um inteiro entre 1 e 20, inclusive. Agora, entre com a mesma linha, novamente. Ele poder resultar em um nmero inteiro diferente. Isto ocorre porque a cada vez que a funo um dado.

randint() chamada, ela retorna um nmero aleatrio, como se estivssemos lanando

>>> >>> 12 >>> 18 >>> 3 >>> 18 >>> 7 >>>

import random random.randint(1, 20) random.randint(1, 20) random.randint(1, 20) random.randint(1, 20) random.randint(1, 20)

Sempre que quisermos adicionar alguma aleatoriedade ao cdigo, esta funo pode ser muito til para casos gerais. Voc tambm pode mudar a faixa de valores, dependendo da sua necessidade. Por exemplo, se eu quiser uma faixa de nmeros entre 1 e 100, posso modicar as linhas 9 e 10 para as seguintes:

4.6.

PASSANDO ARGUMENTOS PARA FUNES

17

number = random.randint(1, 100) print(Well, + name + , I am thinking of a number between 1 and 100.)

E, agora, o programa sortear um nmero entre 1 e 100, inclusive.

4.5.1
a

Chamando funes que pertencem a mdulos


Esteja certo de que, ao chamar a funo para gerar um nmero aleatrio, voc tenha chamadono saber que a

random.randint(1, 20) e no apenas randint(1, 20) ou o computador funo pertence ao mdulo random e poder ocorrer um erros similar a este:
>>> randint(1, 20) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name randint is not defined >>>

Lembre-se que seu programa precisa importar um mdulo antes de utilizar as funes dele (seno, como o computador vai saber onde procurar o que voc precisa?). Por isso que as sentenas de importao de mdulos geralmente so declaradas no incio do programa.

4.6

Passando argumentos para funes


Os valores inteiros entre os parnteses da chamada de funo

chamados de

argumentos.

randon.randint(1, 20)

so

Argumentos so valores passados a uma funo, quando esta chamada. Assim como as entradas (inputs) do usurio alteram o

Eles dizem funo como se comportar.

comportamento do programa, argumentos so entradas para funes. Algumas funes exigem que valores sejam passados elas. Por exemplo:

input() print(Hello) random.randint(1, 20)

A funo

input()

no possui argumentos, mas a funo

print()

possui um e a funo

randint()

possui dois. Quando mais de um argumento exigido, estes devem ser separados por

vrgulas, tambm conhecidas como

delimitadores.

atravs deste recurso que o computador sabe

onde termina um valor e inicia outro. Se voc passar mais (ou menos) argumentos necessrios para a funo, o Python disparar uma mensagem de erro. Por exemplo, se apenas um valor for fornecido funo

randint():

>>> random.randint(1) Traceback (most recent call last): File "<pyshell#1>", line 1, in <module> random.randint(1) TypeError: randint() takes exactly 3 positional arguments (2 given) >>> random.randint(1, 2, 3) Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> random.randint(1, 2, 3) TypeError: randint() takes exactly 3 positional arguments (4 given) >>>

18

4.

ADIVINHE O NMERO

4.7

Saudando o jogador
As linhas 10 e 12 cumprimentam o jogador e o informam sobre o jogo, permitindo, ento, que

o jogador adivinhe o nmero secreto. A linha 10 bem simples, mas a linha 12 inicia um conceito muito importante, chamado lao de repetio.

print(Well, + myName + , I am thinking of a number between 1 and 20.) while guessesTaken < 6:

4.8

Laos de repetio (loops )


A linha 12 possui um lao

while,

que indica o incio de

loop.

Loops so partes do cdigo que


loops no Python6 , vamos ver

so executadas inmeras vezes. Entretanto, antes de aprendermos sobre alguns conceitos.

4.9

Blocos
Um

bloco

denido como uma ou mais linhas de cdigos agrupadas com uma mesma inden-

tao. Determina-se o incio e o m de um bloco, no Python, atravs de sua nmero de espaos no incio da linha). Um bloco inicia quando uma linha indentada em 4 espaos.

indentao

(que o

Qualquer linha seguinte, ser

indentada 4 espaos, para que o bloco continue a ser desenvolvido. Um bloco dentro de outro bloco, possui mais 4 espaos a frente, e assim por diante. O bloco termina quando h uma regresso dos espaos (por exemplo, para incio de um novo bloco). Na gura 4 h um exemplo de utilizao de blocos. As indentaes possuem pontos indicando a quantidade de espaos que caracterizam um bloco.

Figura 4: Blocos e indentao.

Ainda na gura 4, a linha 12 possui indentao zero e no est dentro de nenhum bloco. A linha 13 possui 4 espaos no incio. pertencem a um mesmo bloco . A linha 20 possui 8 espaos (que so mais que quatro!), logo, um novo bloco foi iniciado. Este bloco est dentro de um outro bloco. A linha 22 possui apenas 4 espaos e a linha anterior possui 8. Isto que dizer que o bloco anterior foi nalizado. O bloco da linha 22 pertence ao mesmo bloco em que as linhas possuem 4 espaos iniciais. A linha 23 aumenta o nmero de espaos, logo, deu incio a um novo bloco. A indentao maior que a anterior caracteriza o incio de um bloco. As linhas 14, 15, 17, e 19 tambm possuem a mesma indentao, o que caracteriza que elas

6 Embora 7 As

a estrutura dos

loops

seja bem simples, eventualmente, no Python, eles so tratados um pouco diferentes

do que em outras linguagens, por isso vamos abordar alguns tpicos comuns com mais detalhes ao longo do curso. linhas em branco no contam!

4.10.

DADO BOOLEANO

19

4.10

Dado booleano
O tipo de dado booleano possui apenas dois valores:

True (verdadeiro) ou False (falso).

Estes

valores so

case-sensitive e no so string; em outras palavras, no so utilizadas aspas ao se referir

a tais valores. Utilizamos estes valores com operdores de comparao, para formar condies.

4.11

Operadores de comparao

Tabela 3: Operadores de comparao.

Sinal
< > <= >= == !=

Nome
menor que maior que menor ou igual a maior ou igual a igual a diferente de

Na linha 12 do programa, h uma sentena

while:

while guessesTaken < 6:

A expresso que segue a palavra-chave

while contm dois valores (o valor da varivel guessesTaken

rador de comparao.
ou

e o inteiro

6)

conectados por um operador (o sinal de menor que <). O sinal < chamado de

ope-

Este tipo de operador utilizado para comparar dois valores e concluir se o resultado

True

False.

Observe os tipos de comparadores disponveis na tabela 3.

4.12

Condies
Uma

condio

uma expresso que combina dois valores com um operador de comparao e

resulta em um valor booleano. Uma condio apenas um nome para uma expresso que resulta em

True True.

ou

False.

Por exemplo, a expresso

guessesTaken < 6

o mesmo que perguntarmos o

valor armazenado em Caso

guessesTaken contrrio, em False.

menor que 6?

Em caso armativo, a condio resulta em

20

4.

ADIVINHE O NMERO

Tarefa 4.1
Entre com as seguintes operaes no terminal interativo: 1. 0 < 6 2. 6 < 0 3. 50 < 10 4. 10 < 11 5. 10 < 10 6. 10 == 10 7. 10 == 11 8. 11 == 10 9. 10 != 10 10. 10 != 11 11. `Hello' == `Hello' 12. `Hello' == `Good bye' 13. `Hello' == `HELLO' 14. `Good bye' != `Hello' Qual o resultado de cada uma delas? Justique/comente as respostas que mais lhe chamaram a ateno.

No deixe de reparar a diferena entre os sinais valores.

==

=.

Quando utilizamos apenas um sinal

de igual, estamos atribuindo um valor, enquanto ao utilizarmos dois sinais, queremos comparar dois

4.13

Loops com sentenas


A sentena

while
while, ela True, o bloco
verica a condio executado. Se a

while marca o

incio de um loop. Eventualmente, em nossos programas, queremos Se a condio resultar em

que algo ocorra vrias vezes. Quando a execuo chega em um bloco em sequncia palavra-chave condio resulta em Um bloco

while.

False, a execuo pula o bloco while e continua executando o que vier depois. while pode ser traduzido da seguinte forma: enquanto a condio for verdadeira,

continue executando o que estiver neste bloco. Observe a gura 5. vlido lembrar que algum erro de programao pode gerar loops que no terminam! Por isso, estes blocos exigem maior ateno ao serem implementados, ou o programa poder no sair do bloco e no terminar a execuo.

4.14

As tentativas do jogador
As linhas 13 a 17 pedem ao jogador para adivinhar o nmero sorteado e, obviamente, per-

mite com que um palpite seja dado como entrada. Este palpite armazenado na varivel posteriormente, este valor convertido de uma string para um inteiro.

guess

e,

print(Take a guess.) guess = input() guess = int(guess)

4.14.1
mento.

Convertendo strings para inteiros

Na linha 15, chamamos uma nova funo, chamada A funo

int().

A funo

int()

exige um argu-

input()

retorna uma string, do texto que o usurio digitou.

Entretanto, neste

programa, precisamos de um inteiro e no de uma string. Desta forma, a funo o valor string dado e retornar um inteiro.

int() transformar

Voc deve se perguntar o que acontece se o argumento dado esta funo no for um nmero. Voc pode testar isto (e outros inmeros palpites) no terminal interativo. No jogo adivinhe o nmero, se o jogador digitar algo que no seja um nmero, a chamada da funo

int()

resultar em um erro. Alm disso, no podemos fazer comparaes matemticas

4.14.

AS TENTATIVAS DO JOGADOR

21

Figura 5: Funcionamento de um loop

while.

entre nmero e string. Portanto, nos prximos programas, adicionaremos cdigo para condies de erro como esta e dar uma nova chance para o jogador continuar com a execuo do programa. Observe que chamar a funo so

int(guess)

apenas transforma o valor armazenado na varivel

int(guess) no modica o valor da varivel guess. A expresguess em um inteiro. Para que

a varivel receba o valor inteiro gerado, devemos atribu-lo novamente varivel. Por isso, a linha 15 se torna til.

Tarefa 4.2
Verique o acontece com as seguintes entradas: 1. int(`42') 2. int(42) 3. int(`hello') 4. int(` 42 ') 5. int(`forty-two') 6. 3 + int(`2')

Tarefa 4.3

Pesquise sobre a funo

int()

e quais os tipos de argumentos que ela aceita.

4.14.2

Incrementando variveis
guessesTaken = guessestaken + 1

Uma vez que o jogador faz um palpite, devemos aumentar o nmero de palpites dados, pois existe um limite. Na primeira vez que entrarmos no loop, a varivel

guessesTaken

possui o valor

zero. O Python pegar este valor e somar 1 esta varivel com a linha 17. alguma varivel. Quando subtramos uma unidade, dizemos que estamos varivel.

Quando adicionamos 1 a um valor inteiro, usualmente dizemos que estamos

incrementando decrementando alguma

22

4.

ADIVINHE O NMERO

4.15

Sentenas

if

if guess < number: print(Your guess is too low.)


A linha 19 inicia uma sentena com a palavra-chave

if.

Seguido do

if,

h uma condio. A

linha 20 inicia um novo bloco (devido indentao). Este um bloco condicional. Um bloco utilizado quando queremos executar algo somente quando alguma condio verdadeira. Assim como o bloco

if

while,

o bloco

if

tambm possui uma palavra-chave, seguida de uma

condio, e, ento, um bloco de cdigo a ser executado. Observe a gura 6.

Figura 6: Sentenas

if

while.
Entretanto, em um bloco

Uma sentena

if funciona da mesma forma que uma sentena while.

while,

a execuo no sai imediatamente aps o m do bloco, mas continua enquanto a condio for

verdadeira. Se a condio que o jogador der nica linha dentro do bloco

True, ento, todas as linhas do bloco if so executadas. Por exemplo, h uma if, iniciado na linha 19, chamando uma funo print(). Se o inteiro entrada for menor que o inteiro aleatrio gerado, o programa mostra Your guess
o nmero gerado, ento a condio deste bloco

is too low. Se o palpite do jogador for maior que resultar em False, e o bloco no ser executado.

4.16

Saindo de

loops

com o comando

break

if guess == number: break


Este bloco

if

verica se o palpite do jogador igual ao inteiro gerado no programa. Se for, o

programa entra em um bloco que possui uma sentena bloco

while

para a primeira linha seguinte a ele .

break,

que faz com que o programa saia do

No caso deste jogo, se o palpite do jogador no for igual ao nmero gerado, ele continua executando o loop, at que as chances do jogador se esgotem. Se o loop terminar ou for interrompido com o

break, a prxima ao a ser realizada pelo computador executar as linhas de cdigo restantes.

4.17

Vericar se o jogador venceu

if guess == number:
Diferentemente do cdigo da linha 25, este bloco

if

no possui indentao. Logo, isto signica

que o bloco

while

terminou na linha anterior a este. Para entrarmos neste bloco

if

saimos do bloco

8 Um

comando

break

no faz a vericao da condio do loop novamente, apenas encerra o bloco imediatamente.

4.18.

RESUMO: O QUE EXATAMENTE PROGRAMAO?

23

while

por ter extrapolado as tentativas ou por ter adivinhado o nmero. Se for o caso de o jogador

ter acertado o nmero, o programa executar o cdigo seguinte linha 28.

if guess == number: guessesTaken = str(guessesTaken) print(Good job, + myName + ! You guessed my number in + guessesTaken + guesses!)

As linhas 29 e 30 esto dentro do bloco

if,

que sero executadas apenas se a condio da

linha 28 for verdadeira. Na linha 29, chamamos a funo

str()

que retorna uma string atravs do

argumento dado. Esta linha se torna til, pois para imprimir na tela, chamando a funo

print(),

devem ser utilizados apenas strings, j que s permitida a operao de concatenao entre strings.

4.17.1

Vericar se o jogador perdeu

if guess != number: number = str(number) print(Nope. The number I was thinking of was + number)

Na linha 33, utilizamos o operador de comparao

!=

na sentena

if,

signicando diferente

de. Se as chances do jogador se esgotarem, ento a condio deste bloco ser verdadeira, e as linhas 34 e 35 sero executadas. Desta forma, dito ao jogador que ele falhou em adivinhar o nmero, alm de inform-lo qual era este nmero, de forma anloga ao bloco

if

anterior.

4.18

Resumo: o que exatamente programao?


Se algum lhe perguntar o que exatamente programao?, qual seria a sua resposta? Pro-

gramar apenas escrever cdigos para programas que podem ser executados por um computador. Mas, exatamente, o que um programa? Quando voc v algum utilizando um programa, como este que acabamos de estudar, tudo o que vemos um texto aparecendo na tela. O programa decide o que ser mostrado na tela (chamado de dado como entrada pelo jogador (ou seja, o mostrar ao usurio. Que tipos de instrues?

output), baseado em suas instrues e no texto input). O programa apenas possui instrues sobre o que Ou seja, um programa nada mais que uma coleo de instrues.
H alguns tipos diferentes de instrues, na verdade. Expresses

so instrues que resultam em um valor nal, como

2 + 2 resulta em 4.

Chamadas de funo tambm

so partes de expresses, pois elas resultam em um valor nico, que pode ser conectado a outros valores por meio de operadores. Quando expresses esto acompanhadas de palavras-chave como ou

if

while,

elas so chamadas de condies. Sentenas de atribuio servem para guardar valores em e

variveis para que estes possam ser utilizados posteriormente.

if, while

break

so exemplos de sentenas de

controle de uxo,

pois elas estabelecem

quais instrues so executadas. O uxo normal de execuo para um programa iniciar da primeira linha e executar cada instruo, uma a uma. Entretanto, estas estruturas permitem que instrues sejam puladas, repetidas ou interrompidas. Chamadas de funo tambm mudam o uxo de execuo, pulando para onde a funo se encontra. A funo

print() mostra um texto na tela.

A funo

entrada, pelo teclado. Isto chamado de operao de sadas do programa.

I/O

input() armazena um texto dado como

(input/output), pois lida com entradas e

Por enquanto, temos tudo isto como incio do trabalho. Com o passar do tempo, sero aprendidos novos conceitos sobre tipos de dados e operadores, alm de sentenas de controle de uxo e novas funes. Tambm veremos diferentes tipos de I/O (entrada pelo mouse; sada de sons, grcos e imagens, etc.). Para o usurio, apenas importam as operaes de I/O de um programa. O jogador digita alguma coisa ou clica em outra e quer ver o que acontece, atravs de sons e imagens. Mas, para o computador produzir qualquer sada necessrio um programa, uma srie de instrues que iremos desenvolver.

24

4.

ADIVINHE O NMERO

4.19

Exerccios complementares

1. Faa um Programa que leia trs nmeros e mostre o maior deles. 2. Faa um Programa que verique se uma letra digitada F ou M. Conforme a letra escrever: F - Feminino, M - Masculino, Sexo Invlido. 3. Tendo como dados de entrada a altura e o sexo e peso de uma pessoa, construa um algoritmo que calcule seu peso ideal e informe se ela est dentro, acima ou abaixo do peso, utilizando as seguintes frmulas: Para homens:

(72.7 h) 58;

Para mulheres:

(62.1 h) 44.7

(h = altura)

4. Faa um Programa que pergunte em que turno voc estuda. Pea para digitar M-matutino ou V-Vespertino ou N- Noturno. Imprima a mensagem Bom Dia!, Boa Tarde! ou Boa Noite! ou Valor Invlido!, conforme o caso. 5. Faa um programa que faa 5 perguntas para uma pessoa sobre um crime. As perguntas so: Telefonou para a vtima?, Esteve no local do crime?, Mora perto da vtima?, Devia para a vtima? e J trabalhou com a vtima? O programa deve no nal emitir uma classicao sobre a participao da pessoa no crime. Se a pessoa responder positivamente a 2 questes ela deve ser classicada como Suspeita, entre 3 e 4 como Cmplice e 5 como Assassino. Caso contrrio, ele ser classicado como Inocente. Dica: use uma varivel contadora responsvel por contar cada vez que o usurio responda sim 6. Faa um programa que pea uma nota, entre zero e dez. Mostre uma mensagem caso o valor seja invlido e continue pedindo at que o usurio informe um valor vlido. Dica: use o comando

while.
7. Faa um programa que leia um nome de usurio e a sua senha e no aceite a senha igual ao nome do usurio, mostrando uma mensagem de erro e voltando a pedir as informaes.

5 O Reino do Drago
Tpicos abordados neste captulo:

O mdulo A funo A

time time.sleep() palavra-chave return def and, or


e

Criar as prprias funes com a palavra-chave Os operadores booleanos Tabelas-verdade Escopo de varivel local e global Parmetros e argumentos Diagramas de execuo

not

5.1

Introduo funes
J utilizamos duas funes, anteriormente,

input()

print().

Nos programas anteriores,

chamamos estas funes para que o cdigo dentro delas fosse executado. Neste captulo, faremos as nossas prprias funes. Conforme j mencionado, uma funo como um programa dentro do nosso programa. Muitas vezes, queremos que o nosso programa execute um mesmo procedimento vrias vezes, em diferentes pontos do cdigo, de forma que no podemos fazer um simples loop. Ao invs de digit-lo inmeras vezes, construimos uma funo e a chamamos sempre que quisermos. Este recurso possui a vantagem de, caso haja algum erro, fazermos correes em um nico bloco de cdigo. O programa que construiremos para aprender funes chamado O Reino do Drago e permite que o jogador faa um palpite entre duas cavernas que, aleatoriamente, possuem um tesouro ou maldio.

5.2

Como jogar O Reino do Drago


Neste jogo, o jogador est em uma terra cheia de drages. Os drages vivem em cavernas com Alguns drages so amigveis e compartilharo o tesouro com o

grandes quantidades de tesouros.

jogador. Outros so gananciosos e famintos, e devoraro qualquer um que entrar em sua caverna. O jogador est em frente a duas cavernas, uma com um drago amigvel e outra com um ganancioso. Ele pode escolher entre uma das cavernas.

5.2.1

Modelo de sada do jogo

You are in a land full of dragons. In front of you, you see two caves. In one cave, the dragon is friendly and will share his treasure with you. The other dragon is greedy and hungry, and will eat you on sight. Which cave will you go into? (1 or 2) 1 You approach the cave... It is dark and spooky... A large dragon jumps out in front of you! He opens his jaws and... Gobbles you down in one bite! Do you want to play again? (yes or no) no

25

26

5.

O REINO DO DRAGO

5.3

Cdigo-fonte do programa
Aqui est o cdigo fonte do jogo. Digit-lo uma boa prtica para tornar-se acostumado com

o cdigo. O principal a saber sobre o cdigo 3: a funo seja chamada. os blocos precedentes por

def

so como as funes

so declaradas no Python. Entretanto, o cdigo em cada bloco de funo no executado at que Desta forma, o programa no ser executado linha a linha, da primeira a ltima, conforme seria o esperado. Isto ser discutido mais adiante.

Cdigo 3: O Reino do Drago.

import random import time def displayIntro(): print(You are in a land full of dragons. In front of you,) print(you see two caves. In one cave, the dragon is friendly) print(and will share his treasure with you. The other dragon) print(is greedy and hungry, and will eat you on sight.) print() def chooseCave(): cave = while cave != 1 and cave != 2: print(Which cave will you go into? (1 or 2)) cave = input() return cave def checkCave(chosenCave): print(You approach the cave...) time.sleep(2) print(It is dark and spooky...) time.sleep(2) print(A large dragon jumps out in front of you! He opens his jaws and... ) print() time.sleep(2) friendlyCave = random.randint(1, 2) if chosenCave == str(friendlyCave): print(Gives you his treasure!) else: print(Gobbles you down in one bite!) playAgain = yes while playAgain == yes or playAgain == y: displayIntro() caveNumber = chooseCave() checkCave(caveNumber) print(Do you want to play again? (yes or no)) playAgain = input()

5.4.

COMO O PROGRAMA FUNCIONA

27

5.4

Como o programa funciona


Aqui, temos duas sentenas de importao. Importamos o mdulo

random,

como no jogo

adivinhe o nmero. Neste programa, tambm precisaremos de funes relacionadas a tempo, por isso importamos o mdulo

time.

5.4.1

Denindo funes

def displayIntro(): print(You are in a land full of dragons. In front of you,) print(you see two caves. In one cave, the dragon is friendly) print(and will share his treasure with you. The other dragon) print(is greedy and hungry, and will eat you on sight.) print()
A gura 7 mostra um novo tipo de sentena, uma declarao de funo. Este tipo de bloco

feito com a palavra-chave

def,

seguido do nome da funo e um par de parnteses. Para nalizar,

dois pontos para abrir um bloco.

Figura 7: Partes de uma denio de funo no Python.

O bloco que inicia na linha 4 no uma chamada para a funo programa. Depois de

displayIntro().

Ao invs

disso, uma funo est sendo criada (ou denida), para que possamos cham-la posteriormente no

denirmos9

esta funo, podemos cham-la da mesma forma que zemos com Quando a

outras funes, assim, o cdigo dentro dela ser executado. Assim que chamarmos a funo, a execuo pula para a linha 5 do programa. Na funo execuo da funo termina, o programa continua na linha seguinte em que ela foi chamada.

chooseCave(),

temos as linhas:

cave = while cave != 1 and cave != 2:

em que criamos uma varivel chamada loop

cave

e armazenamos uma string vazia. Ento, iniciamos um

while.

Neste loop, h um novo operador, que ainda no foi abordado, o operador

como o sinal de menos () ou de multiplicao () so operadores matemticos, e operadores de comparao, o

and. Assim == ou ! = so

and

um operador booleano.

5.4.2

Operadores booleanos
A lgica booleana lida com operaes que resultam em verdadeiro ou falso. Operadores boPor exemplo, o operador

oleanos comparam dois valores e resultam em um nico valor booleano.

and

avalia se uma expresso verdadeira quando ambos os lados forem verdadeiros. Observe: gatos

miam e cachorros latem". Esta sentena verdadeira, pois ambos os lados (esquecendo de eventuais excees) so verdadeiros. Para uma sentena Agora, voltando linha 13:

and ser verdadeira,

vale a mesma analogia. A sentena

inteira ser verdadeira se, e somente se, ambos os lados forem verdadeiros.

9 Utilizamos

o termo denir para variveis tambm. Assim como declarar.

28

5.

O REINO DO DRAGO

while cave != 1 and cave != 2:


A condio que acompanha o bloco

while

possui duas expresses conectadas pelo operador

and.

Primeiro, cada expresso avaliada como A string armazenada na varivel Alm do

True

ou

False

para depois a expresso inteira

resultar tambm em um valor booleano.

cave

vazia, logo, diferente de

1 not.

ou

2,

assim, todas

as expresses so verdadeiras. Desta forma, entramos no loop, pois a expresso resulta em

True. not

and,

existem outros operadores booleanos, como o

or

e o

No caso do operador

or,

uma sentena verdadeira se

pelo menos uma das expresses verdadeira. O operador

anlogo ao

! =,

visto anteriormente, entretanto, ele trabalha apenas com um valor, invertendo o valor

booleano de alguma entidade. Por exemplo, observe e teste estas sentenas no terminal interativo:

>>> not True False >>> not False True >>> True and not False True

5.4.3

Tabelas-verdade
Para observar os resultados de operadores booleanos, frequentemente utilizado um recurso

chamado tabela-verdade. Uma tabela-verdade mostra todas as possibilidades de uma expresso booleana de acordo com os possveis valores de cada varivel. Observe as tabelas 4, 5 e 6.
Tabela 4: Tabela-verdade do operador

and

A
True True False False

and
and and and and

B
True False True False

Resultado
True False False False

Tabela 5: Tabela-verdade do operador

or

A
True True False False

or
or or or or

B
True False True False

Resultado
True True True False

Tabela 6: Tabela-verdade do operador

not

not
not not

A
True False

Resultado
False True

5.4.4

Obtendo a entrada do jogador


print(Which cave will you go into? (1 or 2)) cave = input()

5.4.

COMO O PROGRAMA FUNCIONA

29

Neste trecho, pedido ao jogador para digitar 1 ou 2 e pressionar Enter. Qualquer string que o jogador digitar ser armazenada em ser

cave.

Mas, se o jogador digitar 1 ou 2, ento o valor de

cave

ou

2.

Se for este o caso, ento a condio do loop ser falsa e o programa no entrar

mais no loop. Em outras palavras, o motivo pela existncia deste loop no caso de o jogador digitar qualquer outra coisa alm de 1 ou 2. O computador perguntar vrias vezes a mesma coisa, at que o jogador d alguma resposta vlida.

5.4.5

Retorno de valores
return cave
Uma sentena de retorno apenas aparece em blocos de funo. Lembre-se que a funo

retornava qualquer valor que fosse dado como entrada pelo teclado. Na funo que ser retornado o valor que estiver armazenado na varivel Isto signica que se tivssemos alguma sentena do tipo dentro da funo valores

input() chooseCave(), o
o cdigo

cave. spam = chooseCave(), spam)

chooseCave()
pois o loop

ser executado e o resultado ser armazenado na varivel garante que, ao chegar na linha 17, o valor de

spam.
seja

Neste caso, o valor de retorno (ou seja, que seria armazenado na varivel

poderia assumir os

ou

2,

while

cave

apenas um deles. Uma sentena com return faz o programa sair imediatamente de uma funo, assim como o break interrompe um loop. A execuo volta linha seguinte em que a funo foi chamada. Tambm possvel usar apenas return para sair de uma funo, sem atribuir nenhum valor de retorno.

5.4.6

Escopo de variveis
Assim como os valores armazenados em variveis so esquecidos quando um programa termina,

variveis criadas dentro de funes so esquecidas assim que estas terminam a execuo. No apenas isso, mas no possvel alterar variveis dentro de funes em outros pontos do programa que no seja dentro da funo. Isto denido pelo

escopo da varivel.

As variveis utilizadas dentro de uma

funo so apenas aquelas que foram criadas dentro de tal funo. Variveis criadas fora das funes, em um programa, possuem escopo (ou acesso) fora das funes. Por exemplo, se uma varivel signica que, se alterarmos o valor de

spam

foi criada dentro de um funo, e outra, com o mesmo o valor da varivel com o mesmo nome,

nome, foi criada fora da funo, o Python interpretar como se fossem duas variveis distintas. Isto

spam dentro da funo,

fora da funo, no ser alterado. Isto porque as variveis possuem escopo diferente, global e local.

Escopo global e local


O escopo que abrange a rea fora de qualquer funo chamado de uma funo, chama-se

escopo local.

escopo global.

Dentro de

Cada programa possui apenas um escopo global e cada funo

possui um escopo local prprio.

5.4.7

Denindo a funo

checkCave(chosenCave)

def checkCave(chosenCave):
Observa-se que, ao declarar a funo

checkCave(),

h um texto dentro dos parnteses da

funo, no caso,

tros.

chosenCave.

Este texto dentro dos parnteses so variveis, chamadas

parme-

str() e checkCave(), devemos passar um valor como parmetro. Este valor identicado dentro da funo com o nome de chosenCave. Esta a forma com que passamos valores randint().
Ao chamarmos para funes, desde que elas no possuem acesso a variveis fora de seu escopo. Em resumo, parmetros so variveis locais que so denidas quando a funo chamada. O valor armazenado no parmetro o argumento que foi passado na chamada da funo.

Lembre-se que j passamos parmetros para funes anteriormente, com as funes

30

5.

O REINO DO DRAGO

5.4.8

Onde denir funes


Uma denio de funo, em Python, deve vir antes que ela seja chamada. a mesma ideia de

ter que atribuir um valor a uma varivel antes que ela seja utilizada. Observe:

sayGoodBye() def sayGoodBye(): print(Good bye!)


Este cdigo gera um erro, pois a funo foi chamada antes de ser denida. Para corrigir isto,

devemos apenas mover a chamada da funo para depois da denio da mesma.

def sayGoodBye(): print(Good bye!) sayGoodBye()

5.4.9

Mostrando o resultado do jogo


De volta ao cdigo do programa:

print(You approach the cave...) time.sleep(2) print(It is dark and spooky...) time.sleep(2) print(A large dragon jumps out in front of you! He opens his jaws and...) print() time.sleep(2)

Mostramos um texto ao jogador e depois chamamos a funo foi chamada a funo mdulo

randint()

no jogo de adivinhar o nmero. A funo

time.sleep(). Lembre-se sleep() faz

de como parte do

time,

importado no incio do programa. Esta funo faz com que o programa d uma pausa Desta forma, a cada vez em que a funo

de quantos segundos lhe forem dados como argumento.

sleep()

chamada neste programa, dada uma pausa de dois segundos.

Estas pausas do suspense ao jogo, ao invs de mostrar o todo o texto de uma vez.

5.4.10

Decidindo em que caverna est o drago amigvel


friendlyCave = random.randint(1, 2) if chosenCave == str(friendlyCave): print(Gives you his treasure!) else: print(Gobbles you down in one bite!)

Agora o programa selecionar aleatoriamente em que caverna o drago amigvel est. Para isto, chamamos a funo na varivel

random.randint() com um retorno entre os nmeros 1 e friendlyCave. Em seguida vericamos se o inteiro gerado igual
10 .

2 e o armazenamos entrada do usurio,

transformando o nmero em uma string um inteiro. Observe:

Tambm poderia ser feito o contrrio, ou seja, transformar a string digitada pelo usurio em

if int(chosenCave) == friendlyCave:
Finalmente, se a condio do bloco o jogo. Do contrrio, o bloco

if

for verdadeira, o jogador informado de que ele ganhou

else

executado e o jogador perde o jogo.

10 Lembre-se

que s podemos fazer comparaes de uma string com outra string, por isso utilizamos a funo

str(),

j que o retorno da funo

==

sempre resultar em

randint() False.

um inteiro. Ao comparar valores de diferentes tipo, o a operao de igualdade

5.5.

PROJETANDO UM PROGRAMA

31

Dois-pontos
Voc pode ter notado que os blocos de um novo bloco.

if, else, while ou funo, tm sua primeira linha seguida

por dois pontos. Este sinal marca o m de uma sentena e nos informa que a prxima linha o incio

5.4.11

Onde o programa realmente comea

playAgain = yes while playAgain == yes or playAgain == y: displayIntro() caveNumber = chooseCave() checkCave(caveNumber) print(Do you want to play again? (yes or no)) playAgain = input()
A linha 35 a primeira linha que no uma funo (ou seja, que no est dentro de um bloco

def).

nesta linha que o programa realmente comea. Os blocos anteriores so apenas declarao A linha 36 sinaliza o incio de um loop

de funes que no so executadas se no forem chamadas. valor da varivel

playAgain,

que foi iniciada com

while. Entramos a primeira vez no yes e faz com que a condio

loop atravs do seja verdadeira.

5.4.12

Chamando funes no programa

Na linha 38, chamamos a funo

displayIntro().

Esta no uma funo do Python, mas

uma funo que criamos. Quando esta funo chamada, o programa pula para a linha 5 e executa o que est no bloco da respectiva funo. Quando todas as linhas da funo forem executadas, a execuo continua na linha seguinte em que a funo foi chamada. Em seguida, uma varivel recebe o valor gerado pela funo envia o valor da varivel ir.

chooseCave(),

que tambm foi

criada neste programa, para o jogador escolher qual caverna seguir. Feito isso, a execuo continua e

caveNumber

funo

checkCave().

Esta funo vai comparar os valores

do jogador e da caverna e mostrar na tela o resultado do jogo, dependendo de onde o jogador escolheu

5.4.13

Perguntando se o jogador quer jogar novamente

Depois que o jogo terminar, o jogador tem a escolha de jogar novamente, antes de nalizar o programa. A varivel

playAgain armazena a escolha do jogador. Entretanto, diferente da funo chooseCave(), discutida anteriormente, o loop nal s ser executado se o jogador digitar yes 11 ou y . Se o jogador digitar qualquer outra coisa, a condio resultar em False e o loop
pulado. Contudo, no h mais linhas de cdigo a serem executadas, aps este loop, e o programa, ento, termina.

5.5

Projetando um programa
O Reino do Drago um jogo bem simples. Os prximos sero um pouco mais complicados.

Desta forma, de grande ajuda escrever (sim, no papel) o ser feito em um programa. Isto se chama projetar um programa. Por exemplo, desenhar um

uxograma

pode ajudar no entendimento. Um uxograma um

desenho que mostra cada ao possvel que deve acontecer no programa e em que ordem elas devem ocorrer. Normalmente, criamos estes projetos antes de escrever um programa, pois assim lembramos de escrever o cdigo de todas as partes do programa. Observe a gura 8.

11 Nem

se o jogador digitar

YES

a condio resultar em

True,

pois,

yes

diferente de

YES,

para o Python.

Verique voc mesmo no terminal interativo.

32

5.

O REINO DO DRAGO

Figura 8: Fluxograma para o jogo O Reino do Drago.

Para entender o que acontece no jogo, siga as setas a partir do quadrado que diz INCIO. Perceba que, ao chegar no quadrado Vericar drago amigvel ou faminto o programa escolher se o jogador ganha ou perde. Ento, o programa pergunta se o jogador deseja jogar novamente e ele executado novamente ou termina.

5.6

Resumo
No jogo O Reino do Drago, criamos nossas prprias funes. Podemos pensar em funes

como mini-programas dentro do nosso programa, que s sero executados quando a funo for chamada. Utilizar funes pode tornar o cdigo mais simples para ser lido. Tambm podemos executar vrias vezes um mesmo cdigo utilizando funes. As entradas para funes so os ainda funes que no retornam nada. Tambm aprendemos sobre escopo de variveis. Variveis criadas dentro de uma funo possuem escopo local, enquanto aquelas criadas fora de funes so de escopo global. O cdigo em escopo global no tem acesso variveis locais. Se uma varivel local possui o mesmo nome de uma varivel global, o Python ir interpret-las como duas variveis distintas. Em outras palavras, alterar o valor de uma delas no altera o valor da outra. Entender como o escopo de variveis funciona pode parecer simples, mas ao utiliz-lo pode parecer complicado. Entretanto, uma ferramenta til para organizar funes como pedaos de cdigo independentes em um programa. Como cada funo tem seu escopo local, podemos ter certeza de que uma funo no interferir em outra parte do cdigo. Programas mais prximos de um nvel prossional utilizam funes, assim como o restante dos jogos que sero vistos. Ao entender como as funes funcionam, podemos facilitar o trabalho futuramente, reaproveitando funes j construdas.

argumentos passados em uma chamada de funo. A funo

envia ao programa principal uma resposta, ou seja, um valor de retorno, que a sada da funo. H

5.7.

EXERCCIOS COMPLEMENTARES

33

Tarefa 5.1
1. Utilize o cdigo 3 e faa um jogo mais elaborado, com os conceitos aprendidos at agora. 2. Pesquise sobre o

debugger do IDLE.

5.7

Exerccios complementares
Por exemplo, o programa deve converter 14:25 em 2:25 P.M. A entrada dada em dois inteiros. Deve haver pelo menos duas funes: uma para fazer a converso e uma para a sada. Registre a informao A.M./P.M. como um valor `A' para A.M. e `P' para P.M. Assim, a funo para efetuar as converses ter um parmetro formal para registrar se A.M.

1. Faa um programa que converta da notao de 24 horas para a notao de 12 horas.

2.

Jogo de Craps.

Faa um programa de implemente um jogo de Craps. O jogador lana um

par de dados, obtendo um valor entre 2 e 12. Se, na primeira jogada, voc tirar 7 ou 11, voc um natural e ganhou. Se voc tirar 2, 3 ou 12 na primeira jogada, isto chamado de craps e voc perdeu. Se, na primeira jogada, voc fez um 4, 5, 6, 8, 9 ou 10, este seu Ponto. Seu objetivo agora continuar jogando os dados at tirar este nmero novamente. Voc perde, no entanto, se tirar um 7 antes de tirar este Ponto novamente. 3.

Data com ms por extenso. Desenha moldura.

Construa uma funo que receba uma data no formato

DD/M M/AAAA

e devolva uma string no formato D de 4.

mesPorExtenso

de AAAA. Opcionalmente, valide a

data e retorne NULL caso a data seja invlida. Construa uma funo que desenhe um retngulo usando os caracteres `+' , `' e `|'. Esta funo deve receber dois parmetros, linhas e colunas, sendo que o valor por omisso o valor mnimo igual a 1 e o valor mximo 20. Se valores fora da faixa forem informados, eles devem ser modicados para valores dentro da faixa de forma elegante.

6 Jogo da forca
Tpicos abordados neste captulo:

Projeto de um programa Arte ASCII Mtodos

append() lower() e upper() O mtodo de lista reverse() O mtodo de string split() A funo range() A funo list() Loops for Sentenas elif Os mtodos de string startswith() e endswith()
Os mtodos de string Neste captulo, ser desenvolvido um jogo de forca. Este jogo mais complicado do que os

O mtodo de lista

anteriores, mas tambm muito mais divertido. Devido maior complexidade do programa, vamos inicialmente projet-lo, utilizando um uxograma. Este jogo apresenta vrios conceitos novos. Para nos acostumarmos com tais conceitos, o terminal interativo de grande ajuda. Alguns tipos de dados (como strings ou listas) possuem funes associadas a seus valores, chamadas mtodos. Veremos alguns destes mtodos, alm de uma nova forma de loop (for) e blocos condicionais mais elaborados.

34

6.1.

MODELO DE SADA DO JOGO DE FORCA

35

6.1

Modelo de sada do jogo de forca


Aqui est um exemplo do que o jogador ver quando executar o jogo de forca.

H A N G M A N +---+ | | | | | | ========= Missed letters: _ _ _ Guess a letter. a +---+ | | | | | | ========= Missed letters: _ a _ Guess a letter. o +---+ | | O | | | | ========= Missed letters: o _ a _ Guess a letter. r +---+ | | O | | | | ========= Missed letters: or _ a _ Guess a letter. t

+---+ | | O | | |

36

6.

JOGO DA FORCA

| ========= Missed letters: or _ a t Guess a letter. a You have already guessed that letter. Choose again. Guess a letter. c Yes! The secret word is "cat"! You have won! Do you want to play again? (yes or no) no

6.2

Arte ASCII
Como pode-se perceber no exemplo de execuo do jogo da forca, algumas linhas de sada

no so bem um cdigo (com comandos, etc), mas strings de vrias linhas que utilizam caracteres do teclado para desenhar imagens. Este tipo de recurso grco chamado de caracteres do teclado so chamados de caracteres ASCII Observe o exemplo disponvel no site

12 . Para as primeiras aplicaes, em que no

arte ASCII,

pois os

estamos lidando com imagens e sons, uma sada de texto criativa pode chamar a ateno do jogador.

http://www.chris.com/ascii/:

_ (_) | . . |L /| . _ _ . |\ _| \--+._/| . (_) / ||\| Y J ) / |/| ./ J |)( | F./ _ -<| F __ .-< (_) | / .-. . /-. L___ J \ < \ | | O\|.- _ _J \ .\/ O | | \ |F (_) -F -<_. \ .- - L__ __J _ _. >- )._. |- -|. /_. \_| F /.. _.< / /. . \ /L / |/ _.--\ /J ___.---\| |\ .-- V | . |/. -. ._) / .-.\ VK \ ( \ .\
E o exemplo disponvel em

http://www.asciiarte.com/index.html.

___,A.A_ __ \ , 7"_/ ~"T( r r) | \ Y | ~\ .| | |- | | | | | | | | j l / \ Y Y l \ : | /\ )( ( / \ I| |\


12 American
Standard Code for Information Interchange.

6.3.

PROJETANDO UM PROGRAMA ATRAVS DE UM FLUXOGRAMA

37

Y I l| | Y j ( )( ) l / . \ | |\ -Row Y \ i | ! Y l .\_ I |/ | \ / [\[][]/] j ~~~~~~~~~~~~~~~~~~~~~~~

6.3

Projetando um programa atravs de um uxograma


Este jogo mais complicado do que j vimos at agora. Ento, vamos pensar um pouco sobre

o que precisamos e depois partimos para a implementao. Primeiro, vamos criar um uxograma, como aquele visto na gura 8, para nos ajudar a visualizar o que este programa far. Um mostram quais passos seguir. Iniciamos na caixa de incio. Vamos percorrendo o uxograma de acordo com a direo das setas e no podemos voltar algum passo, a no ser que haja alguma seta que nos permita isso. Observe o uxograma para o jogo da forca na gura 9.

uxograma13

um diagrama que nos mostra uma srie de passos,

representados por caixas conectadas por setas. Cada caixa representa um passo, enquanto as setas

Figura 9: Fluxograma para o jogo da forca.

13 H

algumas convenes para confeco de uxogramas, entretanto, no abordaremos tais formalismos. O uso deste

recurso ser meramente para esclarecer como um programa funciona, mostrando o passo-a-passo de forma que evite confuses na implementao.

38

6.

JOGO DA FORCA

claro que no precisamos fazer um uxograma e podemos simplesmente comear a escrever o cdigo. Entretanto, ao programar, eventualmente pensamos nas coisas que precisam ser mudadas ou adicionadas que, em um primeiro momento, no tnhamos pensado. Acabamos apagando vrias linhas de cdigo e reescrevendo-as, deixando coisas passarem desapercebidas, enm, coisas que podem ser desperdcio de esforo. Para evitar estes desconfortos, sempre interessante pensar cuidadosamente e planejar o trabalho. O uxograma da gura 9 um exemplo mais robusto de como estes diagramas funcionam. Para trabalhar neste material, no ser necessrio planejar cada programa, pois eles j esto implementados. Entretanto, ao fazer projetos prprios, esta ferramenta muito til e economiza muito tempo de implementao.

6.4

Cdigo-fonte do jogo de forca


Cdigo 4: Jogo de forca.

import random HANGMANPICS = [ +---+ | | | | | | =========, +---+ | | O | | | | =========, +---+ | | O | | | | | =========, +---+ | | O | /| | | | =========, +---+ | | O | /|\ | | | =========, +---+ | |

6.4.

CDIGO-FONTE DO JOGO DE FORCA

39

| | | | =========, +---+ | | O | /|\ | / \ | | =========] words = ant baboon badger bat bear beaver camel cat clam cobra cougar coyote crow deer dog donkey duck eagle ferret fox frog goat goose hawk lion lizard llama mole monkey moose mouse mule newt otter owl panda parrot pigeon python rabbit ram rat raven rhino salmon seal shark sheep skunk sloth snake spider stork swan tiger toad trout turkey turtle weasel whale wolf wombat zebra.split() def getRandomWord(wordList): # Esta funcao retorna uma string aleatoria da lista de strings wordIndex = random.randint(0, len(wordList) - 1) return wordList[wordIndex] def displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord): print(HANGMANPICS[len(missedLetters)]) print() print(Missed letters:, end= ) for letter in missedLetters: print(letter, end= ) print() blanks = _ * len(secretWord) for i in range(len(secretWord)): # substitui os espacos em branco pelas letras adivinhadas corretamente if secretWord[i] in correctLetters: blanks = blanks[:i] + secretWord[i] + blanks[i+1:] for letter in blanks: # mostra a palavra secreta com espacos entre cada letra print(letter, end= ) print() def getGuess(alreadyGuessed): # Retorna a letra que o jogador escolheu. Esta funcao garante que o jogador digitou uma unica letra e nada mais. while True: print(Guess a letter.) guess = input() guess = guess.lower() if len(guess) != 1: print(Please enter a single letter.) elif guess in alreadyGuessed: print(You have already guessed that letter. Choose again.) elif guess not in abcdefghijklmnopqrstuvwxyz: print(Please enter a LETTER.) else: return guess

O /|\ /

40

6.

JOGO DA FORCA

def playAgain(): # Esta funcao retorna True se o jogador quiser jogar novamente. Do contrario, retorna False. print(Do you want to play again? (yes or no)) return input().lower().startswith(y)

print(H A N G M A N) missedLetters = correctLetters = secretWord = getRandomWord(words) gameIsDone = False while True: displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord) # Permite que o jogador digite uma letra guess = getGuess(missedLetters + correctLetters) if guess in secretWord: correctLetters = correctLetters + guess # Verifica se o jogador venceu foundAllLetters = True for i in range(len(secretWord)): if secretWord[i] not in correctLetters: foundAllLetters = False break if foundAllLetters: print(Yes! The secret word is " + secretWord + "! You have won !) gameIsDone = True else: missedLetters = missedLetters + guess # Verifica se o jogador perdeu if len(missedLetters) == len(HANGMANPICS) - 1: displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord) print(You have run out of guesses!\nAfter + str(len( missedLetters)) + missed guesses and + str(len( correctLetters)) + correct guesses, the word was " + secretWord + ") gameIsDone = True # Pergunta ao jogador que ele gostaria de jogar novamente (apenas se o jogo foi encerrado). if gameIsDone: if playAgain(): missedLetters = correctLetters = gameIsDone = False secretWord = getRandomWord(words) else: break

6.5

Como funcionam algumas coisas


Iniciamos importando o mdulo

random,

que nos ajudar a escolher aleatoriamente uma pala-

vra secreta da lista de palavras no programa. Em seguida, denimos as strings que ilustraro o jogo.

6.5.

COMO FUNCIONAM ALGUMAS COISAS

41

Para ajudar no entendimento das estruturas utilizadas no programa, vamos aprender sobre strings de vrias linhas e listas.

import random HANGMANPICS = [ +---+ | | | | | | =========, # o resto do bloco muito grande para ser mostrado aqui

A linha 2 simplesmente uma declarao de varivel, mas ela ocupa vrias linhas no cdigofonte. Esta linha vai at a linha 58

6.5.1

Strings de vrias linhas


Normalmente, quando voc escreve strings em seu cdigo-fonte, elas devem ocupar uma nica

linha. Entretanto, utilizando trs aspas simples para iniciar e terminar uma string, ela pode possuir vrias linhas. Por exemplo, verique o seguinte no terminal interativo:

>>> fizz = Dear Alice, I will return home at the end of the month. I will see you then. Your friend, Bob >>> print fizz

Se no existisse esta estrutura, teramos que utilizar o comando especial para pular linha exemplo a seguir.

\n.

Porm, isto pode fazer com que a string que mais difcil de ser lida, pelo programador, como no

>>> fizz = Dear Alice,\nI will return home at the end of the month. I will see you then.\nYour friend,\nBob >>> print fizz

Strings de vrias linhas no necessitam ter a mesma indentao para permanecer no mesmo bloco. Para este tipo de string, o Python ignora as regras de indentao.

6.5.2

Constantes
Voc deve ter notado que a varivel

HANGMANPICS

est com todas as letras em maisculas.

Esta a conveno de programao para declarar constantes. programador alertado a no escrever cdigo que as alterem.

Constantes so variveis cujos valores

no mudam ao longo do programa. Embora sejamos permitidos a alterar o valor destas variveis, o Constantes so muito teis para fornecer descries para valores que tenham um signicado especial. A varivel

HANGMANPICS

nunca muda, e muito mais fcil escrever

HANGMANPICS

do que

escrever cada string. Entretanto, como qualquer conveno, no somos obrigados a usar constantes ou utilizar letras maisculas para declar-las. Ainda assim, estas convenes fazem com que o cdigo seja mais fcil de ser lido, principalmente, por outros programadores ou quando voc for consultar o cdigo futuramente.

42

6.

JOGO DA FORCA

6.5.3

Listas
Agora, aprenderemos sobre um novo tipo de dado, chamado

lista.

Uma lista contm alguns

valores armazenados. Por exemplo, contm trs valores string. uma varivel, como

[apples, oranges, HELLO WORLD] uma lista que

Como qualquer outro tipo de dado, possvel armazenar uma lista em Cada

spam = [apples, oranges, HELLO WORLD].

Listas so um eciente modo de armazenar diferentes valores em uma nica varivel. valor dentro de uma lista chamado de posio do item na lista.

item.

Cada item pode ser acessado utilizando colchetes e a

>>> animals = [aardvark, anteater, antelope, albert] >>> animals[0] aardvark >>> animals[1] anteater >>> animals[2] antelope >>> animals[3] albert >>>
O nmero entre os colchetes denominado zero, ao invs do nmero um terceiro o anterior:

14 . Assim, com o primeiro ndice sendo o

ndice.

Em Python, o primeiro ndice o nmero

0,

o segundo ndice o

1,

2,

etc. Uma lista um recurso muito bom quando precisamos armazenar vrios valores,

sem ter que designar uma varivel para cada valor. Do contrrio, teramos o seguinte para o exemplo

>>> >>> >>> >>>

animals1 animals2 animals3 animals4

= = = =

aardvark anteater antelope albert

Utilizando listas, podemos tratar os itens como qualquer outro valor. Observe:

>>> animals[0] + animals[2] aardvarkantelope

animals[0] resultar na string aardvark animals[0] + animals[2] resulta antelope.


ento a expresso uma lista? Digite

Por

animals[2]

resultar em

no mesmo que a operao

antelope, aardvark +

Mas o que acontece se tentarmos acessar um ndice que maior do que o nmero de itens de

animals[0]

ou

animals[99]

no terminal interativo.

Alterando valores de itens de uma lista atravs do uso de ndices


muito simples mudar o valor de um item em uma determinada posio de uma lista. Basta atribuir um novo valor posio desejada, da mesma forma que isto feito com qualquer varivel. Observe.

>>> animals = [aardvark, anteater, antelope, albert] >>> animals[1] = ANTEATER >>> animals [aardvark, ANTEATER, antelope, albert]

Concatenando listas
possvel juntar vrias listas em uma s com o operador strings. exemplo.

+,

Quando juntamos listas, a operao conhecida como

concatenao de listas.

da mesma forma que feito com Veja o

14 Esta

numerao bem comum entre as linguagens de programao.

6.5.

COMO FUNCIONAM ALGUMAS COISAS

43

>>> [1, 2, 3, 4] + [apples, oranges] + [Alice, Bob] [1, 2, 3, 4, apples, oranges, Alice, Bob] >>>

Comparao entre listas e strings


Uma string, na verdade, sequncia da caracteres, enquanto que uma lista uma sequncia de itens quisquer

15 . Nos dois casos, concatenao e repetio16 funcionam de forma logicamente idntica.

Elementos individuais podem ser visualizados, mas somente nas listas possivel altera-los. Veja os exemplos a seguir:

>>> name = "John" >>> print (name[0]) J >>> name[0] = "L" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: str object does not support item assignment >>> names = ["John","Mary","Carl"] >>> print (names[1]) Mary >>> names[1] = "Joe" >>> print (names) [John,Joe,Carl]

6.5.4

O operador
O operador

in
True
se o valor est na lista e

in

torna fcil a vericao de um valor dentro de uma lista. Expresses que usam

o operador na lista.

in

retornam um valor booleano:

False

se o valor no est

>>> animals = [aardvark, anteater, antelope, albert] >>> antelope in animals True
A expresso expresso

encontrada na lista. Entretanto, a expresso

antelope in animals retorna True pois a string antelope pode ser ant in animals resultaria em False. Mas a ant in [beetle, wasp, ant] resultaria em True.

6.5.5

Removendo itens de listas


possvel remover itens de uma lista com uma sentena

del.

>>> >>> >>> [2, >>>

spam = [2, 4, 6, 8, 10] del spam[1] spam 6, 8, 10]

Note que, ao deletar o item que estava na posio 1, o item que estava na posio 2 tomou lugar do item excludo. Os outros itens tambm tiveram seus ndices atualizados. Voc pode deletar vrias vezes o mesmo item.

15 Em 16 Na

algumas linguagens de programao populares, listas e strings so chamadas de vetores, sendo strings vetor de operao de repetio, voc pode multiplicar alguma lista ou string am de repetir sua impresso. Teste no

caracteres terminal interativo o comando:

"ol"5

44

6.

JOGO DA FORCA

>>> >>> >>> [2, >>> >>> [2, >>> >>> [2,

spam = [2, 4, 6, 8, 10] del spam[1] spam 6, 8, 10] del spam[1] spam 8, 10] del spam[1] spam 10]

Lembre-se que o uso do nenhum valor de retorno.

del

uma sentena, no uma funo ou operador.

Logo, no h

6.5.6

Listas de listas
Uma lista uma tipo de dado que pode conter vrios valores como itens. Estes itens tambm

podem ser outras listas. Observe.

>>> groceries = [eggs, milk, soup, apples, bread] >>> chores = [clean, mow the lawn, go grocery shopping] >>> favoritePies = [apple, frumbleberry] >>> listOfLists = [groceries, chores, favoritePies] >>> listOfLists [[eggs, milk, soup, apples, bread], [clean, mow the lawn, go grocery shopping], [apple, frumbleberry]] >>>
Alternativamente, o exemplo anterior pode ser designado da seguinte forma.

>>> listOfLists = [[eggs, milk, soup, apples, bread], [clean, mow the lawn, go grocery shopping], [apple, frumbleberry]] >>> groceries = listOfLists[0] >>> chores = listOfLists[1] >>> favoritePies = listOfLists[2] >>> groceries [eggs, milk, soup, apples, bread] >>> chores [clean, mow the lawn, go grocery shopping] >>> favoritePies [apple, frumbleberry] >>>
Para acessar os itens das listas dentro de uma lista, necessrio utilizar dois ndices. Um para

listOfLists[1][2] resulta go grocery shopping. Isto porque listOfLists[1] resulta na lista [clean,mow the lawn, go grocery shopping][2]. Esta, nalmente resulta no terceiro item da lista, go grocery shopping.
em Para tornar mais fcil a identicao dos itens em uma lista de listas, observe a gura 10.

referenciar a sublista e outra para referenciar o item da sublista, como

6.5.7

Mtodos

Mtodos so como funes, mas esto sempre anexados a algum valor.


valores string possuem um mtodo

Por exemplo, todos os

lower(), que retorna uma cpia da string em letras minsculas. No possvel apenas chamar lower() ou passar um argumento, como visto anteriormente, da forma lower(Hello). necessrio anexar o mtodo a alguma string especca, usando um ponto.

6.5.

COMO FUNCIONAM ALGUMAS COISAS

45

Figura 10: ndices em uma lista que contm outras listas.

Os mtodos de string lower() e upper()


O mtodo

lower(),

conforme mencionado anteriormente, retorna uma cpia de uma string

em letras minsculas. Do contrrio, o mtodo maisculas. Observe o exemplo:

upper(),

retorna uma cpia de uma string em letras

>>> Hello world.lower() hello world! >>> Hello world.upper() HELLO WORLD!
Devido aos mtodos retornarem uma string, eles podem ser vistos como uma string e utilizados como tal. Desta forma, podemos fazer o seguinte:

>>> Hello world.upper().lower() hello world! >>> Hello world.lower().upper() HELLO WORLD!
Se uma string est armazenada em uma varivel, pode-se tratar da mesma forma.

>>> fizz = Hello world >>> fizz.upper() HELLO WORLD

6.5.8

Os mtodos de lista

reverse()

append()
reverse()
inverte a ordem dos

O tipo de dado de lista tambm possui mtodos. O mtodo itens na lista.

>>> spam = [1, 2, 3, 4, 5, 6, meow, woof] >>> spam.reverse() >>> spam [woof, meow, 6, 5, 4, 3, 2, 1]
O mtodo de lista mais comum o parmetro, no m da lista.

append().

Este mtodo adiciona um valor passado por

46

6.

JOGO DA FORCA

>>> eggs = [] >>> eggs.append(hovercraft) >>> eggs [hovercraft] >>> eggs.append(eels) >>> eggs [hovercraft, eels] >>> eggs.append(42) >>> eggs [hovercraft, eels, 42]

6.6

A diferena entre mtodos e funes


Voc pode se perguntar porque o Python possui mtodos, j que eles se comportam como

funes. Alguns tipos de dados possuem mtodos. Mtodos so funes associadas a valores de algum determinado tipo de dado. Por exemplo, mtodos de string so funes que podem ser utilizadas (chamadas) por qualquer string. No possvel chamar mtodos de string para outros tipos de dados. Por exemplo,

[1, 2,

apple].upper()

resultaria em um erro, pois

[1, 2, apple]

uma lista e no uma string.

Os valores que possuem mtodos so chamados de objetos. Objeto um conceito de programao orientada a objetos. No necessrio saber realmente, neste momento, o que programao orientada a objetos. Vamos explorando os conceitos necessrios no decorrer do curso. Por enquanto, necessrio entender que os tipos de dados que possuem mtodos so chamados de objetos.

6.6.1

O mtodo de lista

split()
tambm para strings.

A linha 59 uma longa linha de cdigo, mas apenas uma atribuio de varivel. Esta linha tambm utiliza o mtodo

split(),

words = ant baboon badger bat bear beaver camel cat clam cobra cougar coyote crow deer dog donkey duck eagle ferret fox frog goat goose hawk lion lizard llama mole monkey moose mouse mule newt otter owl panda parrot pigeon python rabbit ram rat raven rhino salmon seal shark sheep skunk sloth snake spider stork swan tiger toad trout turkey turtle weasel whale wolf wombat zebra.split()
Como voc pode perceber, esta linha apenas uma longa string, cheia de palavras separadas por espaos. No m da string, chamamos o mtodo

split().

Este mtodo transforma a string em

uma lista, em que cada palavra se torna um item. A diviso ocorre sempre que houver um espao. O motivo de utilizarmos esta funo, ao invs de declarar uma lista, que bem mais fcil escrever uma string longa do que digitar cada palavra como um item de uma lista. Observe um exemplo:

>>> My very energetic mother just served us nine pies.split() [My, very, energetic, mother, just, served, us, nine, pies]
O resultado uma lista de nove strings, cada uma para cada palavra da string original. No caso do jogo da forca, a lista

words conter cada palavra secreta utilizada na forca.

Voc pode adicionar suas

prprias palavras na string, ou remover tambm. Apenas tenha certeza de que as palavras estejam separadas por espaos.

6.7

Como o cdigo funciona


Iniciando na linha 61, denimos uma nova funo chamada

getRandomWord(), que posui um

nico parmetro chamado lista

wordlist.

Chamamos esta funo para escolher uma palavra secreta da

words.

6.7.

COMO O CDIGO FUNCIONA

47

def getRandomWord(wordList): # Esta funcao retorna uma string aleatoria da lista de strings wordIndex = random.randint(0, len(wordList) - 1) return wordList[wordIndex]
A funo

getRandomWord()

recebe uma lista de strings como argumento para o parmetro

wordList.
na varivel segundo

Na linha 63, armazenamos um ndice aleatrio, para ser utilizado na lista recebida,

wordIndex.

Fazemos isto atravs da funo

randint(),

com dois argumentos, que em um inteiro.

caracterizam a faixa de nmeros que a funo poder escolher. O primeiro argumento o zero e o

len(wordList) - 1. O segundo argumento uma expresso que resulta len(wordList) retornar o tamanho (um inteiro) da lista passada para a funo.

Diminumos uma unidade do tamanho da lista, pois os itens so identicados a partir do zero. Logo, o ltimo item da lista possuir ndice com o valor da quantidade de itens menos 1.

6.7.1

Mostrando a ilustrao para o jogador

def displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord): print(HANGMANPICS[len(missedLetters)]) print()


Aqui, foi criada uma funo que imprimir a ilustrao do jogo de forca, com as letras que o

jogador acertou (ou no). Este cdigo dene uma funo chamada quatro parmetros. Aqui est o que cada parmetro signica:

displayBoard(),

que recebe

HANGMANPICS:

a lista de strings de vrias linhas que ser mostrada como arte ASCII. Passa-

HANGMANPICS como argumento para este parmetro. missedLetters: uma string de palpites (letras) que o jogador errou. correctLetters: uma string de palpites (letras) que o jogador acertou. secretWord: esta string a palavra secreta que o jogador deve adivinhar.
A primeira chamada da funo O nmero de letras em ndice da lista incorretos.

remos a varivel global

print()

mostrar a ilustrao do jogo.

HANGMANPICS

lista de strings que possuem os passos do corpo do enforcado. fez. Para saber esta quantidade, chamamos

missedLetters armazenar quantos palpites incorretos o jogador len(missedLetters). Este nmero utilizado como

HANGMANPICS,

para que seja impressa a ilustrao correta, de acordo com os palpites

print(Missed letters:, end= ) for letter in missedLetters: print(letter, end= ) print()


A linha 71 apresenta um novo tipo de loop, o loop

for.

A linha 72 o que compe o bloco

do loop adiante.

for.

A funo

range()

frequentemente utilizada com loops

for.

Veremos esta funo

O argumento end
Nas linhas 70 e 72 h um segundo argumento fornecido funo argumento opcional. Passando uma string em branco para o

print(), o end= . Este end o mesmo que dizer funo para

que uma nova linha no seja inserida ao m da string. Ao invs disso, este argumento faz com que um espao em branco seja adicionado a string impressa. por isso que a linha seguinte a ser impressa (no caso da linha 70, a linha 72) aparece na mesma linha que a anterior.

6.7.2

As funes
A funo

range()

list()
Ela pode ser chamada com um ou dois argumentos

range()

fcil de entender.

inteiros. Quando chamada com um argumento,

range()

retornar uma srie de valores inteiros, de

48

6.

JOGO DA FORCA

zero ao argumento menos uma unidade. Esta srie pode ser convertida para uma lista com a funo

list().
>>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Se forem passados dois argumentos funo

range,

a lista de inteiros retornada compreende

desde o primeiro argumento at o segundo argumento menos uma unidade. Observe:

>>> list(range(10, 20)) [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
A funo

poderosos que o loop

range muito while).

til, pois frequentemente usada em loops

for

(que so muito mais

6.7.3

Loops
O loop

for
uma boa ferramenta para percorrer listas de valores. diferente do loop

for

while,

que faz repeties enquanto uma condio verdadeira. Uma sentena chave

for

comea com a palavra-

for,

seguida por uma varivel e a palavra-chave

in,

seguida por uma sequncia (como uma

lista ou string) ou uma srie de valores (retornada pela funo dois-pontos. A cada Observe o exemplo:

iterao, a varivel na sentena for recebe o valor do prximo item da lista.

range()).

Para nalizar a sentena,

>>> for i in range(10): ... print(i) ... 0 1 2 3 4 5 6 7 8 9 >>>


Com loops o comando

for, no h necessidade de converter o objeto srie (range()) para uma lista com list(). O loop for faz isto automaticamente. Ele executa o cdigo em seu bloco uma

vez para cada item da lista. Cada vez que o cdigo executado, a varivel do loop recebe o valor do prximo item da lista. Logo, no necessrio que a iterao do loop possua nmeros. Observe:

>>> for thing in [cats, pasta, programming, spam]: ... print(I really like + thing) ... I really like cats I really like pasta I really like programming I really like spam >>> for i in Hello world!: ... print(i) ... H e l l o

6.7.

COMO O CDIGO FUNCIONA

49

w o r l d !
Outro ponto importante sobre loops um loop da lista em que ser feita a iterao. O trecho seguinte da funo

for, a utilizao da palavra-chave in. O uso do in em for diferente do que foi visto at ento. Aqui, o in possui a utilidade de separar a varivel displayBoard()
mostra as letras faltantes e cria a string da

palavra secreta de todos os palpites errados, com espaos.


Se

print(Missed letters:, end= ) for letter in missedLetters: print(letter, end= ) print()

missedLetters

for igual a

aush,

ento este loop imprimir

a u s h.

Equivalncia de um loop while para um loop for


atravs de uma lista, um loop se

for bem semelhante a um loop while, mas, quando necessrio realizar uma iterao for torna o cdigo mais sucinto. Ainda assim, um loop while pode comportar da mesma forma que um loop for com linhas extras de cdigo. Observe:
>>> sequence = [cats, pasta, programming, spam] >>> index = 0 >>> while (index < len(sequence)): ... thing = sequence[index] ... print(I really like + thing) ... index = index + 1 ... I really like cats I really like pasta I really like programming I really like spam >>>
Perceba que necessrio criar mais cdigo para esta alternativa. Visando tornar o cdigo

O loop

sempre o mais legvel e sucinto, o loop

for

ser amplamente utilizado nos prximos programas.

6.7.4

Mostrando os espaos para as letras da palavra secreta


blanks = _ * len(secretWord) for i in range(len(secretWord)): if secretWord[i] in correctLetters: blanks = blanks[:i] + secretWord[i] + blanks[i+1:] for letter in blanks: print(letter, end= ) print()
At ento, j sabemos como mostrar ao jogador os palpites errados. Agora, veremos como

imprimir linhas em branco para cada letra da palavra secreta. Para tal, utilizaremos o caracter de sublinhado

17 para as letras no adivinhadas. Inicialmente, uma string com um caractere de sublinhado

17 Underscore.

50

6.

JOGO DA FORCA

para cada letra da palavra secreta criada na linha 75. Observe que utilizado o operador Este operador pode ser utilizado entre uma string e um inteiro. Por exemplo, a expresso

com o _. hello *

resulta em

hellohellohello.

No programa, a varivel

blanks

armazenar em sublinhados

o nmero de caracteres da palavra secreta. Em seguida, usamos um loop for para percorrer cada letra da palavra secreta na varivel secretWord e substituir o sublinhado com a letra respectiva caso esta exista em correctLetters. A linha 79 pode parecer confusa, pois ela utiliza colchetes nas varivels blanks e secretWords, que so strings, no listas. Assim como a funo len(), utilizada anteriormente, apenas aceita listas como parmetros, no strings. Porm, em Python, muitas coisas feitas com listas tambm podem sem feitas com strings.

Tarefa 6.1
Pesquise sobre

string slices em Python.

6.7.5

Substituindo sublinhados por letras adivinhadas corretamente


for i in range(len(secretWord)): if secretWord[i] in correctLetters: blanks = blanks[:i] + secretWord[i] + blanks[i+1:]

Vamos ilustrar este bloco atravs de um exemplo. Suponha que a palavra secreva em secretWord otter e que o jogador adivinhou as letras tr, armazenado em correctLetters. Assim, len(secretWord) retornar 5. Desta forma, range(len(secretWord)) retornar [0, 1, 2, 3, 4]. Devido ao valor de i tornar-se cada elemento da srie a cada iterao, o loop for, neste seja exemplo se torna o seguinte:

if secretWord[0] in correctLetters: blanks = blanks[:0] + secretWord[0] if secretWord[1] in correctLetters: blanks = blanks[:1] + secretWord[1] if secretWord[2] in correctLetters: blanks = blanks[:2] + secretWord[2] if secretWord[3] in correctLetters: blanks = blanks[:3] + secretWord[3] if secretWord[4] in correctLetters: blanks = blanks[:4] + secretWord[4]
Reescrevendo:

+ blanks[1:] + blanks[2:] + blanks[3:] + blanks[4:] + blanks[5:]

if o in tr: # Condio falsa, blanks == _____ blanks = + o + ____ # Esta linha no executada. if t in tr: # Condio verdadeira, blanks == _____ blanks = _ + t + ___ # Esta linha executada. if t in tr: # Condio verdadeira, blanks == _t___ blanks = _t + t + __ # Esta linha executada. if e in tr: # Condio falsa, blanks == _tt__ blanks = _tt + e + _ # Esta linha no executada. if r in tr: # Condio verdadeira, blanks == _tt__ blanks = _tt_ + r + # Esta linha executada. # blanks agora equivalente a _tt_r
As prximas linhas de cdigo mostram o valor armazenado na varivel entre cada caracter.

blanks

com espaos

for letter in blanks: print(letter, end= ) print()

6.8.

SENTENAS

ELIF (ELSE IF)

51

6.7.6

Obtendo os palpites do jogador


A funo

getGuess()

ser chamada a cada vez que o jogador tiver que digitar uma letra. A

funo retorna a o palpite como uma string. Alm disso, apenas uma letra, antes de fazer o seu retorno.

getGuess()

faz com que o jogador digite

def getGuess(alreadyGuessed): while True: print(Guess a letter.) guess = input() guess = guess.lower() if len(guess) != 1: print(Please enter a single letter.) elif guess in alreadyGuessed: print(You have already guessed that letter. Choose again.) elif guess not in abcdefghijklmnopqrstuvwxyz: print(Please enter a LETTER.) else: return guess
Esta funo possui um parmetro chamado

alreadyGuessed

que contm as letras que o

jogador j adivinhou. Ela ir pedir ao jogador para que o palpite seja apenas uma letra. Este palpite ser o retorno da funo. Usamos o loop valor booleano

while

pois o palpite do jogador dever ser uma e somente uma letra que ele

no tenha tentado adivinhar anteriormente. Observe que a condio para o loop

True.

Isto signica que a execuo sair do loop somente com um

while break,

apenas o que para

imediatamente a funo, ou

return,

que sai da funo assim que obtm um resultado ou cumpre

alguma condio. Este tipo de loop chamado de

innito.

O cdigo dentro desta funo pede um palpite para o jogador, que armazenado na varivel

guess.

Se o jogador entrar com uma letra maiscula, ela ser convertida para minscula com o

comando da linha 90.

6.8

Sentenas

elif (else if)

Observe o seguinte cdigo:

if catName == Fuzzball: print(Your cat is fuzzy.) else: print(Your cat is not very fuzzy at all.)
um cdigo bem simples: se a varivel algo, do contrrio, imprimir outra coisa. Entretanto, apenas duas escolhas podem no ser o suciente para a prtica da programao. Desta forma, podemos adaptar o

catName

for igual string

Fuzzball

imprimir

if-else

anterior para algo do tipo:

if catName == Fuzzball: print(Your cat is fuzzy.) else: if catName == Spots print(Your cat is spotted.) else: if catName == FattyKitty print(Your cat is fat.) else: if catName == Puff print(Your cat is puffy.) else:

52

6.

JOGO DA FORCA

print(Your cat is neither fuzzy nor spotted nor fat nor puffy.)
Contudo, digitar esta poro de espaos no nada eciente e mais suscetvel a erros. Para vrias opes, o Python fornece o

elif.

Desta forma, o cdigo anterior toma a seguinte forma:

if catName == Fuzzball: print(Your cat is fuzzy.) elif catName == Spots print(Your cat is spotted.) elif catName == FattyKitty print(Your cat is fat.) elif catName == Puff print(Your cat is puffy.) else: print(Your cat is neither fuzzy nor spotted nor fat nor puffy.)
Se a condio do primeiro primeiro bloco

if

for falsa, ento o programa vericar a prxima condio, do

elif.

Se esta for falsa tambm, o programa vericar a prxima condio e assim por

diante, at chegar no ltimo

else, que executado quando no h mais condies a serem vericadas.

Se uma condio for verdadeira, no bloco como um todo, o sub-bloco, cuja condio for verdadeira, executado e todos os outros so ignorados. Ou seja, apenas um bloco executado em uma sequncia de

if-elif-else.

A ltima sada

else

pode ser omitida, caso no haja situao cabvel

a uma alternativa geral.

6.8.1

Ter certeza que o jogador deu um palpite vlido


if len(guess) != 1: print(Please enter a single letter.) elif guess in alreadyGuessed: print(You have already guessed that letter. Choose again.) elif guess not in abcdefghijklmnopqrstuvwxyz: print(Please enter a LETTER.) else: return guess
A varivel

guess possui o texto que o jogador deu como palpite. getGuess()

Precisamos ter certeza de que

este palpite seja uma nica letra, do contrrio, pedimos novamente para que ele digite uma entrada vlida. Desta forma, temos o bloco da funo Este bloco verica: 1. Se a entrada possui apenas um caracter, atravs da funo 2. Se a entrada repetida, atravs da vericao da string 3. Se a entrada uma letra e no qualquer outro caracter Todas as vericaes resultam em uma mensagem de erro, caso sejam verdadeiras. Na ltima alternativa, o palpite do jogador retornado. Isto quer dizer nenhuma das condies anteriores verdadeira, logo, o jogador deu uma entrada vlida para o programa, no caso, uma letra. Lembre-se que apenas um destes blocos executado. a partir da linha 91.

len(guess) guess em alreadyGuessed

6.8.2

Perguntando se o jogador deseja jogar novamente

def playAgain(): print(Do you want to play again? (yes or no)) return input().lower().startswith(y)
A funo

playAgain() apenas imprime uma frase perguntando se o jogador deseja permanecer

no jogo e retorna o resultado baseado no que o jogador digitar.

6.9.

REVISO DAS FUNES CRIADAS PARA ESTE JOGO

53

Embora a expresso de retorno parea complicada, ela bem simples. Ela no possui opera-

input() e os startswith(). A funo retorna o texto que o jogador digitar. A partir desta string, o mtodo lower() a transformar em letras minsculas e o mtodo startswith() vericar se a string inicia com a letra y. Desta forma, a expresso, como um todo, retorna um
mtodos so

dores, mas h uma chamada de funo e duas chamadas de mtodos. A funo a

lower()
18 .

valor booleano

6.9
1. 2.

Reviso das funes criadas para este jogo


getRandomWord(wordList):
palavra secreta do jogo atravs de uma lista de strings, sortear uma e retornar como mos-

displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord):


palpites equivocados. Esta funo precisa de quatro argumentos:

tra o estado atual do jogo, incluindo ilustrao, o quanto a palavra secreta foi adivinhada e os

HANGMANPICS a lista de missedLetters so as strings das letras que o jogador adivinhou e as que ele no adivinhou, respectivamente; e, secretWord
strings que contm a ilustrao da forca;

correctLetters

a palavra secreta que o jogador dever adivinhar. 3.

getGuess(alreadyGuessed):

atravs de uma string de letras que o jogador j tentou adi-

vinhar, a funo continua pedindo ao jogador uma letra que ele ainda no tenha dado como palpite. Por m, o palpite vlido retornado. 4. forca. Retorna

playAgain(): a funo que pergunta ao jogador que ele gostaria True se o jogador quiser e False, do contrrio.

de jogar outra rodada da

6.10

Cdigo principal do jogo


O cdigo que precisamos escrever foi ilustrado na gura 9. Boa parte j foi feita, mas ainda

necessrio colocar tudo isso em ordem e saber como chamar as funes. Assim, tudo comea a ser executado, na verdade, na linha 106.

print(H A N G M A N) missedLetters = correctLetters = secretWord = getRandomWord(words) gameIsDone = False


Neste primeiro bloco, apenas impresso o nome do jogo e atribudo uma string vazia para as

variveis varivel zando,

missedLetters e correctLetters. Em seguida, uma palavra escolhida atribuda secretWord, atravs da lista denida anteriormente, atribuda varivel words. Finali atribudo o valor booleano False para a varivel gameIsDone. Todo este processo feito

antes de o jogador dar o seu primeiro palpite. Para alterar o valor desta ltima varivel, o jogo dever ser terminado e o programa dever perguntar ao jogador se ele gostaria de jogar novamente.

6.10.1

Mostrando a ilustrao ao jogador

O loop

while

possui a condio sempre verdadeira, assim, tudo o que est no bloco ser

executado at que seja encontrado um ou vencer o jogo).

break.

Isto feito quando o jogo acaba (se o jogador perder

while True: displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord)


A linha 113 chama a funo

displayBoard(),

passando os estados da forca em forma de

string e as variveis criadas anteriormente. De acordo com quantas letras o jogador adivinhou ou no, esta funo mostra o estado atual da forca ao jogador.

18 Ainda

h o mtodo

endswith(),

que verica o m da string.

54

6.

JOGO DA FORCA

6.10.2

Permitindo o jogador a fazer um palpite e vericando se o palpite est na palavra secreta


guess = getGuess(missedLetters + correctLetters) if guess in secretWord: correctLetters = correctLetters + guess

A linha 116 chama a funo

getGuess()

passando os palpites do jogador como argumento.

Observe que tanto os acertos quanto os erros so enviados funo. Isto feito pois a funo verica tanto os palpites corretos quanto os errados, e, dependendo do prximo palpite do jogador, o programa se comporta de uma forma diferente. Em seguida, feita a vericao de se o palpite (vlido) do jogador est presente na palavra sorteada. Se esta condio for verdadeira, ento o bloco os acertos do jogador atualizada.

if

ser executado e a varivel que carrega

6.10.3

Vericar se o jogador venceu ou perdeu o jogo

O cdigo entre as linhas 121 e 137 faz a vericao se o jogador ganhou ou perdeu o jogo. Primeiro, discutiremos o bloco que verica se o jogador venceu, em seguida, se o jogador perdeu. Como saber se o jogador adivinhou todas as letras da palavra secreta? possui cada letra que o jogador acertou, enquanto No podemos fazer a vericao

correctLetters secretWord possui a palavra a ser adivinhada. correctLetters == secretWord porque as letras no so adiDesta forma, cada letra em

vinhadas na ordem, e podem haver repeties de uma mesma letra.

secretWord

comparada s letras de

correctLetters

para vericar se o jogador venceu o jogo.

Este processo executado entre as linhas 122 e 126. Observe que a vericao de de

correctLetters

em

pode ser um subconjunto corretamente.

secretWord em correctLetters diferente da vericao secretWord. O conjunto de palpites armazenado em correctLetters de secretWord, o que no quer dizer que o jogador adivinhou a palavra
Inicialmente, assumimos que todas as letras

Ento, na prtica, como feita a vericao? foram adivinhadas, em

foundAllLetters = True. O estado desta varivel alterado no loop for seguinte, quando executar bloco if dentro do loop. No caso de foundAllLetters no ter sido alterada, o jogador venceu o jogo e o bloco if seguinte executado.
Aps esta vericao e o jogador ter ganhado o jogo, o programa dever informar isto ao jogador. Desta forma, uma varivel

gameIsDone

designada como

True.

Esta varivel utilizada

para o programa saber se o jogador dever continuar seus palpites ou encerrar. No caso de o jogador ter dado palpites incorretos, a execuo cair no bloco bloco ser executado, a condio do bloco

if

Devido ao palpite do jogador ter sido errado,

else. Para este if guess in secretWord:, na linha 118. ele ser armazenado em missedLetters. Em seguida,
anterior Se a condio for verdadeira, ento recebe o valor

vericado se o jogador cometeu o mximo de erros possvel. Novamente, a varivel que verica se o jogo chegou ao m

mostrado a ltima ilustrao para a forca com uma mensagem de que o jogador perdeu o jogo.

gameIsDone

True.

6.10.4

Iniciando uma nova rodada

Se o jogador ganhou ou perdeu o jogo, ele poder escolher entre continuar o jogo ou no. Para isto, temos o ltimo bloco exige que a varivel

if. Este bloco ser sempre executado quando um jogo terminar, pois ele gameIsDone tenha o valor True, que feito em ambos os blocos que vericam if playAgain():,
que perguntar se o jogador deseja jogar

se o jogador ganhou ou perdeu o jogo. Logo, a execuo cair no bloco novamente. estamos no bloco Em caso armativo, as variveis iniciais so resetadas e o ciclo recomea, pois ainda

while

principal.

No caso de o jogador no quiser uma nova rodada, ocorre um

break

e o programa termina.

6.11.

RESUMO

55

6.11

Resumo
Este foi um longo captulo e, nalmente, terminamos. Muitos conceitos foram introduzidos e

este jogo foi o mais avanado at agora. Como os programas se tornaro mais complexos, uma boa forma de se organizar atravs de uxogramas. Cinco minutos desenhando um uxograma podem economizar horas de produo de cdigo. Entre os conceitos abordados tivemos: 1. Mtodos: funes associadas com valores. O valor de retorno dos mtodos dependem dos valores aos quais o mtodo est associado. 2. Loops

for

iteram atravs de cada valor da lista. A funo

range()

frequetemente utilizada

com estes loops, pois uma forma fcil para criar listas de nmeros sequenciais. 3. Sentenas

elif

so executadas se a condio do bloco for verdadeira e as condies anteriores

forem falsas.

Tarefa 6.2
Pesquise sobre o tipo

dictionary e a diferena do tipo list (lista). Desenvolva como o dictionary

pode ser utilizado neste jogo de forca.

Tarefa 6.3

Pesquise sobre mltiplas atribuies de variveis no Python.

6.12

Exerccios complementares

1. Faa um programa que leia uma lista de 10 nmeros reais e mostre-os na ordem inversa. 2. Faa um programa que simule um lanamento de dados. Lance o dado 100 vezes e armazene os resultados em uma lista. Depois, mostre quantas vezes cada valor foi conseguido. Dica: use uma lista de contadores (1-6) e uma funo para gerar numeros aleatrios, simulando os lanamentos dos dados. 3. Faa um programa que leia duas listas com 10 elementos cada. Gere uma terceira lista de 20 elementos, cujos valores devero ser compostos pelos elementos intercalados das duas outras listas. 4.

Nome na vertical.
ou no.

Faa um programa que solicite o nome do usurio e imprima-o na vertical.

5. Faa um programa que leia uma sequncia de caracteres, mostre-a e diga se um palndromo 6.

19

Jogo da palavra embaralhada.

Desenvolva um jogo em que o usurio tenha que adivinhar O programa ter uma lista de

uma palavra que ser mostrada com as letras embaralhadas.

palavras e escolher uma aleatoriamente. O jogador ter seis tentativas para adivinhar a palavra. Ao nal a palavra deve ser mostrada na tela, informando se o usurio ganhou ou perdeu o jogo.

19 Um

palndromo uma sequncia de caracteres cuja leitura idntica se feita da direita para esquerda ou vice-versa

7 Jogo da velha
Tpicos abordados neste captulo:

Introduo inteligncia artical Referncias de lista O valor

None

Aprenderemos agora a criar um jogo da velha, em que o jogador enfrentar uma inteligncia articial simples. Um programa com Inteligncia Articial (

IA20 ) um programa de computador que

pode responder com inteligncia para os movimentos do jogador. Este jogo no introduz nenhum conceito muito difcil, apenas mais linhas de cdigo a serem analisadas. O jogo da velha um jogo muito simples, geralmente jogado com caneta e papel, por duas pessoas. Uma pessoa representa suas jogadas por um X e outra por um crculo. Aqui, ilustraremos estes smbolos com as letras X e O. Se o jogador zer uma combinao de trs smbolos em uma linha ou diagonal, ele vence. O princpio deste jogo aqui o mesmo. A inteligncia articial ser utilizada para o computador confrontar o jogador. Ou seja, no haver duas pessoas, como de costume, neste jogo. Ser o jogador contra o computador. Este captulo no introduz muitos conceitos novos, mas aprimora a habilidade para desenvolver jogos. Anal, o principal de um jogo no apenas o uso de recursos grcos e sonoros, mas uma boa lgica, funcionando adequadamente.

7.1

Modelo de sada do jogo da velha

Welcome to Tic Tac Toe! Do you want to be X or O? o The computer will go first. | | | | | | ----------| | | | | | ----------| | | | X | | What is your next move? (1-9) 4 | | | | X | | ----------| | O | | | | ----------| | | | X | |
20

AI

, em ingls, de

articial intelligence.
56

7.1.

MODELO DE SADA DO JOGO DA VELHA

57

What is your next move? (1-9) 6 | | | | X | | ----------| | O | X | O | | ----------| | | | X | | What is your next move? (1-9) 1 | | X | | X | | ----------| | O | X | O | | ----------| | O | | X | | The computer has beaten you! You lose. Do you want to play again? (yes or no) no

58

7.

JOGO DA VELHA

7.2

Cdigo-fonte do jogo da velha


Cdigo 5: Jogo da velha.

# Jogo da velha import random def drawBoard(board): # Esta funcao imprime o tabuleiro do jogo # "board" eh uma lista o indice 0) print( | |) print( + board[7] + print( | |) print(-----------) print( | |) print( + board[4] + print( | |) print(-----------) print( | |) print( + board[1] + print( | |) de 12 strings representando o tabuleiro (ignorando

| + board[8] + | + board[9])

| + board[5] + | + board[6])

| + board[2] + | + board[3])

def inputPlayerLetter(): # Deixa o jogador escolher com qual letra ele gostaria de ser representado no jogo # Retorna uma lista com a letra que o jogador escolheu como o primeiro item e a do computador como o segundo letter = while not (letter == X or letter == O): print(Do you want to be X or O?) letter = input().upper() # o primeiro elemento na tupla eh a letra do jogador, a segunda eh a do computador if letter == X: return [X, O] else: return [O, X] def whoGoesFirst(): # Aleatoriamente escolhe quem o jogador que inicia o jogo if random.randint(0, 1) == 0: return computer else: return player def playAgain(): # Esta funcao retorna True se o jogador quiser jogar novamente. print(Do you want to play again? (yes or no)) return input().lower().startswith(y) def makeMove(board, letter, move): board[move] = letter def isWinner(bo, le): # Esta funcao retorna True se o jogador vencer o jogo # Usamos bo, ao inves de board, e le, ao inves de letter, para que nao precisemos digitar tanto return ((bo[7] == le and bo[8] == le and bo[9] == le) or

7.2.

CDIGO-FONTE DO JOGO DA VELHA

59

(bo[4] (bo[1] (bo[7] (bo[8] (bo[9] (bo[7] (bo[9]

== == == == == == ==

le le le le le le le

and and and and and and and

bo[5] bo[2] bo[4] bo[5] bo[6] bo[5] bo[5]

== == == == == == ==

le le le le le le le

and and and and and and and

bo[6] bo[3] bo[1] bo[2] bo[3] bo[3] bo[1]

== == == == == == ==

le) or le) or le) or le) or le) or le) or le))

def getBoardCopy(board): # Faz uma copia da lista do tabuleiro e retorna dupeBoard = [] for i in board: dupeBoard.append(i) return dupeBoard def isSpaceFree(board, move): # Retorna True se a jogada esta livre no tabuleiro return board[move] == def getPlayerMove(board): # Permite ao jogador digitar seu movimento move = while move not in 1 2 3 4 5 6 7 8 9.split() or not isSpaceFree(board, int(move)): print(What is your next move? (1-9)) move = input() return int(move) def chooseRandomMoveFromList(board, movesList): # Retorna um movimento valido da lista passada no tabuleiro possibleMoves = [] for i in movesList: if isSpaceFree(board, i): possibleMoves.append(i) if len(possibleMoves) != 0: return random.choice(possibleMoves) else: return None def getComputerMove(board, computerLetter): # Dado um tabuleiro e o simbolo do jogador, a funcao determina onde jogar e retorna o movimento if computerLetter == X: playerLetter = O else: playerLetter = X # Aqui esta o algoritmo para a inteligencia artificial do jogo da velha # Primeiro, verificamos se eh possivel vencer na proxima jogada for i in range(1, 10): copy = getBoardCopy(board) if isSpaceFree(copy, i): makeMove(copy, computerLetter, i) if isWinner(copy, computerLetter): return i # Verifica se o jogador pode vencer na proxima jogada e, entao, o bloqueia for i in range(1, 10):

60

7.

JOGO DA VELHA

copy = getBoardCopy(board) if isSpaceFree(copy, i): makeMove(copy, playerLetter, i) if isWinner(copy, playerLetter): return i # Tenta ocupar algum dos cantos, se eles estiverem livres move = chooseRandomMoveFromList(board, [1, 3, 7, 9]) if move != None: return move # Tenta ocupar o centro, se estiver livre if isSpaceFree(board, 5): return 5 # Ocupa os lados return chooseRandomMoveFromList(board, [2, 4, 6, 8]) def isBoardFull(board): # Retorna True se todos os espacos do tabuleiro estiverem ocupados for i in range(1, 10): if isSpaceFree(board, i): return False return True

print(Welcome to Tic Tac Toe!) while True: # Reinicia o tabuleiro theBoard = [ ] * 10 playerLetter, computerLetter = inputPlayerLetter() turn = whoGoesFirst() print(The + turn + will go first.) gameIsPlaying = True while gameIsPlaying: if turn == player: # Vez do jogador drawBoard(theBoard) move = getPlayerMove(theBoard) makeMove(theBoard, playerLetter, move) if isWinner(theBoard, playerLetter): drawBoard(theBoard) print(Hooray! You have won the game!) gameIsPlaying = False else: if isBoardFull(theBoard): drawBoard(theBoard) print(The game is a tie!) break else: turn = computer else: # Vez do computador move = getComputerMove(theBoard, computerLetter) makeMove(theBoard, computerLetter, move) if isWinner(theBoard, computerLetter): drawBoard(theBoard)

7.3.

PROJETANDO O PROGRAMA

61

print(The computer has beaten you! You lose.) gameIsPlaying = False else: if isBoardFull(theBoard): drawBoard(theBoard) print(The game is a tie!) break else: turn = player if not playAgain(): break

7.3

Projetando o programa
O jogo da velha um jogo muito fcil e rpido, quando jogado no papel entre duas pessoas. No

computador, este processo um pouco mais complicado, pois devemos mand-lo executar passo-apasso o que quisermos que acontea. Desta forma, projetaremos este jogo utilizando um uxograma. Observe a gura 11.

Figura 11: Fluxograma para o jogo da velha.

7.4

Representando o tabuleiro
Primeiro, devemos descobrir como representar o tabuleiro como uma varivel. No papel, cruza-

mos duas linhas horizontais com duas verticais e preenchemos os espaos em branco, com cada smbolo representando cada jogador.

62

7.

JOGO DA VELHA

No programa, vamos represent-lo como uma lista de strings. Cada string representar uma das nove posies do tabuleiro. Iremos numer-las da mesma forma que um teclado numrico, para que seja fcil lembrarmos cada posio. Veja a gura 12

Figura 12: Representao do tabuleiro para o jogo da velha.

Os smbolos que representaro os jogadores sero as strings

e uma string de espao

representar as casas em que ainda no foi feita uma jogada.

7.5

Raciocnio do jogo
Para o computador responder ao jogo, devemos identicar os locais em que as jogadas sero

feitas. Para tal, identicamos o tabuleiro de acordo com o esquema da gura 13.

Figura 13: Representao do tabuleiro do jogo da velha para o computador.

O raciocnio do jogo (IA) segue um algoritmo simples. Um

algoritmo uma srie de instrues

que executam algo. Logo, tudo o que zemos at agora, baseou-se em algoritmos. No caso deste jogo da velha, o algoritmo determinar os passos que denem a melhor jogada. Este algoritmo possui os seguintes passos: 1. Primeiro, vericar se o prximo movimento do computador pode ganhar o jogo. Em caso armativo, executar este movimento. Do contrrio, seguir prximo passo. 2. Verica se h algum movimento do jogador que possa faz-lo ganhar o jogo. computador bloqueia o jogador. Do contrrio, seguir prximo passo. 3. Verica se h espaos livres nos cantos (posies 1, 3, 7, ou 9) e ocupa um deles. Caso no haja, seguir prximo passo. 4. Verica se o centro est livre. Se estiver, a jogada vai para esta posio. Caso contrrio, seguir prximo passo. 5. A jogada ir para qualquer outra posio dos lados (2, 4, 6 ou 8). No h mais passos, pois, ao chegar nesta alternativa, o computador j vericou se poderia ocupar qualquer outra posio disponvel no tabuleiro. Todo este procedimento o que ocorre na caixa do uxograma da gura 11 que indica obter o movimento do computador. Este passo pode ser expandido atravs dos itens 1 a 5 anteriores. Observe a gura 14. Se houver, o

7.6.

COMO O PROGRAMA FUNCIONA

63

Figura 14: Expanso do passo Obter o movimento do computador no uxograma.

Este algoritmo implementado em

getComputerMove() e nas funes que esta funo chama.

7.6

Como o programa funciona


A partir de agora, as explicaes dos cdigos tornar-se-o mais sucintas. At este ponto, voc

j deve ter desenvolvido a habilidade de observar e compreender o que est acontecendo no programa, atravs da anlise do cdigo. No repetiremos mais tantas linhas de cdigo ou mostraremos exemplos extensos, pois supomos que a sua capacidade de investigao tambm tenha se desenvolvido. Desta forma, a explicao se extender atravs dos pontos principais do programa.

7.6.1

Imprimindo o tabuleiro na tela


A funo

drawBoard()

imprime o tabuleiro na tela, recebendo o parmetro

board.

Lembre-

se que o nosso tabuleiro (board) representado por uma lista de dez strings e que ignoramos a string com o ndice 0, para que utilizemos os ndices das strings de acordo com a posio do tabuleiro, ilustrada na gura 12. Outras funes tambm funcionaro atravs deste parmetro de dez strings. Tenha certeza de que os espaos do tabuleiro estejam dispostos corretamente, ou a ilustrao no sair adequada. Programas de computador apenas fazem exatamente o que voc os manda fazer, mesmo que esteja errado. Por isso, preste ateno em cada passo do programa.

7.6.2

Permitindo o jogador a escolher o smbolo desejado


A funo

inputPlayerLetter()

bem simples, que apenas pergunta se o jogador deseja

ser representado por X ou O e mantm a pergunta at que o jogador escolha uma alternativa vlida (atravs do loop com o mtodo de string

while). Observe que a linha 27 transforma a entrada do jogador em letra maiscula, upper(). if-else
entre as linhas 30 e

Em seguida, a funo retorna uma lista de dois itens. O primeiro item (ndice 0) ser o smbolo escolhido pelo jogador; o segundo, o smbolo do computador. O bloco 33 determina qual lista retornar.

64

7.

JOGO DA VELHA

7.6.3
funo Se der

Decidindo quem inicia o jogo


A funo

whoGoesFirst() funciona como um jogo de cara ou coroa virtual. Atravs da randint(), sorteamos um nmero que ser ou 0 ou 1. Se der 0, o computador inicia o jogo. 1, o jogador inicia. Observe que whoGoesFirst() retorna uma string.
Perguntando se o jogador deseja jogar novamente

7.6.4

Esta opo a mesma do jogo da forca e foi apresentada no teis.

6. Desta forma, reaproveitamos

o cdigo (no caso, a funo) do cdigo 4 e j podemos perceber como funes podem ser realmente

7.6.5

Mostrando a jogada no tabuleiro


A funo

makeMove()

muito simples e desenvolvida em apenas uma linha. Os parmetros

que ela recebe so: o tabuleiro (com as dez strings que o representam), representam a jogada do usurio,

board;

uma das letras que

letter;

e um inteiro de 1 a 9,

move. board,
ela no

Mas... Espere! Por utilizarmos uma funo para mudar o valor de um item de forma especial quando passadas para funes. funo, mas uma referncia dela.

esquecer o valor alterado logo que sair da funo? A resposta no. Listas so tratadas de uma Isto porque no passamos a lista em si para uma

7.7

Referncias de lista
Entre com as seguintes linhas no terminal interativo:

>>> >>> >>> >>> 100 >>> 42

spam = 42 cheese = spam spam = 100 spam cheese

Estas linhas fazem sentido, baseado no que aprendemos at agora. Para refrescar a memria: atribumos 42 varivel ocorre porque

spam

e ento fazemos uma cpia deste valor para a varivel

teriormente, alteramos o valor da varivel

spam

para 100, o que no afeta o valor em

cheese. Poscheese. Isto

spam

cheese

so variveis diferentes, que armazenam valores diferentes.

Contudo, quando se diz respeito listas, o processo um pouco diferente. Quando uma lista atribuda a uma varivel com o sinal de igual varivel uma referncia lista. Uma uma Observe:

referncia de lista um valor que aponta para uma lista.


>>> >>> >>> >>> [0, >>> [0, spam = [0, 1, 2, 3, 4, 5] cheese = spam cheese[1] = Hello! spam Hello!, 2, 3, 4, 5] cheese Hello!, 2, 3, 4, 5]

referncia um valor que aponta a algum tipo de dado, logo,

=,

na verdade, o que est sendo atribudo nova

cheese = spam copia uma referncia da lista de spam para cheese ao invs de copiar Isto ocorre porque o valor armazenado em spam no uma lista, mas a referncia para uma lista. Isto signica que os valores atribudos spam e cheese referem-se mesma lista, logo, os valores da lista no foram copiados. Assim, se o valor da lista referenciada por cheese for modicado, o valor da lista referenciada por spam tambm muda, pois h apenas uma lista. Em makeMove(), quando passamos board como parmetro, a varivel local recebe uma cpia da referncia, no a lista como um todo. letter e move so variveis que recebem cpias dos valores
A linha a lista inteira.

7.8.

VERIFICAR SE O JOGADOR VENCEU

65

passados como argumento (uma string e um inteiro).

Desta forma, possvel alterar os valores de

letter

move

sem alterar as variveis originais.

Entretanto, ao alterarmos o valor de alguma das posies da lista em ser alterado. Ao m da funo, a referncia que est em lista permanecer.

board,

o valor original

board

ser esquecida, mas a alterao na

7.8

Vericar se o jogador venceu


A funo

isWinner()

dene as jogadas que fazem um jogador vencedor, ou seja, os trios de

smbolos iguais, de acordo com as regras do jogo da velha. Para isso, fornecido o tabuleiro no estado atual e o smbolo que representa um jogador. Esta funo , na verdade, um longo bloco

if. and,
seja

H oito formas de vencer o jogo da velha, entre diagonais, verticais e horizontais. Observe que cada linha da funo possui uma destas combinaes, com cada item interligado com o operador e cada uma das oito combinaes est interligada com o operador o vencedor.

or.

Isto quer dizer que apenas

uma das oito combinaes deve ser verdadeira para que o jogador representado pela varivel

le

7.9

Duplicando o tabuleiro
A funo

getBoardCopy()

faz uma cpia das strings que representam o tabuleiro do jogo da

velha. Isto feito pois h momentos em que o algoritmo de inteligncia articial far modicaes temporrias e isto no dever afetar o tabuleiro original. A linha 64 cria uma lista vazia e a referencia em que retornado ao m da funo.

dupeboard.

O loop

for

seguinte percorrer

o tabuleiro, passado por parmetro, adicionando uma cpia do tabuleiro original para

dupeboard,

7.10

Vericando se um espao no tabuleiro est livre


A funo

isSpaceFree() retorna se o espao requisitado est livre ou no.

Lembre-se que os

espaos livres do tabuleiro so marcados com uma string que possui apenas um espao.

7.11

Permitindo que o jogador entre com a sua jogada


A funo

getPlayerMove()

pede ao jogador para entrar com o nmero do respectivo espao

que ele deseja jogar. A funo assegura que a entrada seja vlida (um inteiro de 1 a 9) e tambm verica se o espao escolhido j est ocupado.

7.12

Escolhendo um movimento da lista de movimentos


A funo

chooseRandomMoveFromList() utilizada para a implementao da inteligncia board a lista de 10 strings, que representam o tabuleiro do jogo. o segundo parmetro movesList a lista de inteiros que representam os movimentos possveis. Esta funo escolher um dos movimentos da lista possibleMoves, que carrega todos os movimentos possveis do tabuleiro, obtidos atravs da vericao pela funo isSpaceFree(). A cada vericao de um movimento que for ume espao vazio, este adicionado lista possiblemoves com o mtodo append().
articial. O primeiro parmetro Considerando a possibilidade de esta lista estar vazia, ou seja, se no houver mais espaos disponveis e o tamanho da lista (o nmero de elementos) for igual a zero, o bloco da linha 91, retornar

if-else,

a partir

None.

7.12.1

O valor

None
NoneType (assim como os valores booleanos so apenas dois, o NoneType s

None

um valor especial que pode ser atribudo a uma varivel. Ele representa a falta de um

valor, e nico do tipo

66

7.

JOGO DA VELHA

possui um valor). Este valor pode ser til quando no h uma atribuio vlida para uma varivel. Por exemplo, se, em um jogo de perguntas e respostas a pessoa tem a opo de no responder a alguma questo, a varivel que carrega a resposta pode receber o valor

None.

7.13
tabuleiro

Criando a inteligncia articial


A funo

getcomputerMove() onde o algoritmo ser implementado. Os parmetros so o board e qual letra representar o computador. Esta funo retorna o inteiro que representa

o espao que o computador ir jogar. Lembre-se de como o algoritmo funciona, ele foi descrito na seo 7.5.

7.13.1

O computador verica se pode vencer em um movimento

O loop

for

iniciado na linha 105, verica todos os espaos, para saber se o computador pode

vencer na prxima jogada. A primeira linha do loop faz uma cpia do tabuleiro e ento verica se alguma das jogadas possveis pode vencer o jogo, se puder, retornada esta jogada para o tabuleiro original. Se no h jogadas possveis para uma vitria imediata, o loop termina e o prximo passo executado.

7.13.2

O computador verica se o jogador pode vencer em uma jogada

A partir da linha 113, h um loop similar ao anterior, mas, desta vez, o computador verica se o jogador poder vencer na prxima jogada. Se for, o computador bloqueia a jogada. Se no houver como, o loop termina e o computador decidir a prxima jogada de outra forma.

7.13.3

Vericando os cantos, o centro e os lados (nesta ordem)

Na linha 121, a chamada da funo

chooseRandomMoveFromList()

com a lista

[1, 3,

7, 9],

vai retornar um inteiro correspondente a um dos espaos dos cantos.

Se todos os espaos

estiverem tomados, o retorno ser

None

e a execuo continua na linha 125, que verica se o centro

est ocupado. Caso nenhuma das opes anteriores seja satisfeita, o computador escolher um dos lados do tabuleiro, tambm chamando a funo que indica a posio dos lados como parmetro. Assim, a funo que implementa a inteligncia articial do jogo encerrada. A cada jogada ela ser executada novamente.

chooseRandomMoveFromList(),

mas com a lista

7.14
jogadas

Vericando se o tabuleiro est cheio


A ltima funo escrita

isBoardFull() que retorna True se a lista de strings que possui as False.

O for

estiver cheia (excetuando-se a posio zero, ignorada neste programa). Se houver, desta funo vericar todas as posies do tabuleiro e, se ele for at o m, quer

pelo menos, uma posio em que haja um espao e no uma jogada, a funo retorna O loop

dizer que todos as posies esto ocupadas, caracterizando a velha (o empate). Se houver alguma posio vazia, o loop interrompido e retorna

False.

7.15

O incio do jogo
O jogo inicia, de fato, na linha 140. feita uma saldao ao jogador e uma lista com 10

posies, cada uma possuindo um espao, criada. Em seguida, pedido que o jogador escolha o smbolo que o representar no jogo. O smbolo do jogador e do computador so designados s variveis mltipla atribuio, com a funo Ento, decidido quem

playerLetter e computerLetter inputPlayerLetter(). joga primeiro, na linha 145, com a funo whoGoesFirst().

por

7.16.

EXERCCIOS COMPLEMENTARES

67

7.15.1

Rodando a vez do jogador

Para controlar isto, criada a varivel

while, e permanece neste loop at que seja nalizado. gameIsPlaying e designada o valor True a ela. A funo whoGoesFirst() retorna player ou computer. No caso de ela retornar player, continua
a execuo na linha 151. Do contrrio, ir para a linha 169. Se for a vez do jogador, a primeira coisa feita mostrar o tabuleiro, chamando a funo

Na linha 150, o jogo comea, em um loop

drewBoard() makeMove().

e passando a varivel

sua jogada, atravs da funo

theBoard. getPlayerMove()

Em seguida, pedido que o jogador digite a e a jogada feita, de fato, ao chamar a funo

Agora que o jogador fez a sua jogada, o programa vericar se ele ganhou o jogo. Se retorna

isWinner()

True,

o tabuleiro da vitria deve ser mostrado, seguido de uma mensagem de que o jogador

venceu. Consequentemente,

gameIsPlaying

recebe

False

e o jogo termina.

Pelo contrrio, se o jogador no venceu o jogo, verica-se se o tabuleiro est cheio e deu empate, pois o movimento do jogador pode ter ocupado a ltima casa do tabuleiro e no haver vencedores. Esta condio vericada pela funo

isBoardFull().

7.15.2

Rodando a vez do computador

Se nenhuma das opes anteriores terminar o jogo, ento vez do computador e a varivel

turn

recebe

computer.

O cdigo bem similar ao movimento do jogador, entretanto, no h a

necessidade de mostrar o jogo na tela. Ainda, se o jogo no for encerrado, a vez do jogador e o processo se repete at o m do jogo.

7.15.3

Finalizando o jogo

No m do bloco

while

que caracteriza a execuo do jogo, h um

if

para o jogador escolher

jogar novamente. Esta escolha permitida pela funo

playAgain()

e, se o jogador desejar, o loop

while

que inicia o jogo continua executando. Seno, o loop interrompido e o programa termina.

7.16
1.

Exerccios complementares
xxx.xxx.xxx xx
e indique se um nmero vlido ou invlido atravs da validao

Vericao de CPF. Desenvolva um programa que solicite a digitao de um nmero de CPF


no formato dos dgitos vericadores e dos caracteres de formatao. Implemente uma funo para fazer cada vericao. Dica: faa uma pesquisa na internet para entender como vericado se um CPF vlido ou no.

2. (Adaptada de ACM ICPC) -

Damas do Xadrez.
n

Desenvolva um programa que dado duas

posies em um jogo de xadrez retorne quantas jogadas preciso para uma dama se mover da primeira para a segunda posio. 3. Crie um programa que dada um sequencia de 4. nmeros ordene em ordem decrescente. Obs.: Voc dever criar a funo para ordenar os nmeros, e no utilizar funes prontas de ordenao.

Quadrado mgico.
834 159 672

Um quadrado mgico aquele dividido em linhas e colunas, com um Por

nmero em cada posio e no qual a soma das linhas, colunas e diagonais a mesma. exemplo, veja um quadrado mgico de lado

3,

com nmeros de

9:

Elabore um programa que receba como entrada um quadrado quadrado mgico. 5. Adapte exerccio anterior para receber qualquer quadrado valor fornecido ao programa.

3x3

e retorne se ele ou no um

nxn,

o valor de

deve ser o primeiro

8 Bagels
Tpicos abordados neste captulo:

Operadores compostos, A funo Os

+ =, =, =, / = random.shuffle() mtodos de lista sort() e join() %s

Interpolao (formatao) de strings Especicador de converso Loops aninhados Neste captulo, sero apresentadas mais funes do Python. Alm disso, duas formas de sim-

plicar algumas operaes so apresentadas: formatao de strings e operadores compostos.

Bagels um jogo simples: um nmero de trs dgitos sem repetio sorteado o jogador tenta
adivinhar qual este nmero. Aps cada palpite, uma dica dada sobre tal nmero, relacionada com o tal palpite. Se a dica for um dos algarismos est correto, mas no lugar errado; e, nalmente, de for algarismo certo no lugar certo. O jogo tambm fornece mltiplas dicas depois de cada palpite. Se o nmero for 456 e o palpite 546, o palpite ser fermi pico pico, pois um dgito est correto e no lugar certo tambm, mas dois dgitos esto em lugares errados.

bagels, quer dizer que nenhum algarismo est correto; se for pico, ento fermi, o palpite possui um

8.1

Modelo de execuo
I am thinking of a 3-digit number. Try to guess what it is. Here are some clues: When I say: That means: Pico One digit is correct but in the wrong position. Fermi One digit is correct and in the right position. Bagels No digit is correct. I have thought up a number. You have 10 guesses to get it. Guess #1: 753 Pico Guess #2: 890 Bagels Guess #3: 764 Fermi Guess #4: 524 Bagels Guess #5: 364 Fermi Fermi Guess #6: 314 Fermi Pico Guess #7: 361 You got it! Do you want to play again? (yes or no) no

68

8.2.

CDIGO-FONTE DO JOGO

69

8.2

Cdigo-fonte do jogo

Cdigo 6: Bagels.

import random def getSecretNum(numDigits): # Retorna uma string do tamanho numDigits, com algarismos diferentes. numbers = list(range(10)) random.shuffle(numbers) secretNum = for i in range(numDigits): secretNum += str(numbers[i]) return secretNum def getClues(guess, secretNum): # Retorna uma string com as dicas pico, fermi, bagels ao usuario. if guess == secretNum: return You got it! clue = [] for i in range(len(guess)): if guess[i] == secretNum[i]: clue.append(Fermi) elif guess[i] in secretNum: clue.append(Pico) if len(clue) == 0: return Bagels clue.sort() return .join(clue) def isOnlyDigits(num): # Retorna True se num for uma string. Do contrario, retorna False. if num == : return False for i in num: if i not in 0 1 2 3 4 5 6 7 8 9.split(): return False return True def playAgain(): # Esta funcao retorna True se o jogador deseja jogar novamente. print(Do you want to play again? (yes or no)) return input().lower().startswith(y) NUMDIGITS = 3 MAXGUESS = 10 print(I am thinking of a %s-digit number. Try to guess what it is. % ( NUMDIGITS)) print(Here are some clues:) print(When I say: That means:) print( Pico One digit is correct but in the wrong position.) print( Fermi One digit is correct and in the right position.) print( Bagels No digit is correct.) while True: secretNum = getSecretNum(NUMDIGITS)

70

8.

BAGELS

print(I have thought up a number. You have %s guesses to get it. % ( MAXGUESS)) numGuesses = 1 while numGuesses <= MAXGUESS: guess = while len(guess) != NUMDIGITS or not isOnlyDigits(guess): print(Guess #%s: % (numGuesses)) guess = input() clue = getClues(guess, secretNum) print(clue) numGuesses += 1 if guess == secretNum: break if numGuesses > MAXGUESS: print(You ran out of guesses. The answer was %s. % (secretNum)) if not playAgain(): break

8.3

Projeto do jogo
O uxograma que caracteriza o funcionamento do jogo est ilustrado na gura 15.

Figura 15: Fluxograma para o jogo Bagels.

8.4.

COMO O PROGRAMA FUNCIONA

71

8.4

Como o programa funciona


No incio do programa, chamamos o mdulo

nmero aleatrio para o jogador adivinhar. A funo do cdigo produzir apenas um nmero de trs exemplo). Para tal, utilizada funo 0 a 9 criada. Em seguida, a funo

random e criamos uma funo para gerar um getSecretNum() gera este nmero ao invs dgitos, utilizamos o parmetro numDigits para

estabelecer quantos sero estes dgitos (desta forma, podemos gerar nmeros com 4 ou 6 dgitos, por

range() com a funo list() e, assim, random.shuffle() chamado e a

uma lista de inteiros de referncia a esta lista

passada por parmetro. Esta funo no retorna valor algum, ela apenas muda os elementos de lugar. O nmero secreto ser dado pelos trs primeiros nmeros da lista embaralhada (pois vale 3, neste jogo). Este nmero ser armazenado na string

numDigits

secretNum,

que inicia vazia, e ser o

retorno da funo. Observe que este retorno no um nmero, mas uma string.

8.4.1

Operadores compostos
H um novo operador na linha 8, o

+ =.

Este tipo de operao chamada de operao

composta, e utilizada para incrementar uma varivel ou concatenar strings. Neste programa, os trs primeiros nmeros da lista embaralhada so concatenados atravs do loop

for.

Uma maneira frequentemente utilizada para incremento de variveis, por exemplo, em um loop, atribuir o valor de uma varivel a ela mesma, mais um certo valor. Observe:

>>> var1 = 3 >>> var1 += 1 >>> var1 4

# esta linha o mesmo que var1 = var1 + 1

Tambm possvel utilizar este formato de operao para outras alm da soma, como a subtrao

-=,

multiplicao

*=

e diviso

/=.

8.4.2

Retornando a dica ao jogador


A funo

getClues()

dar a dica em forma de string (podendo ser mais de uma) para o

jogador, dependendo do que ela recebe como argumento, atravs dos parmetros

guess secretNum.

O passo mais bvio (e o primeiro da vericao) saber se o palpite do jogador est correto. Se o palpite no for o nmero sorteado, necessria a vericao de cada algarismo, para dar a(s) dica(s) ao jogador. Para tal, armazenamos as dicas em uma lista atravs da entrada do jogador no lao

clue

e feita a comparao

for

que inicia na linha 18.

Caso no haja nenhum dgito correto no palpite do jogador, ento a lista esta a condio para que seja impresso

clue

estar vazia e

Bagels,

no bloco

if

da linha 23.

8.4.3

O mtodo de lista
Na linha 26, a lista

sort()
chama o mtodo

clue

sort().

Este mtodo ordena os elementos em A

ordem alfabtica, no retornando uma nova lista ordenada, mas ordenando-os na prpria lista. tornando o jogo mais difcil.

inteno de ordenar as dicas passadas para o jogador no indicar a qual dgito cada dica pertence,

8.4.4

O mtodo de string

join()
com a string que chamou o mtodo. Ou seja, as dicas string com um espao entre cada elemento (dica).

O retorno dado na linha 27 possui uma string contendo um espao e chamando o mtodo

join(), que concatena as strings de uma lista da lista clue sero agrupadas em uma mesma
8.4.5
retorna

Vericando se a string possui apenas nmeros


A funo

isOnlydigits() verica se a entrada do jogador possui apenas nmeros. Ela False se o palpite no houver 3 algarismos e mantm-se pedindo ao jogador um novo palpite,

at que este seja vlido.

72

8.

BAGELS

8.5

Incio do jogo
O jogo inicia a ser executado, de fato, na linha 45. A quantidade de dgitos do nmero adi-

vinhado assim como a quantidade de palpites possveis so denidos pelas constantes

NUMDIGITS

MAXGUESS.

8.5.1

Interpolao de strings
Interpolao/formatao de strings outro atalho para operaes, mas, desta vez, com strings.

Normalmente, quando necessrio concatenar uma string armazenada em uma varivel, utiliza-se o operador

+.

Entretanto, isto pode no ser conveniente ao utilizar muitas variveis a serem impressas.

Portanto, h uma forma mais sucinta de lidar com muitas variveis que carregam strings, utilizando o substituto

%s

indicando onde cada varivel deva ser impressa. Observe o exemplo:

>>> name = Alice >>> event = party >>> where = the pool >>> when = Saturday >>> time = 6:00pm >>> print(Hello, %s. Will you go to the %s at %s this %s at %s? % (name, event, where, when, time)) Hello, Alice. Will you go to the party at the pool this Saturday at 6:00pm? >>>

Estes substitutos so chamados de

especicadores de converso e permitem que as variveis

sejam colocadas todas de uma vez no m de uma sentena. Outra vantagem desta ferramenta que ela pode ser utilizada com qualquer tipo de varivel, no apenas strings:

>>> var1 = 76 >>> print(var 1 == %s %(var1)) var 1 == 76

8.5.2

Utilizando as funes descritas e vericando a vitria do jogador


O cdigo a partir da linha 55 similar ao dos programas anteriores, mantendo o jogo rodando

dentro de um loop. Neste loop, as funes para criar um nmero e obter o palpite do jogador so utilizadas, assim como a funo para dar as dicas ao jogador, nesta ordem. Para vericar se o jogador venceu o jogo ou no, so vericadas as condies nos blocos entrada, se for, ento o jogador vence. condio vericada no segundo

if

iniciados na linha 70. A vericao bvia se o nmero sorteado o mesmo que o jogador deu como Outra alternativa o jogador esgotar os palpites e perder, Para

if,

da linha 72.

As outras funcionalidades do programa so similares ao contedo que j foi estudado.

esclarecer como o programa funciona, se ainda for necessrio, faa o teste de mesa do programa. programa, supondo entradas do usurio e rodando o programa no papel. Esta prtica muito til

Teste de mesa de um programa quando o programador verica passo a passo, cuidadosamente, o


para encontrar erros no programa (ou em trechos dele) e entender, de fato, como um cdigo funciona.

8.5.

INCIO DO JOGO

73

Tarefa 8.1
Pesquise, para a prxima aula, sobre os seguinte mtodos:

Tarefa 8.2

Listas bidimensionais (listas de listas) e aplicaes. O mtodo de lista A funo O mtodo de string

remove() isdigit() sys.exit()

Pesquise sobre coordenadas cartesianas e nmeros negativos. Relacione esta pesquisa ao desenvolvimento de jogos (mesmo que seja de jogos simples, como os desenvolvidos nesta ocina). Procure ter anidade com estes tpicos, pois eles sero frequentemente utilizados em jogos com interface grca. 1. Esta pesquisa poder ser entregue por e-mail ou na forma impressa. No caso do e-mail, atravs de um documento em anexo em formato .doc ou .pdf, de preferncia pdf. 2. Entrega: no mximo, 15 dias aps esta aula. 3. Formato: fonte 12pt, preferencialmente Arial, Times New Roman ou similares. Trabalhos em Comic Sans e outras fontes informais ou estranhas no sero aceitos. 4. Contedo: mnimo duas, mximo cinco pginas, no necessrio ter capa/folha de rosto/etc., permitido que seja feito em forma de artigo. 5. O trabalho dever ser devidamente referenciado e Wikipedia ou uma nica referncia (ou seja, copy/paste) no sero aceitas.

9 O Criptograma de Csar
Tpicos abordados neste captulo:

Criptograa e criptogramas Encriptao e decodicao de mensagens Valores ASCII Funes

chr()

Os mtodos de string

ord() isalpha(), isupper()

islower()
Este

Mtodo de fora bruta O programa deste captulo no bem um jogo, mas divertido, de qualquer forma.

programa converter uma frase em um cdigo secreto e converter cdigos secretos de volta frase original. Apenas quem souber como o cdigo secreto composto ir decodicar a mensagem. Atravs destes procedimentos, sero abordados novos mtodos e funes para lidar com strings. Alm disso, ser apresentado como lidar com aritmtica envolvendo strings.

9.1

Criptograa
A cincia de codicar mensagens chamada de criptograa. Ela tem sido utilizada por milhares

de anos, para enviar mensagens que apenas o destinatrio poder entender. O sistema utilizado para codicar uma mensagem chamado de

criptograma.

Em criptograa, a mensagem a ser criptografada chamada de texto puro. convertido em uma mensagem encriptada.

Este texto

Neste programa, a mensagem encriptada parecer uma

srie de letras aleatrias, e no ser possivel entend-lo da mesma forma que a mensagem original. Entretanto, se a criptograa da mensagem for conhecida, possvel decodic-la para obter o texto original. Muitas criptograas utilizam chaves.

Chaves

so valores secretos que permitem decodicar

uma mensagem que foi encriptada utilizando um sistema particular.

9.2

A encriptao de Csar
Ao encriptar uma mensagem, utiliza-se uma chave para encript-la ou desencript-la. A chave

para o programa desenvolvido aqui ser um nmero entre 1 e 26. Somente sabendo a chave correta possvel decodicar a mensagem. O criptograma de Csar um dos mais antigos j inventados. Neste criptograma, cada letra substituda por um caractere frente de acordo com a ordem do alfabeto. Em criptograa, estas letras so chamadas de

smbolos,

pois podem ser letras, nmeros ou qualquer outra coisa. Observe

um exemplo de como funcionaria a correspondncia com a chave 3 na gura 16.

Figura 16: Alfabeto substitudo por caracteres 3 casas frente.

9.3

ASCII, utilizando nmeros para localizar letras


Como implementar o avano dos caracteres neste programa? Isto feito representando cada

letra com um nmero (ordinal) e ento somando ou subtraindo este nmero para formar um novo, correspondendo uma nova letra, consequentemente. que 32 so no imprimveis, logo, no sero utilizados. 74 O cdigo ASCII faz a correspondncia para cada caracter em um nmero entre 32 e 127. Os caracteres que correspondem aos nmeros menores

9.4.

AS FUNES

CHR() ORD()
Tabela 7: Tabela ASCII.

75

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

(espao) ! "

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

0 1 2 3 4 5 6 7 8 9 : ; < = > ?

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

@ A B C D E F G H I J K L M N O

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95

P Q R S T U V W X Y Z [

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

a b c d e f g h i j k l m n o

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

p q r s t u v w x y z

#
$ % & ' ( ) * + , . /

{
|

\
]

As letras maisculas, de A a Z, so representadas pelos nmeros 65 a 90. As minsculas, de a a z, so representadas pelos nmeros entre 97 e 122. Os dgitos de 0 a 9 so representados pelos nmeros entre 48 e 57. Observe a tabela 7. no nmero 65. Ento, Se quisermos avanar 3 casas para a letra A, por exemplo, converte-se gerando a letra D. Usaremos as funes

65 + 3 = 68,

chr()

ord()

para

converso entre letras e nmeros.

9.4

As funes
A funo

chr() ord()
A funo

chr()

(de char, verso curta de character) obtm o caracter ASCII para o pa-

rmetro, que deve ser um nmero.

ord()

(de ordinal) faz o inverso, retorna um valor

inteiro, correspondente ao valor ASCII do caracter passado por parmetro.

9.5

Modelo de execuo do programa

Do you wish to encrypt or decrypt a message? encrypt Enter your message: The sky above the port was the color of television, tuned to adead channel. Enter the key number (1-26) 13 Your translated text is: Gur fxl nobir gur cbeg jnf gur pbybe bs gryrivfvba, gharq gb n qrnq punaary. Now we will run the program and decrypt the text that we just encrypted. Do you wish to encrypt or decrypt a message? decrypt Enter your message: Gur fxl nobir gur cbeg jnf gur pbybe bs gryrivfvba, gharq gb nqrnq punaary. Enter the key number (1-26) 13 Your translated text is:

76

9.

O CRIPTOGRAMA DE CSAR

The sky above the port was the color of television, tuned to a dead channel.
Observe o que ocorre se for dada a chave errada:

Do you wish to encrypt or decrypt a message? decrypt Enter your message: Gur fxl nobir gur cbeg jnf gur pbybe bs gryrivfvba, gharq gb nqrnq punaary. Enter the key number (1-26) 15 Your translated text is: Rfc qiw yzmtc rfc nmpr uyq rfc amjmp md rcjctgqgml, rslcb rm y bcyb afyllcj.

9.6

Cdigo-fonte
Cdigo 7: Criptograma de Csar.

# Caesar Cipher MAX_KEY_SIZE = 26 def getMode(): while True: print(Do you wish to encrypt or decrypt a message?) mode = input().lower() if mode in encrypt e decrypt d.split(): return mode else: print(Enter either "encrypt" or "e" or "decrypt" or "d".) def getMessage(): print(Enter your message:) return input() def getKey(): key = 0 while True: print(Enter the key number (1-%s) % (MAX_KEY_SIZE)) key = int(input()) if (key >= 1 and key <= MAX_KEY_SIZE): return key def getTranslatedMessage(mode, message, key): if mode[0] == d: key = -key translated = for symbol in message: if symbol.isalpha(): num = ord(symbol) num += key if symbol.isupper(): if num > ord(Z): num -= 26 elif num < ord(A): num += 26 elif symbol.islower():

9.7.

COMO O CDIGO FUNCIONA

77

if num > ord(z): num -= 26 elif num < ord(a): num += 26 translated += chr(num) else: translated += symbol return translated mode = getMode() message = getMessage() key = getKey() print(Your translated text is:) print(getTranslatedMessage(mode, message, key))

9.7

Como o cdigo funciona


Este cdigo bem mais curto do que os anteriores, entretanto, os conceitos abordados neste

captulo so muito teis no desenvolvimento de jogos. Observemos os tpicos principais deste programa.

9.7.1

Decidindo se o usurio quer encriptar ou desencriptar uma mensagem


A funo

getMode()

permite que o usurio faa a escolha entre encriptar ou desencriptar/de-

codicar uma mensagem. Ela retorna a resposta do jogador, obtida atravs da comparao da entrada do usurio com a lista gerada por

encrypt e decrypt d.split().

9.7.2

Obtendo a mensagem do jogador


A funo

getMessage()

obtm a mensagem a ser codicada ou decodicada e a retorna.

9.7.3

Obtendo a chave do jogador


A funo

a mensagem que ser fornecida. O loop

getKey() permite ao jogador digitar a chave que permitir encriptar ou desencriptar while, da linha 20, assegura que a funo retorne uma chave

vlida, que um nmero entre 1 e 26. Desta forma, a funo retorna um inteiro.

9.7.4

Encriptando ou desencriptando a mensagem com a chave dada

getTranslatedMessage() a funo que faz a encriptao ou desencriptao no programa.


Ela possui trs parmetros:

mode: dene se a funo ir encriptar ou desencriptar a message: mensagem a ser encriptada ou desencriptada key: chave utilizada na (de)codicao

mensagem.

A primeira linha da funo determina o modo de trabalho da funo, comparando a primeira letra da entrada do jogador e, neste caso, mudar o sinal da chave para fazer o processo inverso (que seria a encritpao).

translated

a string que armazenar o resultado nal: ou a mensagem encriptada ou a

desencriptada. Esta varivel apenas recebe strings concatenadas, iniciando por uma string vazia.

9.7.5

Encriptando e desencriptando cada letra


Este processo bem simples e o mesmo bloco de cdigo utilizado para a converso de cada

caracter. O cdigo a partir da linha 36 verica se a string possui algum caracter em letras maisculas.

78

9.

O CRIPTOGRAMA DE CSAR

Se houver, h duas situaes para se preocupar: se a letra Z (ou seja, a ltima letra do alfabeto) e o deslocamento resultar em um caracter que no seja uma letra; e no caso de a letra for A, que o deslocamento dever ser maior que o nmero ASCII deste caracter. O mesmo ocorre para mensagens com `a' e `z'. Se o programa estiver no modo de desencriptao, a chave ser negativa, assim, o processo inverso ocorrer. A string

translated

obter os caracteres de cada encriptao ou desencriptao.

Se o smbolo no for uma letra, o cdigo da linha 48 executar e o smbolo original aparecer na string transformada. Isto signica que outros caracteres no passaro pelo processo. A ltima linha da funo

getTranslatedMessage()

retorna a string transformada.

9.7.6

O incio do programa
O programa inicia a execuo na linha 52. Cada funo denida chamada e armazenada em

uma varivel, pois elas possuem valores de retorno. Ento, estes valores so passados para a funo

getTranslatedMessage(),

que retorna o valor a ser impresso para o usurio.

9.8

O mtodo de string
Este mtodo retornar

isalpha()

True se a string for inteiramente composta de maisculas ou minsculas False.

de A a Z, sem espaos ou se no for uma string em branco. Se a string contm quaisquer caracteres que no sejam letras, ento o retorno

9.9
e

Os mtodos de string

isupper()

islower()

Os mtodos isupper() e islower() funcionam de forma similar aos mtodos isdigit() isalpha(). isupper() retornar True se a string a qual o chama possuir pelo menos uma letra maiscula e nenhuma letra minscula. O mtodo islower() funciona ao contrrio: retorna True se a string possuir apenas letras minsculas. Se as condies no forem satisfeitas, o retorno False. A existncia de caracteres que no sejam letras no afetam a sada, ou seja, os mtodos analisam apenas as letras de uma string.

9.10

Fora Bruta
Embora o programa possa enganar algumas pessoas e esconder as mensagens, o cdigo pode

ser quebrado atravs de anlise criptogrca. Um dos mtodos de desencriptao sem saber a chave (ou o cdigo) por trs de uma mensagem a fora bruta. correto.

Fora bruta

a tcnica de tentar todo

procedimento possvel (no caso deste programa, testar todas as chaves) at encontrar o resultado O nmero de chaves deste programa relativamente pequeno e pode-se gerar todos os resultados possveis at encontrar algum que faa sentido. Vamos adicionar um mtodo de fora bruta ao programa.

9.10.1

Adicionando um mtodo de fora bruta ao programa

Observe as alteraes na funo

getMode():

def getMode(): while True: print(Do you wish to encrypt or decrypt or brute force a message?) mode = input().lower() if mode in encrypt e decrypt d brute b.split(): return mode[0] else: print(Enter either "encrypt" or "e" or "decrypt" or "d" or "brute" or "b".)
Estas alteraes permitem que a fora bruta seja uma opo do programa. Ento, adicione e

modique as seguintes linhas do programa:

9.11.

EXERCCIOS COMPLEMENTARES

79

mode = getMode() message = getMessage() if mode[0] != b: key = getKey() print(Your translated text is:) if mode[0] != b: print(getTranslatedMessage(mode, message, key)) else: for key in range(1, MAX_KEY_SIZE + 1): print(key, getTranslatedMessage(decrypt, message, key))
Estas mudanas fazem o seu programa pedir ao usurio uma chave, se no estiver no modo de

fora bruta. Se for o caso, ento a funo que anteriormente.

getTranslatedMessage()

funcionar da mesma forma

Entretanto, se o modo fora bruta for acionado, ento a funo executar um loop iterando de 1 a

getTranslatedMessage()

MAX_KEY_SIZE

(que 26). Este programa imprimir todas as

tradues possveis de uma mensagem.

9.11

Exerccios complementares
Caesar Cipher para que:

1. Explique apenas as alteraes que voc faria no programa

No fosse necessrio fazer as comparaes das linhas

37, 39, 42

44

para que as operaes

no ultrapassem o limite de letras da tabela ASCII. Dica: Use o operador de mdulo. Usando suas alteraes do exerccio acima (economizar algumas linhas de cdigo) implemente um mtodo alternativo e mais seguro de criptograa e descriptograa neste programa. Para cada posio da string que ser criptografada:

     

Calcule o resto da diviso do ndice por quatro Caso o resto seja Caso o resto seja Caso o resto seja Caso o resto seja

0, 1, 2, 3,

adicione 10 ao valor numrico do caractere subtraia 10 do valor numrico do caractere adicione 20 ao valor numrico do caractere subtraia 20 do valor numrico do caractere

Adicione o valor do ndice ao valor numerico do caractere

Crie um mtodo prprio para criptografar e descriptografar a string

10 Introduo Grcos e Animao (parte 1)


Tpicos abordados neste captulo:

Bibliotecas de software Pygame Interfaces grcas de usurio (GUI: Graphical User Interfaces) Desenhos primitivos Criando uma janela GUI com o Pygame Cores em Pygame Fontes em Pygame Grcos linearizados Atributos Os tipos de dados Construtores A funo

pygame.font.Font, pygame.Surface, pygame.Rect, pygame.PixelArray

type() blit()
para objetos

Funes de desenho do Pygame O mtodo Eventos O loop de um jogo At agora, os jogos e programas trabalhados utilizavam apenas modo texto: um texto era

Surface

mostrado na tela, como sada, e o jogador digitava algo do teclado (outro texto). Tudo isto serviu para introduzir os conceitos fundamentais de programao. A partir desta aula, veremos como utilizar recursos grcos atravs da biblioteca Pygame. Nas prximas aulas, o conceito da lgica de um jogo ser mais simples do que foi visto at agora, mas todas as ferramentas apresentadas podero ser utilizadas com lgicas mais robustas, como o jogo da velha ou da forca. Uma biblioteca permite ao programador adicionar mais recursos ao seu programa, de maneira genrica, mas customizvel, sem precisar se preocupar em programar todo o cdigo. programao de jogos. O Pygame uma biblioteca que possui mdulos para grcos, sons e outros recursos comumente utilizado para a

10.1

Pygame
O Pygame uma biblioteca de software que no faz parte do Python nativo. Mas, assim como

o Python, essa biblioteca est disponvel gratuitamente, multiplataforma. Assegure-se que a verso que voc for baixar seja compatvel com o Python 3, utilizado nesta ocina.

10.2

Hello World
Novamente, criaremos um Hello World, como no incio do curso. Entretanto, adicionaremos

recursos grcos, como uma janela de

interface grca para usurio (GUI). Uma interface grca

permite que sejam criadas janelas, cores, formas e imagens que podem ser desenhadas pelo programa, assim como aceitar entradas pelo mouse (e no apenas pelo teclado). As formas bsicas so chamadas de

desenhos primitivos.

Alm disso, janelas so utilizadas ao invs do terminal.

O Pygame no trabalha muito bem com o terminal pois ele exige um terminal interativo. Alm disso, programas do Pygame no utilizam a funo captadas atravs do mouse ou do teclado por

loop de jogo (que ser

explicado posteriormente). Devido a isto, no possvel enviar comandos para o Pygame atravs do

input().

No h texto de entrada

ou sada. Ao invs disso, as sadas do programa so dadas atravs de uma janela. As entradas so

eventos,
80

que sero vistos na prxima aula. Porm, se

o programa tiver erros, eles sero mostrados na linha de comando.

10.3.

CDIGO-FONTE DO HELLO WORLD

81

Pode-se usar a funo

print(), entretanto, a mensagem aparecer na linha de comando, sendo


21 .

ineciente para sada, mas inteligente para debug. Por exemplo, o resultado de uma operao pode ser impresso para o programador saber se aquele trecho do programa est funcionando corretamente

10.3

Cdigo-fonte do Hello World


Iniciaremos com um programa bem simples, que mostra texto e algumas formas em uma janela.

Execute o cdigo 8.
Cdigo 8: Hello World grco.

import pygame, sys from pygame.locals import * # inicia o pygame pygame.init() # inicia a janela windowSurface = pygame.display.set_mode((500, 400), 0, 32) pygame.display.set_caption(Hello world!) # inicia as cores utilizadas BLACK = (0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # inicia as fontes basicFont = pygame.font.SysFont(None, 48) # inicia o texto text = basicFont.render(Hello world!, True, WHITE, BLUE) textRect = text.get_rect() textRect.centerx = windowSurface.get_rect().centerx textRect.centery = windowSurface.get_rect().centery # desenha o fundo branco windowSurface.fill(WHITE) # desenha um poligono verde na superficie pygame.draw.polygon(windowSurface, GREEN, ((146, 0), (291, 106), (236, 277), (56, 277), (0, 106))) # desenha algumas linhas azuis na superficie pygame.draw.line(windowSurface, BLUE, (60, 60), (120, 60), 4) pygame.draw.line(windowSurface, BLUE, (120, 60), (60, 120)) pygame.draw.line(windowSurface, BLUE, (60, 120), (120, 120), 4) # desenha um circulo azul na superficie pygame.draw.circle(windowSurface, BLUE, (300, 50), 20, 0) # desenha uma elipse vermelha na superficie pygame.draw.ellipse(windowSurface, RED, (300, 250, 40, 80), 1) # desenha o retangulo do fundo do texto na superficie pygame.draw.rect(windowSurface, RED, (textRect.left - 20, textRect.top - 20, textRect.width + 40, textRect.height + 40))

21 Voc

pode consultar informaes de como utilizar o Pygame atravs do site do desenvolvedor:

http://pygame.

org/docs/ref/.

82

10.

INTRODUO GRFICOS E ANIMAO (PARTE 1)

# obtem um array de pixel da superficie pixArray = pygame.PixelArray(windowSurface) pixArray[480][380] = BLACK del pixArray # desenha o texto na janela windowSurface.blit(text, textRect) # desenha a janela na tela pygame.display.update() # roda o loop do jogo while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit()
A execuo deste programa resultar em uma janela similar gura 17.

Figura 17: Resultado da execuo do cdigo 8.

O interessante em utilizar uma GUI ao invs do console, que o texto pode aparecer em qualquer lugar da janela, no apenas depois do ltimo texto impresso. Alm disso, o texto pode ter qualquer cor ou tamanho. O Pygame utiliza muitas tuplas, estruturas parecidas com listas, mas com parnteses delimitadores ao invs de colchetes. A maior diferena entre tuplas e listas que no possvel alterar, adicionar ou remover valores em uma tupla. Por razes tcnicas, sabendo que os valores no podem ser alterados em uma tupla, permite-se ao Python que trabalhe de forma mais eciente.

10.4

Importando o mdulo Pygame


Na primeira linha do programa, os mdulos

pygame

sys

so importados para que seja

permitido utilizar suas funes. separados por vrgulas. tes, como

Pode-se chamar mais de uma mdulo em uma mesma sentena,

pygame.locals. Este mdulo contm inmeras constanQUIT e K_ESCAPE, explicadas posteriormente. Usando a forma from nomeDoMdulo import * faz com que no seja necessrio digitar pygame.locals antes de cada funo deste mdulo, como vm sendo feito desde os primeiros programas. O asterisco da sentena signica que todo o contedo do mdulo importado para o programa. Se o mdulo

A segunda linha importa o mdulo

sys fosse importado da forma from sys import *, ao invs de import sys, seria possvel chamar apenas a funo exit() ao invs de sys.exit(). Entretanto, indicado que se use o nome dos mdulos para que o programador
saiba a qual deles pertencem as funes do programa.

10.5.

FUNES E MTODOS DO PROGRAMA

83

10.5
10.5.1

Funes e mtodos do programa

pygame.init()

O software da biblioteca Pygame possui um cdigo inicial que precisa ser executado antes de utiliz-la. Todos os programas que utilizem o Pygame devem executar este cdigo atravs da linha

pygame.init(),
deste mdulo.

logo depois de ter importado o mdulo

pygame,

mas antes de chamar as funes

10.5.2

pygame.display.set_mode()
dentro do mdulo

A linha 8 cria uma janela GUI, para o programa, chamando o mtodo

pygame.display. (O mdulo display um mdulo O mtodo set_mode() exige trs parmetros: o


largura e altura da janela, em pixels. Um imagens. Utilizou-se a tupla

set_mode() do mdulo pygame.)

pixel

primeiro uma tupla de dois inteiros para a

o menor ponto de uma tela de computador. Um

nico pixel pode ser de qualquer cor. Todos os pixels da tela trabalham mutuamente para gerar as

(500, 400)

para o primeiro parmetro do mtodo

set_mode()

para

estabelecer a dimenso da janela. O segundo e o terceiro parmetros so para opes avanadas da GUI. Como, por enquanto, estes parmetros so desnecessrios, os valores zero e 32 foram passados, pois o mtodo no pode receber menos parmetros do que o esperado. O mtodo como objetos qualquer

set_caption() retorna um objeto pygame.Surface (que sero denominados Surface, para simplicar) com texto. Pode-se armazenar objetos em variveis, como outro valor. O objeto Surface representa a janela e a varivel windowSurface dever

ser inclusa em todas as chamadas de funo de desenho.

10.6

Referncias de objetos
Variveis que guardam objetos, na verdade, funcionam como variveis de referncia listas,

vistas anteriormente. Diferentemente das variveis comuns, ou seja, que podem fazer a cpia de um valor e, assim, mant-lo armazenado, as variveis as quais possuem objetos atribudos apenas levam uma referncia deste objeto. que elas carregam o mesmo. Logo, se duas variveis referenciarem um objeto e apenas uma delas sofrer alterao, automaticamente a outra tambm ser alterada, pois o valor (ou conjunto de valores)

10.7

Cores em Pygame
As linhas 12 a 16 do cdigo 8 possuem valores declarados como tuplas de trs elementos, com

valores que identicam cores em RGB. Cada valor dos parnteses se refere quantidade da cor em vermelho (R, red), verde (G, green) e azul (B, blue), respectivamente. A tabela 8 possui algumas combinaes RGB de cores comuns. No cdigo 8, as variveis receberam nomes em maisculas para indicar que so constantes, ou seja, no mudaro ao longo do programa. Desta forma, ca mais fcil referenciar a cor preta por

BLACK

ao invs de sempre digitar

(0, 0, 0).

10.8

Fontes
Uma

fonte

um conjunto de letras, nmeros e smbolos diversos que seguem em estilo esta-

belecido. Nos programas em linha de comando, no possvel estabelecer uma fonte prpria para o programa, apenas para todo o console. Entretanto, possvel desenhar letras diferentes atravs de uma GUI, dizendo ao Pygame onde e como desenhar o grco desejado.

10.8.1

A funo

pygame.font.SysFont()
pygame.font.Font criado (que ser chamado de objeto Font, pygame.font.SysFont(). O primeiro parmetro o

Na linha 19, um objeto

para facilitar) atravs da chamada de funo

84

10.

INTRODUO GRFICOS E ANIMAO (PARTE 1)

Tabela 8: Cores RGB.

Cor
Amarelo Azul Azul claro (cornower) Azul escuro Azul petrleo Azul-piscina Branco Cinza Fcsia Marrom Roxo Verde Verde claro (lime) Verde oliva Vermelho Prateado Preto

Valores RGB
(255, 255, 0) (0, 0, 255) (100, 149, 237) (0, 0, 128) (0, 128, 128) (0, 255, 255) (0, 0, 0) (128, 128, 128) (255, 0, 255) (128, 0, 0) (128, 0, 128) (0, 128, 0) (0, 255, 0) (128, 128, 0) (255, 0, 0) (192, 192, 192) (0, 0, 0)

nome da fonte, que utilizado

None,

para dizer ao programa que ser utilizado o padro do sistema.

O segundo parmetro o tamanho da fonte, dado como 48 pt.

10.8.2

O mtodo

render()

para objetos

Font

Na linha 22, o objeto mtodo cria um objeto

Font armazenado em basicFont, chamou o mtodo render(). Este Surface, com o texto desejado. O primeiro parmetro a string a ser
anti-aliasing. O anti-aliasing uma tcnica

desenhada, o segundo a escolha da aplicao da tcnica

que faz com que o desenho seja menos brusco, tornando as linhas mais suaves. Esta tcnica utilizada para o desenho da fonte. O terceiro e o quarto parmetro so as cores para desenho do texto e do fundo do texto, respectivamente.

Figura 18: Tcnica de anti-aliasing aplicada a uma reta.

10.9

Atributos
O tipo

pygame.Rect

(que ser chamado de

Rect,

por convenincia), facilita o trabalho com

formas retangulares. retngulo, da forma:

Para criar um objeto

Rect

chama-se a funo

pygame.Rect(),

passando

parmetros inteiros de coordenadas XY do canto superior esquerdo, seguidos pela largura e altura do

pygame.Rect(coordEsquerda, coordAcima, largura, altura). rect

Assim como mtodos so como funes associadas a um objeto, adas a um objeto. O tipo

atributos so variveis associ-

possui muitos atributos que descrevem um retngulo e so chamadas

10.10. MTODOS

GET_RECT() PARA OS OBJETOS PYGAME.FONT.FONT E PYGAME.SURFACE85

como um ponto, assim como os mtodos (ver linhas 24 e 25 do cdigo 8). Observe a tabela 9, em que

myRect

um objeto

Rect

qualquer.
Tabela 9: Atributos dos objetos

Rect.

Atributo pygame.Rect
myRect.left myRect.right myRect.top myRect.bottom myRect.centerx myRect.centery myRect.width myRect.height myRect.size myRect.topleft myRect.topright myRect.bottomleft myRect.bottomright myRect.midleft myRect.midright myRect.midtop myRect.midbottom

Descrio
O valor inteiro da coordenada X do lado esquerdo do retngulo O valor inteiro da coordenada X do lado direito do retngulo O valor inteiro da coordenada Y do lado de cima do retngulo O valor inteiro da coordenada Y do lado de baixo do retngulo O valor inteiro da coordenada X do centro do retngulo O valor inteiro da coordenada Y do lado centro do retngulo O valor inteiro da largura do retngulo O valor inteiro da altura do retngulo Uma tupla de dois inteiros: Uma tupla de dois inteiros: Uma tupla de dois inteiros: Uma tupla de dois inteiros: Uma tupla de dois inteiros: Uma tupla de dois inteiros: Uma tupla de dois inteiros: Uma tupla de dois inteiros: Uma tupla de dois inteiros:

(largura, altura) (esquerda, acima) (direita, acima) (esquerda, abaixo) (direita, abaixo) (esquerda, centroY) (direita, centroY) (centroX, acima) (centroX, abaixo)

10.10

Mtodos e

get_rect() para os objetos pygame.font.Font pygame.Surface


chamam o mtodo

Observe que os objetos vel

windowSurface)

Font (armazenado na varivel text) e Surface (armazenado na variget_rect(). Tecnicamente, eles so mtodos diferentes. Font
ou

Entretanto, possuem o mesmo nome por executarem um procedimento similar, retornando objetos

Rect

que representam o tamanho e a posio de um objeto Alm disso, lembre-se que o

Surface.

mdulo, esto disponveis os

pygame um mdulo mdulos font e surface.

importado pelo programa e, dentro deste E dentro destes mdulos, esto os tipos

Font

Surface.

A diferena entre as letras maisculas no incio dos objetos e minsculas para os

mdulos por conveno, para facilitar a distino entre os tipos.

10.11

Funo construtor e

type()
construtores.

Criou-se um objeto

pygame.Rect()
As funes

possui o mesmo nome do tipo de dado

pygame.Rect atravs da chamada de funo pygame.Rect(). A funo pygame.Rect. Funes que possuem o str()
tambm so construtores. A funo

mesmo nome de seu tipo de dado e criam objetos ou valores do seu tipo so chamadas de

int()

int()

retorna um inteiro do

que estiver dentro dos parnteses, por exemplo, desde que especicado corretamente. Para descobrir o tipo de um dado, utiliza-se a funo

type():

>>> type(21) <class str> >>> type(12) <class int> >>> type(19.32) <class float>

86

10.

INTRODUO GRFICOS E ANIMAO (PARTE 1)

>>> import pygame >>> pygame.init() (6, 0) >>> retangulo = pygame.Rect(20, 20, 40, 40) >>> type(retangulo) <class pygame.Rect> >>> pygame.quit()
( necessrio chamar a funo Observe que a funo

pygame.quit()) quando terminar de utilizar o mdulo pygame


no retorna uma string, mas um valor do tipo

no terminal interativo, para evitar que acontea algum procedimento indesejado no Python.)

type()

type:

>>> type(type(12)) <class type>

10.12

O mtodo

fill()

para objetos

Surface

A linha 28 traz o primeiro desenho do programa. O que esta linha faz preencher a superfcie inteira, armazenada em

windowSurface com a cor branca (WHITE). O mtodo fill() ir preencher

completamente a superfcie com a cor passada por parmetro. Algo importante a saber sobre o Pygame que a janela na tela no mudar quando o mtodo

fill() for chamado, assim como qualquer outra funo de desenho. Estes desenhos esto em um objeto Surface, mas este objeto no ser desenhado na tela do usurio at que pygame.display.update() for chamado. Isto porque desenhar em um objeto Surface muito mais rpido do que desenhar na
tela do computador. Assim, mais eciente desenhar na tela tudo de uma vez depois que todos os desenhos j estejam em um

Surface.

10.13
10.13.1

Mais funes

pygame.draw.poligon()
pygame.draw.poligon() desenha qualquer forma e preenche o espao dentro

Um polgono uma forma geomtrica que possui vrios lados e apenas linhas retas, em duas dimenses. A funo forma, em ordem. desta forma. A tupla de tuplas passada a esta funo representa as coordanadas XY dos pontos da A ltima tupla conectar uma linha reta primeira, formando um polgono. Observe a linha 31 do cdigo 8.

10.13.2

Desenhos genricos

Algumas funes de desenho so bem similares, exceto pela forma com que resultam e nos dados que precisam para gerar esta forma. Vejamos algumas delas:

pygame.draw.circle():
rmetros: 1. Objeto 2. Cor

desenha um crculo em um objeto

Surface

dado (linha 39). Pa-

Surface

a ser desenhado

3. Tupla com as coordenadas inteiras X e Y indicando o centro do crculo 4. Raio, em pixels 5. Preenchimento, 0 (zero) signica que a forma ser preenchida

pygame.draw.ellipse():
Parmetros: 1. Objeto 2. Cor

desenha uma elipse em um objeto

Surface

dado (linha 42).

Surface

a ser desenhado

3. Tupla com as coordenadas inteiras indicando limite superior, limite inferior, largura e altura 4. Preenchimento, 1 (zero) signica que a forma no ser preenchida

10.14.

O TIPO DE DADO

PYGAME.PIXELARRAY
desenha um retngulo em um objeto

87

pygame.draw.rect():
rmetros: 1. Objeto 2. Cor

Surface

dado (linha 45). Pa-

Surface

a ser desenhado

3. Tupla com as coordenadas inteiras indicando limite esquerda, limite superior, largura e altura. Um objeto

Rect

tambm pode ser passado neste parmetro

4. Preenchimento, 1 (zero) signica que a forma no ser preenchida

10.14

O tipo de dado

pygame.PixelArray

pygame.PixelArray criado (que ser chamado de PixelArray por Surface, passado por parmetro. O objeto windowSurface foi passado para o construtor PixelArray() na linha 48. Em seguida, atribuiu-se BLACK a pixArray[480][380], para ser um pixel preto. O Pygame ir alterar automaticamente o objeto windowSurface para esta congurao. O primeiro ndice do objeto PixelArray a coordenada X, o segundo, a coordenada Y.
convenincia). Este objeto uma lista de listas de tuplas de cores que representam o objeto Objetos deste tipo tornam fceis de gerar pixels individuais de um objeto em uma cor especca. Criar um objeto Para destravar o que nenhuma chamada de funo

Na linha 48, um objeto

PixelArray de um objeto Surface trava este segundo objeto. Isto signica blit() (explicada adiante) pode ser feita ao objeto Surface. objeto, necessrio deletar o objeto PixelArray com o operador del (linha 50).

Se isto no for feito, ocorrer erro.

10.14.1

O mtodo

blit()

para objetos

Surface

exemplo, na linha 54 desenhado o texto

Surface em outro objeto Surface. Por Hello World!, armazenado na varivel text, em um objeto Surface e, por sua vez, este objeto armazenado na varivel windowSurface. O objeto text havia Hello World! desenhado na linha 22, pelo mtodo render(). Objetos Surface so armazenados na memria (como qualquer outra varivel), e no so desenhados na tela imediatamente. O objeto armazenado em windowSurface desenhado na tela somente quando ocorre a chamada pygame.display.update(), na linha 56, pois este objeto foi criado pela funo pygame.display.set_mode(). O segundo parmetro para blit() especica onde, na superfcie windowSurface (isto , onde no objeto Surface), text deve ser desenhado. No caso da linha 53, o objeto Rect foi passado, obtido atravs da linha 23 em text.get_Rect(). blit()

O mtodo

desenha contedo de um objeto

10.15

A funo

pygame.display.update()
pygame.display.update() Surface
chamada.

No Pygame, nada desenhado at que a funo

Este procedimento necessrio pois desenhar na tela uma operao muito lenta para o computador, comparada, por exemplo, simples criao e armazenamento de objetos retornados por em na memria.

Surface pygame.display.set_mode(). (Neste programa, h apenas o objeto armazenado windowSurface.) Isto se tornar mais importante quando lidarmos com animaes.

Para cada atualizao da tela esta funo deve ser chamada para mostrar os objetos

10.16

Eventos e loop do jogo


input().

Nos programas anteriores, toda a sada era impressa at que houvesse uma chamada de

Neste ponto, o programa para e espera a entrada do usurio. O Pygame no funciona desta forma. Ao invs disso, os programas esto constantemente rodando em um loop (neste programa, executa-se todas as linhas de cdigo cerca de cem vezes por segundo). O da janela e desenha, o que for programado, na tela.

loop do jogo um lao que verica constantemente por novos eventos, atualizaes de estado Eventos so valores do tipo pygame.event.Event,

gerados pelo Pygame sempre que algo ocorrer atravs da interface de usurio, como uma tecla pressi-

88

10.

INTRODUO GRFICOS E ANIMAO (PARTE 1)

onada ou cliques e movimentos do mouse. Chamar objetos

pygame.event.get()

retorna quaisquer novos

pygame.event.Event

gerados desde a ltima chamada da mesma funo.

O incio deste programa na linha 59, em um loop innito. O programa terminar somente se um evento ocorrer, conforme declarado no bloco condicional seguinte.

10.16.1

A funo

pygame.event.get()

pygame.event.get() retorna uma lista de objetos pygame.event.Event. Esta Event possuem um atributo chamado type, que informa qual o tipo de tal evento. Estes tipos sero vistos posteriormente, nesta aula veremos apenas o evento QUIT.) O Pygame possui suas prprias constantes no mdulo pygame.locals, que importado na segunda linha do programa. A linha from pygame.locals import * signica que no necessrio digitar pygame.locals antes de utilizar qualquer recurso deste mdulo. Por isso, utilizase apenas QUIT no programa. Na linha 60, um loop for inicia e verica cada objeto Event na lista retornada por pygame.event.get(). 22 for igual ao contedo de QUIT (que fornecido pelo mdulo pygame.locals), Se o atributo type
lista possui todo evento ocorrido entre uma e outra chamada desta funo. Todos os objetos ento o programa saber que o usurio quer fechar o programa. O Pygame gera o evento

A funo

QUIT quando o usurio clica no boto de fechar (X) no topo da janela


Por qualquer motivo que

do programa. Este evento tambm gerado quando o computador est desligando e tenta terminar todos os programas que esto abertos.

QUIT

for gerado, sabe-se que o

usurio deseja terminar/fechar o programa. Entretanto, pode-se simplesmente ignorar esta ao, o que causaria confuso ao usurio, provavelmente.

10.16.2

A funo

pygame.quit()
for gerado, sabe-se que o usurio tentou fechar a janela. Neste caso, deve-se

Se o evento

QUIT

chamar a funo do Pygame Este foi o exemplo

pygame.quit() e a funo do Python sys.exit(). Hello World feito no Pygame. De fato, este programa no executa nada

de til, mas serviu para introduzir ferramentas grcas muito teis, com a nalidade de implementar recursos adicionais aos seus projetos. Embora possam parecer complicados, o Pygame fornece procedimentos que podem tornar os programas mais divertidos e interessantes do que os jogos anteriores, em modo texto. Na prxima aula, veremos como lidar com animaes.

10.17

Exerccios Complementares

1. Faa um programa que desenhe a seguinte situao de um jogo da velha na tela:

O| |X ----O|X| ----O|X|O
O fundo da tela deve ser Branco Dever estar escrito centralizado em cima do tabuleiro o ttulo "Jogo da Velha"na cor Preto. O tabuleiro, no tamanho e na posio que voc preferir, dever estar na cor Steel Azul As jogadas "X"devero ser desenhados como duas linhas cruzadas e estar na cor Verde Hunter As jogadas "O"devero ser desenhadas crculos no preenchidos estar na cor Vermelho Indiano Dever ter um trao em cima do trio vencedor com uma cor aleatria e largura aleatria entre 1 e 10.

22 Lembre-se

que atributo apenas uma varivel que caracteriza um objeto.

10.17.

EXERCCIOS COMPLEMENTARES

89

2. Faa um programa que receba uma string do usurio e imprima cada letra em um local aleatrio na tela. As as cores das letras devem ser aleatrias seguindo o seguinte padro: Considere que h duas linhas verticais imaginarias na tela que a divide em trs partes iguais:

Todas as letras que sero posicionadas antes da primeira linha devem ter o componente R da escala RGB maior que 127 e os outros menores Todas as letras que sero posicionadas entre a primeira e a segunda linha devem ter o componente G maior que 127 e os outros menores Todas as letras que sero posicionadas depois da segunda linha devem ter o componente B maior que 127 e os outros menores

11 Introduo Grcos e Animao (parte 2)


O programa deste captulo bem simples, em questo de execuo. Alguns blocos caminham na tela, batendo nas bordas da janela. em direes na diagonal. Os blocos so de diferentes tamanhos e cores e se movem Para animar os blocos (isto , dar movimentos a eles) ser utilizado um loop, fazendo iteraes nos pixels de cada forma. Desta forma, novos blocos sero desenhados a cada momento, alguns pontos frente em relao direo em que cada um estiver se movendo, dando a impresso de movimento.

11.1

Cdigo-fonte
Cdigo 9: Animaes.

import pygame, sys, time from pygame.locals import * # set up pygame pygame.init() # set up the window WINDOWWIDTH = 400 WINDOWHEIGHT = 400 windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32) pygame.display.set_caption(Animation) # set up direction variables DOWNLEFT = 1 DOWNRIGHT = 3 UPLEFT = 7 UPRIGHT = 9 MOVESPEED = 4 # set up the colors BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # set up the block data structure b1 = {rect:pygame.Rect(300, 80, 50, 100), color:RED, dir:UPRIGHT} b2 = {rect:pygame.Rect(200, 200, 20, 20), color:GREEN, dir:UPLEFT} b3 = {rect:pygame.Rect(100, 150, 60, 60), color:BLUE, dir:DOWNLEFT} blocks = [b1, b2, b3] # run the game loop while True: # check for the QUIT event for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() # draw the black background onto the surface windowSurface.fill(BLACK) for b in blocks:
90

11.2.

COMO O PROGRAMA FUNCIONA

91

# move the block data structure if b[dir] == DOWNLEFT: b[rect].left -= MOVESPEED b[rect].top += MOVESPEED if b[dir] == DOWNRIGHT: b[rect].left += MOVESPEED b[rect].top += MOVESPEED if b[dir] == UPLEFT: b[rect].left -= MOVESPEED b[rect].top -= MOVESPEED if b[dir] == UPRIGHT: b[rect].left += MOVESPEED b[rect].top -= MOVESPEED # check if the block has move out of the window if b[rect].top < 0: # block has moved past the top if b[dir] == UPLEFT: b[dir] = DOWNLEFT if b[dir] == UPRIGHT: b[dir] = DOWNRIGHT if b[rect].bottom > WINDOWHEIGHT: # block has moved past the bottom if b[dir] == DOWNLEFT: b[dir] = UPLEFT if b[dir] == DOWNRIGHT: b[dir] = UPRIGHT if b[rect].left < 0: # block has moved past the left side if b[dir] == DOWNLEFT: b[dir] = DOWNRIGHT if b[dir] == UPLEFT: b[dir] = UPRIGHT if b[rect].right > WINDOWWIDTH: # block has moved past the right side if b[dir] == DOWNRIGHT: b[dir] = DOWNLEFT if b[dir] == UPRIGHT: b[dir] = UPLEFT # draw the block onto the surface pygame.draw.rect(windowSurface, b[color], b[rect]) # draw the window onto the screen pygame.display.update() time.sleep(0.02)
A execuo deste programa resultar em algo parecido (e animado) com a gura 19.

11.2
11.2.1

Como o programa funciona


Movendo e rebatendo os blocos

Para gerar os movimentos dos blocos, necessrio que saibamos exatamente qual trajetria eles devem percorrer, alm de ter uma boa noo espacial, para que a trajetria no siga de forma errada. Cada bloco, neste programa, se move em um de quatro movimentos na diagonal: abaixo e esquerda, abaixo e direita, acima e esquerda, acima e direita. Quando o bloco bate em algum lado da janela, ele dever ser rebatido, mantendo-se dentro da janela e se movendo em uma nova direo na diagonal. A nova direo do bloco depende de duas condies: qual a direo que ele estava se movendo antes de ser rebatido e qual parede ele colidiu. H um total de oito formas possveis que um bloco

92

11.

INTRODUO GRFICOS E ANIMAO (PARTE 2)

Figura 19: Resultado da execuo do cdigo 9.

pode colidir com uma parede: duas para cada uma das quatro paredes. janela, ento este bloco dever ser rebatido para a direita e para cima.

Observe a gura 20.

Por

exemplo, se um bloco est se movendo para baixo e para a direita e colide com a parede debaixo da

Figura 20: Formas de coliso possveis neste programa.

Para representar os blocos, utiliza-se objetos quatro direes o bloco est se movendo. dos blocos so ajustadas no objeto

Rect,

para indicar as posies e tamanho de um

bloco. Uma tupla de trs inteiros representam a cor de um bloco e um inteiro representa qual das A cada iterao do loop do jogo, as coordenadas X e Y Alm disso, a cada iterao os blocos so desenhados na

Rect.

nova posio. Com a execuo contnua do programa, os blocos se movem gradualmente pela tela, parecendo que eles esto se movendo e sendo rebatidos ao colidirem com as paredes.

11.3
11.3.1

Como o programa funciona


Criando a janela principal e iniciando o Pygame

Neste programa, o mdulo gura em

time

importado, alm dos mdulos do programa anterior. desenhando a janela em uma varivel

Entre as linhas 8 e 10, determina-se o tamanho da janela, atravs das dimenses de altura e lar-

WINDOWWIDTH

WINDOWHEIGHT,

windowSurface.

As dimenses so armazenadas em constantes pois estes valores sero utilizados alm da funo

set_mode().

Desta forma, por convenincia, utilizam-se variveis e constantes de forma que o

11.3.

COMO O PROGRAMA FUNCIONA

93

programa torna-se mais legvel para o programador. Se estas constantes no fossem utilizadas, por exemplo, cada ocorrncia deveria deveria ser substituda pelo valor que elas carregam, o que no torna muito agradvel para o programador, ainda mais no caso de um programa com uma grande densidade de linhas de cdigo. Para este programa, d-se ttulo de Animation para a janela, atravs da funo

set_caption().

Em seguida, das linhas 15 a 18, constantes com nmeros que simbolizam a posio da janela atravs da disposio dos nmeros no teclado numrico (como no jogo da velha) so denidas para determinar a direo das formas. Por exemplo,

1 corresponde direo abaixo e esquerda, 3 abaixo

e a direita, e assim por diante. Poderiam ser utilizados quaisquer valores para denir estas direes, desde que sejam valores diferentes. Eles servem para que o programa saiba em que direo seguir aps uma coliso. Uma outra constante, dos blocos.

MOVESPEED denida como a velocidade em que os blocos iro se mover.

No caso, isto indica que os blocos se movero 4 pixels a cada iterao do loop que faz o movimento

11.3.2

Iniciando as estruturas de dados dos blocos

A linha 28 inicia um dado do tipo dicionrio (este tipo de dado j foi indicado como pesquisa, anteriormente) que representa um dos retngulos do programa. O mesmo feito em seguida para os outros retngulos. O dicionrio possuir as chaves

rect

(com um objeto

Rect

atribudo) e

color

(com uma tupla de inteiros atribuda), alm da direo inicial em Na linha 31, estes dados so armazenados em uma lista, o retorno seria

dir. blocks.

Cada posio de

conter uma varivel do tipo dicionrio. Ao realizar uma chamada do tipo sendo iniciado por

blocks blocks[0][color],

(255,0,0). blocks.

Desta forma, quaisquer dos valores de qualquer bloco pode ser acessado,

11.3.3

Rodando o loop principal

Dentro do loop principal, queremos mover todos os blocos pela tela na direo em que eles foram denidos e, ento, serem rebatidos assim que colidirem com uma das paredes. Assim, os blocos so desenhados na superfcie e ento a funo tela. Alm disso, a funo

pygame.display.update() para atualizar a imagem na pygame.event.get() para vericar se o usurio quer fechar o programa. O loop for verica todos os eventos da lista retornada por pygame.event.get(). Depois de ter desenhado os blocos em windowSurface, a base preta e, em seguida, redesenhar os retngulos
nas novas posies.

11.3.4

Movendo cada bloco

O bloco por

for

iniciado na linha 44 atualiza a posio de cada bloco. Deve-se percorrer a lista

de retngulos e rodar o mesmo cdigo em cada estrutura. Dentro do loop, cada bloco representado

b,

tornando mais fcil de digitar. O novo valor de

left

top,

por exemplo, de cada retngulo (ou seja, os atributos), depen-

dem da direo em que o bloco est se movendo. Lembre-se que as coordenadas X e Y iniciam em zero no extremo esquerdo superior da janela. Desta forma, se a direo do bloco for

DOWNRIGHT,

o atributo

decrementar o atributo

top top.

ser incrementado.

Se a direo for

UPLEFT

ou

DOWNLEFT ou UPRIGHT, queremos

mesma forma, se a direo for o

DOWNRIGHT ou UPRIGHT, o atributo left ser incrementado. Da DOWNLEFT ou UPLEFT, o atributo left decrementado. Tambm seria possvel modicar os atributos right e bottom ao invs de top e left, pois Pygame ir atualizar o objeto Rect de qualquer forma.
Vericando se o bloco foi rebatido

Se a direo do bloco

11.3.5

O bloco

if da linha 60 verica se o bloco passou dos limites da janela.

Alm disso, dependendo

da direo e da parede que o bloco colidir, uma nova direo estabelecida de forma que d a impresso de o bloco ter sido rebatido pela parede em que colidiu.

94

11.

INTRODUO GRFICOS E ANIMAO (PARTE 2)

11.3.6

Mudando a direo do bloco rebatido

Observar a gura 20 facilita a viso da trajetria que os blocos devem seguir ao colidir com cada parede. Desta forma, a sequncia de blocos eles chegam at ela.

if

aninhados em cada bloco aps a linha 60 estabelece

as novas direes de cada bloco, dependendo da parede em que ocorrer a coliso e da direo em que

11.3.7

Desenhando os blocos em suas novas posies


Lembre-se

Depois de ter suas direes atualizadas, necessrio desenhar o bloco na tela. que o bloco desenhado, primeiramente, em um objeto o usurio. superfcie). Finalmente, um intervalo de

Surface

para depois aparecer na tela para

Esta sequncia de passos ocorre nas linhas 86 (m do loop

for)

e 89 (que atualiza a

0.02

segundos dado para que a execuo no ocorra muito

rapidamente e seja invivel de observar o movimento dos blocos na tela. Tente comentar esta linha e ver como ocorre o movimento dos blocos.

11.4
1.

Exerccios complementares

(Vale 10% da nota e pode ser entregue em at duas semanas, a partir desta aula)
Modique o programa da animao dos blocos de acordo com os seguintes itens:

Adicionar mais formas geomtricas (pelo menos uma) Formas geomtricas em, pelo menos, 3 formas primitivas distintas Velocidades distintas para cada forma Condio de aparecer um texto caso uma situao especca ocorra (a sua escolha) Condio de mudana de cor caso a forma colida com determinada parede (por exemplo, se a forma A colidir com a parede esquerda, ela deve se tornar azul), podendo ser apenas com uma parede especca, mas todas as formas devem sofrer esta alterao

(Associado com a condio anterior) Mudar a cor de fundo se a cor de uma, ou mais, formas tambm mudar (pode ser com uma forma especca  por exemplo, apenas se o tringulo bater em uma parede e ele mudar de cor, ento a cor de fundo tambm mudar  ou mais de uma forma, seno todas), a sua escolha

ADICIONAL (vale 5% a mais na nota e o aluno deve sinalizar que este item foi

feito, na entrega do exerccio):

as formas colidem umas com as outras e ambas tomam

direes diferentes

12 Deteco de colises
Tpicos abordados neste captulo:

Deteco de coliso Entrada por teclado Entrada por mouse Um comportamento muito comum em jogos com recursos grcos a deteco de coliso, ou seja, quando dois objetos na tela se tocam. Este procedimento muito comum no decorrer dos jogos. Por exemplo, se um jogador toca um inimigo, ele pode perder uma vida no jogo. Detectar coliso pode ajudar a determinar se o personagem est no cho ou se no h nada abaixo dele. O prximo programa cobre este fenmeno. Posteriormente, sero detectadas as entradas do usurio atravs do teclado e mouse, que mais complicado do que o uso da funo

input().

12.1

Cdigo fonte: coliso


Muito deste cdigo similar ao programa introdutrio de animao, logo, o que diz respeito Para

aos fenmenos relacionados coliso nas paredes da janela, no ser abordado novamente. iniciar, o programa ser baseado no princpio do jogo

pacman. Uma lista de objetos

pygame.Rect

representar as comidas desenhadas na tela. A cada iterao dentro do loop principal, o programa ler cada objeto nesta lista e desenhar um retngulo verde na janela. A cada quarenta iteraes do loop do jogo, o programa desenhar um novo quadrado verde na janela, assim, a janela sempre ter comidas. Quem comer os quadrados verdes (uma representao do pacman) ser um quadrado branco, representado por um tipo

dictionary,

similar aos retngulos declarados no programa que tratava

sobre animaes, possuindo suas caractersticas e uma direo a ser seguida. Assim que o quadrado percorre a janela, verica-se se ele colidiu com quaisquer dos quadrados que representam as comidas. Se isto ocorrer, o quadrado da comida deletado. O cdigo que executa este procedimento est no cdigo 10.
Cdigo 10: Deteco de colises.

import pygame, sys, random from pygame.locals import * def doRectsOverlap(rect1, rect2): for a, b in [(rect1, rect2), (rect2, rect1)]: # Check if as corners are inside b if ((isPointInsideRect(a.left, a.top, b)) or (isPointInsideRect(a.left, a.bottom, b)) or (isPointInsideRect(a.right, a.top, b)) or (isPointInsideRect(a.right, a.bottom, b))): return True return False def isPointInsideRect(x, y, rect): if (x > rect.left) and (x < rect.right) and (y > rect.top) and (y < rect. bottom): return True else: return False

# set up pygame
95

96

12.

DETECO DE COLISES

pygame.init() mainClock = pygame.time.Clock() # set up the window WINDOWWIDTH = 400 WINDOWHEIGHT = 400 windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32) pygame.display.set_caption(Collision Detection) # set up direction variables DOWNLEFT = 1 DOWNRIGHT = 3 UPLEFT = 7 UPRIGHT = 9 MOVESPEED = 4 # set BLACK GREEN WHITE up the colors = (0, 0, 0) = (0, 255, 0) = (255, 255, 255)

# set up the bouncer and food data structures foodCounter = 0 NEWFOOD = 40 FOODSIZE = 20 bouncer = {rect:pygame.Rect(300, 100, 50, 50), dir:UPLEFT} foods = [] for i in range(20): foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - FOODSIZE), random.randint(0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE)) # run the game loop while True: # check for the QUIT event for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() foodCounter += 1 if foodCounter >= NEWFOOD: # add new food foodCounter = 0 foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - FOODSIZE), random.randint(0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE)) # draw the black background onto the surface windowSurface.fill(BLACK) # move the bouncer data structure if bouncer[dir] == DOWNLEFT: bouncer[rect].left -= MOVESPEED bouncer[rect].top += MOVESPEED if bouncer[dir] == DOWNRIGHT: bouncer[rect].left += MOVESPEED bouncer[rect].top += MOVESPEED if bouncer[dir] == UPLEFT: bouncer[rect].left -= MOVESPEED bouncer[rect].top -= MOVESPEED if bouncer[dir] == UPRIGHT: bouncer[rect].left += MOVESPEED

12.2.

COMO O PROGRAMA FUNCIONA

97

bouncer[rect].top -= MOVESPEED # check if the bouncer has move out of the window if bouncer[rect].top < 0: # bouncer has moved past the top if bouncer[dir] == UPLEFT: bouncer[dir] = DOWNLEFT if bouncer[dir] == UPRIGHT: bouncer[dir] = DOWNRIGHT if bouncer[rect].bottom > WINDOWHEIGHT: # bouncer has moved past the bottom if bouncer[dir] == DOWNLEFT: bouncer[dir] = UPLEFT if bouncer[dir] == DOWNRIGHT: bouncer[dir] = UPRIGHT if bouncer[rect].left < 0: # bouncer has moved past the left side if bouncer[dir] == DOWNLEFT: bouncer[dir] = DOWNRIGHT if bouncer[dir] == UPLEFT: bouncer[dir] = UPRIGHT if bouncer[rect].right > WINDOWWIDTH: # bouncer has moved past the right side if bouncer[dir] == DOWNRIGHT: bouncer[dir] = DOWNLEFT if bouncer[dir] == UPRIGHT: bouncer[dir] = UPLEFT # draw the bouncer onto the surface pygame.draw.rect(windowSurface, WHITE, bouncer[rect]) # check if the bouncer has intersected with any food squares. for food in foods[:]: if doRectsOverlap(bouncer[rect], food): foods.remove(food) # draw the food for i in range(len(foods)): pygame.draw.rect(windowSurface, GREEN, foods[i]) # draw the window onto the screen pygame.display.update() mainClock.tick(40)
A execuo do cdigo 10 gerar uma janela parecida com a gura 21.

12.2
o mdulo

Como o programa funciona


Este programa importa os mesmos mdulos do programa de introduo animao, incluindo

random.
A funo de deteco de coliso

12.2.1

Na linha 4, inicia-se uma funo que determina se dois retngulos se interceptam, a A esta funo so passados dois objetos se isto no ocorrer.

Rect

e ela retornar

True

se eles se interceptarem e

doRectsOverlap(). False,

H uma regra muito simples que determina se dois retngulos colidem: baseando-se nos quatro cantos de ambos, se um destes cantos estiver um dentro do outro retngulo, ento eles colidiram. A partir desta anlise, a resposta da funo ser

True

ou

False.

Esta vercao realizada no bloco

if

iniciado na linha 7.

98

12.

DETECO DE COLISES

Figura 21: Resultado da execuo do cdigo 10.

12.2.2

Determinando se um ponto est dentro de um retngulo

Esta funo retornar

isPointInsideRect() utilizada pela funo citada anteriormente, doRectOverlap(). True se as coordenadas XY passadas pelos primeiro e segundo parmetros esto dentro do objeto pygame.Rect passado como terceiro parmetro, ou False, caso contrrio. Esta vericao feita atravs do bloco if da funo isPointInsideRect(). Se todas as condies forem verdadeiras, ento o retorno ser True, pois so condies interligadas com and. Se
qualquer uma das condies for falsa, a sentena inteira tambm ser. Estas funes associadas (doRectsOverlap() e

A funo

isPointInsideRect())

detectam a coli-

so entre dois retngulos e so utilizadas para quaisquer dois retngulos.

12.2.3

O objeto

pygame.time.Clock

e o mtodo

tick()
pygame.time.Clock.

A maior parte do cdigo entre as linhas 22 e 43 j foi visto no cdigo sobre animao, da aula anterior. Entretanto, h um novo recurso na linha 24, a criao de um objeto Anteriormente, havia sido utilizada a funo

time.sleep(),

para diminuir a velocidade da

execuo e de forma que fosse possvel que o usurio visualize o movimento das formas. Entretanto, o problema com esta funo que ela pode rodar muito rpido ou muito devagar, dependendo do desempenho do computador. Para limitar o nmero mximo de iteraes por segundo, utiliza-se o objeto A linha 125 chama

mainClock.tick(40)

dentro do loop do jogo. O mtodo

pygame.time.Clock. tick() verica se o

nmero de iteraes por segundo foi o desejado (no caso, 40) durante o ltimo segundo. Se o nmero de iteraes for maior, ento colocado um pequeno intervalo entre as iteraes, baseado no nmero de vezes que o mtodo do que o desejado.

tick()

foi chamado. Isto assegura que o programa nunca rode mais rpido

12.2.4

Colidindo com os quadrados verdes

A linha 115 inicia o bloco que verica se o quadrado branco colidiu com qualquer outro quadrado verde na tela. No caso de ter ocorrido coliso, o devido quadrado ser eliminado da lista forma, o computador no desenhar os quadrados verdes que tenham sido "comidos".

foods.

Desta

12.3.

CDIGO-FONTE: ENTRADA DO USURIO

99

12.2.5

No adicione ou remova itens de uma lista enquanto houver iteraes sobre ela
ela feita sobre zttfoods[:]. Basicamente,

Observe que h algo um pouco diferente no loop da linha 115. Ao invs de fazer iteraes sobre

foods,
itens de

foods[:]

cria uma nova lista com uma cpia dos

foods.

Esta uma forma resumida de fazer uma cpia de uma lista.

Mas qual o motivo de no fazer iteraes na lista original? Esta medida tomada pois no possvel adicionar ou remover itens de uma lista enquanto h iteraes sobre ela (ou seja, quando ela faz parte da declarao de um loop).

12.2.6

Removendo os quadrados verdes

A linha 116 onde a funo ento o retorno ser

doRectsOverlap()

utilizada. Dois parmetros so passados

para a funo, o quadrado branco e o quadrado verde mais prximo. Se estes dois retngulos colidirem,

True

e o quadrado verde ser removido da lista.

12.2.7
vetor

Desenhando os quadrados verdes na tela


percorrido e ento um quadrado verde desenhado na

As linhas 120 e 121 so bem similares em relao a como se desenham os retngulos na tela. O

foods

windowSurface.

Os ltimos programas so interessantes para v-los funcionando, entretanto, no h nenhuma interao com o usurio. obtidos atravs do teclado. Para introduzir estes conceitos, o prximo programa tratar de eventos

12.3

Cdigo-fonte: entrada do usurio


A execuo deste programa similar ao anterior, com a diferena que o retngulo maior se

movimenta a partir das setas que so recebidas como entrada do usurio. Uma alternativa para os movimentos so as letras

W, A, S, D.
Cdigo 11: Deteco de entrada do usurio.

import pygame, sys, random from pygame.locals import * # set up pygame pygame.init() mainClock = pygame.time.Clock() # set up the window WINDOWWIDTH = 400 WINDOWHEIGHT = 400 windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32) pygame.display.set_caption(Input) # set BLACK GREEN WHITE up the colors = (0, 0, 0) = (0, 255, 0) = (255, 255, 255)

# set up the player and food data structure foodCounter = 0 NEWFOOD = 40 FOODSIZE = 20 player = pygame.Rect(300, 100, 50, 50) foods = [] for i in range(20): foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - FOODSIZE), random.randint(0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE))

100

12.

DETECO DE COLISES

# set up movement variables moveLeft = False moveRight = False moveUp = False moveDown = False MOVESPEED = 6

# run the game loop while True: # check for events for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() if event.type == KEYDOWN: # change the keyboard variables if event.key == K_LEFT or event.key == ord(a): moveRight = False moveLeft = True if event.key == K_RIGHT or event.key == ord(d): moveLeft = False moveRight = True if event.key == K_UP or event.key == ord(w): moveDown = False moveUp = True if event.key == K_DOWN or event.key == ord(s): moveUp = False moveDown = True if event.type == KEYUP: if event.key == K_ESCAPE: pygame.quit() sys.exit() if event.key == K_LEFT or event.key == ord(a): moveLeft = False if event.key == K_RIGHT or event.key == ord(d): moveRight = False if event.key == K_UP or event.key == ord(w): moveUp = False if event.key == K_DOWN or event.key == ord(s): moveDown = False if event.key == ord(x): player.top = random.randint(0, WINDOWHEIGHT - player.height) player.left = random.randint(0, WINDOWWIDTH - player.width) if event.type == MOUSEBUTTONUP: foods.append(pygame.Rect(event.pos[0], event.pos[1], FOODSIZE, FOODSIZE)) foodCounter += 1 if foodCounter >= NEWFOOD: # add new food foodCounter = 0 foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - FOODSIZE), random.randint(0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE)) # draw the black background onto the surface windowSurface.fill(BLACK) # move the player if moveDown and player.bottom < WINDOWHEIGHT:

12.3.

CDIGO-FONTE: ENTRADA DO USURIO

101

player.top += MOVESPEED if moveUp and player.top > 0: player.top -= MOVESPEED if moveLeft and player.left > 0: player.left -= MOVESPEED if moveRight and player.right < WINDOWWIDTH: player.right += MOVESPEED # draw the player onto the surface pygame.draw.rect(windowSurface, WHITE, player) # check if the player has intersected with any food squares. for food in foods[:]: if player.colliderect(food): foods.remove(food) # draw the food for i in range(len(foods)): pygame.draw.rect(windowSurface, GREEN, foods[i]) # draw the window onto the screen pygame.display.update() mainClock.tick(40)

12.3.1

Iniciando os movimentos
Quatro

Entre as linhas 29 e 33, so denidos os movimentos iniciais do quadrado branco. para a direita. dada como Os movimentos (direes) iniciais so denidos como

variveis diferentes so utilizadas para indicar as direes para cima, para baixo, para a esquerda e

False

de forma que, a cada

momento que uma das teclas indicadas fora acionada, a varivel que for relacionada a tal direo ser

True.

As linhas 34 a 43 so idnticas aos cdigos anteriores.

Tarefa 12.1
Pesquise detalhes sobre os eventos de mouse e teclado no Pygame (QUIT, KEYDOWN, KEYUP, MOUSEMOTION, MOUSEBUTTONDOWN e MOUSEBUTTONUP, principalmente) e causas que podem ger-los. Este tpico pode ser til para o trabalho nal.

12.3.2

Lidando com as variveis do teclado

Os blocos

if

iniciados na linha 44 at a linha 57 atribuem os movimentos s variveis deni-

das no incio do programa. Primeiro, vericado se alguma tecla pressionada, atravs do evento

KEYDOWN.
Adicionalmente, o bloco

if

da linha 58 verica se alguma tecla deixou de ser pressionada.

Em caso armativo, ainda vericado se a prxima tecla a ser pressionada a tecla teclado

Esc,

alm dos

movimentos comuns. Isto quer dizer que o usurio quer fechar o programa atravs do comando do

23 .

12.3.3

O evento

MOUSEBUTTONUP

Eventos gerados pelo mouse so tratados da mesma forma que eventos de teclado. O evento

MOUSEBUTTONUP ocorre quando o usurio clica sobre a janela do programa. O atributo pos no objeto Event uma tupla de dois inteiros que carregam as coordenadas XY do clique. Na linha 75, observase que a coordenada X armazenada em event.pos[0] e, a coordenada Y, em event.pos[1]. Uma novo objeto Rect criado para representar um novo quadrado verde onde o evento ocorreu. Adicionando um novo objeto Rect lista foods, um novo quadrado verde aparecer na tela.
23 Descubra
o que acontece quando a tecla 'x' pressionada e como isto acontece

102

12.

DETECO DE COLISES

12.3.4

Movendo o jogador pela tela

A sequncia de blocos

ou no. O quadrado do jogador ser movimentado a partir do quadrado armazenado em ajustando as coordenadas XY desta varivel.

if entre as linhas 87 e 94 denem se o jogador est pressionando as setas player,

12.3.5
(colide).

O mtodo

colliderect()

No cdigo 10, zemos nossa prpria funo para vericar se um retngulo intercepta outro Esta funo foi includa nesta aula para que voc saiba como funciona o procedimento Neste programa, ser utilizada a funo que j para objetos O mtodo de analisar a coliso entre doia objetos na tela. detecta coliso, do Pygame. na linha 100. Ele retorna

colliderect()

segundo retngulo como parmetro e verica se eles colidem, utilizado no loop

pygame.Rect recebe um for que se inicia

True

se existe coliso. o mesmo procedimento que foi feito na funo

doRectOverlap()

com o auxlio da funo

isPointInsideRect(),

do cdigo 10.

O restante do cdigo similar ao cdigo 10.

12.4

Exerccios complementares

1. Altere o cdigo 11 de acordo com as seguintes situaes:

Cada quadrado verde capturado soma um ponto e esta pontuao mostrada para o usurio na janela do jogo Insira quadrados de diferentes cores (pode ser apenas mais uma cor), e a cor adicional possuir pontuao diferente dos quadrados verdes (por exemplo, quadrado verde vale um ponto e quadrados vermelhos valem 2 pontos) e tempo para aparecer na tela diferente dos quadrados verdes.

Insira um quadrado de uma cor diferente das utilizadas, que se move aleatoriamente (voc dene este aleatrio, que pode no ser to aleatrio assim) e, se o jogador colidir com este quadrado, ele perde pontos.

13 Dodger
Tpicos abordados neste captulo:

A ag

pygame.FULLSCREEN move_ip() para objetos Rect pygame.mouse.set_pos()


Dodger

Constantes do Pygame para o teclado O mtodo A funo

Implementao de cheat codes em seus jogos Modicar o jogo

Neste captulo, muitos dos conceitos apresentados anteriormente sero aplicados para desenvolver um jogo mais sosticado, utilizando grande parte dos recursos aprendidos nos captulos que abordaram interface grca. Este jogo possui como jogador um pequeno homem que deve se esquivar do monte de blocos que caem do topo da tela. Quanto maior o tempo que o jogador se mantm desviando dos blocos, maior a sua pontuao. Alguns cheats tambm foram colocados no jogo. Experimente pressionar as teclas

ou

z.

13.1

Reviso dos tipos bsicos de dados do Pygame


A seguir, h um resumo de alguns tipos bsicos de recursos do Pygame vistos at agora.

pygame.Rect: Rect
e (como

objetos do tipo

Rect

representam um espao retangular com localizao e e

tamanho. A localizao deste tipo de objeto pode ser obtida atravs dos atributos dos objetos

topleft, topright, bottomleft


Objetos

bottomright).

Estes atributos so uma

tupla de inteiros com coordenadas XY. O tamanho pode ser determinado pelos atributos

height, que retornam valores em pixels.


objetos

width Rect possuem o mtodo colliderect(),

que vericam se h interseco entre dois destes objetos.

pygame.Surface:

Surface

so reas de pixels coloridos. Estes objetos representam

Rect representa apenas um espao e localizao Surface possuem o mtodo blit() que utilizado para desenhar uma imagem de um objeto Surface em outro objeto Surface. Lembre-se que os objetos Surface possuem coisas desenhadas que no so possveis de ver
de um retngulo. Objetos enquanto esto apenas armazenadas na memria do computador. necessrio mandar que o computador as mostre para o usurio, atravs do mtodo

uma imagem retangular, enquanto um objeto

pygame.event.Event:

os tipos de dados

Event,

cada vez que h uma interao do usurio com o retorna uma lista de objetos

blit(). pygame.Event, gera eventos a programa. A funo pygame.event.get()


do mdulo

pygame.font.Font:
texto formatado no

Event. pygame.font possui o tipo de dado Font que representa um Pygame. Cria-se um objeto Font chamando o construtor pygame.font.
o mdulo

SysFont().

Os argumentos passados so uma string e um inteiro, com o nome da fonte e o

tamanho, respectivamente. comum passar o valor fonte padro do sistema.

None

para o nome da fonte, para utilizar a

pygame.time.Clock:

o objeto

Clock, do mdulo pygame.time, til para manter os jogos Clock

rodando o mais rpido possvel. Entretanto, isto pode no ser um recurso muito desejvel, visto que h o risco de o jogador no conseguir acompanhar o jogo adequadamente. Os objetos possuem o mtodo

tick(),

que controla quantos frames por segundo (fps) o programador quer

que o jogo execute. Quanto maior o fps, maior a velocidade do jogo. Utilizou-se 40 fps nos jogos anteriores. Observe que o mdulo a funo

pygame.time

diferente daquele mdulo

time

que contm

sleep().
103

104

13.

DODGER

13.2

Cdigo-fonte
Novamente, baixe os recursos de imagem e som para este programa no site

http://inventwithpython.

com/resources.
Cdigo 12: Jogo Dodger.

import pygame, random, sys from pygame.locals import * WINDOWWIDTH = 600 WINDOWHEIGHT = 600 TEXTCOLOR = (255, 255, 255) BACKGROUNDCOLOR = (0, 0, 0) FPS = 40 BADDIEMINSIZE = 10 BADDIEMAXSIZE = 40 BADDIEMINSPEED = 1 BADDIEMAXSPEED = 8 ADDNEWBADDIERATE = 6 PLAYERMOVERATE = 5 def terminate(): pygame.quit() sys.exit() def waitForPlayerToPressKey(): while True: for event in pygame.event.get(): if event.type == QUIT: terminate() if event.type == KEYDOWN: if event.key == K_ESCAPE: # pressing escape quits terminate() return def playerHasHitBaddie(playerRect, baddies): for b in baddies: if playerRect.colliderect(b[rect]): return True return False def drawText(text, font, surface, x, y): textobj = font.render(text, 1, TEXTCOLOR) textrect = textobj.get_rect() textrect.topleft = (x, y) surface.blit(textobj, textrect) # set up pygame, the window, and the mouse cursor pygame.init() mainClock = pygame.time.Clock() windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT)) pygame.display.set_caption(Dodger) pygame.mouse.set_visible(False) # set up fonts font = pygame.font.SysFont(None, 48) # set up sounds gameOverSound = pygame.mixer.Sound(gameover.wav) pygame.mixer.music.load(background.mid) # set up images

13.2.

CDIGO-FONTE

105

playerImage = pygame.image.load(player.png) playerRect = playerImage.get_rect() baddieImage = pygame.image.load(baddie.png) # show the "Start" screen drawText(Dodger, font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3) ) drawText(Press a key to start., font, windowSurface, (WINDOWWIDTH / 3) 30, (WINDOWHEIGHT / 3) + 50) pygame.display.update() waitForPlayerToPressKey()

topScore = 0 while True: # set up the start of the game baddies = [] score = 0 playerRect.topleft = (WINDOWWIDTH / 2, WINDOWHEIGHT - 50) moveLeft = moveRight = moveUp = moveDown = False reverseCheat = slowCheat = False baddieAddCounter = 0 pygame.mixer.music.play(-1, 0.0) while True: # the game loop runs while the game part is playing score += 1 # increase score for event in pygame.event.get(): if event.type == QUIT: terminate() if event.type == KEYDOWN: if event.key == ord(z): reverseCheat = True if event.key == ord(x): slowCheat = True if event.key == K_LEFT or event.key == ord(a): moveRight = False moveLeft = True if event.key == K_RIGHT or event.key == ord(d): moveLeft = False moveRight = True if event.key == K_UP or event.key == ord(w): moveDown = False moveUp = True if event.key == K_DOWN or event.key == ord(s): moveUp = False moveDown = True if event.type == KEYUP: if event.key == ord(z): reverseCheat = False score = 0 if event.key == ord(x): slowCheat = False score = 0 if event.key == K_ESCAPE: terminate() if event.key == K_LEFT or event.key == ord(a): moveLeft = False if event.key == K_RIGHT or event.key == ord(d):

106

13.

DODGER

moveRight = False if event.key == K_UP or event.key == ord(w): moveUp = False if event.key == K_DOWN or event.key == ord(s): moveDown = False if event.type == MOUSEMOTION: # If the mouse moves, move the player where the cursor is. playerRect.move_ip(event.pos[0] - playerRect.centerx, event. pos[1] - playerRect.centery) # Add new baddies at the top of the screen, if needed. if not reverseCheat and not slowCheat: baddieAddCounter += 1 if baddieAddCounter == ADDNEWBADDIERATE: baddieAddCounter = 0 baddieSize = random.randint(BADDIEMINSIZE, BADDIEMAXSIZE) newBaddie = {rect: pygame.Rect(random.randint(0, WINDOWWIDTHbaddieSize), 0 - baddieSize, baddieSize, baddieSize), speed: random.randint(BADDIEMINSPEED, BADDIEMAXSPEED), surface:pygame.transform.scale(baddieImage, ( baddieSize, baddieSize)), } baddies.append(newBaddie) # Move the player around. if moveLeft and playerRect.left > 0: playerRect.move_ip(-1 * PLAYERMOVERATE, 0) if moveRight and playerRect.right < WINDOWWIDTH: playerRect.move_ip(PLAYERMOVERATE, 0) if moveUp and playerRect.top > 0: playerRect.move_ip(0, -1 * PLAYERMOVERATE) if moveDown and playerRect.bottom < WINDOWHEIGHT: playerRect.move_ip(0, PLAYERMOVERATE) # Move the mouse cursor to match the player. pygame.mouse.set_pos(playerRect.centerx, playerRect.centery) # Move the baddies down. for b in baddies: if not reverseCheat and not slowCheat: b[rect].move_ip(0, b[speed]) elif reverseCheat: b[rect].move_ip(0, -5) elif slowCheat: b[rect].move_ip(0, 1) # Delete baddies that have fallen past the bottom. for b in baddies[:]: if b[rect].top > WINDOWHEIGHT: baddies.remove(b) # Draw the game world on the window. windowSurface.fill(BACKGROUNDCOLOR) # Draw the score and top score. drawText(Score: %s % (score), font, windowSurface, 10, 0) drawText(Top Score: %s % (topScore), font, windowSurface, 10, 40) # Draw the players rectangle

13.2.

CDIGO-FONTE

107

windowSurface.blit(playerImage, playerRect) # Draw each baddie for b in baddies: windowSurface.blit(b[surface], b[rect]) pygame.display.update() # Check if any of the baddies have hit the player. if playerHasHitBaddie(playerRect, baddies): if score > topScore: topScore = score # set new top score break mainClock.tick(FPS) # Stop the game and show the "Game Over" screen. pygame.mixer.music.stop() gameOverSound.play() drawText(GAME OVER, font, windowSurface, (WINDOWWIDTH / 3), ( WINDOWHEIGHT / 3)) drawText(Press a key to play again., font, windowSurface, (WINDOWWIDTH / 3) - 80, (WINDOWHEIGHT / 3) + 50) pygame.display.update() waitForPlayerToPressKey() gameOverSound.stop()

A execuo deste programa parecida com a gura 22.

Figura 22: Execuo do programa Dodger.

108

13.

DODGER

13.3

Como o programa funciona e recursos adicionais


Este programa aborda praticamente todos os conceitos j estudados, com alguns recursos adi-

cionais. Observe como algumas tcnicas so utilizadas a m de facilitar a prtica da programao e, consequentemente, diminuir a taxa de erros que podem ocorrer em um programa.

13.3.1

Importando os mdulos

Este jogo importa todos os mdulos que os jogos anteriores com o Pygame utilizavam:

pygame,

random, sys import *,


13.3.2

pygame.locals.

O mdulo

pygame.locals
ao invs de

possui vrias constantes que o Py-

game utiliza como tipos de evento e tipos de teclas. Utilizando a sentena podemos utilizar a constante

QUIT

from pygame.locals pygame.locals.QUIT.

Explorando o uso de constantes

H vrias constantes neste jogo. Utilizam-se constantes em um programa para facilitar o manuseio de muitas variveis. Estas ainda, que podem ter o mesmo valor, podem ser alteradas a desejo do programador e no desejvel percorrer todo o programa para procurar tais valores. Desta forma, utilizam-se constantes (ou variveis) declaradas, geralmente, no incio do programa ou de um bloco, e, ao invs de escrever sempre um mesmo valor, escreve-se a constante que o carrega. Assim, ao alterar uma constante, em todos os locais que ela for citada, no programa, recebero o novo valor. Observe as linhas 4 a 14 do cdigo 12.

13.3.3

Explorando o uso de funes

Funes, assim como as variveis, auxiliam o programador a no precisar digitar um mesmo trecho de cdigo mais de uma vez, evitando erros de sintaxe e/ou lgica no programa. Observe as funes

terminate(), waitForPlayerToPressKey(), playerHasHitBaddie() e drawText().

As funes que o programador criar em seu programa devem ter nomes que sugerem o que ser executado em cada trecho de cdigo, a m de aumentar a legibilidade do cdigo. Todas as funes deste programa abordam tpicos que j foram vistos anteriormente.

13.3.4

Cursor do mouse

Neste programa, possvel controlar a personagem do jogador com o mouse. A seta do mouse no mostrada. Entretanto, se for desejado que a seta aparea, basta mudar a linha 47 para

pygame.display.set_visible(True)

13.3.5

Modo fullscreen

A funo

pygame.display.set_mode()

possui um segundo parmetro, opcional. Altere a

linha 45 do programa, da seguinte forma:

pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), pygame.FULLSCREEN)

13.3.6

Mostrando a tela inicial

O cdigo entre as linhas 62 e 65 chama as funes necessrias para mostrar a tela inicial, que aguarda o usurio pressionar alguma tela, para, ento, iniciar o jogo. Observe que, nas linhas 62 e 63, chamou-se a funo coordenadas XY do objeto A funo loop do jogo. A tabela 10 mostra alguns dos principais eventos de teclado que podem ser teis para os seus jogos. a string para a aparecer na tela, o tipo de fonte, o objeto

drawtext(), passando cinco argumentos: Surface para projetar o texto, e as

Surface para que o texto seja desenhado. waitForPlayerToPressKey() vericar os eventos de presso de tecla (KEYDOWN)

no programa. Dependendo da interao do jogador, a execuo ou termina o jogo ou prossegue no

13.3.

COMO O PROGRAMA FUNCIONA E RECURSOS ADICIONAIS

109

Tabela 10: Constantes de evento para as teclas pressionadas.

Constante do Pygame
K_LEFT K_RIGHT K_UP K_DOWN K_ESCAPE K_BACKSPACE K_TAB K_RETURN K_SPACE K_DELETE K_LSHIFT K_RSHIFT K_LCTRL K_RCTRL K_LALT K_RALT

Tecla
Seta esquerda Seta direita Seta para cima Seta para baixo Esc Backspace Tab Return ou Enter Barra de espao Del Shift da esquerda Shift da direita Ctrl da esquerda Ctrl da direita Alt da esquerda Alt da direita

Constante do Pygame
K_HOME K_END K_PAGEUP K_PAGEDOWN K_F1 K_F2 K_F3 K_F4 K_F5 K_F6 K_F7 K_F8 K_F9 K_F10 K_F11 K_F12

Tecla
Home End Page Up Page Down F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12

13.3.7

O mtodo mouse

move_ip()

para objetos

Rect

e evento de movimento do
Mas, e se o personagem tambm

Os eventos de teclado j foram abordados anteriormente. No jogo

puder ser controlado pelo mouse? Isto feito no bloco entre as linhas 123 e 125.

Dodger, no h efeitos se o mouse for clicado, mas ele responde aos movimentos do

mouse. Isto d ao jogador outra forma de controle no jogo, alm do teclado. O evento que controla este movimento do tipo a cada vez que o mouse movido. chamado na tela. O mtodo Objetos

Event

do tipo

MOUSEMOTION. Um MOUSEMOTION

evento deste gerado possuem um atributo

pos.

Este atributo armazena uma tupla de coordenadas XY da posio do cursor do mouse

move_ip(),

para objetos

Rect,

mover a localizao de um objeto Por exemplo,

talmente ou verticalmente, por um nmero de pixels.

Rect horizonplayerRect.move_ip(10,

20)

mover o objeto 10 pixels para a direita e 20 pixels abaixo. Por exemplo,

Para mover o objeto para cima

ou para baixo, basta passar valores negativos. mover o objeto O local.

playerRect.move_ip(-5, -15)

Rect

5 pixels para a esquerda e 15 pixels acima.

ip, deste mtodo, se refere in place. Isto devido ao mtodo mudar o prprio objeto de

Existe, ainda, o mtodo

move(),

que no muda um objeto

Rect,

mas cria outro com uma

nova posio. Este mtodo til quando se deseja preservar a localizao de um objeto um novo objeto em um novo local.

Rect

e obter

13.3.8

Movendo a personagem do jogador

Os blocos entre as linhas 141 e 148 vericam os movimentos do jogador e determinam as margens em que ele pode se mover (limites da janela). O mtodo personagem do jogador.

move_ip()

utilizado para movimentar a

13.3.9
A funo mento.

A funo

pygame.mouse.set_pos()
move o mouse s coordenadas XY lhe passadas como argue

A linha 151 move o cursor do mouse de acordo com a posio da personagem do jogador.

pygame.mouse.set_pos()

Especicamente, o cursor estar no meio da imagem da personagem do jogador se forem

passadas as posies

playerRect.centerx

playerRect.centery.

O cursos existe e pode ser

110

13.

DODGER

movido mesmo que a congurao previamente.

pygame.mouse.set_visible(False)

tenha sido estabelecida

O motivo de fazer o cursor do mouse acompanhar a localizao do jogador evitar pulos. Imagine que o jogador inicie o jogo com o controle do teclado e, no meio do jogo, decida mudar para o mouse. Dependendo de onde o ponteiro do mouse estiver, a personagem do jogador poder sofrer um salto para esta posio (pois, provavelmente, a posio do cursor no ser a mesma que o jogador parou).

13.3.10

Desenhando o placar do jogo


Observe que esta funo j foi utilizada algumas vezes e como seria inconveniente

As linhas 171 e 172 mandam as informaes, para serem mostradas no placar, funo

drawText().

digitar sempre os mesmos comandos para mostrar um texto na tela. Novamente, observa-se a facilidade que as funes trazem a um programa.

13.4

Finalizando o projeto
Voc j est apto a entender o restante das linhas de cdigo do programa que no foram citadas

nesta aula, visto que muitas delas se baseiam em conceitos j apresentados anteriormente. Exercite a sua lgica e faa o

teste de mesa deste programa para realmente entend-lo.

Voc perceber que

esta prtica ir ajudar-lhe a aprimorar seu entendimento das prticas e da lgica de programao. Aguardamos pela apresentao do seu projeto nal, com as habilidades aprendidas ao longo das aulas e at com recursos no apresentados durante o percurso. A seguir, alguns links que podem contribuir para o seu conhecimento acerca do assunto:

http://gamedevlessons.com http://www.hobbygamedev.com/ http://www.pygame.org/ http://pyopengl.sf.net


O grupo PET-CoCE espera que voc tenha feito bom proveito desta ocina!

A Fluxogramas
Conforme citado no 6, um uxograma uma maneira de representar um algoritmo grca. Cada caixa representa um passo, e cada seta, a sequncia do algoritmo. desenvolvimento que pensamos nas estratgias pra resolver o problema proposto.

24 em forma

nesta fase do

A.1

Criando um Fluxograma
Tenha em mente que seus uxogramas nem sempre devem estar exatamente como este. Voc

apenas deve compreender que o uxograma que voc fez ser til enquanto estiver programando. Veja o seguinte exemplo da criao do uxograma do jogo da forca implementado no 6:

1. Em todo uxograma devemos representar as caixas de incio e m, como segue o exemplo na gura 23.

Figura 23: Comeando seu uxograma com as caixas incio e m.

2. Agora vamos pensar na estratgia algortmica para resolver o problema (no caso programar o jogo da forca). Primeiro, um jogador pensa numa palavra secreta, desenha a forca e desenha os espaos correspondentes a cada letra (neste caso ser o computador). Ento o segundo jogador (o usurio do jogo) tentar adivinhar as letras. Tambm devemos adicionar as caixas com as aes para estes eventos. O uxograma ca igual gura 24.

24 Um

algoritmo uma sequncia de passos para a realizao de uma tarefa. Por exemplo, uma receita de bolo um

algoritmo, pois explica como fazer o bolo passo-a-passo.

111

112

APNDICE A.

FLUXOGRAMAS

Figura 24: Desenhando os trs primeiros passos do Fluxograma.

3. Mas o jogo no acaba aps o jogador tentar adivinhar a letra. est na palavra secreta ou no.

preciso vericar se a letra

Assim, precisamos adicionar duas novas caixas para o nosso

uxograma. Isto vai criar uma ramicao, como mostrado na gura 25.

Figura 25: Ramicando o uxograma.

4. Os processos de desenhar a forca e os espaos correspondentes a cada letra, pedir para que o jogador adivinhe a prxima letra e checar se a letra est ou no na palavra secreta devem ser repetidos vrias vezes durante o jogo. Para isso precisamos criar um lao de repetio, como podemos ver na gura 26.

A.1.

CRIANDO UM FLUXOGRAMA

113

Figura 26: Criando os laos no uxograma.

5. O jogador precisa ter o

feedback do que est acontecendo no jogo, para isso ser preciso imprimir

as letras acertadas e a situao da forca aps cada tentativa. Tambm preciso vericar se o palpite do jogador j foi dado anteriormente no jogo, para isso fazemos algumas alteraes na segunda intruo e incluiremos uma nova caixa no uxograma para representar essa nova tarefa. Veja isso na gura 27.

Figura 27: Alterando o segundo comando e adicionando a nova caixa.

6. Agora precisamos denir as codies de parada do jogo, caso contrrio ele permanerer em um lao innito. Aps cada palpite e resposta, antes de nalizar o jogo, precisamos vericar se todas as letras foram adivinhadas, ou se todas as partes do boneco esto na forca, caso alguma dessas condies sejam satisfeitas o jogo dever acabar com vitria ou derrota respectivamente. Ver gura 28

114

APNDICE A.

FLUXOGRAMAS

Figura 28: Incluindo as novas caixas.

7. Antes de nalizar, podemos tambm incluir a opo de iniciar um novo jogo.

Para isso de-

vemos incluir um novo lao iniciando na primeira instruo onde sorteada a palavra secreta e terminando antes do m do programa, concluindo assim o nosso uxograma mostrado na gura 29. Pode parecer muito trabalho elaborar um uxograma antes de escrever o cdigo. Mas muito mais fcil fazer mudanas e encontrar problemas pensando em como vai funcionar o programa antes de escrever o cdigo. Se pular esta parte e ir escrever o cdigo, voc pode descobrir problemas que exige que voc altere o cdigo j escrito. Toda vez que voc altera o seu cdigo, aumenta a chance de criar

bugs. melhor saber o que voc quer construir antes de construir.


Quanto mais complexo for o programa, maior e mais carregado ca o uxograma. Isso faz com

que programadores mais experientes usem outras ferramentas para planejar seus programas com um maior nvel de abstrao

25 .

25 Habilidade
tantes.

de concentrar nos aspectos essenciais de um contexto qualquer, ignorando caractersticas menos impor-

A.1.

CRIANDO UM FLUXOGRAMA

115

Figura 29: Fluxograma completo: Incluindo a nova caixa e o novo lao.

Referncias Bibliogrcas
1 MENDES, M. A. L.

Python Brasil - Lista de Exerccios. 2012. Disponvel em:

<http://www-

.python.org.br/wiki/ListaDeExerciciosl>. Acesso em: 13 ago. 2012. 2 SHAW, Z. A.

The Hard Way is Easier. 2012. Disponvel em:

<http://learnpythonthehardway<http:/-

.org/book/intro.html>. Acesso em: 15 jul. 2012. 3 SWEIGART, A.

Invent Your Own Games with Python. 2010. Disponvel em:

/inventwithpython.com/IYOCGwP book1.pdf>. Acesso em: 20 jul. 2012.

116