Программирование на языке Python: младшая группа

Введение: объекты, переменные, основы ввода и вывода данных

Основные определения

Интерпретатор

Программа, реализующая построчный анализ, обработку и выполнение исходного кода программы.

IDLE (читается — айдл)

(Integrated Development and Learning Environment) — это интегрированная среда разработки и обучения на языке Python.

Данные в языке Python представлены в форме объектов.

Каждый объект имеет идентификатор, тип и значение.

Литерал

Форма записи для «фиксированного» представления значения объекта. Примеры литералов: 42, 4.2, "Hello, World!".

Идентификатор

Однозначно идентифицирует объект. Его можно считать адресом области в памяти компьютера, где хранится объект.

Тип данных

Тип определяет возможные значения и их смысл, операции, а также способы хранения значений типа.

Переменная

Именованная ссылка на конкретный объект.

Оператор присваивания связывает переменную и объект. Пример:

>>> x = 5

Первую привязку переменной к объекту в программе называем определением и инициализацией переменной.

Базовые конструкции языка

Вывод на экран: print

Функция print позволяет вывести любое сообщение на экран. Для этого нужно в скобках указать сообщение или переменную с данными:

print("Привет мир!")

message = "Hello world!"
print(message)

В результате будет выведено 2 приветствия мира на разных языка

Также можно передавать несколько параметров, чтобы вевести их друг за другом в одной строке:

a = 2
print(1, a, 3)

Переменные

Переменные позволяют записывать в себя значение, чтобы после этого им можно было пользоваться в любом месте программы:

a = "Hi!"
print(a)
print(a)

Полезным свойством является возможность изменения значения в одном месте, чтобы изменить поведение всей программы

Ввод данных: input

Функция input используется для получения данных от пользователя:

x = input()
print("Hi,", x)

Чтобы пользователь знал, что его просят ввести, можно предоставить строку приглашения:

name = input("Введите имя: ")
print("Привет,", name)

Если хотим работать с данными как с числами, нужно использовать функцию int:

age = int(input("Введите ваш возраст: "))
print("Сейчас вам", age, "лет")

Арифметические действия

В питоне можно производить арифметические вычисления:

a = 12
b = 3

print(a + b)
# 15

print(a - b)
# 12

print(a * b)
# 36

print(a / b)
# 4

Цикл for

Цикл позволяет многократно повторять какое-либо действие:

for i in range(4):
    print("Сообщение в цикле!")
print("Вышел из цикла!")

В данном случае мы просим 4 раза вывести первое сообщение на экран и после этого вевести второе сообщение. Результат будет следующим:

Сообщение в цикле!
Сообщение в цикле!
Сообщение в цикле!
Сообщение в цикле!
Вышел из цикла!

Turtle

Черепашья графика впервые появилась вместе с языком Logo (1967 г.) и являлась его частью. Суть заключается в наличие исполнителя черепашки, который может передвигаться в разных направлениях и оставлять за собой след

Пример рисования треугольника:

from turtle import *

color("blue")

forward(100)
left(120)
forward(100)
left(120)
forward(100)

done()

Для создания сложных фигур можно использовать циклы:

from turtle import *
for i in range(5):
    fd(100)
    lt(72)
done()

Перемещение черепашки

forward(n)
fd(n)

Перемещеает черепашку на n пикселей вперёд

backward(n)
bk(n)

Перемещеает черепашку на n пикселей назад

rt(n)

Поворачивает черепашку на n градусов вправо

left(n)
lt(n)

Поворачивает черепашку на n градусов влево

done()

Говорит не закрывать окно после завершения рисования

Управление пером

down()

Опускает перо, чтобы черепашка при передвижении оставляла след

up()

Поднимает перо

width(n)

Устанавливает ширину следа от пера

Настройка цветов

color(pen_color)

Устанавливает цвет следа пера в соответсвии с pen_color

bgcolor(s)

Устанавливает цвет полотна (фона)

Задачи

  1. Напишите программу, которая будет говорить, сколько вам будет лет в следующем году. Она должна получить на вход ваш текущий возраст

  2. Написать алгоритм для черепашки, который будет рисовать правильный многоугольник. На вход программа должна принимать сколько сторон должно быть у фигуры.

  3. Написать программу для рисования круга

Домашнее задание

  1. Установить Python на домашний ПК. Официальный сайт: https://www.python.org/

  2. Реализовать приложение для вычисления периметра и площади прямоугольника. Приложение запрашивает у пользователя два целых числа — длины сторон прямоугольника. Пример работы приложения:

    Input a: 5
    Input b: 4
    
    P = 18
    S = 20
    

Функции

Функции – это многократно используемые фрагменты программы. Они позволяют дать имя определенному блоку команд для того, чтобы выполнять этот блок поуказанному имени в любом месте программы и сколь угодно много раз. Это называется вызовом функции. Мы уже использовали встроенные функции: print, input, fd.

Пример создания функции:

def say_hello():
    print('Hello')

say_hello()  # вызов функции
say_hello()  # ещё один вызов функции

Параметры функций

Функции могут принимать параметры, т.е. некоторые значения, передаваемые функции для того, чтобы она что-либо сделала с ними.

Параметры указываются в скобках при объявлении функции и разделяются запятыми. Аналогично мы передаём значения, когда вызываем функцию. Обратите внимание на терминологию: имена, указанные в объявлении функции, называются параметрами, тогда как значения, которые передаются в функцию при её вызове – аргументами.

Пример:

from turtle import *

def star(s):
    for i in range(5):
        fd(s)
        lt(144)

star(200) # вызов функции с аргументом s = 200

Управление черепашкой

seth(angle)
setheading(angle)

Устанавливает текущее направление черепашки на заданный угол

goto(x, y)

Перемещает черепашку в заданные координаты. Если перо опущено, черепашка будет оставлять след при перемещении

begin_fill()

Заставляет черепашку начинать отслеживать замкнутые фигуры

end_fill()

Закрашивает все замкнутые фигуры, которая создала черепашка при рисовании

pencolor(color)

Устанавливает цвет следа черепашки в color

fillcolor(color)

Устанавливает цвет закрашивания фигур черепашкой в color

Задачи

  1. Напишите функцию для рисования треугольника.

  2. Создадите функцию, которая будет рисовать закрашенный треугольник

  3. Напишите функцию sgoto(x, y), которая будет перемещать черепашку в заданные координаты, так чтобы при этом она не оставляла след

  4. Объединив функции выше, нарисуйте еловый лес

  5. Нарисуйте пейзаж ночного леса со звёздным небом и луной

Домашнее задание

  1. Напишите программу, которая будет рисовать правильный шестиугольник из шести правильных треугольников. Создание треугольника вынести в отдельную функцию, рисовать шестиугольник через цикл

  2. Нарисуйте улыбающийся смайлик. Для этого вынесите в отдельную функцию рисование круга заданного размера.

Ветвление

Ветвления это способ изменить поведение программы в завивимости от каких-либо условий. Например, если пользователь ввёл логин и пароль, мы можем пустить его дальше, иначе мы просим ввести его данные заново:

login = input("Логин: ")
password = input("Пароль: ")

if len(login) > 6 and len(password) > 8:
    print("Приветствуем!")
else:
    print("Введите данные полностью")

Здесь мы просим пользователя ввести свой логин и пароль. Пока что ограничимся простой проверкой - если длина логина больше шести символов и вместе с этим длина пароля больше восьми, мы его приветствуем.

Здесь есть сразу несколько новых вещей, во первых это len, во вторых это главное за чем мы здесь собрались - конструкция ветвления.

len(s)

Возвращает длину переданной строки:

word = "Condition"
word_length = len(word)

print(word_length)

Условный оператор

Условный оператор позволяет выполнить какое-либо действие если выполняется условие. В результате проверки порождается особый тип данных bool булевый. Данный тип способен принимать всего 2 значения - истина и ложь.

>>> 20 > 15
True
>>> 20 < 15
False

Оператор if проверяет условие и если оно истинно, выполняет действие:

price = 32.5
cash = 50

if cash > price:
    print("Вам хватит денег для покупки")

Блок else выполняется в том случае, если результат проверки оказался ложным:

your_age = int(input("Введите ваш возраст: "))
required_age = 18

