Журнал LinuxFormat - перейти на главную

LXF102:Flash-карточки

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Новая: {{Цикл/Программирование}} == Кодируем: Flash-карточки == : ''ЧАСТЬ 2 Улучшите навыки программиста и выучите и...)
 
Строка 3: Строка 3:
 
: ''ЧАСТЬ 2 Улучшите навыки программиста и выучите иностранный язык – помогут '''Майк Сондерс''' и ваш собственный инструмент для показа всплывающих карточек...''
 
: ''ЧАСТЬ 2 Улучшите навыки программиста и выучите иностранный язык – помогут '''Майк Сондерс''' и ваш собственный инструмент для показа всплывающих карточек...''
  
Одна из причин нашей любви к компьютерам – их способ-
+
Одна из причин нашей любви к компьютерам – их способность просто работать. Конечно, устройства могут ломаться,
ность просто работать. Конечно, устройства могут ломаться,
+
 
а программы – содержать ошибки, но когда все в порядке,
 
а программы – содержать ошибки, но когда все в порядке,
ваши данные не исчезнут как по волшебству. Если вы загрузите, ска-
+
ваши данные не исчезнут как по волшебству. Если вы загрузите, скажем, норвежский словарь, ваш ПК без возражений сохранит его для
жем, норвежский словарь, ваш ПК без возражений сохранит его для
+
 
последующих вызовов. ПК не будет уставать или пытаться изучить
 
последующих вызовов. ПК не будет уставать или пытаться изучить
 
другой язык; не сможет он и упиться до полного забвения места, куда
 
другой язык; не сможет он и упиться до полного забвения места, куда
Строка 13: Строка 11:
 
ее файлы на почве ревности. В целостной системе данные всегда
 
ее файлы на почве ревности. В целостной системе данные всегда
 
под рукой.
 
под рукой.
Однако здесь, в царстве людей, мы постоянно боремся с недочета-
+
 
ми и изворотами нашей мысли. Мы вечно все забываем, меняем свое
+
Однако здесь, в царстве людей, мы постоянно боремся с недочетами и изворотами нашей мысли. Мы вечно все забываем, меняем свое
 
мнение – короче, лучше бы наш мозг походил на ОЗУ, а не на серые
 
мнение – короче, лучше бы наш мозг походил на ОЗУ, а не на серые
комки органики. Всего очевиднее это при изучении иностранного язы-
+
комки органики. Всего очевиднее это при изучении иностранного языка: компьютер хранит миллионы слов и никогда их не «забывает», а мы
ка: компьютер хранит миллионы слов и никогда их не «забывает», а мы
+
с трудом припоминаем, как по-английски «встреча», даже если использовали это слово вчера. Спасибо, мозг.
с трудом припоминаем, как по-английски «встреча», даже если исполь-
+
 
зовали это слово вчера. Спасибо, мозг.
+
 
Итак, проект кодирования этого месяца – создание программы
 
Итак, проект кодирования этого месяца – создание программы
 
всплывающих карточек (flash-карт), которая помогает запоминать
 
всплывающих карточек (flash-карт), которая помогает запоминать
Строка 35: Строка 32:
 
языку Python (выпуски [[LXF74-75:Python|74/75]]–[[LXF83:Python|83]]). Не пугайтесь, если вы пропустили
 
языку Python (выпуски [[LXF74-75:Python|74/75]]–[[LXF83:Python|83]]). Не пугайтесь, если вы пропустили
 
прошлый номер или никогда не писали на Python: в нем очень легко
 
прошлый номер или никогда не писали на Python: в нем очень легко
разобраться. Если вы знакомы хоть с одним языком программирова-
+
разобраться. Если вы знакомы хоть с одним языком программирования, то не встретите проблем при работе с этим кодом.
ния, то не встретите проблем при работе с этим кодом.
+
 
 
Наше приложение flash-карт должно будет читать текстовые файлы
 
Наше приложение flash-карт должно будет читать текстовые файлы
 
и генерировать случайные числа. Открытие файлов в Python – плевое
 
и генерировать случайные числа. Открытие файлов в Python – плевое
Строка 43: Строка 40:
 
Теперь создайте файл с именем test.py, также в домашнем каталоге, со
 
Теперь создайте файл с именем test.py, также в домашнем каталоге, со
 
следующим содержимым:
 
следующим содержимым:
file = open(‘foo.txt’, ‘r’)
+
<source lang="python">file = open(‘foo.txt’, ‘r’)
print file.readlines()
+
print file.readlines()</source>
 
Для запуска этого Python-скрипта откройте терминал и введите:
 
Для запуска этого Python-скрипта откройте терминал и введите:
python test.py
+
python test.py
Этот код открывает foo.txt (‘r’ означает «только для чтения») и свя-
+
Этот код открывает foo.txt (‘r’ означает «только для чтения») и связывает его содержимое с новым объектом по имени file.
зывает его содержимое с новым объектом по имени file.
+
 
 
Во второй строке кода мы вызываем readlines() нашего объекта file,
 
Во второй строке кода мы вызываем readlines() нашего объекта file,
 
который сканирует foo.txt и сохраняет его строки как элементы массива.
 
который сканирует foo.txt и сохраняет его строки как элементы массива.
 
При его печати на экране мы увидим:
 
При его печати на экране мы увидим:
[‘hello\n’, ‘banana\n’, ‘cupcake\n’]
+
<source lang="python">[‘hello\n’, ‘banana\n’, ‘cupcake\n’]</source>
Понятно, слова будут те, которые вы ввели в foo.txt. Но отсюда вид-
+
Понятно, слова будут те, которые вы ввели в foo.txt. Но отсюда видно, как Python получает текст из файла и выводит элементы массива
но, как Python получает текст из файла и выводит элементы массива
+
 
через запятую. Ну, хорошо; а если мы хотим нормально отобразить
 
через запятую. Ну, хорошо; а если мы хотим нормально отобразить
 
текст файла?
 
текст файла?
file = open(‘foo.txt’, ‘r’)
+
<source lang="python">file = open(‘foo.txt’, ‘r’)
 
for line in file:
 
for line in file:
print line
+
print line</source>
 
Этот код выводит все строки из foo.txt. Заметьте, что отступы в
 
