Python

индекс
250,37

Пишем игру Реверси на Python + PyQt4

Задали нам как-то написать небольшой проект — игру Реверси.
А так как сейчас я изучаю Python, решил писать на нем. Вместе с графической библиотекой PyQt4.
Ну так за чем же дело встало? Создаем SVN и вперед!

Вот такое чудо у меня получилось:
Скриншот игры

По словам википедии (а я с ней вполне согласен)
В игре используется квадратная доска размером 8 × 8 клеток (все клетки могут быть одного цвета) и 64 специальные фишки, окрашенные с разных сторон в контрастные цвета, например, в белый и чёрный. Клетки доски нумеруются от верхнего левого угла: вертикали — латинскими буквами, горизонтали — цифрами. Один из игроков играет белыми, другой — чёрными. Делая ход, игрок ставит фишку на клетку доски «своим» цветом вверх.
В начале игры в центр доски выставляются 4 фишки: чёрные на d5 и e4, белые на d4 и e5.
  • Первый ход делают чёрные. Далее игроки ходят по очереди.
  • Делая ход, игрок должен поставить свою фишку на одну из клеток доски таким образом, чтобы между этой поставленной фишкой и одной из имеющихся уже на доске фишек его цвета находился непрерывный ряд фишек соперника, горизонтальный, вертикальный или диагональный (другими словами, чтобы непрерывный ряд фишек соперника оказался «закрыт» фишками игрока с двух сторон). Все фишки соперника, входящие в «закрытый» на этом ходу ряд, переворачиваются на другую сторону (меняют цвет) и переходят к ходившему игроку.
  • Если в результате одного хода «закрывается» одновременно более одного ряда фишек противника, то переворачиваются все фишки, оказавшиеся на всех «закрытых» рядах.
  • Игрок вправе выбирать любой из возможных для него ходов. Если игрок имеет возможные ходы, он не может отказаться от хода. Если игрок не имеет допустимых ходов, то ход передаётся сопернику.
  • Игра прекращается, когда на доску выставлены все фишки или когда ни один из игроков не может сделать хода. По окончании игры проводится подсчёт фишек каждого цвета, и игрок, чьих фишек на доске выставлено больше, объявляется победителем. В случае равенства количества фишек засчитывается ничья.


Python я знаю на базовом уровне. Что-то писал под Google App Engine (например, костыль для себя для получения удобного RSS канала пользователя YouTube, но не об этом речь). Что-то просто так. Что-то для проекта Эйлера (отличный сайт надо сказать). В общем, игрался:)

С Qt до этого дела не имел. Но разобраться, как оказалось, совсем не сложно.
Основа основ, на русском. А также документация тут и тут. Вместе с дистрибутивом PyQT4 идет хорошая база примеров, которые тоже помогли мне разобраться.

На установке и настройке интерпретатора и библиотек останавливаться смысла нет, это и так кучу раз разжевано и никаких подводных камней мне не встретилось.
Как я уже написал, с Qt я до этого не работал. И первой сложностью было разобраться с системой виджетов, как вообще строится взаимодействие с пользователем. Но впринципе, разобраться совсем несложно, сверяясь с примерами и документацией.
Следующей сложностью было написать простенький AI. Идея была подсмотрена где-то в дебрях интернета и адаптирована под реверси.
Copy Source | Copy HTML
  1. def compStep(player):
  2.     table = [
  3.                 [1, 8, 2, 2, 2, 2, 8, 1],
  4.                 [8, 8, 6, 5, 5, 6, 8, 8],
  5.                 [2, 6, 4, 3, 3, 4, 6, 2],
  6.                 [2, 5, 3, 1, 1, 3, 5, 2],
  7.                 [2, 5, 3, 1, 1, 3, 5, 2],
  8.                 [2, 6, 4, 3, 3, 4, 6, 2],
  9.                 [8, 8, 6, 5, 5, 6, 8, 8],
  10.                 [1, 8, 2, 2, 2, 2, 8, 1]
  11.             ]
  12.     pX = [ 0] * 61
  13.     pY = [ 0] * 61
  14.     minE = 9
  15.     maxE =  0
  16.     NP =  0
  17.     for row in range(8):
  18.         for col in range(8):
  19.             E = eated(row, col, player)
  20.             if (minE > table[row][col]) & (E < 255) & (E >  0):
  21.                 minE = table[row][col]
  22.                 NP =  0
  23.                 maxE =  0
  24.             if (minE == table[row][col]) & (E < 255):
  25.                 if E > maxE:
  26.                     maxE = E
  27.                     NP = 1
  28.                     pX[NP] = row
  29.                     pY[NP] = col
  30.                 elif E == maxE:
  31.                     NP = NP + 1
  32.                     pX[NP] = row
  33.                     pY[NP] = col
  34.     E = 1
  35.     makeStep(player, pX[E], pY[E])
  36.     area[pX[E]][pY[E]] = player


