« Программируем трехмерную графику с Irrlicht . Часть 3 | Программируем трехмерную графику с Irrlicht . Часть 5 » |
Программируем трехмерную графику с Irrlicht . Часть 4
Эффективное программирование 3d-приложений с помощью Irrlicht и jython. Часть 4.
Продолжим начатое в предыдущей статье серии рассмотрение возможностей python. В прошлый раз мы дошли только до условного оператора, позволяющего делать выбор из некоторого количества альтернатив развития алгоритма. На основании определенного условия мы совершаем одно действие, если условие выполнилось или истинно, и другое если это не так.
И так давайте рассмотрим более сложный пример, это будет игра “угадай число”. В ней машина загадывает некоторое число и предлагает пользователю угадать это число за некоторое количество попыток, всякий раз, когда пользователь ошибается, программа сообщает ему больше или меньше введенное им число, чем то, которое загадала машина.
Этот пример пройдет почти через весь оставшийся материал, отведенный для изучения собственно средств python до перехода к irrlicht. Вам будет нужно дорабатывать и развивать задачу, добавляя новые функции, демонстрирующие разные приемы программирования и культуры разработки:
>>> import sys
>>> secret_num = 1
>>> while 1:
... print 'guess secret num - угадай какое число я задумал'
... num = int ( sys.stdin.readline () )
... if (num == secret_num):
... print 'yes - да ты угадал - это действительно число', num
... break
... elif num > secret_num:
... print 'less - число должно быть меньше'
... else:
... print 'bigg - число должно быть больше'
...
guess secret num - угадай какое число я задумал
12
less - число должно быть меньше
guess secret num - угадай какое число я задумал
23
less - число должно быть меньше
guess secret num - угадай какое число я задумал
1
yes - да ты угадал - это действительно число 1
Дело в том, что почти любая самая сложная программа определяется как некоторая комбинация или чередования элементарных шагов, которые бывают линейными, это когда есть несколько действий выполняемых друг за другом и именно в таком порядке, именно эти действия, и эти шаги неизменны как налоги и смерть. Что более часто бывает, так это выбор из двух, трех, ста и более вариантов возможных алгоритмов расчета.
В примерах выше мы рассчитывали количество дней в високосном году на основании делимости номера года на 4. И нас были две возможные ситуации либо номер года поделился на 4, либо нет. Какая из этих двух ситуаций сработает в общем случае не известно до тех пор пока не программа не получит от пользователя все необходимые для работы данные.
Третий типовой прием – это цикл, многократное выполнение некоторого набора действий – его мы называем телом цикла. Если есть тело, то должна быть и голова – под головой принимают то, что определяет или принимает решение сколько раз, или до какого момента следует повторять те действия, которые и организуют тело цикла.
В простейших случаях мы можем легко вычислить сколько раз нужно выполнить тело цикла, в более сложных этот момент нам не известен. Например, в примере ниже я точно знаю сколько раз нужно выполнить тело.
>>> i = 0
>>> while (i < 10) :
... print i
... i = 1 + i
...
В условии (голове цикла) проверяется то, что переменная i не превзошла собой 10, если это так, то делаем два действия образующих тело цикла: распечатываем текущее значение переменной на экран, а увеличиваем ее на единицу.
Один из самых страшных врагов настоящего программиста это бесконечный цикл, называется он так, потому что он никогда не заканчивается. Так в примере выше если бы я забыл присвоить переменной I значение на единицу более, или же ошибочно присвоил бы ей значение I = I – 1, то условие головы цикла никогда бы не выполнилось, и заполнился бы ваш экран бесконечным потоком ползущих цифр, прямо “матрица дома” какая то получается.
Хотя, рано или поздно вы все равно сделаете сами свой первый бесконечный цикл, давайте посмотрим, что делать в подобной ситуации.
Итак, сделайте вышеозначенный бесконечный цикл, убрав увеличение, или как говорят настоящие программисты инкремент, переменной I (соответственно, термин декремент означает уменьшение значения переменной на единицу). И запустите скрипт заново.
Давным-давно, когда я писал на c/c++, то при возникновении бесконечного цикла, не только процессор загружался на все 100%, но ощутимо притормаживала система: мышь перемещалась медленно и степенно, иногда было проще нажать reset, чем дождаться реакции О.С. Время меняется, сейчас таких эффектов нет.
Когда вам надоест бесконечное мельтешение цифр на экране, просто нажмите ctrl-break или ctrl-c, что скажет машине python стоп, хватит выполнять текущую программу. В отдельных случаях бесконечные циклы нужны, т.е. конечно, они не нужны, но прием их использования бывает полезен.
В примере с игрой угадай число, условие головы цикла записано как просто 1 - цифра один. Те из вас кто знаком с с/с++ и им подобными языками скажет, ага здесь тоже истина - не ноль, а ноль – ложь. Что в переводе на понятный язык означает, когда вы записываете какое-либо выражение в условии оператора if или же while, то машина python все сводит только к двум полярным состояниям: ноль и не ноль. Например, while 1 – это не ноль, while 2+3 – тоже не ноль, и даже while 1 < 2 – также не ноль, а вот while 0, while 1 > 2 или while ‘’ или же while “” – это ноль, примите это пока как аксиому.
Так вот если вычисленное выражение в заголовке оператора – это не ноль, то тело оператора if или while выполняется, если же это не так, и выражение в голове вычислялось как ноль, то тело соответственно не выполняется. Всегда можно прервать выполнение оператора цикла с помощью команды break – дословно, стоп, хватит выполнять данный цикл, и не важно чему равно условие в его заголовке. Для чтения данных используется функция num = int ( sys.stdin.readline () ), здесь идет обращение к импортированном нами (в первой строке программы) модулю sys, далее через точку.
Точку воспринимайте как аналог слова “внутри”. И так внутри sys есть stdin, внутри которого есть функция (почему функция – потому что когда функция вызывается, то после ее имени всегда пишется круглые скобки и иногда даже что-то внутри этих скобок – то что называется хитрым словом аргумент). Так стоп, что есть функция и модуль.
Т.е. конечно все мы интуитивно понимаем, что такое функция, но нам нужно четкое определение и обязательно с учетом специфики программирования и конкретно python.
Под функций понимают некоторое количество кода, строк, операторов простых, условных или операторов цикла, которые так часто используются, что мы решили дать им имя, и получить возможность вызова этого набора команд только по его имени.
Делаем это мы не только из-за лени, настоящий программист, как известно, должен быть ленив, чтобы сделать один раз так, чтобы в последующие разы ничего не нужно было делать. Например, функция может, скажем, выводить на экран фразу “Здравствуйте дорогой, Василий Пупкин” и ожидать нажатия любой клавиши для продолжения. Но зачем нам нужна функция, которая умеет приветствовать только одного Василия Пупкина. Это не универсально и, следовательно, не позволяет достичь нирваны ничего не делания.
Функции могут получать в качестве входных данных (или аргументов) некоторые переменные, например переменная fio, хранящая ФИО пользователя. Функции в математике нечто другое, да у них тоже есть какие то аргументы, но они и возвращают некоторую величину, рассчитанную на основании этих аргументов. Функции в Python (а равно как и в любом другом языке программирования, также что-то возвращают). Вот вам еще пример функции.
>>> import math
>>> print math.sin(1);
0.841470984808
>>> d = math.sin(1);
>>> print d;
0.841470984808
Конечно, если вам работодатель платит деньги на почасовой основе, то можете этим заниматься снова и снова. Мне же платят именно за конечный продукт. Запомните, централизация – это ключ к успеху, собрав в одном месте все потенциально повторяющиеся фрагменты кода и оформив их как функции, вы экономите свое время и нервы. Собрав же все функции в одном месте, почему бы не дать этой коллекции отдельное имя и не обозначить термином модуль. (Да я знаю, уважаемые многоопытные программисты на python, что здесь я немного лукавлю, но нельзя же все делать сразу).
Возвращаясь к примеру, мы прочитали строку с помощью sys.stdin.readline (), но теперь необходимо преобразовать ее к типу данных число, целое если быть точнее, для этого и служит оператор int (то, что нужно преобразовать к числу).
>>> print 1 == "1"
False
>>> print 1 == int("1")
True
Последний момент: мы организовали с помощью операторов if проверку трех возможных ситуаций: число было угадано - в этом случае необходимо сообщить пользователю об успехе и прекратить цикл, а раз он был организован как бесконечный, то необходим способ досрочного прерывания цикла с помощью оператора break. Остальные две ситуации когда число было не угадано, тривиальны – необходимо сообщить пользователю об неудаче и подсказать больше или меньше оно чем задуманное машиной число.
Теперь начнем развивать данную задачу для самотренировки (я буду ставить перед вами цель, код достигающий которую вам нужно писать самим, сам же ограничусь схожими примерами и разъяснения теоретических моментов):
Развивающее задание № 1. Загаданное машиной число должно быть не явно задано в теле программы, а генерироваться случайно, в некотором диапазоне от A до B. Вам будет нужна функция random.randint (0, 100), которая служит для генерации случайного числа в отрезке от и до. Только предварительно нужно проимпортировать модуль random. Два числа A,B задающие диапазон в котором будет генерироваться число должно вводиться с клавиатуры пользователем. Не забудьте выполнить проверку введенных чисел на корректность, очевидно что A должно быть менее чем B. Если это условие не выполняется, то дальнейшее продолжение программы не возможно. Сообщите об ошибке пользователю и прервите выполнение программы досрочно.
Вот вам маленькая подсказка:
import random
import os
print 'hello user' #печатаем приветствие
num = random.randint (0, 100) # генерируем случайное число
print num # печатаем случайное число
if num < 50:# если это число менее чем 50 то завершаем работу программы
print 'number to small'
raw_input ("press any key to close application")
os._exit (0)# завершаем работу программы
print num, ' * ',num,'= ', num*num # если же число достаточно велико то вычисляем значение его квадрата
raw_input ("press any key to close application")
Комментарии начинаются с символа # и продолжаются до конца строки, вы вольны писать в них, что угодно, но общей рекомендацией является не дублировать код, например, так:
print ‘hello’ # распечатываем на экран слово hello
print ‘hello’ # начинаем программу с приветствия пользователю см. тех. задание раздел 2.1
>>> import random
>>> help(random.randint)
Help on method randint in module random:
randint(self, a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
Развивающее задание № 2. За каждую неудачную попытку должны будут начисляться штрафные очки, по правилу: с первой по 3-ю неудачные попытки– 0 штрафных баллов, для 4-ой неудачной попытки – 1 балл, для 5-ой попытки – 2 балла, для 6-ой – 3 балла и так далее. В конце работы программы должно выводиться число штрафных баллов.
Развивающее задание № 3. Наша игра должна длиться не один раунд как сейчас, а произвольное их количество. Так после того как пользователь угадает число, необходимо спросить его желает ли он продолжить игру. Если он ответить да (например, введя слово yes в ответ на наш запрос) – игра продолжается. В противной ситуации необходимо завершить работу программы указав сколько всего раундов было сыграно, а также среднее число попыток которое тратилось во всех раундах для того чтобы угадать число.
Вот вам еще маленькая подсказка:
import sys
print 'вводите числа пока вам не надоест это'
count = 0
sum = 0
while 1:
print 'Введи очередное число, или слово "stop" для того чтобы прервать программу'
line = sys.stdin.readline ()
line = line.strip ()
# это очень важный момент в программе, дело в том, что функция readline
читает строку с клавиатуры включая символ ввода, который завершает строку,
если не вызвать функцию strip, то в следующей строке сравнение будет
всегда неудачно, ведь слово ‘stop’ не равно слову stop с завершающим символом ввода.
if line == 'stop':
break
else:
count = 1 + count
# подсчет количества введенных чисел
sum = float(line) + sum
# накапливаем сумму вводимых чисел,
важно здесь необходимо выполнить преобразование введенной строки к вещественному числу
print 'среднее арифметическое всех введенных чисел: ', sum / count
# очень приятный прием позволяющий выводить длинные строки текста,
# мы можем разбить одну длинную строку на несколько используя для разделения
# символ обратного слэша перед началом второй строки текста
print 'очень длинная строка содержащая много много\
символов, так что они не умещаются ...'
raw_input ("press any key to close application")
« Программируем трехмерную графику с Irrlicht . Часть 3 | Программируем трехмерную графику с Irrlicht . Часть 5 » |