Этот код выводит все строки из foo.txt. Заметьте, что отступы в
 
Python важны – табуляция перед print line говорит о том, что этот код
 
Python важны – табуляция перед print line говорит о том, что этот код
Строка 65: Строка 61:
 
(for) каждой строки открытого нами файла, напечатать ее, и так до
 
(for) каждой строки открытого нами файла, напечатать ее, и так до
 
конца файла.
 
конца файла.
 +
 
Итак, мы теперь можем получать текст из файлов и использовать
 
Итак, мы теперь можем получать текст из файлов и использовать
 
списки слов для наших flash-карточек. Но надо сделать еще кое-что:
 
списки слов для наших flash-карточек. Но надо сделать еще кое-что:
 
наша программа должна отобразить список возможных ответов при
 
наша программа должна отобразить список возможных ответов при
выводе слова. Кроме того, было бы крайне бесполезно, если бы вер-
+
выводе слова. Кроме того, было бы крайне бесполезно, если бы верным ответом был всегда первый! Поэтому в нашей программе мы собираемся отображать три возможных ответа, один из которых правильный. Вот как получить случайные числа:
ным ответом был всегда первый! Поэтому в нашей программе мы соби-
+
<source lang="python">import random
раемся отображать три возможных ответа, один из которых правиль-
+
ный. Вот как получить случайные числа:
+
import random
+
 
a = random.randint(1, 5)
 
a = random.randint(1, 5)
 
b = random.randint(30, 100)
 
b = random.randint(30, 100)
print a, b
+
print a, b</source>
Первая строка говорит Python, что мы хотим использовать его гене-
+
Первая строка говорит Python, что мы хотим использовать его генератор случайных чисел. После этого мы создаем две переменные: a и
ратор случайных чисел. После этого мы создаем две переменные: a и
+
 
b, и присваиваем им случайные значения стандартной подпрограммой
 
b, и присваиваем им случайные значения стандартной подпрограммой
Python random.randint(). Мы указываем диапазон значений – для пере-
+
Python random.randint(). Мы указываем диапазон значений – для переменной a это будет число от 1 до 5 (включительно). Для b – число между 30 и 100. Легко!
менной a это будет число от 1 до 5 (включительно). Для b – число меж-
+
ду 30 и 100. Легко!
+
  
 
=== Создаем flashcard.py 1.0 ===
 
=== Создаем flashcard.py 1.0 ===
 +
[[Изображение:LXF102 69 1.png|thumb|Первая инкарнация нашей программы flash-карт – простой текстовый вариант.]]
 
Давайте поработаем с программой. Нам понадобятся два текстовых
 
Давайте поработаем с программой. Нам понадобятся два текстовых
 
файла: в одном – английские слова, в другом – соответствующие
 
файла: в одном – английские слова, в другом – соответствующие
Строка 89: Строка 81:
 
а во втором – названия их столиц.) Важно, чтобы оба файла имели
 
а во втором – названия их столиц.) Важно, чтобы оба файла имели
 
одинаковое число строк и соответствие слов для каждой их пары.
 
одинаковое число строк и соответствие слов для каждой их пары.
Если вы используете названия столиц и седьмая строка первого фай-
+
Если вы используете названия столиц и седьмая строка первого файла – это «Япония», то седьмая строка второго файла должна содержать
ла – это «Япония», то седьмая строка второго файла должна содержать
+
 
«Токио». Иначе ответы не подойдут!
 
«Токио». Иначе ответы не подойдут!
Итак, создадим два текстовых файла в домашнем каталоге и вве-
+
 
дем по десять слов в каждый из них, по одному в строке. В нашем при-
+
Итак, создадим два текстовых файла в домашнем каталоге и введем по десять слов в каждый из них, по одному в строке. В нашем примере, первый файл называется english.txt и содержит слова ‘Thanks,
мере, первый файл называется english.txt и содержит слова ‘Thanks,
+
word, job’ и т.д.; второй файл называется russian.txt и содержит ‘спасибо, слово, работа’ и т.д. Теперь нам необходим код на Python, чтобы
word, job’ и т.д.; второй файл называется russian.txt и содержит ‘спа-
+
сибо, слово, работа’ и т.д. Теперь нам необходим код на Python, чтобы
+
 
работать с этими текстовыми файлами в домашнем каталоге – и вот
 
работать с этими текстовыми файлами в домашнем каталоге – и вот
вам листинг. Он есть на нашем DVD (flashcard.py в разделе Magazine/
+
вам листинг. Он есть на нашем DVD (flashcard.py в разделе Magazine/CodeProject), но пока просто пробегитесь по нему...
CodeProject), но пока просто пробегитесь по нему...
+
 
<source lang="python"># -*- coding: utf_8 -*-
 
<source lang="python"># -*- coding: utf_8 -*-
 
import os, random
 
import os, random
Строка 130: Строка 118:
 
каталоге откройте терминал и введите python flashcard.py. Вы увидите,
 
каталоге откройте терминал и введите python flashcard.py. Вы увидите,
 
что программа отображает английское слово, а ниже – три возможных
 
что программа отображает английское слово, а ниже – три возможных
русских эквивалента. Эти эквиваленты пронумерованы, и если вы счи-
+
русских эквивалента. Эти эквиваленты пронумерованы, и если вы считаете, что верный ответ – это 3, просто нажмите 3, а затем Enter. После
таете, что верный ответ – это 3, просто нажмите 3, а затем Enter. После
+
 
этого программа скажет вам, правы вы или ошибаетесь – всего будет
 
этого программа скажет вам, правы вы или ошибаетесь – всего будет
 
задано десять вопросов.
 
задано десять вопросов.
 +
 
Давайте рассмотрим код более детально. Мы начали строкой с
 
Давайте рассмотрим код более детально. Мы начали строкой с
 
import [Русская версия скрипта начинается с указания используемой
 
import [Русская версия скрипта начинается с указания используемой
в системе кодировки, в противном случае программа не будет выпол-
+
в системе кодировки, в противном случае программа не будет выполняться, – прим. пер.], которая говорит Python, какие возможности
няться, – прим. пер.], которая говорит Python, какие возможности
+
 
мы собираемся использовать. В нашем случае необходимо вызывать
 