Исходник, если интересно, можете сами пощупать. Кто знает, проблем с запуском не возникнет (нужна библиотека pyqt4).
http://reversi-free0u.googlecode.com/svn/trunk/main.py

Специально для windows. Exe'шник.
http://reversi-free0u.googlecode.com/files/Reversi.7z

Упаковано с помощью py2exe. Я столкнулся с двумя проблемами.

Первая:
Сначала изображения клетки и фишек в игре являли собою картинки, вставляющиеся в игру. И упакованное приложение их успешно не видело.
Проблема решилась просто — отрисовкой изображений средствами Qt (мне просто лень было так делать изначально).

Вторая:
Успешно упакованное приложение запускалось у меня, но отказывалось работать на другом компьютере. После небольших поисков, оказалось, что эта проблема также легко решается :)
Оказалось что не хватает рантайм библиотек visual studio.
I have not seriously used Python 2.6 with py2exe, also I have no experience
with this new manifest stuff, but a little experiment showed that this approach
seems to work for simple cases (I tested only on XP machines, not Vista!):

I deinstalled python 2.6 (since I had installed it 'for all users') and
installed it again 'for me only'. This installation copied the msvcr90.dll
and Microsoft.VC90.CRT.manifest files into the c:\python26 folder.

Then I ran py2exe over a very simple script ('print «Hi»') which created
an executable. This executable worked fine on a machine where msvcr90.dll
was installed in Windows\SxS (or how it's called), but did NOT run on another
machine where msvcr90.dll is not installed in Windows\SxS.

Then I copied the msvcr90.dll and Microsoft.VC90.CRT.manifest files into the dist
folder where py2exe had created my executable. Now the exe works on both machines.

When I tried to do the same for a simple wxPython script py2exe crashed because
it tried to load msvcp90.dll (IIRC), but didn't find it (it seems only to be installed
in the Windows\SxS folder). This may be a bug in py2exe.
То есть самое сложное положить к программе библиотеку и файл манифеста.

Главный минус — большой размер получившегося приложения. Но ничего не поделать. Все таки python — интерпретируемый язык.

Что мне дал этот потраченный на игру выходной?
  • Удовольствие от процесса изучения и написания gui приложение на python
  • Желание поделиться этим с Вами)
За этот топик я получил инвайт

Перенес в коллективный блог. В этой жизни надо попробовать всё 8)

upd: немного изменил имена переменных в исходниках

upd2: для страждущих, версия питона 2.6.4
+63
10 марта 2010, 16:32
91

комментарии (35)