if your_age < required_age:
    print("Вы слишком юны для вождения автомобиля")
else:
    print("Вы можете водить автомобиль")

Блок elif выполняется если предыдущая проверка не увенчалась успехом, но есть ещё другие варианты проверок. В данной программе предлагается ввести имеющееся у вас количество денег чтобы узнать что стоит покупать:

cash = int(input("Введите имеющееся количество денег: "))
if cash > 100:
    print("Купить шоколадку")
elif cash > 50:
    print("Купить чипсы")
else:
    print("Не брать ничего")

Здесь программа просит вас ввести ваш возраст возраст и говорит, можно ли вам водить автомобиль. Когда введёте число, будет произведена проверка - если ваш возраст меньше 18, результат будет истина и тогда выполнится код, написанный внутри блока if. Если же вы ввели число 18 или больше, то в результате проверки получится ложь и тогда выполнится код внутри блока else.

Объединение проверок

Если мы с вами хотим проверить несколько вещей и на их основе выполнить действие, то нам придётся использовать 2 ключевых слова: and и or. Они позволяют объединить результаты нескольких проверок вместе. Например, если пользователь вводит или свою почту или номер телефона, он будет получать уведомления с новостями:

email = input("Введите электронную почту: ")
phone = input("Введите номер телефона:")

if len(email) > 8 or len(phone) > 10:
    print("Мы уведомим вас о наших обновлениях")
else:
    print("Мы не сможем уведомить вас, поскольку не знаем ваших данных")

Логическое «И» (конъюнкция, логическое умножение)

A

B

A and B

0

0

0

0

1

0

1

0

0

1

1

1

Логическое «ИЛИ» (дизъюнкция, логическое сложение)

A

B

A or B

0

0

0

0

1

1

1

0

1

1

1

1

Логическое «НЕ» (инверсия, отрицание)

A

not A

0

1

1

0

Задачи

  1. Получить от пользователя число и сообщить является оно положительным, отрицательным или нулём.

  2. Фирма набирает сотрудников и ей нужны молодые кадры со стажем. Возраст от 20 лет, стаж от трёх. Приложение запрашивает у пользователя его возраст и стаж и говорит, подходит ли тот под требования фирмы.

  3. Написать программу, которая будет запрашивать у пользователя 6 раз направление движения и передвигать черепашку в указанном направлении. Должны поддерживаться команды “вверх”, “вниз”, “влево”, “вправо”. Для реализации движения в заданных направлениях предлагается создать соответствующие функции. Для установки нужного угла использовать функцию seth(angle).

  4. Пользователь вводит номер месяца, приложение сообщает, какое это время года. Весна (3,4,5), лето (6,7,8), осень (9,10,11) зима (12,1,2)).

    Пример:

    Номер месяца: 6
    Лето
    
    Номер месяца: 12
    Зима
    
    Номер месяца: 13
    Такого месяца нет
    

Списки

Список - изменяемая упорядоченная коллекция объектов

Работа со списками

Для создания списков имеется специальный синтаксис:

s = [1, 2, 3, 4, 5, 6]
print(s)

Здесь мы создаём список из шести элементов - чисел от 1 до 6 и выводим его.

Основные методы работы со списками

s[i]

Обращение к элементу под индексом i в списке s. Индексация начинается с нуля:

s = ["answer", "to", "question"]

print(s[2])
x in s

Проверяет, находится ли элемент x в списке s:

if 4 in [1, 2, 3, 4]:
    print("Четвёрка есть в этом списке")
else:
    print("Четвёрки в этом списке нет")
s.append(x)

Добавляет элемент x в конец списка s

s.extend(x)

Добавляет все элементы из списка x в список s:

s  = [1, 2, 3]
li = [20, 21, 22]
s.extend(li)

print(s)
s.pop()
s.pop(x)

Извлекает элемент под индексом x из списка. Если индекс не указан, извлекает последний элемент из списка.

s = [1, 2, 3] b = s.pop()

print(b, s) # 3 [1, 2]

По спискам можно удобно проходить с помощью цикла for:

li = ["Colors:", "red", "crimson"]
for s in li:
    print(s)

Задачи

  1. В цикле получите от пользователя названия четырёх цветов и сохраните их в список. Выведите получившийся список на экран.

  2. Объедините 2 списка, недопуская при этом дублирования элементов.

  3. Вам дан список чисел. Напишите функцию для подсчёта сумму всех эелементов и произведения.

  4. Нарисуйте квадрат, у которого цвета каждой стороны будут различаться.

  5. Напишите функцию для сортировки списка методом пузырька.

Строки

Строка - неизменяемая последовательность символов

Способы создания строк

Самый распространённый способ создания строк - с помощью двойных кавычек:

s = "Hello"
print(s)

Однако есть несколько других способов, которые имееются в языке:

s = 'Hello'
s = """Hello"""
s = '''Hello'''

Все 3 способа записи приводят к одному результату - созданию строки hello

Разные способы записи нужны для удобного создания строк с специальными символами:

q = "What's your name"
t = 'He said: "Bond, James Bond"'

Если бы в языке не было разных способов создания данных строк, то пришлось бы использовать экранирование:

t = "He said: \", James Bond\""

Некоторые специальные символы, которые могут находиться внутри строки:

Последовательность

Описание

\\

Обратный слеш (\)

\'

Апостроф

\"

Кавычка

\t

Символ табуляции

\n

Перевод строки

Тройные кавычки используются для создания больших строк:

s = """
Здесь может быть написан текст,
занимающий любое количество строк
"""

Операции со строками

len(s)

Получение длины строки:

>>> len("Hello")
5
s1 + s2

Конкатенация (объединение) строк:

>>> "Hello " + "World"
'Hello World'
s * n

Повторение строки n раз:

>>> "python " * 3
'python python python '
s[i]

Обращение к символу i строки s. Индексация начинается с нуля. Индексы могут быть отрицательными, тогда отсчет ведется с конца строки:

>>> s = 'abcdef'
>>> s[0]
'a'
>>> s[5]
'f'
>>> s[-1]
'f'
>>> s[-2]
'e'
s[begin:end:step]

Получение среза строки от позиции begin до позиции end с шагом step. Любой параметр может быть пропущен:

>>> s = "abcdef"
>>> s[1:]
'bcdef'
>>> s[:-1]
'abcde'
>>> s[1:-1]
'bcde'
>>> s[1::2]
'bdf'
>>> s[::2]
'ace'
>>> s[::-2]
'fdb'

Задачи

  1. Получите от пользователя 2 строки, объедините их и выведите экран

  2. Получите от пользователя слово, выведите первую и последнюю букву

  3. Получение от пользователя строку и выведите количество цифр в данный строке

  4. Получите от пользователя строку, в которой будет несколько слов, выведите их количество. Считать что слова отделены друг от друга одним пробелом

  5. Дана строка, содержащая путь к файлу:

    C:\Python3\python.exe
    

    С помощью срезов вывести отдельно имя файла, его расширение, имя каталога и полный путь к каталогу. Пример вывода:

    Имя файла: python.exe
    Расширение: exe
    Имя каталога: Python3
    Полный путь к каталогу: C:\Python3\
    
  6. Получите от пользователя несколько строк, занесите их в список, с помощью циклов найдите самую длинную строку и выведите её на экран

Домашнее задание

На вход программе подается строка. Необходимо вывести:

  1. Сначала выведите третий символ этой строки.

  2. Во второй строке выведите предпоследний символ этой строки.

  3. третьей строке выведите первые пять символов этой строки.

  4. В четвертой строке выведите всю строку, кроме последних двух символов.

  5. В пятой строке выведите все символы с четными индексами (считая, что индексация начинается с 0, поэтому символы выводятся начиная с первого).

  6. В шестой строке выведите все символы с нечетными индексами, то есть начиная со второго символа строки.

  7. В седьмой строке выведите все символы в обратном порядке.

  8. В восьмой строке выведите все символы строки через один в обратном порядке, начиная с последнего.

  9. В девятой строке выведите длину данной строки.

Пример:

Input: Abrakadabra
Output:
r
r
Abrak
Abrakadab
Arkdba
baaar
arbadakarbA
abdkrA
11

Методы строк

s.lower()
s.upper()
s.title()

