sexta-feira, 16 de outubro de 2015

Tiro ao alvo

Já todos jogamos com arco e flechas. O objectivo é acertar num alvo colocado a uma certa distância. A nossa ideia é simular com um programa de computador o treino de um jogador. Para começar vamos supor que apenas se pretende calcular a percentagem de vezes que acerta no alvo. Assumimos que o alvo tem a forma de um circulo. Podemos começar com uma primeiro esboço do programa.
1.def tiro_alvo(raio, num):
2. # inicialização
3. for i in range(num):
4.  # atira flecha
5.  # verifica se acertou
6.        pass
7. # calcula percentagem de acertos
Temos assim que resolver vários subproblemas. Comecemos pelo mais simples: calcular a percentagem. Isso envolve contar os acertos e dividir pelo número total de lançamentos.
1.def tiro_alvo(raio, num):
2. # inicialização
3. conta = 0
4. for i in range(num):
5.  # atira flecha
6.  # verifica se acertou
7. # calcula percentagem de acertos
8. return conta / num
Estamos perante o padrão ciclo-acumulador.

Como simular o lançamento da flecha? Uma hipótese simples é escolher de modo aleatório as coordenadas do ponto onde vai incidir a flecha. Recorremos ao módulo random.
01.import random
02. 
03.def tiro_alvo(raio, num):
04. # inicialização
05. conta = 0
06. for i in range(num):
07.  # atira flecha
08.  x = random.randint(-raio,raio)
09.  y = random.randint(-raio,raio)
10.  # verifica se acertou
11. # calcula percentagem de acertos
12. return conta / num
Na solução acima escolhemos considerar que os pontos onde vai cair a flecha se encontra num quadrado de lado 2*raio e centrado no ponto (0,0). Falta agora verificar se acertamos no alvo ou não. A solução passa por calcular a distância (euclidiana) do ponto ao centro. Se for maior do que o raio, então estará fora do alvo.
01.import random
02.import math
03. 
04.def tiro_alvo(raio, num):
05. # inicialização
06. conta = 0
07. for i in range(num):
08.  # atira flecha
09.  x = random.randint(-raio,raio)
10.  y = random.randint(-raio,raio)
11.  # verifica se acertou
12.  if math.sqrt(x**2 + y**2) < raio:
13.   conta = conta + 1
14. # calcula percentagem de acertos
15. return conta / num
E pronto, chegámos ao fim. Como se observou é possível construir uma solução por etapas a partir de um modelo geral.

Podemos tornar o problema ligeiramente diferente, considerando um alvo mais realista contendo várias zonas, sendo que cada uma tem um valor associado: vale tanto mais o nosso lançamento quanto mais perto estiver do centro. Na solução que vamos apresentar considerámos que existem três zonas. Por outro lado, agora o resultado pretendido é a soma de pontos obtido por um jogador.
01.def tiro_ao_arco_2(raio_1,raio_2,raio_3,num):
02.    pontos = 0
03.    for i in range(num):
04.        # atira flecha
05.        x = random.randint(-raio_1,raio_1)
06.        y = random.randint(-raio_1,raio_1)
07.        dist_centro = math.sqrt(x**2 + y**2)
08.        if dist_centro <= raio_3:
09.            pontos = pontos + 50
10.        elif dist_centro <= raio_2:
11.            pontos = pontos + 20
12.        elif dist_centro <= raio_3:
13.            pontos = pontos + 10
14.        else:
15.            pontos = pontos - 5
16.    return pontos
A partir daqui pode imaginar as variantes que quiser, incluindo desenhar, usando o turtle o alvo e a localização das flechas…

Sem comentários:

Enviar um comentário