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.
def tiro_alvo(raio, num):
 # inicialização
 for i in range(num):
  # atira flecha
  # verifica se acertou
        pass
 # 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.
def tiro_alvo(raio, num):
 # inicialização
 conta = 0
 for i in range(num):
  # atira flecha
  # verifica se acertou
 # calcula percentagem de acertos
 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.
import random

def tiro_alvo(raio, num):
 # inicialização
 conta = 0
 for i in range(num):
  # atira flecha
  x = random.randint(-raio,raio)
  y = random.randint(-raio,raio)
  # verifica se acertou
 # calcula percentagem de acertos
 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.
import random
import math

def tiro_alvo(raio, num):
 # inicialização
 conta = 0
 for i in range(num):
  # atira flecha
  x = random.randint(-raio,raio)
  y = random.randint(-raio,raio)
  # verifica se acertou
  if math.sqrt(x**2 + y**2) < raio:
   conta = conta + 1
 # calcula percentagem de acertos
 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.
def tiro_ao_arco_2(raio_1,raio_2,raio_3,num):
    pontos = 0
    for i in range(num):
        # atira flecha
        x = random.randint(-raio_1,raio_1)
        y = random.randint(-raio_1,raio_1)
        dist_centro = math.sqrt(x**2 + y**2)
        if dist_centro <= raio_3:
            pontos = pontos + 50
        elif dist_centro <= raio_2:
            pontos = pontos + 20
        elif dist_centro <= raio_3:
            pontos = pontos + 10
        else:
            pontos = pontos - 5
    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