Методы приводят строку к нижнему, верхнему и title регистру соответственно:

>>> 'world'.upper()
'WORLD'
>>> 'HELLO'.lower()
'hello'
>>> 'hello'.upper()
'HELLO'
>>> 'hello'.title()
'Hello'
s.count(sub)

Возвращает количество вхождений подстроки sub в строку s.

s.find(sub)

Возвращает минимальный индекс вхождения подстроки sub в строку s:

>>> 'otto'.find('t')
1
s.rfind(sub)

Возвращает максимальный индекс вхождения подстроки sub в строку s:

>>> 'otto'.rfind('t')
2
s.ljust(width)

Возвращает строку, выровненную по левой границе поля ширины width. Строка дополняется пробелами справа:

>>> 'hello'.ljust(10)
'hello     '
s.rjust(width)

Возвращает строку, выровненную по правой границе поля ширины width. Строка дополняется пробелами слева:

>>> 'hello'.rjust(10)
'     hello'
s.replace(old, new)

Возвращает строку, в которой все вхождения подстроки old заменены на подстроку new.

Задачи

  1. Пользователь вводит фамилию, имя и отчество. Приложение должно вывести фамилию и инициалы. Пример:

    Фамилия: Ершов
    Имя: Андрей
    Отчество: Петрович
    
    Ершов А. П.
    
  2. Доработать приложение из предыдущей задачи так, чтобы программа исправляла регистр символов. Пример:

    Фамилия: ерШоВ
    Имя: андрей
    Отчество: петрович
    
    Ершов А. П.
    
  3. Пользователь вводит слово. Подсчитать количество символов ‘a’ в нем. Пример:

    word: abracadabra
    
    5
    
  4. Пользователь вводит строку и два слова. Приложение заменяет все вхождения первого слова на второе. Пример:

    > To be or not to be.
    Find: be
    Replace: eat
    
    To eat or not to eat.
    
  5. Приложение принимает на вход строку и заменяет все вхождения буквы «ё» на букву «е».

  6. Пользователь вводит строку. Нужно удалить из нее первое слово. Разделителем слов считать пробел. Пример:

    > Hello, World!
    World
    
  7. Пользователь вводит строку. Нужно удалить из нее последнее слово.

  8. Пользователь вводит строку, содержащую два слова. Приложение выводит их в обратном порядке. Пример:

    Harry Potter
    Potter Harry
    
  9. Написать приложение, выполняющее транслитерацию введенного слова. Пример:

    > Привет
    
    Privet
    

Ветвления продолжение

str.isalpha()

Возвращает True, если строка str состоит из букв:

s = "hi"
print(s.isalpha())
str.isnumeric()

Возвращает True, если строка str состоит из цифр.

str.isalnum()

Возвращает True, если строка str состоит из букв и/или цифр.

str.islower()
str.isupper()
str.istitle()

Методы возвращают True, если строка str записана в нижнем, верхнем или title регистре соответственно.

Задачи

  1. Пользователь вводит имя. Приложение сообщает, является ли имя корректным. Имя считается корректным, если записано в title case и состоит только из букв.

  2. Пользователь вводит двузначное число. Определить:

    1. Какой из его разрядов больше: старший или младший.

    2. Одинаковы ли разряды.

  3. По длинам трех отрезков, введенных пользователем, определить возможность существования треугольника, составленного из этих отрезков. Если такой треугольник существует, то определить, является ли он разносторонним, равнобедренным или равносторонним.

  4. Пользователь вводит слово. Проверить, является ли оно палиндромом, то есть читается слева направо и справо налево одинаково. Пример:

    Слово: шалаш
    Это палиндром
    
    Слово: карандаш
    Это не палиндром
    
  5. Доработать предыдущую задачу так, чтобы приложение игнорировало регистр символов.

  6. Пользователь вводит число. Приложение сообщает количество хомячков в с учетом падежа. Пример:

    Число: 21
    
    21 хомячок
    
    
    Число: 42
    
    42 хомячка
    
    
    Число: 12
    
    12 хомячков
    
  7. Приложение запрашивает имя пользователя. Если пользователь вводит «admin», то дополнительно запрашивает пароль. Если пароль равен «123», то приветствует пользователя. Если пользователь представляется другим именем, то приложение приветствует его без запроса пароля.

  8. Пользователь вводит пароль. Приложение сообщает, надежен ли он. Пароль считается надежным, если:

    1. Его длина более 6 символов

    2. Есть символы как в верхнем, так и в нижнем регистре

    3. Есть цифры или специальные символы (пока считаем, что достаточно проверить наличие любых символов помимо букв)

  9. Пользователь вводит два числа: день и месяц невисокосного кода. Вывести дату следующего дня.

Циклы

Цикл while

Цикл while позволяет многократно выполнять блок команд до тех пор, пока выполняется некоторое условие. Пример:

n = 5

while n > 0:
    print(f'n = {n}')
    n -= 1

Вывод:

n = 5
n = 4
n = 3
n = 2
n = 1

Цикл for

Цикл for..in осуществляет итерацию по последовательности объектов, т.е. проходит через каждый элемент в последовательности. Мы узнаем больше о последовательностях на следующих уроках, а пока просто запомните, что последовательность – это упорядоченный набор элементов.

Пример:

for i in range(1, 6):
    print(f'i = {i}')

Вывод:

i = 1
i = 2
i = 3
i = 4
i = 5

В этом примере функция range возвращает объект последовательнсоти. Обратите внимание, что правая граница не включается.

Есть несколько способов создания последовательности с помощью функции range.

range(stop)
range(start, stop)
range(start, stop, step)

Возвращает последовательность от start до stop (не включительно) с шагом step.

Оператор break

Оператор break служит для прерывания цикла, т.е. остановки выполнения команд даже если условие выполнения цикла ещё не приняло значения False или последовательность элементов не закончилась.

Пример:

while True:
    command = input('> ')
    if command == 'exit':
        break

Оператор continue

Оператор continue используется, чтобы пропустить все оставшиеся команды в текущем блоке цикла и продолжить со следующей итерации цикла. Пример:

for i in range(5):
    if i == 2 or i == 3:
        continue
    print(i)

Задачи

В задачах указано, какой цикл рекомендуется использовать для их решения.

  1. [for] Пользователь вводит числа a и b. Вывести все целые числа, расположенные между ними.

  2. [for] Доработать предыдущую задачу так, чтобы выводились только числа, делящиеся на 5 без остатка.

  3. [for] Пользователь вводит число. Вывести таблицу умножения на это число

  4. [for] В цикле получать от пользователя оценки по четырём экзаменам. Вывести сумму набранных им баллов.

  5. [while] В бесконечном цикле приложение запрашивает у пользователя числа. Ввод завершается, как только пользователь вводит слово ‘end’. После завершения ввода приложение выводит сумму чисел.

  6. [while] Получить от пользователя натуральное число, посчитать сумму цифр в нём.

  7. Пользователь вводит число n и цифру a. Определить, сколько раз цифра встречается в числе. (не использовать метод count)

Easygui

Easygui - библиотека, которая используется для быстрого создания простых графичеческих интерфейсов

Функции

msgbox(message)

Создаёт новое окно, в котором будет написано сообщение message и кнопка ok

buttonbox(message, choices=[])

Создаёт новое окно с заданными кнопками. В возвращает текст кнопки, которая была нажата

integerbox(message, lowerbound=0, upperbound=99)

Создаёт новое окно, в котором можно вводить числа в диапозоне от lowerbound до upperbound, возвращает введённое пользователем число

Официальная документация: https://easygui.readthedocs.io/en/master/api.html

Задание

Используя шаблон проекта, реализуйте игры «Камень, ножницы, бумага» и «Угадай число»:

import easygui


def rock_paper_scissors():
    easygui.msgbox('Здесь будет игра "Камень, ножницы, бумага"')


def guess_the_number():
    easygui.msgbox('Здесь будет игра "Угадай число"')


games = [
    'Камень, ножницы, бумага',
    'Угадай число'
]

games_entry_points = [
    rock_paper_scissors,
    guess_the_number
]

while True:
    res = easygui.buttonbox('Выбери игру!', choices=games)
    if res is None:
        break
    games_entry_points[games.index(res)]()

Шаблон проекта в архиве: games.zip