мы собираемся использовать. В нашем случае необходимо вызывать
 
функцию ОС (для очистки экрана) и генерировать случайные числа.
 
функцию ОС (для очистки экрана) и генерировать случайные числа.
Затем мы описываем две переменные, count и score – первая исполь-
+
Затем мы описываем две переменные, count и score – первая используется для отображения десяти вопросов, а вторая запоминает число
зуется для отображения десяти вопросов, а вторая запоминает число
+
 
верных ответов. Далее идет:
 
верных ответов. Далее идет:
file1 = open(‘english.txt’, ‘r’)
+
<source lang="python">file1 = open(‘english.txt’, ‘r’)
 
file2 = open(‘russian.txt’, ‘r’)
 
file2 = open(‘russian.txt’, ‘r’)
 
f1content = file1.readlines()
 
f1content = file1.readlines()
f2content = file2.readlines()
+
f2content = file2.readlines()</source>
Здесь мы открываем два файла и связываем их с двумя перемен-
+
Здесь мы открываем два файла и связываем их с двумя переменными с именами file1 и file2. Эти переменные – вроде дескрипторов
ными с именами file1 и file2. Эти переменные – вроде дескрипторов
+
 
этих файлов: они представляют файлы, сохраненные в памяти. Но нам
 
этих файлов: они представляют файлы, сохраненные в памяти. Но нам
не нужны просто сами файлы; нам необходимо их содержимое, поэто-
+
не нужны просто сами файлы; нам необходимо их содержимое, поэтому следующие две строки кода по кусочкам переносят реальный текст
му следующие две строки кода по кусочкам переносят реальный текст
+
 
в два массива с именами f1content и f2content. Теперь у нас есть список
 
в два массива с именами f1content и f2content. Теперь у нас есть список
 
английских слов в f1content и список русских слов в f2content. Затем
 
английских слов в f1content и список русских слов в f2content. Затем
 
начинается основной цикл программы:
 
начинается основной цикл программы:
while count < 10:
+
<source lang="python">while count < 10:
 
os.system(‘clear’)
 
os.system(‘clear’)
 
wordnum = random.randint(0, len(f1content)-1)
 
wordnum = random.randint(0, len(f1content)-1)
print ‘Слово:’, f1content[wordnum], ‘’
+
print ‘Слово:’, f1content[wordnum], ‘’</source>
 +
{{Врезка
 +
|Заголовок=Скорая помощь
 +
|Содержание=Если при ваших
 +
экспериментах
 +
с кодом Python
 +
программа
 +
зациклилась,
 +
ее можно снять
 +
из терминала, нажав
 +
Ctrl+C. Вам может
 +
понадобиться сделать
 +
это пару раз,
 +
особенно если
 +
ваша программа
 +
ждет ввода
 +
от пользователя.
 +
Если ваша
 +
программа все-таки
 +
не останавливается,
 +
наберите в терминале
 +
ps ax, найдите номер
 +
процесс Python
 +
вашего скрипта
 +
и введите kill -9
 +
<number>. Это
 +
команда абсолютного
 +
останова программы
 +
|Ширина=200px}}
 
Мы хотим задать десять вопросов, то есть выполнить весь код с
 
Мы хотим задать десять вопросов, то есть выполнить весь код с
отступом десять раз (переменная-счетчик каждый раз увеличивает-
+
отступом десять раз (переменная-счетчик каждый раз увеличивается). Первая строка этого цикла очищает экран, вызывая стандартную
ся). Первая строка этого цикла очищает экран, вызывая стандартную
+
 
утилиту /usr/bin/clear, а затем мы отображаем случайное слово. Мы
 
утилиту /usr/bin/clear, а затем мы отображаем случайное слово. Мы
говорим: wordnum должно принять случайное значение, представ-
+
говорим: wordnum должно принять случайное значение, представляющее строку в файле слов, так что дай мне число между нулем и
ляющее строку в файле слов, так что дай мне число между нулем и
+
 
размером файла (в строках). Хотя файл слов может иметь строки от
 
размером файла (в строках). Хотя файл слов может иметь строки от
 
первой до десятой, массивы нумеруются с нуля, вот почему мы берем
 
первой до десятой, массивы нумеруются с нуля, вот почему мы берем
Строка 171: Строка 181:
 
массива, а строка десять – девятый. Затем мы отображаем слово из
 
массива, а строка десять – девятый. Затем мы отображаем слово из
 
файла english.txt.
 
файла english.txt.
options = [random.randint(0, len(f2content)-1),
+
<source lang="python">options = [random.randint(0, len(f2content)-1),
 
random.randint(0, len(f2content)-1),
 
random.randint(0, len(f2content)-1),
 
random.randint(0, len(f2content)-1)]
 
random.randint(0, len(f2content)-1)]
options[random.randint(0, 2)] = wordnum
+
options[random.randint(0, 2)] = wordnum</source>
 
Далее создается массив трех возможных ответов с именем
 
Далее создается массив трех возможных ответов с именем
options. Мы задаем для каждого ответа случайное число, ограничен-
+
options. Мы задаем для каждого ответа случайное число, ограниченное сверху числом строк в f2content (russian.txt). Теперь у нас есть
ное сверху числом строк в f2content (russian.txt). Теперь у нас есть
+
 
три случайных русских слова – но стойте, одно из них должно быть
 
три случайных русских слова – но стойте, одно из них должно быть
 
верным, ведь так? Иначе получится три неверных ответа! Так что
 
верным, ведь так? Иначе получится три неверных ответа! Так что
положим один из ответов в options равным wordnum – то есть верно-
+
положим один из ответов в options равным wordnum – то есть верному. И вместо того, чтобы верный ответ всегда был, скажем, первым,
му. И вместо того, чтобы верный ответ всегда был, скажем, первым,
+
 
мы размещаем его в случайное место в списке из трех возможных
 
мы размещаем его в случайное место в списке из трех возможных
 
ответов.
 
ответов.
 +
 
Оставшийся код понять очень просто. Он печатает на экране три
 
Оставшийся код понять очень просто. Он печатает на экране три
 
возможных ответа затем запрашивает ответ у пользователя – то
 
