Абсурдно правильний(?) код з поділом математики і екрану, підказками типів і т.п.
import math
from enum import Enum
from typing import List, Dict, Tuple
WIDTH = 67
HEIGHT = 40
SECTORS = 16
CIRCLES = 5
LABELS = {(33,20):'1',(34,20):'0'}
class FieldType(Enum):
BLANK = 1
RED = 2
WHITE = 3
NINE = 4
CENTER = 5
FRAME = 6
CHARACTERS = {FieldType.BLANK: ' ',
FieldType.RED: '%',
FieldType.WHITE: ' ',
FieldType.NINE: '9',
FieldType.CENTER: '.',
FieldType.FRAME: '/'}
class Target:
def __init__(self, *,
radius : float,
circles : int = CIRCLES,
sectors : int = SECTORS):
self.radius : float = radius
self.circles : int = circles
self.sectors : int = sectors
self.ring : float = self.radius/self.circles
def get_type(self, x: float, y: float) -> FieldType:
rho : float = math.hypot(x, y)
phi : float = math.atan2(y, x)
in_center : bool = rho <= self.ring
if in_center:
return FieldType.CENTER
in_nine : bool = rho <= 2 * self.ring
if in_nine:
return FieldType.NINE
in_stripped_area : bool = rho <= self.radius
if not in_stripped_area:
return FieldType.BLANK
in_even_sector : bool = (phi % (2*math.pi / (self.sectors/2))) < (2*math.pi / self.sectors)
in_even_circle : bool = (rho % (2 * self.ring)) < (self.ring)
if in_even_sector == in_even_circle:
return FieldType.WHITE
else:
return FieldType.RED
class ConsoleTarget:
def __init__(self, *,
width : int = WIDTH,
height : int = HEIGHT,
labels : Dict[Tuple[int,int], str] = LABELS,
characters : Dict[FieldType, str] = CHARACTERS):
self.target : Target = Target(radius = height//2)
self.ratio : float = height / width
self.center_x : int = int(self.ratio * width/2)
self.center_y : int = height//2
self.labels : Dict[Tuple[int,int], str] = labels
self.characters : Dict[FieldType, str] = characters
self.width : int = int(2*self.target.radius / self.ratio)
self.height : int = height
self.cframe : str = self.characters[FieldType.FRAME]
self.cblank : str = self.characters[FieldType.BLANK]
self.hline : str = self.cframe * (6 + self.width)
def get_character(self, x_screen: int, y_screen: int) -> str:
if (x_screen,y_screen) in self.labels:
return self.labels[(x_screen,y_screen)]
x: float = x_screen * self.ratio - self.center_x
y: float = y_screen - self.center_y
return self.characters[self.target.get_type(x,y)]
def draw(self):
print(self.hline)
for y in range(self.height+1):
line: str = ''.join( self.get_character(x,y) for x in range(2+self.width))
print(f'{self.cframe}{self.cblank}{line}{self.cblank}{self.cframe}')
print(self.hline)
def main():
c = ConsoleTarget()
c.draw()
if __name__ == '__main__':
main()