Инструкция по установке

  1. Запустить программу “командная строка” (cmd.exe)

  2. Ввести команду “python -m pip install easygui”

Где:

python - интерпретатор питона; -m - команда на запуск другой программы; pip - менеджер пакетов; install - команда на установку какой-либо библиотеки; easygui - название библиотеки.

Игра Города

Классическая игра “Города”

Игра начинается с того что один из игроков называет город и следующему игроку нужно назвать город, который будет начинаться на последнюю букву предыдущего:

- Новосибирск
- Кемерово
- Оренбург

Задание

  1. Реализовать версию, в которой будет возможность вводить любые слова и будет проверка на совпадение первой и последней буквы

  2. Сделать так чтобы можно было вводить слова в любом регистре

  3. Добавить проверку на существование города, который введёт пользователь

  4. Сделать чтобы города не могли повторяться

  5. Добавить графический интерфейс с помощью библиотеки easygui

  6. Добавить возможность играть с компьютером. Для этого потребуется библиотека random и функция choice

    Модули с подготовленными списками городов:

Файловый ввод-вывод

Обычно работа с файлами состоит из следующих этапов:

  1. Открыть файл. При открытии следует указать режим: чтение или запись.

  2. Выполнить чтение или запись данных.

  3. Закрыть файл.

Рассмотрим функции для выполнения этих действий.

open(file_path, mode='r')

Открыть файл file_path в режиме mode. Функция возвращает file object. Полная сигнатура функции приведена в официальной документации: open. Режим может принимать значения:

  • 'r'read, чтение

  • 'w'write, запись

f.write(text)

Записать строку text в файл.

f.read()

Прочитать все данные из файла

f.close()

Закрыть файл f.

Пример работы с файлом:

# Открываем файл для записи
out_file = open('data.txt', 'w')

# Пишем в файл две строки
out_file.write('Hello\n')
out_file.write('World\n')

# Закрываем файл
out_file.close()

# Снова открываем этот же файл, но уже для чтения
in_file = open('data.txt', 'r')

# Файл — итерируемый объект. Следовательно, для
# его построчного чтения можно использовать цикл for
for line in in_file:
    print(f'Got line: {line}')

in_file.close()

Задачи

  1. Написать программу, которая будет получать у пользователя строку и записывать её в файл “data.txt”

  2. Разработать приложение, которое записывает в файл все строки, введенные пользователем. Признак конца ввода — пустая строка. Пример:

    Введите имя файла: data.txt
    Начните вводить строки
    > one
    > two
    > three
    >
    
    Файл записан.
    

    После выполнения программы должен появиться файл data.txt, содержащий три строки:

    one
    two
    three
    
  3. Написать программу, которая будет получать у пользователя путь к файлу и выводить его содержимое на экран

  4. Доработать предыдущее приложение для нумерации строк в файле. Приложение принимает на вход имя файла и выводит его построчно, добавляя к каждой строке её номер. Если использовать файл, созданный в предыдущей задаче, то результат работы программы будет выглядеть так:

    Введите имя файла: data.txt
    
    1 one
    
    2 two
    
    3 three
    

    Используйте метод строки rstrip(), чтобы избавиться от лишних переносов сток. После этого результат работы программы примет вид:

    Введите имя файла: data.txt
    1 one
    2 two
    3 three
    
  5. Разработать приложение для разделения файла на части. Приложение принимает на вход имя файла для разделения и целое число N. На выходе у приложения множество файлов, каждый из которых содержит не более, чем N строк из исходного файла.

    Пусть на вход программе подается файл data.txt, со следующим текстом:

    one
    two
    three
    four
    five
    six
    seven
    eight
    nine
    ten
    

    Будем разделять его на несколько файлов, в каждом из которых окажется не более трех строк:

    Введите имя входного файла: data.txt
    Введите максимальное количество строк: 3
    

    После выполнения программы должны быть созданы файлы 1.txt, 2.txt и так далее. В файле 1.txt будут сроки:

    one
    two
    three
    

    В файле 2.txt:

    four
    five
    six
    

    И так далее.

  6. Разработать приложение для объединения файлов. Приложение принимает на вход имена файлов для объединения (можно использовать файлы, полученные из предыдущего задания) и имя выходного файла.

Дополнительные задачи

  1. Разработайте приложение, которое выводит N первых строк файла.

  2. Разработайте приложение, которое выводит N последних строк файла.

Шифр Цезаря

Шифр Цезаря — это вид шифра подстановки, в котором каждый символ в открытом тексте заменяется символом, находящимся на некотором постоянном числе позиций левее или правее него в алфавите. Например, в шифре со сдвигом вправо на 3, A была бы заменена на D, B станет E, и так далее.

Для кодирования одного символа используется формула:

encoded_symbol = first + (symbol - first + key) % (last - first + 1)

Здесь:

  • encoded_symbol — код зашифрованного символа

  • symbol — код исходного символа

  • key — ключ шифрования

  • first — код первого символа алфавита

  • last — код последнего символа алфавита.

Для преобразования символа в код и обратно используются функции:

ord(c)

Возвращает код символа с.

chr(i)

Возвращает символ, соответствующий коду i.

Задание

Каждая задача — отдельный этап реализации приложения для шифрования.

  1. Напишите функцию encode_symbol. Функция принимает символ и число, на которое его нужно сдвинуть, а также первую и последнюю буквы алфавита.

  2. Используя функцию из предыдущего задания, доработайте программу, чтобы она могла шифровать строки, введённые пользователем. Для удобства можно написать функцию encode_str. Функция принимает строку и ключ шифрования и возвращает зашифрованную строку.

  3. Добавьте возможность шифрования текстовых файлов. Для этого напишите функцию encode_file(input_file_path, output_file_path, key).

  4. Напишите для приложения графический интерфейс с помощью easygui. Для открытия шифруемого файла используйте функцию easygui.fileopenbox(msg=None, title=None). Для сохранения зашифрованного файла используйте easygui.filesavebox(msg=None, title=None). Для ввода ключа — easygui.integerbox(msg="", title=" ").

Словари

Основные определения

Словарь

Неупорядоченная коллекция объектов произвольного типа с доступом по ключу. Представлены типом dict.

Множество

Неупорядоченная коллекция объектов произвольного типа, в которой не имеются дубликаты. Представлены типом set.

Неупорядоченная коллекция

Коллекция, в которой элементы не индексируются и нельзя делать срезы

Создание словарей

>>> d = {}
>>> type(d)
<class 'dict'>
>>> d = {"Name": "John", "Last Name": "Connor"}
>>> d
{'Name': 'John', 'Last Name': 'Connor'}

Динамическое создание словарей:

# Словарь можно создать, передав список пар ключ-значение
pairs = [('Name', 'John'), ('Age', 19)]
d = dict(pairs)
print(d)
{'Name': 'John', 'Age': 19}


# Можно создавать такие пары с помощью функции zip
id = (1, 2, 3, 4,)
logins = ('Vasya', 'Petya', 'Lera')
# Функция zip упаковывает несколько последовательностей в кортежи
d = dict(zip(logins, id))
print(d)
{'Vasya': 1, 'Petya': 2, 'Lera': 3}

Добавление элементов осуществляется с помощью фигурных скобок:

>>> d['Age'] = 19

Получение элемента по ключу:

>>> d['Age']
19

Методы словарей

d.get(key)

Получение элемента по заданному ключу:

>>> d.get('Name')
'John'
>>> d.get('Not Presented Key')
None
d.keys()

Получение списка всех ключей

>>> d.keys()
dict_keys(['Name', 'Last Name'])
d.values()

Получение списка всех значений в словаре

>>> d.values()
dict_values(['John', 'Connor'])
d.items()

Получение списка пар ключ-значение, представленных в виде кортежей:

>>> d.items()
dict_items([('Name', 'John'), ('Last Name', 'Connor')])
d.pop(key)

Извлечение элемента из словаря:

>>> d = {'Name': 'John', 'Last Name': 'Connor'}
>>> d.pop('Name')
'John'
>>> d
{'Last Name': 'Connor'}
dict.fromkeys(seq, value)

Создаёт новый словарь, в котором ключи взяты из последовательности seq и им установлены значения по умолчанию value:

