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

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

Материал из Linuxformat
Версия от 20:40, 5 апреля 2009; Yaleks (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

Кодируем: 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

Давайте поработаем с программой. Нам понадобятся два текстовых файла: в одном – английские слова, в другом – соответствующие русские. (Или, например, в одном файле могут быть названия стран, а во втором – названия их столиц.) Важно, чтобы оба файла имели одинаковое число строк и соответствие слов для каждой их пары. Если вы используете названия столиц и седьмая строка первого фай- ла – это «Япония», то седьмая строка второго файла должна содержать «Токио». Иначе ответы не подойдут! Итак, создадим два текстовых файла в домашнем каталоге и вве- дем по десять слов в каждый из них, по одному в строке. В нашем при- мере, первый файл называется 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], ‘’ Мы хотим задать десять вопросов, то есть выполнить весь код с отступом десять раз (переменная-счетчик каждый раз увеличивает- ся). Первая строка этого цикла очищает экран, вызывая стандартную утилиту /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 также равен семи, так что все верно! Слова совпадают.» В точку.

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

Теперь у нас есть текстовый инструмент 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)) Здесь создается новое изображение с именем text1, содержащее первый случайный вариант из нашего списка слов f1content. True озна- чает, что текст должен быть сглаженным, а (255, 255, 255) – цвет текста в формате красный, зеленый, синий: белый, стало быть. Делаем то же для других вариантов, затем отрисуем (blit) текст на экране и обновим его, чтобы все отобразилось. Оставшийся код с комментариями, который вы можете просмотреть на нашем DVD, обрабатывает ввод пользователя. Мы проверяем, что нажал пользователь – 1, 2 или 3 – и реагируем соответственно: выво- дим «Верно!» и обновляем счетчик очков, или выводим «Неверно!». Затем ждем нажатия Enter и вновь запускаем цикл.

Завершаем

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

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