+1
porqz #
Ой, спасибо за статью. Как раз оказался в подобной ситуации, но в качестве оружия выбрал Ruby.
+7
kAIST #
>Главный минус — большой размер получившегося приложения. Но ничего не поделать
Да нет, сделать то тут кое что можно ;)
1. Выкидываем unicodedata.pyd, bz2.pyd, select.pyd, w9xpopen.exe
2. Выкидываем неиспользуемые модули из library.zip, а так же неиспользуемые кодировки.
3. Указываем опцию optimize:2 в setup.exe. При этом модули будут компилироваться в pyo а не pyc, что еще уменьшит размер library.zip
4. Сжать dll и pyd файлы upx'ом (скажется только на размере распакованного приложения)
На пару метров это все должно уменьшить размер.
+1
free0u #
А я только upx'ом упаковал, но все равно, ощутимо легче стало (было 20 с чем-то мб, сейчас 8,6).
+1
ckopn #
Ого.
+1
free0u #
Хм… Есть ли смысл перенести в тематический блог (Язык программирования Python)?
+1
Boomburum #
C почином на Хабре ;)
+4
free0u #
Спасибо)
+2
ayambit #
Увидел картинку — подумал, это игра жизнь. Только потом заголовок прочитал.
+1
free0u #
Вся наша жизнь — игра, а люди в ней актеры…
0
KL7 #
Python + Qt — отличный выбор, хотя мне пока доводилось пользоваться лишь каждым в отдельности. =)
По поводу уроков — ничто не заменит документацию, но для быстрого ознакомления я бы посоветовал вот эти — ZetCode PyQt Tutorial (ENG).
0
free0u #
Посмотрел. Ощутил дежавю. Оказалось, что переводы статей проскакивали на хабре :)
+4
smbd #
Вы знаете, всё отлично, но тем не менее…
Нехорошо смешивать русские и иностранные слова в именовании чего бы то ни было, как то: newKletki() и createFishki().
0
free0u #
Ох, до хорошего стиля мне еще пахать и пахать.
0
Antigluk #
Оо. Это так режет глаз что прям ужос.
А игрушка прикольная, респект)
Как-раз думал посмотреть в сторону qt
+1
free0u #
Fixed.
+1
vostryakov #
Молодец!
+2
Vladson #
Огромное спасибо, действительно интересный пост. С одной стороны ничего революционно нового, с другой стороны очень приятно было читать.
+1
sindrom #
Ваш исходник отлично запустился в моей убунте. Игра работает, выглядит нативно. Оказывается, python в связке с qt — это отличная комбинация :)
НЛО прилетело и опубликовало эту надпись здесь
0
texamus #
в 548 строчке можно заменить math.trunc на int и тогда код будет работать и в Python 2.5 (иначе только 2.6)
0
bobry #
for row in table:
for col in row:

очень рад что вы открыли для себя pyqt, но пора учиться более pythonic коду
+1
bobry #
да, похоже мне нельзя использовать ссылки, посему только так: www.fantascienza.net/leonardo/ar/python_best_practices.html
+1
neithere #
особенно PEP 8.
–1
petergreen #
реверся… я рубился в неё наверное месяц, но так и не дошёл до результата 64-0, максимум 63-1 на своём палме
0
coolmiha #
Версию питона укажите;)
Эх, на тройке написать бы. Когда ее допилят уже?
0
free0u #
Сейчас добавлю
+1
helm2004 #
Спасибо, за исходники!
0
free0u #
На здоровье :)
+1
Liksys #
>> if (minE == table[row][col]) & (E < 255):

Не стоит так писать, используйте в логический выражениях and вместо &.

>> Все таки python — интерпретируемый язык.

Компилируемый в байт-код.

И еще хотелось бы, чтобы вы рассказали про работу с py2exe :-)
–3
lig #
Ну, да, reversi.
Кружочки двух цветов, да…
Ну QT, хотя могло быть GTK, но это не важно.
Важно вот что: ИИ где? На фиг оно не нужно для игры вдвоем без искуственного противника или сетевой игры.
Так и не понял зачем это? Чтобы с QT поиграть? Чтобы с py2exe поиграть? Для чего тут это?

P.S.: SVN?.. ФУ!
+1
free0u #
Важно вот что: ИИ где? На фиг оно не нужно для игры вдвоем без искуственного противника или сетевой игры.
AI есть. И даже его исходник в статью вставлен.

Так и не понял зачем это? Чтобы с QT поиграть? Чтобы с py2exe поиграть? Для чего тут это?
А зачем тут все остальное?

P.S.: SVN?.. ФУ!
А что не так с SVN? По моему удобно.
–1
lig #
> AI есть.
Тогда сорри. А отчет о скрещивании с другими алгоритмами?

> А зачем тут все остальное?
Не знаю, поэтому интересуюсь.

> А что не так с SVN? По моему удобно.
Откройте дял себя git.
+1
stas_agarkov #
вы писали код по конвенции питона? ;)
0
free0u #
Во всяком случае, я делал попытки :)
+1
tibalt #
позволю себе дать совет по поводу имен переменных (фигня, конечно, но вдруг интересно):
eated — если это от глагола eat (есть), то надо писать eaten (съеден). но еще более правильно captured (захвачен)
makeStep — вместо step (шаг) используй слово turn (ход)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.