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

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

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

    По словам википедии (а я с ней вполне согласен)
    В игре используется квадратная доска размером 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

    UPDATE: Теперь код доступен на Github. За работоспособность не ручаюсь.

    Специально для 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

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 35

      +1
      Ой, спасибо за статью. Как раз оказался в подобной ситуации, но в качестве оружия выбрал Ruby.
        +7
        >Главный минус — большой размер получившегося приложения. Но ничего не поделать
        Да нет, сделать то тут кое что можно ;)
        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
          А я только upx'ом упаковал, но все равно, ощутимо легче стало (было 20 с чем-то мб, сейчас 8,6).
            +1
            Ого.
          +1
          Хм… Есть ли смысл перенести в тематический блог (Язык программирования Python)?
            +1
            C почином на Хабре ;)
              +4
              Спасибо)
              +2
              Увидел картинку — подумал, это игра жизнь. Только потом заголовок прочитал.
                +1
                Вся наша жизнь — игра, а люди в ней актеры…
                0
                Python + Qt — отличный выбор, хотя мне пока доводилось пользоваться лишь каждым в отдельности. =)
                По поводу уроков — ничто не заменит документацию, но для быстрого ознакомления я бы посоветовал вот эти — ZetCode PyQt Tutorial (ENG).
                  0
                  Посмотрел. Ощутил дежавю. Оказалось, что переводы статей проскакивали на хабре :)
                  +4
                  Вы знаете, всё отлично, но тем не менее…
                  Нехорошо смешивать русские и иностранные слова в именовании чего бы то ни было, как то: newKletki() и createFishki().
                    0
                    Ох, до хорошего стиля мне еще пахать и пахать.
                      0
                      Оо. Это так режет глаз что прям ужос.
                      А игрушка прикольная, респект)
                      Как-раз думал посмотреть в сторону qt
                        +1
                        Fixed.
                      +1
                      Молодец!
                        +2
                        Огромное спасибо, действительно интересный пост. С одной стороны ничего революционно нового, с другой стороны очень приятно было читать.
                          +1
                          Ваш исходник отлично запустился в моей убунте. Игра работает, выглядит нативно. Оказывается, python в связке с qt — это отличная комбинация :)
                          • UFO just landed and posted this here
                              0
                              в 548 строчке можно заменить math.trunc на int и тогда код будет работать и в Python 2.5 (иначе только 2.6)
                              • UFO just landed and posted this here
                                • UFO just landed and posted this here
                                –1
                                реверся… я рубился в неё наверное месяц, но так и не дошёл до результата 64-0, максимум 63-1 на своём палме
                                  0
                                  Версию питона укажите;)
                                  Эх, на тройке написать бы. Когда ее допилят уже?
                                    0
                                    Сейчас добавлю
                                    +1
                                    Спасибо, за исходники!
                                      0
                                      На здоровье :)
                                    • UFO just landed and posted this here
                                        –3
                                        Ну, да, reversi.
                                        Кружочки двух цветов, да…
                                        Ну QT, хотя могло быть GTK, но это не важно.
                                        Важно вот что: ИИ где? На фиг оно не нужно для игры вдвоем без искуственного противника или сетевой игры.
                                        Так и не понял зачем это? Чтобы с QT поиграть? Чтобы с py2exe поиграть? Для чего тут это?

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

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

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

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

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

                                            Only users with full accounts can post comments. Log in, please.