16. Утята.
Условие:
Программа создаёт перемещающийся вверх фон с утятами. Они незначительно отличаются друг от друга: смотрят влево или вправо, обладают одним из двух размеров тела, четырех типов глаз, двух разновидностей ртов и трёх положений крыльев.
В результате получается 96 возможных вариантов утят, непрерывно выводимых программой.
Пример:
Код:
import random, shutil, sys, time, bext
class Duckling:
"""создадим в конструкторе рандомного утёнка"""
def __init__(self):
self.direction = random.choice([LEFT, RIGHT]) # в какую сторону смотрит утёнок
self.body = random.choice([CHUBBY, VERY_CHUBBY]) # утёнок кругленький или нет
self.mouth = random.choice([OPEN, CLOSED]) # открытый клюв или нет
self.wing = random.choice([OUT, UP, DOWN]) # положение крыльев
if self.body == CHUBBY: # У круглых утят могут быть только глаза-бусинки
self.eyes = BEADY
else: # У очень круглых утят будут другие глаза
self.eyes = random.choice([BEADY, WIDE, HAPPY, ALOOF])
self.partToDisplayNext = HEAD
def getHeadStr(self):
"""метод возвращает строковое значение с головой утёнка"""
headStr = ''
if self.direction == LEFT: # ориентация налево
"""рот"""
if self.mouth == OPEN: # рот открыт
headStr += '>'
elif self.mouth == CLOSED: # или рот закрыт
headStr += '='
"""глаза"""
if self.eyes == BEADY and self.body == CHUBBY: # если глаза бусинки и тело круглое
headStr += '"'
elif self.eyes == BEADY and self.body == VERY_CHUBBY: # если глаза бусинки и тело очень круглое
headStr += '" '
elif self.eyes == WIDE: # просто широкие глаза
headStr += "''"
elif self.eyes == HAPPY: # просто счастливые глаза
headStr += '^^'
elif self.eyes == ALOOF: # отчужденные глаза
headStr += '``'
"""затылок"""
headStr += ') '
if self.direction == RIGHT: # ориентация направо
"""затылок"""
headStr += ' ('
"""глаза"""
if self.eyes == BEADY and self.body == CHUBBY: # если глаза бусинки и тело круглое
headStr += '"'
elif self.eyes == BEADY and self.body == VERY_CHUBBY: # если глаза бусинки и тело очень круглое
headStr += ' "'
elif self.eyes == WIDE: # просто широкие глаза
headStr += "''"
elif self.eyes == HAPPY: # просто счастливые глаза
headStr += '^^'
elif self.eyes == ALOOF: # отчужденные глаза
headStr += '``'
"""рот"""
if self.mouth == OPEN: # рот открыт
headStr += '<'
elif self.mouth == CLOSED: # или рот закрыт
headStr += '='
if self.body == CHUBBY: # если тело просто круглое добавить пробел
headStr += ' '
return headStr # готовая голова утёнка
def getBodyStr(self):
"""метод возвращает строковое значение с телом утёнка"""
bodyStr = '(' # левая часть тела
if self.direction == LEFT: # ориентация налево
"""размер тела"""
if self.body == CHUBBY: # тело круглое
bodyStr += ' '
elif self.body == VERY_CHUBBY: # тело очень круглое
bodyStr += ' '
"""крылья"""
if self.wing == OUT:
bodyStr += '>'
elif self.wing == UP:
bodyStr += '^'
elif self.wing == DOWN:
bodyStr += 'v'
if self.direction == RIGHT: # ориентация направо
"""крылья"""
if self.wing == OUT:
bodyStr += '<'
elif self.wing == UP:
bodyStr += '^'
elif self.wing == DOWN:
bodyStr += 'v'
"""размер тела"""
if self.body == CHUBBY:
bodyStr += ' '
elif self.body == VERY_CHUBBY:
bodyStr += ' '
bodyStr += ')' # правая часть тела
if self.body == CHUBBY: # если тело просто круглое добавить пробел
bodyStr += ' '
return bodyStr # готовое тело утёнка
def getFeetStr(self):
"""метод возвращает строковое значение с лапами утёнка"""
if self.body == CHUBBY:
return ' ^^ '
elif self.body == VERY_CHUBBY:
return ' ^ ^ '
def getNextBodyPart(self):
"""метод последовательности отрисовки утёнка"""
if self.partToDisplayNext == HEAD:
self.partToDisplayNext = BODY
return self.getHeadStr()
elif self.partToDisplayNext == BODY:
self.partToDisplayNext = FEET
return self.getBodyStr()
elif self.partToDisplayNext == FEET:
self.partToDisplayNext = None
return self.getFeetStr()
def main():
bext.clear()
bext.fg("red")
print('Нажмите Ctrl-C для выхода...')
time.sleep(2)
ducklingLanes = [None] * (WIDTH // DUCKLING_WIDTH) # определим какое количество уток поместится в окне терминала (это количество элементов списка)
while True:
for laneNum, ducklingObj in enumerate(ducklingLanes):
if (ducklingObj == None and random.random() <= DENSITY):
ducklingObj = Duckling() # создаётся объект "утёнок", при подходящих условиях
ducklingLanes[laneNum] = ducklingObj # в список, вместо None, помещается объект "утёнок"
if ducklingObj != None:
print(ducklingObj.getNextBodyPart(), end='')
if ducklingObj.partToDisplayNext == None: # если дошла печать до ног, то изменяем объект "утёнок" в списке на None
ducklingLanes[laneNum] = None
else:
print(' ' * DUCKLING_WIDTH, end='')
print()
time.sleep(PAUSE)
# ввод констант
PAUSE = 0.2
DENSITY = 0.10
DUCKLING_WIDTH = 5
LEFT = 'left'
RIGHT = 'right'
BEADY = 'beady'
WIDE = 'wide'
HAPPY = 'happy'
ALOOF = 'aloof'
CHUBBY = 'chubby'
VERY_CHUBBY = 'very chubby'
OPEN = 'open'
CLOSED = 'closed'
OUT = 'out'
DOWN = 'down'
UP = 'up'
HEAD = 'head'
BODY = 'body'
FEET = 'feet'
WIDTH = shutil.get_terminal_size()[0] # получить ширину текущего терминала
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
sys.exit()