>>> lst = ['uesr1', 'user2', 'user3']
>>> user_logins_with_passwords = dict.fromkeys(lst, 123456)
>>> user_logins_with_passwords
{'user1': 123456, 'user2': 123456, 'user3': 123456}

Задачи

  1. Напишите программу, которая получает на вход набор слов и выводит на экран только уникальные. Использовать тип set.

  2. Доработать программу, чтобы она получала от пользователя путь до файла со словами

  3. Написать программу, которая на вход получает файл и выводит на экран какое слово сколько раз встречалось. Использовать тип dict. Содержимое файла:

    слово
    фраза
    предложение
    слово
    

    Пример вывода:

    Путь к файлу: words.txt
    слово: 2
    фраза: 1
    предложение: 1
    
  4. Создайте функцию compute_bill, считающаю итоговую сумму товаров в чеке. Функция должна принимать 1 параметр - словарь, в котором указано количество едениц товара. Цены хранятся в словаре:

    prices = {
      "banana": 4,
      "apple": 2,
      "orange": 1.5,
      "pear": 3
    }
    
  5. Создайте программу, которая будет выводить все возможные комбинации при броске 2 игральных костей и сумму их значений. Пример вывода:

    2: [(1, 1)]
    3: [(1, 2), (2, 1)]
    ...
    

Основы работы с библиотекой requests

В основе ежедневной работы пользователей в сети Интернет лежит обмен данными между клиентскими приложениями (например браузер) и веб-серверами. В соответствии с прикладным протоколом HTTP, клиент отправляет запрос (request) на получение определенного ресурса к серверу и получает от него ответ (response). Ответ, помимо самого запрошенного ресурса, содержит также служебную информацию.

Библиотека requests предоставляет удобный способ отправки HTTP-запросов и обработки ответов от сервера.

Рассмотрим функцию get, которая нам потребуются для отправки простых запросов.

requests.get(url, params=None, **kwargs)

Отправить GET-запрос. Функция принимает URL-адрес запрашиваемого ресурса и возвращает объект типа Response. Также возможна передача в функцию дополнительных параметров запроса.

Пример отправки запроса на получение ресурса:

url = 'http://api.forismatic.com/api/1.0/'
payload  = {'method': 'getQuote', 'format': 'json', 'lang': 'ru'}
res = requests.get(url, params=payload))

Теперь мы можем получить все необходимые данные из Response-объекта res.

Проверяем URL ресурса:

>>> res.url
'http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=ru'

Проверяем код ответа HTTP:

>>> res.status_code
200

Получаем заголовки ответа:

>>> res.headers
{'Date': 'Tue, 19 Feb 2019 19:27:34 GMT', 'Content-Type': 'application/json' ... }

Получаем содержимое ответа в текстовом формате:

>>> res.text

В случае бинарного содержимого ответа воспользуемся атрибутом content:

>>> res.content

Если данные в ответе представлены в формате json их можно декодировать и получить словарь:

>>> data = res.json()
>>> data['quoteText']
'Тот, кто не смотрит вперед, оказывается позади'
>>> data['quoteAuthor']
'Герберт Уэллс '

Подробная документация к библиотеке доступна по адресу: http://docs.python-requests.org/en/master/api/

Множество интернет-сервисов предоставляют программистам API (Application programming interface) — интерфейс получения данных посредством запросов, а также документацию к нему.

Задачи

  1. Реализовать приложение для получения случайных цитат.

    Шаг 1. Изучите API сервиса forismatic.com: http://forismatic.com/en/api/

    Шаг 2. С помощью модуля easygui разработайте приложение с графическим интерфейсом для получения цитат на русском и английском языках.

  2. Реализовать приложения для загрузки картинок с котиками:

    Шаг 1. Изучите API сервиса cataas.com: https://cataas.com/#/

    Шаг 2. С помощью модуля easygui разработайте приложение для загрузки случайных картинок с котиками. Картинка содержится в ответе от сервера в бинарном виде.

  3. https://date.nager.at/

Игра ‘Лабиринт’

Лабиринт - игра в которой нужно выйти из помещения сложной формы с большим количеством разветвлений.

Пример игрового поля:

maze = [
    "## #########",
    "##        ##",
    "####### ####",
    "#F## #  ## #",
    "#   ## ##  #",
    "###       ##",
    "#########@##"
]

В данном игровом поле ‘#’ обозначает стену, ‘F’ - ключ, а ‘@’ - дверь

Задание

  1. Написать функцию для рисования игрового поля

  2. Добавить возмонжость пользовательского ввода для перемещения персонажа

  3. Добавить проверки на столкновение со стеной

  4. Доработать игру, чтобы можно было подбирать ключ с его помощью открывать дверь

Классы

Класс — шаблон, описывающий правила создания и поведение объекта.

Объект — экземпляр, созданный на основе шаблона.

Поле — используется для хранения значения.

Метод — функция, связанная с классом.

Магический метод — зарезервированные методы, отвечающие за поведение объекта.

Название

Применение

__init__

Инициализация объекта

__str__

Преобразование к строке str(obj)

__eq__

Проверка на равенство ==

__getitem__

Оператор доступа к элементам
some_dict[“item”]

Пример:

class Person:  # Объявление класса
    def __init__(self, name, age): # Метод инициализации или по другому конструктор
        self.age = age   # Установка значений полей
        self.name = name

    def __str__(self):
        return f"{self.name} is {self.age} years old"


person = Person('John', 20)  # Создание экземпляра
person.name = 'James' # Установка значения поля

print(person)

Здесь __init__ определяет как будет создаваться новый объект и какие параметры будет принимать при создании.

__str__ определяет как экземпляр будет печататься на экране с помощью функции print и преобразовываться к строке с помощью str.

Задачи

  1. Создать класс, описывающий человека. Должны быть поля для имени, фамилии и возраста. Создать экземпляр и вывести информацию о человеке.

  2. Доработать предыдущий класс, чтобы вся информация о человеке была доступна при вызове str над экземпляром.

  3. Добавить метод greet, вызов которого будет выводить в консоль информацию о человеке в формате "Привет! Меня зовут Петров Василий, мне 12 лет".

  4. Добавить поле grades, в котором будет храниться список оценок. Создать список учеников, заполняя оценки каждого случайными числами.

  5. Вывести информацию об учениках в порядке убывания среднего балла. Подсчёт среднего балла вынести в отдельный метод.

  6. Создайте класс Point, экземпляры которого будут создаваться из координат x и y.

  7. Создайте класс прямоугольник — Rectangle. Метод __init__ принимает две точки — левый нижний и правый верхний угол. Каждая точка представлена экземпляром класса Point. Реализуйте методы вычисления площади и периметра прямоугольника.

  8. Добавьте в класс Rectangle метод contains. Метод принимает точку и возвращает True, если точка находится внутри прямоугольника и False в противном случае.

Инкапсуляция

В объектно-ориентированных языках программирования есть спецификаторы, ограничивающие доступ к аттрибутам. Главной задачей является отделение деталей реализации логики объекта от того как с ним надо взаимодействовать.

В языке Python в отличие от многих других языков вместо ключевых слов используется знак нижнего подчёркивания.

public - Данный аттрибут доступен всем:

class Person:
  def __init__(self, name):
    self.name = name    # публичный аттрибут

p = Person("John")
p.name = "Mark"

private - Аттрибут сокрыт от посторонних глаз и доступен только самому объекту:

class Person:
  def __init__(self, name, age):
    self.name = name
    self.set_age(age)

  def get_age(self):
    return self.__age

  def set_age(self, age):
    if age >= 0:
      self.__age = int(age)  # __age - приватный аттрибут
    else:
      self.__age = 0
      print("Возраст не может быть отрицательным!")

p = Person("John", 19)
print(p.get_age()) # 19

p.set_age(20)
print(p.get_age()) # 20

p.__age = 21 # Error
p._Person__age = 21
print(p.get_age()) # 21

