Python Dainf
Python Dainf
Python Dainf
ii
Copyright
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:
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
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
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()
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Saudando o jogador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
while
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
As tentativas do jogador
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sentenas
if
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii
iv
SUMRIO
Saindo de
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
. . . . . . . . . . . . . . . . . . . . . . . . . .
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()
. . . . . . . . . . . . . . . . . .
split()
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e
range()
list()
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
for
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sentenas
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Reviso das funes criadas para este jogo Cdigo principal do jogo
SUMRIO
. . . . . . . . . . . . . . . . . . . . . . . . .
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
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
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 se o tabuleiro est cheio . . . . . . . . . . . . . . . . . . . . . . . . . . . . O incio do jogo Rodando a vez do jogador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rodando a vez do computador Finalizando o jogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
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
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
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()
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
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
islower()
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exerccios complementares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
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
pygame.init()
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
pygame.display.set_mode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
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()
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
90
90 91 91 92 92 93 93 93 93 94 94 94
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 . . . . . . . . . . . . .
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
MOUSEBUTTONUP colliderect()
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
pygame.mouse.set_pos()
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
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. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
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. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
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
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Rect.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
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
1.1
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
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
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,
1 Mas
1.
1.1.4
No copie e cole
Esquea o
DIGITAR
(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
pginas
web que explicam cada etapa de instalao, em qualquer sistema operacional, e temos certeza
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.1.1
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
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
2 Observe
ponto.
que, em programao, a vrgula que utilizamos para denir nmeros fracionrios representada por um
2.
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
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
resultado. Mesmo valores nicos so considerados expresses: a expresso Entretanto, se voc digitar apenas erro:
15
resulta no valor
15.
5+,
5+
um operador que espera dois itens a serem conectados no Python. Como apenas
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
dizer
corretamente
dizer
Do
2.2.1
2 + 5 + 8, 2 + 5
2+5
7 + 8,
2.3
variveis.
a mesma analogia de que gatos so animais, mas nem todos os animais so gatos.
2.3.
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.
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
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
O prximo
>>>
aparecer para que a prxima instruo seja digitada. Esta instruo, denominada 15 nela.
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:
o resultado de
spam
15. Devido
spam ter 15 + 5.
spam + 5
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.
possvel mudar o valor armazenado em uma varivel entrando com uma nova sentena de atribuio. Por exemplo, tente o seguinte:
spam.
Ento, entramos
spam = 3,
spam
+ 5,
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:
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 = spam + 5
spam
o valor atual mais 5. Lembre-se que a varivel do lado esquerdo do sinal jeito e quantas vezes quisermos.
expresso, do lado direito do sinal, vale. Assim, podemos continuar aumentando o valor de
spam
do
= = = =
2.3.1
varivel. Veja o que acontece com o seguinte cdigo dado como entrada no terminal:
2.4.
spam
spam = Hello
Hello
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
oldSpam.
2.4
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
possui o valor 10 e
eggs,
o valor 15.
Figura 3: As variveis
fizz
eggs
ilustradas.
spam,
spam
= fizz + eggs
resultado?
spam.
O valor de nados em
fizz
e em
spam agora 25, porque somamos fizz e eggs, eggs, e armazenamos o resultado em spam.
2.
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...)
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.
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.
Quando digitamos strings, elas devero estar entre aspas simples ('), como o seguinte:
spam
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
+,
de strings. Observe:
10
3.
STRINGS
tipos de dados.
Hello
3.2
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-
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
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.
11
3.3
putador que interpretada pelo Python, de forma que o computador entenda. computador como uma receita de bolo:
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
comentrio.
comentrio.
ignora. Eles so utilizados para lembrar ao programador ou inform-lo sobre o que o cdigo faz.
3.3.2
Funes
Uma
funo
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
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(),
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
print(),
print()
para
>>> print(Hello world) Hello world >>> print("Hello world") Hello world
5 Em
ingls, chamados de
escape characters
12
3.
STRINGS
Comando
\\ \' \" \n \t
O que impresso
Contra-barra (\) Aspas simples (') Aspas duplas (") Nova linha Tabulao
\'
>>> 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
Quando a funo
input()
(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()
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
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).
com a escrita diferente, entre maisculas e minsculas, no so consideradas a mesma coisa. Assim,
spam, SPAM
diferente.
sPAm
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
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
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
4.1
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
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!
Se voc
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.
import
ou
random
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.
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
desejado. A linha 2 do programa para adivinhar um nmero possui uma sentena destas, que traz o
16
4.
ADIVINHE O NMERO
mdulo
random
guessesTaken = 0
Esta linha cria uma nova varivel chamada
guessTaken.
anteriormente.
quando eles precisam de fazer algo que eles j zeram anteriormente. A linha 6 uma chamada para a funo cdigo dentro da funo
print().
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()
randint(),
number.
retorno da funo.
randint()
random,
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
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.
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.
17
number = random.randint(1, 100) print(Well, + name + , I am thinking of a number between 1 and 100.)
4.5.1
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
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
comportamento do programa, argumentos so entradas para funes. Algumas funes exigem que valores sejam passados elas. Por exemplo:
A funo
input()
print()
possui um e a funo
randint()
possui dois. Quando mais de um argumento exigido, estes devem ser separados por
delimitadores.
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
while,
loop.
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
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.
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
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:
Estes
valores so
a tais valores. Utilizamos estes valores com operdores de comparao, para formar condies.
4.11
Operadores de comparao
Sinal
< > <= >= == !=
Nome
menor que maior que menor ou igual a maior ou igual a igual a diferente de
while:
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.
4.12
Condies
Uma
condio
resulta em um valor booleano. Uma condio apenas um nome para uma expresso que resulta em
True True.
ou
False.
guessesTaken < 6
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.
==
=.
de igual, estamos atribuindo um valor, enquanto ao utilizarmos dois sinais, queremos comparar dois
4.13
while
while, ela True, o bloco
verica a condio executado. Se a
while marca o
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,
4.14.1
mento.
int().
A funo
int()
exige um argu-
input()
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()
4.14.
AS TENTATIVAS DO JOGADOR
21
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)
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
int()
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.
22
4.
ADIVINHE O NMERO
4.15
Sentenas
if
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
Figura 6: Sentenas
if
while.
Entretanto, em um bloco
Uma sentena
while,
a execuo no sai imediatamente aps o m do bloco, mas continua enquanto a condio for
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
while
break,
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
if guess == number:
Diferentemente do cdigo da linha 25, este bloco
if
que o bloco
while
if
saimos do bloco
8 Um
comando
break
4.18.
23
while
por ter extrapolado as tentativas ou por ter adivinhado o nmero. Se for o caso de o jogador
if guess == number: guessesTaken = str(guessesTaken) print(Good job, + myName + ! You guessed my number in + guessesTaken + guesses!)
if,
str()
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
if guess != number: number = str(number) print(Nope. The number I was thinking of was + number)
!=
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
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
2 + 2 resulta em 4.
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,
if, while
break
so exemplos de sentenas de
controle de uxo,
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
A funo
I/O
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
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().
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
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
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.
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.
27
5.4
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
def,
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.
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
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:
inteira ser verdadeira se, e somente se, ambos os lados forem verdadeiros.
9 Utilizamos
28
5.
O REINO DO DRAGO
while
and.
True
ou
False
cave
1 not.
ou
2,
assim, todas
True. not
and,
or
e o
No caso do operador
or,
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
or
A
True True False False
or
or or or or
B
True False True False
Resultado
True True True False
not
not
not not
A
True False
Resultado
False True
5.4.4
5.4.
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.
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
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.
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
fora da funo, no ser alterado. Isto porque as variveis possuem escopo diferente, global e local.
escopo local.
escopo global.
Dentro de
5.4.7
Denindo a funo
checkCave(chosenCave)
def checkCave(chosenCave):
Observa-se que, ao declarar a funo
checkCave(),
funo, no caso,
tros.
chosenCave.
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.
30
5.
O REINO DO DRAGO
5.4.8
ter que atribuir um valor a uma varivel antes que ela seja utilizada. Observe:
5.4.9
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()
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
sleep()
Estas pausas do suspense ao jogo, ao invs de mostrar o todo o texto de uma vez.
5.4.10
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 .
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
else
10 Lembre-se
que s podemos fazer comparaes de uma string com outra string, por isso utilizamos a funo
str(),
==
sempre resultar em
randint() False.
5.5.
PROJETANDO UM PROGRAMA
31
Dois-pontos
Voc pode ter notado que os blocos de um novo bloco.
por dois pontos. Este sinal marca o m de uma sentena e nos informa que a prxima linha o incio
5.4.11
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
playAgain,
5.4.12
displayIntro().
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(),
criada neste programa, para o jogador escolher qual caverna seguir. Feito isso, a execuo continua e
caveNumber
funo
checkCave().
do jogador e da caverna e mostrar na tela o resultado do jogo, dependendo de onde o jogador escolheu
5.4.13
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
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.
32
5.
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.
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.
2.
Jogo de Craps.
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.
DD/M M/AAAA
mesPorExtenso
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.
35
6.1
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
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.
6.3.
37
6.3
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
representados por caixas conectadas por setas. Cada caixa representa um passo, enquanto as setas
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
import random HANGMANPICS = [ +---+ | | | | | | =========, +---+ | | O | | | | =========, +---+ | | O | | | | | =========, +---+ | | O | /| | | | =========, +---+ | | O | /|\ | | | =========, +---+ | |
6.4.
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
random,
vra secreta da lista de palavras no programa. Em seguida, denimos as strings que ilustraro o jogo.
6.5.
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
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
Esta a conveno de programao para declarar constantes. programador alertado a no escrever cdigo que as alterem.
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
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.
valores armazenados. Por exemplo, contm trs valores string. uma varivel, como
Como qualquer outro tipo de dado, possvel armazenar uma lista em Cada
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.
>>> 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:
ndice.
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
= = = =
Utilizando listas, podemos tratar os itens como qualquer outro valor. Observe:
Por
animals[2]
resultar em
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.
>>> 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.
+,
concatenao de listas.
14 Esta
6.5.
43
>>> [1, 2, 3, 4] + [apples, oranges] + [Alice, Bob] [1, 2, 3, 4, apples, oranges, Alice, Bob] >>>
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
False
se o valor no est
>>> animals = [aardvark, anteater, antelope, albert] >>> antelope in animals True
A expresso 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
del.
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
"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]
del
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
>>> 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.
6.5.7
Mtodos
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.
45
lower(),
upper(),
>>> 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.
6.5.8
Os mtodos de lista
reverse()
append()
reverse()
inverte a ordem dos
>>> 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().
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
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()
[1, 2, apple]
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().
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
prprias palavras na string, ou remover tambm. Apenas tenha certeza de que as palavras estejam separadas por espaos.
6.7
wordlist.
words.
6.7.
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()
wordList.
na varivel segundo
Na linha 63, armazenamos um ndice aleatrio, para ser utilizado na lista recebida,
wordIndex.
randint(),
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
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.
print()
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,
for.
do loop adiante.
for.
A funo
range()
for.
O argumento end
Nas linhas 70 e 72 h um segundo argumento fornecido funo argumento opcional. Passando uma string em branco para o
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.
range()
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,
>>> list(range(10, 20)) [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
A funo
for
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
for,
in,
lista ou string) ou uma srie de valores (retornada pela funo dois-pontos. A cada Observe o exemplo:
range()).
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.
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
Se
missedLetters
for igual a
aush,
a u s h.
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
for
6.7.4
imprimir linhas em branco para cada letra da palavra secreta. Para tal, utilizaremos o caracter 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
6.7.5
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:
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
6.8.
SENTENAS
51
6.7.6
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()
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
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
True.
while break,
imediatamente a funo, ou
return,
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
6.8
Sentenas
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
Fuzzball
imprimir
if-else
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.
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
elif.
Se esta for falsa tambm, o programa vericar a prxima condio e assim por
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
6.8.1
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.
6.8.2
def playAgain(): print(Do you want to play again? (yes or no)) return input().lower().startswith(y)
A funo
6.9.
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
lower()
18 .
valor booleano
6.9
1. 2.
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
getGuess(alreadyGuessed):
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.
6.10
necessrio colocar tudo isso em ordem e saber como chamar as funes. Assim, tudo comea a ser executado, na verdade, na linha 106.
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
O loop
while
possui a condio sempre verdadeira, assim, tudo o que est no bloco ser
break.
displayBoard(),
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(),
54
6.
JOGO DA FORCA
6.10.2
getGuess()
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
6.10.3
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
secretWord
comparada s letras de
correctLetters
Este processo executado entre as linhas 122 e 126. Observe que a vericao de de
correctLetters
em
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
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.
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
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
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.
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
range()
frequetemente utilizada
com estes loops, pois uma forma fcil para criar listas de nmeros sequenciais. 3. Sentenas
elif
forem falsas.
Tarefa 6.2
Pesquise sobre o tipo
Tarefa 6.3
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.
5. Faa um programa que leia uma sequncia de caracteres, mostre-a e diga se um palndromo 6.
19
Desenvolva um jogo em que o usurio tenha que adivinhar O programa ter uma lista de
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 (
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
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.
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
# 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.
59
== == == == == == ==
le le le le le le le
== == == == == == ==
le le le le le le 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.
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
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.
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.
63
7.6
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
drawBoard()
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
inputPlayerLetter()
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
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
o cdigo (no caso, a funo) do cdigo 4 e j podemos perceber como funes podem ser realmente
7.6.5
makeMove()
que ela recebe so: o tabuleiro (com as dez strings que o representam), representam a jogada do usurio,
board;
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:
Estas linhas fazem sentido, baseado no que aprendemos at agora. Para refrescar a memria: atribumos 42 varivel ocorre porque
spam
spam
spam
cheese
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:
=,
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.
65
letter
move
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
7.8
isWinner()
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.
uma das oito combinaes deve ser verdadeira para que o jogador representado pela varivel
le
7.9
Duplicando o tabuleiro
A funo
getBoardCopy()
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
Lembre-se que os
espaos livres do tabuleiro so marcados com uma string que possui apenas um espao.
7.11
getPlayerMove()
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
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
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
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 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
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
chooseRandomMoveFromList()
com a lista
[1, 3,
7, 9],
Se todos os espaos
None
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(),
7.14
jogadas
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
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
drewBoard() makeMove().
e passando a varivel
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
Se nenhuma das opes anteriores terminar o jogo, ento vez do computador e a varivel
turn
recebe
computer.
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
if
playAgain()
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
Damas do Xadrez.
n
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
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
8 Bagels
Tpicos abordados neste captulo:
Operadores compostos, A funo Os
Interpolao (formatao) de strings Especicador de converso Loops aninhados Neste captulo, sero apresentadas mais funes do Python. Alm disso, duas formas de sim-
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.
8.4.
71
8.4
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
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,
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
+ =.
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:
Tambm possvel utilizar este formato de operao para outras alm da soma, como a subtrao
-=,
multiplicao
*=
e diviso
/=.
8.4.2
getClues()
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
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().
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
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,
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-
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
>>> 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? >>>
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:
8.5.2
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.
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
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
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
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
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
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,
9.3
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
9.4
As funes
A funo
chr() ord()
A funo
chr()
(de char, verso curta de character) obtm o caracter ASCII para o pa-
ord()
9.5
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.
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
captulo so muito teis no desenvolvimento de jogos. Observemos os tpicos principais deste programa.
9.7.1
getMode()
codicar uma mensagem. Ela retorna a resposta do jogador, obtida atravs da comparao da entrada do usurio com a lista gerada por
9.7.2
getMessage()
9.7.3
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
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
desencriptada. Esta varivel apenas recebe strings concatenadas, iniciando por uma string vazia.
9.7.5
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
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()
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(),
9.8
O mtodo de string
Este mtodo retornar
isalpha()
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
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
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
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
getTranslatedMessage()
Entretanto, se o modo fora bruta for acionado, ento a funo executar um loop iterando de 1 a
getTranslatedMessage()
MAX_KEY_SIZE
9.11
Exerccios complementares
Caesar Cipher para que:
37, 39, 42
44
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
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
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.
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
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
10.3.
81
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
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
http://pygame.
org/docs/ref/.
82
10.
# 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.
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
pygame
sys
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
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.
83
10.5
10.5.1
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.
pygame,
10.5.2
pygame.display.set_mode()
dentro do mdulo
pixel
nico pixel pode ser de qualquer cor. Todos os pixels da tela trabalham mutuamente para gerar as
(500, 400)
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
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
(0, 0, 0).
10.8
Fontes
Uma
fonte
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
84
10.
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)
None,
10.8.2
O mtodo
render()
para objetos
Font
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
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.
10.9
Atributos
O tipo
pygame.Rect
Rect,
Rect
chama-se a funo
pygame.Rect(),
passando
parmetros inteiros de coordenadas XY do canto superior esquerdo, seguidos pela largura e altura do
Assim como mtodos so como funes associadas a um objeto, adas a um objeto. O tipo
10.10. MTODOS
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
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
Surface.
importado pelo programa e, dentro deste E dentro destes mdulos, esto os tipos
Font
Surface.
10.11
Funo construtor e
type()
construtores.
Criou-se um objeto
pygame.Rect()
As funes
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.
>>> 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
no terminal interativo, para evitar que acontea algum procedimento indesejado no Python.)
type()
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
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
Surface
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
Surface
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
Surface
a ser desenhado
3. Tupla com as coordenadas inteiras indicando limite esquerda, limite superior, largura e altura. Um objeto
Rect
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
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).
10.14.1
O mtodo
blit()
para objetos
Surface
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
10.15
A funo
pygame.display.update()
pygame.display.update() Surface
chamada.
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
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.
pygame.event.get()
pygame.event.Event
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
do programa. Este evento tambm gerado quando o computador est desligando e tenta terminar todos os programas que esto abertos.
QUIT
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
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
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
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.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.
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
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.
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.
Por
exemplo, se um bloco est se movendo para baixo e para a direita e colide com a parede debaixo da
Para representar os blocos, utiliza-se objetos quatro direes o bloco est se movendo. dos blocos so ajustadas no objeto
Rect,
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
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().
11.3.
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,
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.
No caso, isto indica que os blocos se movero 4 pixels a cada iterao do loop que faz o movimento
11.3.2
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
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
O bloco por
for
de retngulos e rodar o mesmo cdigo em cada estrutura. Dentro do loop, cada bloco representado
b,
left
top,
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
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
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.
11.3.6
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
as novas direes de cada bloco, dependendo da parede em que ocorrer a coliso e da direo em que
11.3.7
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
for)
e 89 (que atualiza a
0.02
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
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
aos fenmenos relacionados coliso nas paredes da janela, no ser abordado novamente. iniciar, o programa ser baseado no princpio do jogo
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,
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.
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
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.
if
iniciado na linha 7.
98
12.
DETECO DE COLISES
12.2.2
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-
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(),
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)
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
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.
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[:]
foods.
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
doRectsOverlap()
para a funo, o quadrado branco e o quadrado verde mais prximo. Se estes dois retngulos colidirem,
True
12.2.7
vetor
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
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.
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
momento que uma das teclas indicadas fora acionada, a varivel que for relacionada a tal direo ser
True.
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
Os blocos
if
das no incio do programa. Primeiro, vericado se alguma tecla pressionada, atravs do evento
KEYDOWN.
Adicionalmente, o bloco
if
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
A sequncia de blocos
ou no. O quadrado do jogador ser movimentado a partir do quadrado armazenado em ajustando as coordenadas XY desta varivel.
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()
True
doRectOverlap()
isPointInsideRect(),
do cdigo 10.
12.4
Exerccios complementares
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
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
pygame.Rect: Rect
e (como
objetos do tipo
Rect
tamanho. A localizao deste tipo de objeto pode ser obtida atravs dos atributos dos objetos
bottomright).
tupla de inteiros com coordenadas XY. O tamanho pode ser determinado pelos atributos
pygame.Surface:
Surface
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
pygame.event.Event:
os tipos de dados
Event,
cada vez que h uma interao do usurio com o retorna uma lista de objetos
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().
None
pygame.time.Clock:
o objeto
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 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
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()
108
13.
DODGER
13.3
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,
pygame.locals.
O mdulo
pygame.locals
ao invs de
game utiliza como tipos de evento e tipos de teclas. Utilizando a sentena podemos utilizar a constante
QUIT
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
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
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()
13.3.6
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
Surface para que o texto seja desenhado. waitForPlayerToPressKey() vericar os eventos de presso de tecla (KEYDOWN)
13.3.
109
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
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
pos.
move_ip(),
para objetos
Rect,
Rect horizonplayerRect.move_ip(10,
20)
playerRect.move_ip(-5, -15)
Rect
ip, deste mtodo, se refere in place. Isto devido ao mtodo mudar o prprio objeto de
move(),
Rect,
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
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()
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()
passadas as posies
playerRect.centerx
playerRect.centery.
110
13.
DODGER
pygame.mouse.set_visible(False)
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
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
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:
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.
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
111
112
APNDICE A.
FLUXOGRAMAS
3. Mas o jogo no acaba aps o jogador tentar adivinhar a letra. est na palavra secreta ou no.
uxograma. Isto vai criar uma ramicao, como mostrado na gura 25.
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
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.
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
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
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
Referncias Bibliogrcas
1 MENDES, M. A. L.
<http://www-
<http://learnpythonthehardway<http:/-
116