возможных ответа затем запрашивает ответ у пользователя – то
есть ввод 1, 2 или 3. Когда пользователь вводит ответ, мы прове-
+
есть ввод 1, 2 или 3. Когда пользователь вводит ответ, мы проверяем, соответствует ли
ряем, соответствует ли
+
 
он верному слову. То
 
он верному слову. То
есть, если русское сло-
+
есть, если русское слово – «спасибо» и номер
во – «спасибо» и номер
+
 
варианта thanks – «2»,
 
варианта thanks – «2»,
когда пользователь вво-
+
когда пользователь вводит 2, наша программа
дит 2, наша программа
+
 
говорит: «Ах! Вариант
 
говорит: «Ах! Вариант
 
два является седьмым
 
два является седьмым
Строка 200: Строка 206:
  
 
=== Версия с картинками ===
 
=== Версия с картинками ===
 +
{{Врезка
 +
|Заголовок=PyGame умеет больше
 +
|Содержание=Наша вторая программа для flash-карт лишь поверхностно
 +
очертила то, что можно сделать с PyGame (http://www.pygame.org).
 +
Данная библиотека предоставляет множество инструментов
 +
для загрузки изображений, перемещения спрайтов, работы
 +
с клавиатурой/мышью и воспроизведения звуковых эффектов.
 +
Это популярный выбор программистов игр с открытым кодом;
 +
примеры того, что можно сделать, см. на http://www.pygame.org/tags/arcade.
 +
 +
А главное, PyGame имеет обширную документацию, включая
 +
учебники для абсолютных новичков и детальный справочник API.
 +
По адресу http://www.pygame.org/docs вы найдете учебники,
 +
описывающие с нуля, как инициализировать PyGame,
 +
перемещать спрайты и использовать пиксельные эффекты.
 +
[[Изображение:LXF102 71 1.png|thumb|300px|PyGame не ограничивается видеоиграми – вы можете использовать ее и для создания медиа-проигрывателя.]]
 +
|Ширина=400px}}
 
Теперь у нас есть текстовый инструмент flash-карт, превосходный для
 
Теперь у нас есть текстовый инструмент flash-карт, превосходный для
 
множества применений, а как насчет графической версии? Допустим,
 
множества применений, а как насчет графической версии? Допустим,
 
картинка с животным и три возможных названия – идеально для детей.
 
картинка с животным и три возможных названия – идеально для детей.
А может, вы захотите нарисовать национальные флаги – кстати, имен-
+
А может, вы захотите нарисовать национальные флаги – кстати, именно это мы и собираемся сделать. Как и прежде, программу можно преобразовать во что угодно, использующее слова и картинки: блюда и их
но это мы и собираемся сделать. Как и прежде, программу можно пре-
+
образовать во что угодно, использующее слова и картинки: блюда и их
+
 
названия на испанском, фотографии звезд и их имена...
 
названия на испанском, фотографии звезд и их имена...
Для этого необходимо выйти за границы командной строки и вос-
+
 
пользоваться графическим слоем. К счастью, у нас есть прекрасный
+
Для этого необходимо выйти за границы командной строки и воспользоваться графическим слоем. К счастью, у нас есть прекрасный
выбор для нашего Python-приключения: PyGame, библиотека, связы-
+
выбор для нашего Python-приключения: PyGame, библиотека, связывающая Python с популярным медиа-слоем SDL. PyGame позволяет
вающая Python с популярным медиа-слоем SDL. PyGame позволяет
+
 
создавать окна и отображать соответствующие картинки на экране,
 
создавать окна и отображать соответствующие картинки на экране,
причем с минимумом усилий. Собственно, большая часть кода оста-
+
причем с минимумом усилий. Собственно, большая часть кода останется той же – надо только заставить отображаться вместо текста
нется той же – надо только заставить отображаться вместо текста
+
 
картинки.
 
картинки.
Наша первая версия flashcard.py использовала два текстовых фай-
+
 
ла с соответствиями слов, а эта графическая инкарнация будет исполь-
+
Наша первая версия flashcard.py использовала два текстовых файла с соответствиями слов, а эта графическая инкарнация будет использовать соответствия слов и картинок. То есть file1.txt может содержать
зовать соответствия слов и картинок. То есть file1.txt может содержать
+
 
«Непал, Канада, Финляндия...», а file2.txt – ‘nepalflag.png, canadaflag.png,
 
«Непал, Канада, Финляндия...», а file2.txt – ‘nepalflag.png, canadaflag.png,
 
finlandflag.png...’ и так далее. Слова будем получать из file1, а картинки
 
finlandflag.png...’ и так далее. Слова будем получать из file1, а картинки
 
для отображения – из file2.
 
для отображения – из file2.
 +
 
Код для этого выйдет более длинный, и чтобы зря не тратить место,
 
Код для этого выйдет более длинный, и чтобы зря не тратить место,
 
мы приведем здесь лишь основную часть. Но это большая часть, и она
 
мы приведем здесь лишь основную часть. Но это большая часть, и она
вам покажет, как работает графическая версия. На нашем DVD в раз-
+
вам покажет, как работает графическая версия. На нашем DVD в разделе Magazine/CodeProject/Graphical имеется полный листинг кода со
деле Magazine/CodeProject/Graphical имеется полный листинг кода со
+
 
множеством комментариев (обозначенных символом #).
 
множеством комментариев (обозначенных символом #).
Заметьте, что перед запуском программы необходимо устано-
+
 
вить библиотеку PyGame: большинство дистрибутивов имеют ее
+
Заметьте, что перед запуском программы необходимо установить библиотеку PyGame: большинство дистрибутивов имеют ее
 
в своих репозиториях (поищите в вашем менеджере пакетов), но
 
в своих репозиториях (поищите в вашем менеджере пакетов), но
 
если это не так, исходный код вы найдете в разделе Разработка
 
если это не так, исходный код вы найдете в разделе Разработка
 
нашего DVD.
 
нашего DVD.
Вот наш основной кусок кода. Здесь есть несколько новых элемен-
+
 
тов, но, в типичной манере Python, по большей части все самодоку-
+
Вот наш основной кусок кода. Здесь есть несколько новых элементов, но, в типичной манере Python, по большей части все самодокументировано – открываем файл изображения, рисуем его на экране в
ментировано – открываем файл изображения, рисуем его на экране в
+
 
указанной позиции, и все.
 
указанной позиции, и все.
 
<source lang="python">init()
 
<source lang="python">init()
Строка 259: Строка 276:
 
display.update()</source>
 
display.update()</source>
 
Первые четыре строки кода говорят PyGame настроить экран. Мы
 
Первые четыре строки кода говорят PyGame настроить экран. Мы
инициализируем PyGame, а затем велим ему создать новое окно раз-
+
инициализируем PyGame, а затем велим ему создать новое окно размером 640 x 480 пикселей, поместив в заголовок окна соответствующий текст. Затем создаем новый шрифт: создадим объект с именем
мером 640 x 480 пикселей, поместив в заголовок окна соответствую-
+
щий текст. Затем создаем новый шрифт: создадим объект с именем
+
 
font, используя собственную систему шрифтов PyGame, и скажем
 
font, используя собственную систему шрифтов PyGame, и скажем
 
‘None’, что означает: нам неважно, какой шрифт использовать – пусть
 
‘None’, что означает: нам неважно, какой шрифт использовать – пусть
будет стандартный системный. А размер шрифта установим 48 пун-
+
будет стандартный системный. А размер шрифта установим 48 пунктов.
ктов.
+
 
 
Затем запускается главный цикл, выдавая десять вопросов. screen.
 
Затем запускается главный цикл, выдавая десять вопросов. screen.
 
fill(0) просто заполняет экран нулевым цветом, то есть черным – это
 
fill(0) просто заполняет экран нулевым цветом, то есть черным – это
Строка 271: Строка 286:
 
случайного слова, которое будет ответом, так же, как и в текстовой
 
случайного слова, которое будет ответом, так же, как и в текстовой
 
версии, а затем у нас идет:
 
версии, а затем у нас идет:
mainpic = image.load(f2content[wordnum].rstrip(‘\n’))
+
<source lang="python">mainpic = image.load(f2content[wordnum].rstrip(‘\n’))</source>
 
Это довольно большая инструкция, так что давайте разберем ее.
 
Это довольно большая инструкция, так что давайте разберем ее.
 
Мы создаем новый объект PyGame: картинку с именем mainpic, для
 
Мы создаем новый объект PyGame: картинку с именем mainpic, для
Строка 277: Строка 292:
 
и это должна быть картинка для верного ответа – а мы здесь сказали,
 
и это должна быть картинка для верного ответа – а мы здесь сказали,
 
чтоб Python выбрал ее случайным образом.
 
чтоб Python выбрал ее случайным образом.
 +
 
Как и до этого, в полном коде мы загружаем два текстовых файла
 
Как и до этого, в полном коде мы загружаем два текстовых файла
в f1content и f2content. f1content содержит список слов – в нашем слу-
+
в f1content и f2content. f1content содержит список слов – в нашем случае, «Непал, Канада, Финляндия...». f2content содержит список имен
чае, «Непал, Канада, Финляндия...». f2content содержит список имен
+
 
соответствующих файлов изображений: ‘nepalflag.png, canadaflag.png,
 
соответствующих файлов изображений: ‘nepalflag.png, canadaflag.png,
 
finlandflag.png...’. Наша переменная wordnum указывает на слово в
 
finlandflag.png...’. Наша переменная wordnum указывает на слово в
 
f1content, а также на имя файла связанного изображения в f2content.
 
f1content, а также на имя файла связанного изображения в f2content.
 
Если wordnum равно 2, то она может указывать на «Непал» в f1content
 
Если wordnum равно 2, то она может указывать на «Непал» в f1content
и ‘nepal.png’ в f2content – вот почему записи в файлах должны попар-
+
и ‘nepal.png’ в f2content – вот почему записи в файлах должны попарно соответствовать друг другу!
но соответствовать друг другу!
+
 
 
Итак, загружаем нашу картинку в соответствии с именем файла из
 
Итак, загружаем нашу картинку в соответствии с именем файла из
 
f2content, удалив символ перевода строки при помощи rstrip – не то
 
f2content, удалив символ перевода строки при помощи rstrip – не то
PyGame нас не поймет! Далее, делаем один из трех вариантов правиль-
+
PyGame нас не поймет! Далее, делаем один из трех вариантов правильным, как и ранее. Затем создаем три отрывка текста для отображения
ным, как и ранее. Затем создаем три отрывка текста для отображения
+
 
на экране. Вот первый:
 
на экране. Вот первый:
text1 = font.render(‘1 - ‘ + f1content[options[0]].rstrip(‘\n’),
+
<source lang="python">text1 = font.render(‘1 - ‘ + f1content[options[0]].rstrip(‘\n’),True, (255, 255, 255))</source>
True, (255, 255, 255))
+
[[Изображение:LXF102 71 2.png|thumb|При помощи Python и PyGame, мы теперь можем создать графический тест вроде этого.]]
 
Здесь создается новое изображение с именем text1, содержащее
 
Здесь создается новое изображение с именем text1, содержащее
первый случайный вариант из нашего списка слов f1content. True озна-
+
первый случайный вариант из нашего списка слов f1content. True означает, что текст должен быть сглаженным, а (255, 255, 255) – цвет текста
чает, что текст должен быть сглаженным, а (255, 255, 255) – цвет текста
+
 
в формате красный, зеленый, синий: белый, стало быть. Делаем то же
 
в формате красный, зеленый, синий: белый, стало быть. Делаем то же
 
для других вариантов, затем отрисуем (blit) текст на экране и обновим
 
для других вариантов, затем отрисуем (blit) текст на экране и обновим
 
его, чтобы все отобразилось.
 
его, чтобы все отобразилось.
 +
 
Оставшийся код с комментариями, который вы можете просмотреть
 
Оставшийся код с комментариями, который вы можете просмотреть
 
на нашем DVD, обрабатывает ввод пользователя. Мы проверяем, что
 
на нашем DVD, обрабатывает ввод пользователя. Мы проверяем, что
нажал пользователь – 1, 2 или 3 – и реагируем соответственно: выво-
+
нажал пользователь – 1, 2 или 3 – и реагируем соответственно: выводим «Верно!» и обновляем счетчик очков, или выводим «Неверно!».
дим «Верно!» и обновляем счетчик очков, или выводим «Неверно!».
+
 
Затем ждем нажатия Enter и вновь запускаем цикл.
 
Затем ждем нажатия Enter и вновь запускаем цикл.
  
Строка 309: Строка 322:
 
flash-карт – возможно, расширить его, включив пять вариантов вместо
 
flash-карт – возможно, расширить его, включив пять вариантов вместо
 
трех. А может быть, вы хотите записывать системное время в начале
 
трех. А может быть, вы хотите записывать системное время в начале
теста и сравнить его со временем по завершении теста, чтобы выстав-
+
теста и сравнить его со временем по завершении теста, чтобы выставлять оценку за быстроту!
лять оценку за быстроту!
+
 
 
С этой программой можно еще много чего сделать, и если у вас
 
С этой программой можно еще много чего сделать, и если у вас
 
получится что-то классное, пожалуйста, сообщите нам, и мы, возможно,
 
получится что-то классное, пожалуйста, сообщите нам, и мы, возможно,

Версия 21:07, 18 апреля 2009

Программирование

Содержание

Кодируем: Flash-карточки

ЧАСТЬ 2 Улучшите навыки программиста и выучите иностранный язык – помогут Майк Сондерс и ваш собственный инструмент для показа всплывающих карточек...

Одна из причин нашей любви к компьютерам – их способность просто работать. Конечно, устройства могут ломаться, а программы – содержать ошибки, но когда все в порядке, ваши данные не исчезнут как по волшебству. Если вы загрузите, скажем, норвежский словарь, ваш ПК без возражений сохранит его для последующих вызовов. ПК не будет уставать или пытаться изучить другой язык; не сможет он и упиться до полного забвения места, куда вчера записал данные. Он не поссорится с ПК-дамой и не уничтожит ее файлы на почве ревности. В целостной системе данные всегда под рукой.

Однако здесь, в царстве людей, мы постоянно боремся с недочетами и изворотами нашей мысли. Мы вечно все забываем, меняем свое мнение – короче, лучше бы наш мозг походил на ОЗУ, а не на серые комки органики. Всего очевиднее это при изучении иностранного языка: компьютер хранит миллионы слов и никогда их не «забывает», а мы с трудом припоминаем, как по-английски «встреча», даже если использовали это слово вчера. Спасибо, мозг.

Итак, проект кодирования этого месяца – создание программы всплывающих карточек (flash-карт), которая помогает запоминать иностранные слова. Она отображает английские слова и просит вас выбрать их русский эквивалент из списка трех, случайным образом выбранных, слов, начисляя вам очки по мере вашего прогресса. Но она не ограничивается только английским и пригодится для любого языка, или вообще для всего, что нужно изучить! Вы сможете даже настроить ее на отображение названий животных: пусть спросит вас об их виде.

Новый опыт Python

На LXFDVD прошлого месяца была опубликована подшивка LXF за 2005–2007 года; помимо прочего, в ней можно найти и учебник по языку Python (выпуски 74/7583). Не пугайтесь, если вы пропустили прошлый номер или никогда не писали на Python: в нем очень легко разобраться. Если вы знакомы хоть с одним языком программирования, то не встретите проблем при работе с этим кодом.

Наше приложение flash-карт должно будет читать текстовые файлы и генерировать случайные числа. Открытие файлов в Python – плевое дело: создайте новый текстовый файл с именем foo.txt, вбейте в него несколько слов (по одному в строке) и сохраните в домашнем каталоге. Теперь создайте файл с именем test.py, также в домашнем каталоге, со следующим содержимым:

file = open(‘foo.txt’, ‘r’)
print file.readlines()

Для запуска этого Python-скрипта откройте терминал и введите:

python test.py

Этот код открывает foo.txt (‘r’ означает «только для чтения») и связывает его содержимое с новым объектом по имени file.

Во второй строке кода мы вызываем readlines() нашего объекта file, который сканирует foo.txt и сохраняет его строки как элементы массива. При его печати на экране мы увидим:

[‘hello\n’, ‘banana\n’, ‘cupcake\n’]

Понятно, слова будут те, которые вы ввели в foo.txt. Но отсюда видно, как Python получает текст из файла и выводит элементы массива через запятую. Ну, хорошо; а если мы хотим нормально отобразить текст файла?

file = open(‘foo.txt’, ‘r’)
for line in file:
 print line

Этот код выводит все строки из foo.txt. Заметьте, что отступы в Python важны – табуляция перед print line говорит о том, что этот код выполняется внутри цикла for. Конкретно этот цикл for говорит: для (for) каждой строки открытого нами файла, напечатать ее, и так до конца файла.

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

import random
a = random.randint(1, 5)
b = random.randint(30, 100)
print a, b

Первая строка говорит Python, что мы хотим использовать его генератор случайных чисел. После этого мы создаем две переменные: a и b, и присваиваем им случайные значения стандартной подпрограммой Python random.randint(). Мы указываем диапазон значений – для переменной a это будет число от 1 до 5 (включительно). Для b – число между 30 и 100. Легко!

Создаем flashcard.py 1.0

(thumbnail)
Первая инкарнация нашей программы flash-карт – простой текстовый вариант.

Давайте поработаем с программой. Нам понадобятся два текстовых файла: в одном – английские слова, в другом – соответствующие русские. (Или, например, в одном файле могут быть названия стран, а во втором – названия их столиц.) Важно, чтобы оба файла имели одинаковое число строк и соответствие слов для каждой их пары. Если вы используете названия столиц и седьмая строка первого файла – это «Япония», то седьмая строка второго файла должна содержать «Токио». Иначе ответы не подойдут!

Итак, создадим два текстовых файла в домашнем каталоге и введем по десять слов в каждый из них, по одному в строке. В нашем примере, первый файл называется english.txt и содержит слова ‘Thanks, word, job’ и т.д.; второй файл называется russian.txt и содержит ‘спасибо, слово, работа’ и т.д. Теперь нам необходим код на Python, чтобы работать с этими текстовыми файлами в домашнем каталоге – и вот вам листинг. Он есть на нашем DVD (flashcard.py в разделе Magazine/CodeProject), но пока просто пробегитесь по нему...

# -*- coding: utf_8 -*-
import os, random
count = 0
score = 0
file1 = open(‘english.txt’, ‘r’)
file2 = open(‘russian.txt’, ‘r’)
f1content = file1.readlines()
f2content = file2.readlines()
while count < 10:
os.system(‘clear’)
wordnum = random.randint(0, len(f1content)-1)
print ‘Слово:’, f1content[wordnum], ‘’
options = [random.randint(0, len(f2content)-1),
random.randint(0, len(f2content)-1),
random.randint(0, len(f2content)-1)]
options[random.randint(0, 2)] = wordnum
print ‘1 -’, f2content[options[0]],
print ‘2 -’, f2content[options[1]],
print ‘3 -’, f2content[options[2]],
answer = input(‘\n Ваш выбор:’)
if options[answer-1] == wordnum:
raw_input(‘\n Верно! Нажмите enter...’)
score = score+1
else:
raw_input(‘\n Неверно! Нажмите enter...’)
count = count+1
print ‘\n Набрано очков:’, score

При наличии flashcard.py, russian.txt и english.txt в вашем домашнем каталоге откройте терминал и введите python flashcard.py. Вы увидите, что программа отображает английское слово, а ниже – три возможных русских эквивалента. Эти эквиваленты пронумерованы, и если вы считаете, что верный ответ – это 3, просто нажмите 3, а затем Enter. После этого программа скажет вам, правы вы или ошибаетесь – всего будет задано десять вопросов.

Давайте рассмотрим код более детально. Мы начали строкой с import [Русская версия скрипта начинается с указания используемой в системе кодировки, в противном случае программа не будет выполняться, – прим. пер.], которая говорит Python, какие возможности мы собираемся использовать. В нашем случае необходимо вызывать функцию ОС (для очистки экрана) и генерировать случайные числа. Затем мы описываем две переменные, count и score – первая используется для отображения десяти вопросов, а вторая запоминает число верных ответов. Далее идет:

file1 = open(‘english.txt’, ‘r’)
file2 = open(‘russian.txt’, ‘r’)
f1content = file1.readlines()
f2content = file2.readlines()

Здесь мы открываем два файла и связываем их с двумя переменными с именами file1 и file2. Эти переменные – вроде дескрипторов этих файлов: они представляют файлы, сохраненные в памяти. Но нам не нужны просто сами файлы; нам необходимо их содержимое, поэтому следующие две строки кода по кусочкам переносят реальный текст в два массива с именами f1content и f2content. Теперь у нас есть список английских слов в f1content и список русских слов в f2content. Затем начинается основной цикл программы:

while count < 10:
os.system(‘clear’)
wordnum = random.randint(0, len(f1content)-1)
print ‘Слово:’, f1content[wordnum], ‘’
Скорая помощь

Если при ваших экспериментах с кодом Python программа зациклилась, ее можно снять из терминала, нажав Ctrl+C. Вам может понадобиться сделать это пару раз, особенно если ваша программа ждет ввода от пользователя. Если ваша программа все-таки не останавливается, наберите в терминале ps ax, найдите номер процесс Python вашего скрипта и введите kill -9 <number>. Это команда абсолютного останова программы

Мы хотим задать десять вопросов, то есть выполнить весь код с отступом десять раз (переменная-счетчик каждый раз увеличивается). Первая строка этого цикла очищает экран, вызывая стандартную утилиту /usr/bin/clear, а затем мы отображаем случайное слово. Мы говорим: wordnum должно принять случайное значение, представляющее строку в файле слов, так что дай мне число между нулем и размером файла (в строках). Хотя файл слов может иметь строки от первой до десятой, массивы нумеруются с нуля, вот почему мы берем случайное число от нуля до числа строк в файле минус один. То есть строка один в f1content (english.txt) – на самом деле нулевой элемент массива, а строка десять – девятый. Затем мы отображаем слово из файла english.txt.

options = [random.randint(0, len(f2content)-1),
random.randint(0, len(f2content)-1),
random.randint(0, len(f2content)-1)]
options[random.randint(0, 2)] = wordnum

Далее создается массив трех возможных ответов с именем options. Мы задаем для каждого ответа случайное число, ограниченное сверху числом строк в f2content (russian.txt). Теперь у нас есть три случайных русских слова – но стойте, одно из них должно быть верным, ведь так? Иначе получится три неверных ответа! Так что положим один из ответов в options равным wordnum – то есть верному. И вместо того, чтобы верный ответ всегда был, скажем, первым, мы размещаем его в случайное место в списке из трех возможных ответов.

Оставшийся код понять очень просто. Он печатает на экране три возможных ответа затем запрашивает ответ у пользователя – то есть ввод 1, 2 или 3. Когда пользователь вводит ответ, мы проверяем, соответствует ли он верному слову. То есть, если русское слово – «спасибо» и номер варианта thanks – «2», когда пользователь вводит 2, наша программа говорит: «Ах! Вариант два является седьмым в файле русских слов. И истинный номер ответа wordnum также равен семи, так что все верно! Слова совпадают.» В точку.

Версия с картинками

PyGame умеет больше

Наша вторая программа для flash-карт лишь поверхностно очертила то, что можно сделать с PyGame (http://www.pygame.org). Данная библиотека предоставляет множество инструментов для загрузки изображений, перемещения спрайтов, работы с клавиатурой/мышью и воспроизведения звуковых эффектов. Это популярный выбор программистов игр с открытым кодом; примеры того, что можно сделать, см. на http://www.pygame.org/tags/arcade.

А главное, PyGame имеет обширную документацию, включая учебники для абсолютных новичков и детальный справочник API. По адресу http://www.pygame.org/docs вы найдете учебники, описывающие с нуля, как инициализировать PyGame, перемещать спрайты и использовать пиксельные эффекты.

(thumbnail)
PyGame не ограничивается видеоиграми – вы можете использовать ее и для создания медиа-проигрывателя.

Теперь у нас есть текстовый инструмент flash-карт, превосходный для множества применений, а как насчет графической версии? Допустим, картинка с животным и три возможных названия – идеально для детей. А может, вы захотите нарисовать национальные флаги – кстати, именно это мы и собираемся сделать. Как и прежде, программу можно преобразовать во что угодно, использующее слова и картинки: блюда и их названия на испанском, фотографии звезд и их имена...

Для этого необходимо выйти за границы командной строки и воспользоваться графическим слоем. К счастью, у нас есть прекрасный выбор для нашего Python-приключения: PyGame, библиотека, связывающая Python с популярным медиа-слоем SDL. PyGame позволяет создавать окна и отображать соответствующие картинки на экране, причем с минимумом усилий. Собственно, большая часть кода останется той же – надо только заставить отображаться вместо текста картинки.

Наша первая версия flashcard.py использовала два текстовых файла с соответствиями слов, а эта графическая инкарнация будет использовать соответствия слов и картинок. То есть file1.txt может содержать «Непал, Канада, Финляндия...», а file2.txt – ‘nepalflag.png, canadaflag.png, finlandflag.png...’ и так далее. Слова будем получать из file1, а картинки для отображения – из file2.

Код для этого выйдет более длинный, и чтобы зря не тратить место, мы приведем здесь лишь основную часть. Но это большая часть, и она вам покажет, как работает графическая версия. На нашем DVD в разделе Magazine/CodeProject/Graphical имеется полный листинг кода со множеством комментариев (обозначенных символом #).

Заметьте, что перед запуском программы необходимо установить библиотеку PyGame: большинство дистрибутивов имеют ее в своих репозиториях (поищите в вашем менеджере пакетов), но если это не так, исходный код вы найдете в разделе Разработка нашего DVD.

Вот наш основной кусок кода. Здесь есть несколько новых элементов, но, в типичной манере Python, по большей части все самодокументировано – открываем файл изображения, рисуем его на экране в указанной позиции, и все.

init()
screen = display.set_mode((640, 480))
display.set_caption(‘Flashcard’)
font = font.Font(None, 48)
while count < 10:
screen.fill(0)
wordnum = random.randint(0, len(f2content)-1)
mainpic = image.load(f2content[wordnum].rstrip(‘\n’))
screen.blit(mainpic, (255, 50))
options = [random.randint(0, len(f1content)-1),
random.randint(0, len(f1content)-1),
random.randint(0, len(f1content)-1)]
options[random.randint(0, 2)] = wordnum
text1 = font.render(‘1 - ‘ + f1content[options[0]].rstrip(‘\n’),
True, (255, 255, 255))
text2 = font.render(‘2 - ‘ + f1content[options[1]].rstrip(‘\n’),
True, (255, 255, 255))
text3 = font.render(‘3 - ‘ + f1content[options[2]].rstrip(‘\n’),
True, (255, 255, 255))
screen.blit(text1, (30, 200))
screen.blit(text2, (30, 300))
screen.blit(text3, (30, 400))
display.update()

Первые четыре строки кода говорят PyGame настроить экран. Мы инициализируем PyGame, а затем велим ему создать новое окно размером 640 x 480 пикселей, поместив в заголовок окна соответствующий текст. Затем создаем новый шрифт: создадим объект с именем font, используя собственную систему шрифтов PyGame, и скажем ‘None’, что означает: нам неважно, какой шрифт использовать – пусть будет стандартный системный. А размер шрифта установим 48 пунктов.

Затем запускается главный цикл, выдавая десять вопросов. screen. fill(0) просто заполняет экран нулевым цветом, то есть черным – это очищает окно для каждого вопроса. Затем мы выбираем строку для случайного слова, которое будет ответом, так же, как и в текстовой версии, а затем у нас идет:

mainpic = image.load(f2content[wordnum].rstrip(‘\n’))

Это довольно большая инструкция, так что давайте разберем ее. Мы создаем новый объект PyGame: картинку с именем mainpic, для отрисовки на экране. Однако картинку необходимо откуда-то загрузить, и это должна быть картинка для верного ответа – а мы здесь сказали, чтоб Python выбрал ее случайным образом.

Как и до этого, в полном коде мы загружаем два текстовых файла в f1content и f2content. f1content содержит список слов – в нашем случае, «Непал, Канада, Финляндия...». f2content содержит список имен соответствующих файлов изображений: ‘nepalflag.png, canadaflag.png, finlandflag.png...’. Наша переменная wordnum указывает на слово в f1content, а также на имя файла связанного изображения в f2content. Если wordnum равно 2, то она может указывать на «Непал» в f1content и ‘nepal.png’ в f2content – вот почему записи в файлах должны попарно соответствовать друг другу!

Итак, загружаем нашу картинку в соответствии с именем файла из f2content, удалив символ перевода строки при помощи rstrip – не то PyGame нас не поймет! Далее, делаем один из трех вариантов правильным, как и ранее. Затем создаем три отрывка текста для отображения на экране. Вот первый:

text1 = font.render(‘1 - ‘ + f1content[options[0]].rstrip(‘\n’),True, (255, 255, 255))
(thumbnail)
При помощи Python и PyGame, мы теперь можем создать графический тест вроде этого.

Здесь создается новое изображение с именем text1, содержащее первый случайный вариант из нашего списка слов f1content. True означает, что текст должен быть сглаженным, а (255, 255, 255) – цвет текста в формате красный, зеленый, синий: белый, стало быть. Делаем то же для других вариантов, затем отрисуем (blit) текст на экране и обновим его, чтобы все отобразилось.

Оставшийся код с комментариями, который вы можете просмотреть на нашем DVD, обрабатывает ввод пользователя. Мы проверяем, что нажал пользователь – 1, 2 или 3 – и реагируем соответственно: выводим «Верно!» и обновляем счетчик очков, или выводим «Неверно!». Затем ждем нажатия Enter и вновь запускаем цикл.

Завершаем

Надеемся, что это вдохновило вас покопаться глубже в вашем проекте flash-карт – возможно, расширить его, включив пять вариантов вместо трех. А может быть, вы хотите записывать системное время в начале теста и сравнить его со временем по завершении теста, чтобы выставлять оценку за быстроту!

С этой программой можно еще много чего сделать, и если у вас получится что-то классное, пожалуйста, сообщите нам, и мы, возможно, разместим это на нашем DVD. Если у вас возникли вопросы по данному уроку, обратитесь к разделу Программирование на http://www.linuxforum.ru. Наслаждайтесь!

Персональные инструменты
купить
подписаться
Яндекс.Метрика