Задачи

  1. Описать класс десятичного счётчика. Он должен обладать внутренней переменной, хранящей текущее значение, методами повышения значения (increment) и понижения (decrement), получения текущего значения get_counter. Учесть, что счётчик не может опускаться ниже 0.

  2. Создать класс для часов. Должна быть возможность установить время при создании объекта. Также необходимо реализовать методы, с помощью которых можно добавлять по одной минуте/секунде или по одному часу к текущему времени. Помнить, что значения минут и секунд не могут превышать 59, а часов 23.

  3. Доработать предыдущую задачу, чтобы можно было складывать двое часов друг с другом. Для перегрузки оператора + использовать метод __add__(self, other).

  4. Создать классы для травоядного животного и травы. Животное должно уметь поедать траву, если испытывает голод, в противном случае отказываться от лакомства. Трава должна обладать питательностью, в зависимости от которой животное будет насыщаться.

Основы PyGame

Pygame — библиотека, предназначенная для разработки мультимедийных приложений с графическим интерфейсом, например игр.

Документация, обучающие материалы и дополнительная информация доступна разработчикам на сайте проекта: https://www.pygame.org/docs/

Начало работы

Начнем знакомство с библиотекой непосредственно с разбора примера простого приложения:

import pygame
import sys

pygame.init()

screen = pygame.display.set_mode((1200, 800))

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

В первую очередь импортируем модуль pygame в наш файл с исходным кодом:

import pygame

Затем вызываем функцию init() для подготовки модулей pygame к работе:

pygame.init()

После этого создаем графическое окно, передав в качестве аргумента в функцию set_mode() его разрешение в виде пары целых чисел. В свою очередь функция вернет нам объект типа Surface, используемый для представления изображений:

screen = pygame.display.set_mode((1200, 800))

Далее, запускаем основной цикл программы, в котором, среди всех событий, происходящих в нашем приложении, перехватываем событие закрытия основного графического окна пользователем:

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

После того как ожидаемое событие наступило, завершаем работу с библиотекой pygame вызовом функции pygame.quit() и нашей программы вызовом функции exit() из модуля sys.

Рисование геометрических фигур

Разместим в окне нашего приложения прямоугольник. Прямоугольные объекты представлены типом Rect:

Rect(left, top, width, height)
Rect((left, top), (width, height))

Для создания объекта этого типа нам необходимо указать координаты левого верхнего угла прямоугольника и длины его сторон:

r = Rect(0, 0, 100, 200)

Обратите внимание, что начало координат (0, 0) находится в левом верхнем углу окна.

В библиотеке pygame функции отображения геометрических фигур находятся в модуле draw. Нарисуем прямоугольник c помощью функции rect():

rect(Surface, color, Rect, width=0) -> Rect

Для этого передадим в функцию в качестве аргументов поверхность, на которой мы размещаем прямоугольник, его цвет, сам прямоугольник и толщину линии — стороны прямоугольника. Если толщина равна нулю прямоугольник закрашивается сплошным цветом.

Рассмотрим готовый пример:

import pygame
import sys

pygame.init()

screen = pygame.display.set_mode((1000, 800))
r = pygame.Rect(50, 50, 100, 200)
pygame.draw.rect(screen, (255, 0, 0), r, 0)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.flip()

Обратите внимание на последнюю строку нашей программы. На самом деле графические объекты которые мы хотим разместить на основном экране сначала попадают в специальный буфер. Чтобы отобразить изменения стали видны вызываем функцию flip().

Функции для рисования графических фигур

pygame.draw.rect(Surface, color, Rect, width=0)

Нарисовать прямоугольник Rect на поверхности Surface, цветом color. Если толщина линии width равна нулю, прямоугольник закрашивается.

pygame.draw.line(Surface, color, start_pos, end_pos, width=1)

Нарисовать линию на поверхности Surface, цветом color, с началом в точке start_pos, концом в точке end_pos и толщиной линии width.

pygame.draw.lines(Surface, color, closed, pointlist, width=1)

Нарисовать линию, соединяющую точки из последовательности pointlist на поверхности Surface, цветом color, с толщиной линии width. Каждая точка представлена парой координат. Если параметр closed равен True, конечная точка соединяется с начальной.

pygame.draw.circle(Surface, color, pos, radius, width=0)

Нарисовать окружность на поверхности Surface, цветом color, с центром в точке pos и радиусом radius. Если толщина линии width равна нулю, окружность закрашивается.

pygame.draw.ellipse(Surface, color, Rect, width=0)

Нарисовать эллипс, ограниченный прямоугольником Rect, на поверхности Surface, цветом color. Если толщина линии width равна нулю, эллипс закрашивается.

pygame.draw.polygon(Surface, color, pointlist, width=0)

Нарисовать многоугольник по точкам из последовательности pointlist на поверхности Surface, цветом color, с толщиной линии width. Каждая точка представлена парой координат. Если толщина линии width равна нулю многоугольник закрашивается.

Цвет

Цвета в библиотеке pygame представлены в соответствии с моделью RGB: https://ru.wikipedia.org/wiki/RGB

Значение для цвета можно задать тройкой чисел, каждое из которых лежит в диапазоне от 0 до 255. Первое значение в последовательности определяет, какое количество красного содержится в данном оттенке, второе - зеленого, третье - голубого. Чем меньше значение числа, тем темнее будет оттенок. Например, красный цвет можно представить как (255, 0, 0), белый как (255, 255, 255), а черный как (0, 0, 0).

Помимо этого, в модуле color из библиотеки pygame содержится словарь THECOLORS, ключами которого являются названия различных цветовых оттенков. Подключить его можно с помощью команды:

from pygame.color import THECOLORS

Закрасим основной экран c помощью метода fill():

screen = pygame.display.set_mode((1200, 800))
screen.fill(THECOLORS['orange'])

Текст и шрифты

При работе с текстом мы будем использовать шрифты - группы символов объединенных по стилистическому или иному признаку. Шрифты в библиотеке pygame представлены типом Font

Чтобы создать объект Font на основе имеющегося в системе шрифта вызовем следующую функцию:

SysFont(name, size, bold=False, italic=False)

С помощью параметра name передаем в функцию имя шрифта, параметр size - размер шрифта в пунктах. Параметры bold и italic отвечают за начертание шрифта.

Список имеющихся в системе шрифтов можно получить с помощью функции get_fonts():

pygame.font.get_fonts() -> list of strings

Далее, с помощью метода render() нашего объекта типа Font получаем изображение с текстом, которое передаем на вход методу blit() для отрисовки на нашем основном экране:

screen = pygame.display.set_mode(size)
screen.fill(THECOLORS['white'])
font = pygame.font.SysFont('couriernew', 40)
text = font.render(str('HELLO'), True, THECOLORS['green'])
screen.blit(text, (50, 50))

Текст размещается в на основном экране по координатам (50, 50)

Задания

1. Используя функции для работы с графикой библиотеки pygame, нарисуйте дом с квадратным основанием и треугольной крышей.

2. Используя функции для работы с графикой библиотеки pygame, нарисуйте белый флаг с олимпийскими кольцами.

3. Разработайте программу, которая разбивает основное игровое окно на клетки заданного размера.

4. Доработайте программу так, чтобы в каждой клетке был записан её порядковый номер.

5. Доработайте в программу возможность закрашивания клетки с произвольным номером случайным цветом. Номера клеток которые необходимо закрасить считывать из файла.

Обработка ввода и анимации

События

Взаимодействие пользователя с компьютером основано на событиях, любые действия производимые пользователем порождают события - движение мыши, нажатия клавиш, специальных кнопок. Внутри библиотеки PyGame есть инструменты для обратки событий, которые происходят внутри приложений.

Мы с вами уже знакомы с методом получения всех произошедших событий - pygame.event.get(), который возвращает события, произошедшие с последнего обращения.

Помимо событий выхода из приложения pygame.QUIT, есть множество других - например, нажатия клавиш pygame.KEYDOWN или отпускания pygame.KEYUP.

Рассмотрим взаимодействие с событиями на примере небольшой программы, в которой по нажатию клавиш показывается квадрат:

import sys
import pygame

pygame.init()

screen = pygame.display.set_mode((640, 480))
rect = pygame.Rect(40, 40, 120, 120)
color = (0, 0, 0)   

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.KEYDOWN:
            color = (255, 255, 255)

    pygame.draw.rect(screen, color, rect, 0)
    pygame.display.flip()

В данном блоке программа занимется обработкой нажатия клавиш. Сначала мы получаем список всех событий, после чего начинаем последовательно проверять их. Если одно из событий соответствует сигналу к завершению программы, закрываем окно. Если же это нажатие клавиши - перекрашиваем прямоугольник в белый цвет.

События

Когда генерируется

KEYDOWN

При нажатии клавиш

KEYUP

При отпускании клавиш

QUIT

При нажатии кнопки закрытия программы

MOUSEMOTION

При движении мыши

Обработка нажатий клавиш

Когда мы нажимаем клавишу, в систему передаётся не только информация о том, что какая-то кнопка нажата, но и её код.

Есть два способа получить нажатые клавиши:
  1. pygame.event.get()

  2. pygame.key.get_pressed()

С первым мы уже знакомы, поэтому стоит внимательнее рассмотреть второй. Он позволяет получить список клавиш, которые нажаты в данный момент в виде кортежа булевых значений. Чтобы узнать нажата ли интересующая нас кнопка, необходимо проверить значение, которе содержится в данном кортеже:

keys = pygame.key.get_pressed()
if keys[pygame.K_RETURN]:
    print("Нажата клавиша enter")

Перемещение объектов

Умея получать от пользователя ввод, мы можем реализовать движения наших фигур на экране:

import sys
import pygame

pygame.init()

screen = pygame.display.set_mode((640, 480))
rect = pygame.Rect(40, 40, 120, 120)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                rect.move_ip(-40, 0)
            elif event.key == pygame.K_RIGHT:
                rect.move_ip(40, 0)
            elif event.key == pygame.K_UP:
                rect.move_ip(0, -40)
            elif event.key == pygame.K_DOWN:
                rect.move_ip(0, 40)

    pygame.draw.rect(screen, (255, 0, 0), rect, 0)

    pygame.display.flip()

Для движения объектов используются методы move() и move_ip(), которыми обладают объекты, созданные с помощью функций из pygame.draw. Первый создаёт новую фигуру такого же типа, находящуюся по заданному смещению, второй непосредственно изменяет положение имеющейся фигуры.

Запустив данный код, вы можете заметить, что при перемещении фигуры от неё остаётся “след”. Это связано с тем, что при перемещении объекта, мы его не перемещаем на экране, а рисуем на новом месте поверх старого кадра.

Чтобы избежать данной проблемы, надо добавить вызов метода fill() у нашего экрана, на котором мы рисуем и передать ему цвет, которым надо закрасить фон. Данное действие надо проводить каждый раз перед отрисовкой кадра:

# здесь могла быть ваша проверка событий
screen.fill((0, 0, 0))
pygame.draw.rect(screen, (255, 0, 0), rect, 0)
pygame.display.flip()

Использование спрайтов

Спрайт - двумерное изображение, используемое в играх.

pygame.image.load(path)

Функция для загрузки спрайта из картинки. Path - путь до изображения, возвращает объект типа Surface, который можно использовать для рисования.

Для отрисовки спрайта на экране надо вызвать метод blit() у поверхности на которой производится отрисовка и передать объект спрайта вместе с координатами на которых необходимо отрисовать:

screen = pygame.display.set_mode((640, 480))
sprite = pygame.image.load("sprite.png")

screen.blit(sprite, (20, 20))
pygame.quit()

Анимации

В pygame анимации создаются при помощи набора спрайтов, которые последовательно отрисовываются:


animation_set = [pygame.image.load(f"r{i}.png") for i in range(1, 6)]

window = pygame.display.set_mode((640, 480))

clock = pygame.time.Clock()
i = 0
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    window.fill((0,0,0))
    window.blit(animation_set[i // 12], (100, 20))
    i += 1
    if i == 60:
        i = 0

    pygame.display.flip()
    clock.tick(60)

Создаём список спрайтов, каждый из которых будет отдельным кадром анимации:

animation_set = [pygame.image.load(f"r{i}.png") for i in range(1, 6)]

Создаём часы, для ограничения количества кадров в секунду:

clock = pygame.time.Clock()

Вспомогательная переменная, которая поможет выбирать нужную анимацию в зависимости от номера кадра:

i = 0

Выбор анимации в зависимости от номера кадра и его отрисовка:

window.blit(animation_set[i // 12], (100, 20))

Изменение переменной, помогающей выбрать нужный кадр:

i += 1
if i == 60:
   i = 0

Ограничение количества кадров в секунду, благодаря чему становится проще просчитывать анимации и синхронизировать события:

clock.tick(60)

Задания

  1. Написать программу, которая будет писать в консоль названия нажатых клавиш. Реализовать поддержку enter, space, w, a, s, d, esc. Названия кнопок внутри библиотеки доступны в официальной документации: https://www.pygame.org/docs/ref/event.html

  2. С помощью циклов, используя квадрат 10х10 пикселей и его след, нарисовать рамку 100х100 пикселей.

  3. Написать программу, в которой по нажатию клавиш будет двигаться квадрат размером 20х20 пикселей. Учесть, что квадрат не должен выходить за границы экрана.

  4. Доработать программу, чтобы квадрат при каждом движении менял свой цвет на случайный.

  5. Реализовать анимацию движения персонажа. При движении влево или вправо должны показываться соответствующие анимации. Кадры для них взять из архива animations.zip

Обработка столкновений

  1. Реализуйте игровую сцену, состоящую из движущейся цели и пушки, стреляющей снарядами.

"""
+-----------------------+
|   ||||||              | <- target
|                       |
|                       |
|           *           | <- bullet
|                       |
|                       |
|          /'\          | <- cannon
+-----------------------+
"""

import random
import sys

import pygame
from pygame.color import THECOLORS

pygame.init()

WIDTH = 640
HEIGHT = 480

screen = pygame.display.set_mode((WIDTH, HEIGHT))


class Cannon:
    def __init__(self):
        # TODO(1.1): создайте атрибуты пушки:
        #  * Цвет
        #  * Список точек
        #  Пусть пушка отображается как равнобедренный треугольник с высотой
        #  и основанием по 50px. Отображается в середине окна
        #  на нижней границе, см. схему в начале файла.
        ...

    def draw(self):
        # TODO(1.2): отобразите созданную в __init__ последовательность точек
        #  заданным цветом.
        ...


class Bullet:
    def __init__(self):
        # TODO(2.1): создайте атрибуты снаряда.
        #  * Центр окружности снаряда
        #  * Радиус
        #  * Цвет
        #  * Скорость (для тестов использовать значение 3)
        ...

    def draw(self):
        # TODO(2.2): отобразите снаряд.
        ...

    def move(self):
        # TODO(2.3): реализуйте перемещение снаряда.
        #  Для этого нужно создать его новый центр со смещением speed по оси OY
        #  к началу коориднат.
        ...


class Target:
    def __init__(self):
        # TODO(3.1): создайте атрибуты мишени.
        #  * Цвет
        #  * Скорость
        #  * Прямоугольник
        ...

    def draw(self):
        # TODO(3.2): отобразите мишень.
        ...

    def move(self):
        # TODO(3.3): реализуйте движение мишени.
        #  При достижении края окна мишень должна менять направление движения
        #  на противположное. Это можно реализовать сменой знака сокрости.
        ...


colors = list(THECOLORS.values())
def get_random_color():
    return random.choice(colors)


cannon = Cannon()
target = Target()
bullet = Bullet()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    screen.fill(THECOLORS['black'])

    target.move()
    bullet.move()

    # TODO(2.4): если снаряд достиг верхней границы окна, создать новый снаряд.

    # TODO(4.1): если мишень и снаряд пересеклись, сменить цвет мишени на
    #  случайный, создать новй снаряд.
    #  Для определения пересечения используйте метод прямоугольника:
    #    Rect.collidepoint(point)

    cannon.draw()
    target.draw()
    bullet.draw()

    pygame.display.flip()
    pygame.time.wait(33)
  1. Реализуйте простейший тир, в котором игрок должен кликать по цели.

import math
import random
import sys

import pygame
from pygame.color import THECOLORS

pygame.mixer.init(22050, -16, 2, 64)
pygame.init()

WIDTH = 640
HEIGHT = 480

screen = pygame.display.set_mode((WIDTH, HEIGHT))

color = THECOLORS['purple1']

circle_radius = 50


def distance(p1, p2):
    # TODO(3.3): Реализуйте функцию, которая вычисляет
    #  расстояние между точками p1 и p2.
    ...


def point_in_circle(p, circle_center, circle_radius):
    # TODO(3.2): Реализуйте функцию, которая возвращает True,
    #  если точка находится внутри круга.
    #  Для полноценной работы функции вам понадобится
    #  реализовать функцию distance, но написать определение
    #  принадлежности точки кругу вы можете уже сейчас.
    ...


def place_circle():
    # TODO(1.1): Функция должна вернуть кортеж, состоящий из
    #   координат центра круга: (x, y)
    ...

# TODO(1.2): инициализируйте центр круга
circle_center = ...

# TODO(5.1): Загрузите звук выстрела.
#  Воспользуйтесь конструктором
#  pygame.mixer.Sound(file_path: str) -> Sound
shot = ...

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        # TODO(2.1): Обработайте событие нажатия кнопки мыши
        #  pygame.MOUSEBUTTONDOWN
        # TODO(2.2): При нажатии кнопки мыши смените цвет круга.
        # TODO(3.1): Доработайте приложение так, чтобы круг менял цвет только
        #  если вы кликаете по нему. Для этого вам понадобирся реализовать
        #  функции point_in_circle и distance.
        # TODO(4.1): доработайте приложение так, чтобы при
        #  клике по кругу он появлялся в случайной точке
        #  экрана.
        # TODO(5.2): Воспроизведите звук выстрела в случае попадания по кругу.
        #  Используйте метод play() объекта класса Sound.
        # TODO(6.1): Реализуйте подсчет очков. Если игрок попал в круг за
        #  секунду, то он получает 100 очков. За 2 секунды - 50. Дольше - 1.
        ...

    screen.fill(THECOLORS['black'])

    # TODO(1.3) Нарисуйте круг выбранного цвета.
    ...

    pygame.display.flip()
    pygame.time.wait(33)
  1. Реализуйте движущийся шар, отскакивающий от стен.

import math
import sys

import pygame
from pygame.color import THECOLORS

pygame.init()

WIDTH = 1280
HEIGHT = 800

screen = pygame.display.set_mode((WIDTH, HEIGHT))

circle_center = (WIDTH // 2, HEIGHT // 2)
circle_radius = 50
circle_color = THECOLORS['purple2']

SPEED = 20

current_angle = -10


def get_move(angle):
    angle = angle / 180. * math.pi
    return (
        int(SPEED * math.cos(angle)),
        int(SPEED * math.sin(angle)))


def move_circle(center, move):
    # TODO(1): функция возвращает новый центр окружности после смещения.
    ...


def get_angle(center):
    # TODO(2): Функция принимает текущий центр круга и определяет,
    #  под каким углом он должен продолжать движение.
    ...

move = get_move(current_angle)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    screen.fill(THECOLORS['black'])

    # TODO(3):
    #  * Вычислить угол движения круга.
    #  * Вычислить вектор движения
    #  * Вычислить новый центр окружности

    pygame.draw.circle(screen, circle_color, circle_center, circle_radius)

    pygame.display.flip()
    pygame.time.wait(33)

Звук выстрела: shot.wav.

Лабиринт

Каркас проекта и руководство в архиве: maze.zip

Змейка

Скачать шаблон: snake.py

import pygame
import random
import sys


# Размеры окна в пикселях
WINDOW_WIDTH = 640
WINDOW_HEIGHT = 480

CELL_SIZE = 20

# Размеры сетки в ячейках
WIDTH = int(WINDOW_WIDTH / CELL_SIZE)
HEIGHT = int(WINDOW_HEIGHT / CELL_SIZE)

# Цвета
BG_COLOR = (0, 0, 0)
GRID_COLOR = (40, 40, 40)
APPLE_COLOR = (255, 0, 0)
APPLE_OUTER_COLOR = (155, 0, 0)
SNAKE_COLOR = (0, 255, 0)
SNAKE_OUTER_COLOR = (0, 155, 0)


UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'

HEAD = 0


FPS = 15


class Cell:
    def __init__(self, x, y):
        self.x = x
        self.y = y


def main():
    global FPS_CLOCK
    global DISPLAY

    pygame.init()
    FPS_CLOCK = pygame.time.Clock()
    DISPLAY = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
    pygame.display.set_caption('Wormy')

    while True:
        # Мы всегда будем начинать игру с начала. После проигрыша сразу
        # начинается следующая.
        run_game()


def run_game():
    # TODO(2.1): создать яблоко в позиции (20, 10)

    # TODO(3.1): создать змейку. Пусть она состоит из трех ячеек
    #  в строке 10 и столбцах 3, 4, 5.
    #  Какой тип данных удобен для представления змейки?

    # TODO(4.1): задать исходное направление движения змейки.
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                terminate()
            # TODO(7.1): обработайте событие pygame.KEYDOWN
            #  и при необходимости измените направление движения змейки.

        # TODO(5.1): если змейка достигла границы окна, завершить игру.
        #  Для проверки воспользуйтесь функцией snake_hit_edge.

        # TODO(8.1): если змейка задела свой хвост, завершить игру.
        #  Для проверки восппользуйтесь функцией snake_hit_self.

        # TODO(6.1): обработайте ситуацию столкновения змейки с яблоком.
        #  В этом случае нужно:
        #  * Увеличить размер змейки
        #  * Создать новое яблоко.

        # TODO(4.2): сдвинуть змейку в заданном направлении
        # TODO(2.2): передать яблоко в функцию отрисовки кадра
        # TODO(3.2): передать змейку в функцию отрисовки кадра
        draw_frame(None, None)
        FPS_CLOCK.tick(FPS)


def draw_frame(snake, apple):
    DISPLAY.fill(BG_COLOR)
    draw_grid()
    draw_snake(snake)
    draw_apple(apple)
    pygame.display.update()


def draw_grid():
    # TODO(1.2): нарисовать сетку.
    #  Шаг CELL_SIZE
    #  Цвет GRID_COLOR
    #  https://www.pygame.org/docs/ref/draw.html#pygame.draw.line
    ...


def draw_apple(apple):
    # TODO(2.3): нарисовать яблоко.
    ...


def draw_snake(snake):
    # TODO(3.3): нарисовать змейку.
    ...


def draw_cell(cell, outer_color, inner_color):
    # TODO(2.4): вспомогательная функция для рисования ячейки.
    #  Ячейка будет состоять из двух квадратов разных цветов:
    #  Больший квадрат закрашивается цветом outer_color,
    #  меньший - inner_color.
    #  Расстояние между внешним и внутренним квадратом
    #  принять за 4 пикселя.
    ...


def move_snake():
    # TODO(4.3): реализовать перемещение змейки на одну ячейку
    #  в заданном направлении.
    #  * Какие параметры будет принимать функция?
    #  * Из каких действий будет состоять перемещение змейки?
    ...


def get_snake_new_head():
    # TODO(4.4): реализовать функцию определения нового
    #  положения головы змейки.
    #  * Какие параметры будет принимать функция?
    #  * Что функция будет возвращать?
    ...


def snake_hit_edge():
    # TODO(5.2): функция возвращает True,
    #  если змейка пересекла одну из границ окна.
    ...


def snake_hit_apple():
    # TODO(6.2): функция возвращает True, если голова
    #  змейки находится в той же ячейке, что и яблоко.
    ...


def snake_grow():
    # TODO(6.3): предложите максимально простой
    #  способ увеличения длины змейки.
    ...


def new_apple():
    # TODO(6.4): функция возвращает случайную ячейку,
    #  в которой будет располагаться яблоко.
    #  Для генерации случайной координаты воспользуйтесь
    #  функцией random.randint(a, b)
    ...


def get_direction():
    # TODO(7.3): функция возвращает направление движения
    #  в зависимости от нажатой клавиши:
    #  * pygame.K_LEFT
    #  * pygame.K_RIGHT
    #  * pygame.K_UP
    #  * pygame.K_DOWN
    #  Если нажата клавиша противоположного направления движения,
    #  то не менять направление.
    ...

def snake_hit_self():
    # TODO(8.2): функция возвращает True, если голова змеи
    #  пересеклась хотя бы с одним блоком хвоста.
    ...


def terminate():
    pygame.quit()
    sys.exit()


if __name__ == '__main__':
    main()