Программируем Reversi на Silverlight

    Давно хотел начать изучать Silverlight, начинал читать литературу, пытался вникать в концепции, паттерны, но все больше как-то абстрактно, в теории. На практике, настоящую программу на Silverlight так и не попытался написать.

    Но вот совсем недавно на просторах Хабра проскочила статья «программируем Reversi на Питоне». Глянув в код, ужаснулся, у меня сразу включился мотиватор. Не то, чтобы я не люблю Питон, просто я очень люблю C#.

    То, что вы увидите было написано за 1 рабочий день человеком, имеющим нулевой практический опыт разработки приложений в WPF/Silverlight.

    Вступление


    Для тех, кто не хочет вникать как работает программа, а хочет посмотреть ее вживую, листайте статью вниз – там ссылка. Игра требует Silverlight 3, надеюсь, вы не входите в те 43% интернетовских пользователей, у которых плагин не установлен или не поддерживается (статистика взята с riastats.com).

    Подготовка


    Для разработки игры я использовал VS.NET 2010 RC c Silverlight Tools 4 (есть один хак, как заставить тулзы проинсталлироваться, линк легко гуглится). Сам проект написано на Silverlight 3, чтобы не напрягать тех, кто не спешит с установкой всяческих бета-версий. Т.е. VS.NET 2008 + Silverlight Tools 3 + Expression Blend 3. Все необходимое и не только можно скачать отсюда: silverlight.net/getstarted

    Особенности


    В игре задействованы следующие принципы Silverlight 3 и С# в частности:
    • Логика принятия решения вынесена в отдельный абстрактный класс. Идею с таблицей важности клеток перенял из питоновской реализации.
    • UI synchronization – поскольку логика игры работает в фоновом потоке, все делегаты и события должны быть правильным образом синхронизированы в UI-поток.
    • Synchronization primitives – когда игре требуется ввод пользователя, используются синхронизационные примитивы потоков – AutoResetEvent.
    • LINQ – поиск лучшего хода AI реализовано с помощью LINQ расширений.
    • Out-of-Browser – игру можно установить локально и играть без подключения к интернету.
    • Automatic Updates – при наличии подключения к интернету, игра обновляется. Размер игры в настоящее время – 14 килобайт.
    • MVVM – статус игры, счет, и т.д. привязаны к модели игры по принципу Model-View-ViewModel.
    • VisualStateManager используется для придания некой жизни интерфейсу посредством анимации фишек.
    • Localization – все сообщения игры локализованы с помощью ресурсов на русском и английском языке. Все тексты привязаны напрямую к ресурсам, т.е. если у вас русские региональные установки –интерфейс будет отображаться на русском.

    Как работает игра


    Есть класс Game – игра, который стартует фоновый поток, в котором будут опрашиваться ходы игроков – объектов класса GamePlayer. Это абстрактный класс, его развивают два других – GameAI – игровой модуль принятия решений и GamePC – логика приема хода от игрока.

    При старте новой игры, в зависимости от выбранного пункта из комбика, конструируется новый объект игры, которому передаются различные комбинации объектов игроков GameAI и GamePC. В первый раз наблюдать битву двух AI — трансцедентально, если не сказать больше :)

    GameAI принимает решения моментально, поэтому ему выставлена стандартная задержка в 100 ms. Сначала я написал игру без использования фоновых процессов, но меня стало напрягать то, что AI делает ход так быстро, что я не успевал заметить своих ходов. Когда я вставил Thread.Sleep в основной UI-поток, пострадала анимация. Я не гуру в Silverlight, гугль ответ не нагуглил, поэтому было решено унести всю логику игры в фоновый поток, а UI-поток разгрузить насовсем.

    При переносе событий в фоновый поток – Silverlight начал брыкаться, ну точь в точь как WinForms. Пришлось пропустить все через глобальный UI диспетчер.

    GameAI ищет оптимальный ход сначала по важности клеток, потом по выигрышу. Когда оптимальных вариантов несколько, подключается фактор случайности, т.н. душа. :) Кстати, без этой «души» белые всегда выигрывали. Теперь AI vs AI результат выигрыша 50 на 50.

    Out-of-Browser приложение делается одним мышиным кликом в опциях проекта. Автоматическое обновления приложения тоже элементарно — единственный вызов в конструкторе приложения – если новая версии игры выложена на сервере, она будет скачана в локальный кэш, второй запуск приложения подхватит уже обновленную версия. Quadratisch, praktisch, gut :)

    Анимация


    С анимацией поначалу было не все гладко. Я хотел заставить класс Ellipse принимать различные визуальные состояния. Но оказалось, что Ellipse – не наследуется от класса Control, поэтому визуальным состоянием не подвержен. Пришлось делать свой собственный контроль Cell. Приделав этому классу двa dependency properties Stroke и Fill, которые просто управляли вложенным эллипсом, я смог заставить его выглядить как эллипс, оставаясь при этом контролем, способным анимировать себя через VisualStateManager.

    В Blend-е я добавил два состояния классу Cell, Normal и Visible. В Visible добавил визуальный переход – масштаб за секунду изменяется с 0.5 до 1 используя эластичную функцию сглаживания. Получилось забавно.

    Скажу так, в Blend-e я провозился больше всего, пока немного разобрался со StoryBoards, States, Transitions. Пришлось даже посмотреть пару видео-роликов из серии «Blend для чайников». Очень помогло.

    Локализация


    В блоге Tim Heuer нашел пост о том, как привязываться напрямую к строкам из ресурсов (resx). Полчаса пытался разобраться – почему у меня это не работает.

    Оказалось, что надо читать повнимательнее. Там сказано, что это известный баг. При изменении видимости класса ресурсов – видимость конструктора не меняется, если класс public, а конструктор нет – создать такой класс через Activator в Silverlight – невозможно. Но дружище Tim уверяет, что баг будет исправлен, а пока вручную лезем в С#-класс ресурсов и меняем internal на public. Не забываем, что после добавления новых строк в ресурсы – файло будем сгенерировано по-новой, и операцию «public constructor» надо будет повторить.

    Выводы


    Почерпнул для себя много важного практического опыта. Получил удовольствие от баловства работы с Blend-ом (дизайнером мне, увы, стать уже не суждено). Разрабатывать оказалось достаточно удобно. Конечно, до WinForms еще далеко, но оно того стоит.

    Приятно то, что много из «большого» фреймворка оказалось доступно, какие-то методы были упрощены, но в целом – все то же самое.
    Стандартным браузером у меня стоит Chrome, со студией в режиме отладки он дружит плохо. Поэтому для отладки Silverlight IE8 – то, что доктор прописал.

    Так же приятно поразил размер готового приложения – 14 кб.

    По заявлениям MS – игра должна работать под Windows XP, Vista, 7, Mac OS X, Xbox, Windows Phone 7 Series. Посмотрим, что приподнесет MIX на следующей неделе.

    Результат


    Играть: тыц
    Исходники: тыдыц

    Код более-менее комментирован, но если есть вопросы – не стесняйтесь задавать в комментах.

    И что дальше?


    В планах — улучшить анимацию, сделать поле пропорционально растягивающимся на весь браузер, вшить в AI персональные игровые трики…

    Ну и то, что предложишь ты, %username%

    UPD: Немного разобрался с Silverlight, добавил диалог новой игры, подкрутил шаблоны фишек, выглядит значительно лучше. Порезал исходники по классам.
    Поделиться публикацией

    Комментарии 45

      +2
      Если попытаться перенести фишку в недопустимое место (или передумать в последний момент, вернуть мышку на фишку, по которой кликнул, или просто кликнуть по фишке), то дальше ход уже сделать нельзя, игра, как бы, зависает.
        +1
        Да, есть такая бяка. Сейчас пофиксим
          +1
          Пофиксил. Закачал новый xap и исходники.
        0
        отлично! спасибо
          +1
          Карма позволяет, перетаскивайте годную статью в нужный блог!
            +1
            Без лукавства, код на C# получился ненамного проще. Но, видимо, такова жизнь. :)

            Спасибо за отличный учебный пример по C# и Silverlight! Успехов Вам!
              0
              Без лукавства, код на C# был поначалу очень прост. Но потом захотелось рюшечек.
              Тут и понеслася: AI vs AI, задержка, фоновые потоки…

              Потом решил, что надо добавить полезных примеров, как локализацию и data-binding.
              Ну вот в итоге и получилось каша-малаша.

              Большое спасибо за feedback
              +1
              Хочу предложить улучшить AI. Довольно он слабенький.
              Я когда-то писал реверси, то AI у меня просчитывал на несколько ходов вперед. Но так как это было время DOS'а, а я был молод и зелен, то это делалось не в фоновом режиме. А сейчас это можно вынести в отдельный поток, который будет трудиться все время, и периодически синхронизировать расчеты с реальной игровой ситуацией.
                +3
                то ли AI сильный, то ли сказывается нулевой опыт игры, но оно меня выиграло
                  +3
                  У меня с тем же нулевым опытом сложилось противоположное мнение =)
                  В любом случае, каким бы ни был AI, реализация самой игры очень достойная.
                    +1
                    с третьего раза понял, какое оно тупое, а с четвертого победил и понял какой я сам тупой
                    +2
                    Желательно анимацию хода AI сделать помедленней раза в два-три, чтоб было заметно, как он ходит.
                      +2
                      неплохо бы показывать доступные поля для следующего хода
                        +1
                        короче, даешь шахматы!
                          +1
                          В шахматы надо, наверное, еще играть уметь, а я только знаю, как некоторые фигуры ходят :)
                            +1
                            Нередко этого уже достаточно. Аппетит приходит во время еды. :)
                              0
                              фигня-война, дебюты-эндшпили, перебор, также за день освоишь
                              если что — задавай вопросы, подскажу
                            +1
                            Вы сказали, что никогда не работали с Silverlight до сегодняшнего дня?
                              0
                              Работать — не работал, писать — не писал, ни Silverlight, ни WCF (насколько я знаю, они во многом похожи).

                              До этого знал C#, WinForms, WCF, еще раньше писал на Java, Delphi, PHP, C++, Turbo Pascal, C, GWBasic, Assembler.

                              Сейчас вот всерьез задумался о том, а не написать новый веб-проект целиком на Silverlight.
                                0
                                В первой строчке — WPF*
                                  0
                                  Наверно вам помог опыт изучения языков =) По каким источникам вы изучали SL?
                                    0
                                    В основном по блогам Scott Guthrie, Tim Heuer, John Papa, Glenn Block, Dinesh Kulkarni etc…

                                    Ну и видео с прошлого микса запоем смотрел. Там одна китаеза женского рода такие вещи показывала, что просто срывала аплодисменты зала…

                                    Прикидываю, что на этом Миксе будет :0
                              • НЛО прилетело и опубликовало эту надпись здесь
                                  0
                                  Хм. А поподробнее можно?

                                  Вы уверены, что этого в .NET framework до Silverlight-а не было?
                                  • НЛО прилетело и опубликовало эту надпись здесь
                                      +2
                                      Это появилось во втором .NET framework-е. Удобная штука.
                                        0
                                        ух-ты, здорово. надо побольше почитать про атрибуты, наверняка какие-нибудь еще фишки есть
                                        0
                                        ну в принципе всегда можно просто переопределить ToString с тем же эффектом, но так конечно приятней.
                                          0
                                          зачем плодить лишние сущности, если это нужно только для отладки и не используется в коде?
                                            –1
                                            ну как будто атрибут — не сущность. :)
                                            а потом, скажем сегодня вам только в дебаге это надо, а завтра захотелось ту же инфу залогировать.
                                              +1
                                              Debug — это debug, а логирование — это логирование, не надо все в одну кучу :)
                                  –9
                                  Не работает, сначала зачем-то просит что, то скачать. А потом пишет «Microsoft Silverlight may not be supported on your computer's hardware or operating system.» Проверял в мозилле, хроме и опере. А еще в мини опере.

                                  Прошу не минусовать, ведь например это davidbau.com/reversi/ работает.

                                  Причем мой Samsung Galaxy и iPhone тоже имеют такое-же мнение.

                                  Пофиксите плиз.
                                    0
                                    Silverlight plugin еще не на каждом телефоне пашет, это да. Но это со временем пройдет.
                                    Кому-то дольше ждать придется, кому-то меньше.
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                      –1
                                      Минуснули. Никогда не будет сервелата на n800 и на CASIO с складов его не будет. А JS там есть. И тут трусы минусуют, им стыдно признать это.

                                      Технология крута, вбухано много денег, но у вас есть 2 пути либо начать продавать эту технологию, либо прекратить её покупать. Вот когда она заработает на 30% компьютеров моей компании, я соглашусь её рассматривать. А анонимные минусеры трусы.
                                        +1
                                        странно, пришли потроллить, а потом удивляетесь, что заминусовали. не заметили, что пост называется не Silverlight vs JS? и что здесь не обсуждается перспективность данного фреймворка? так зачем тогда лезть со своим мнением которое никого тут не интересует и самое главное к теме не относится? или просто любой продукт MS как красная тряпка для быка? ну так от этого теперь лечат разными седативными средствами.
                                          0
                                          Топик был про скорость разработки и удобство сильверлайта против питон кутэ.

                                          Я выразил свое глубочайшее сожаление, в том, что из-за ПОЛИТИЧЕСКИХ причин сильверлайт не может тягаться.

                                          Насчет «или просто любой продукт MS как красная тряпка для быка» я что где, то сказал что он принципиально плох? Это у тех кто минусует красная тряпка, ах он не зааплодировал — ату его ату.
                                            +1
                                            Ну не знаю, какие у вас такие политические причины.

                                            Но у нас — с Silverlight-ом тягаться не может никто.

                                            1) Silverlight — это .NET и C#. Индустриальные стандарты (WCF, RIA Services, XAML, WebServices, Forms/Windows authentication).
                                            2) Silverlight — это VS.NET.
                                            3) Silverlight — это не только Windows и не только Desktop и не только IE. Кроссплатформенность — это хороший плюс, но не религия.

                                            Нам не нужны форм-факторы складских штрих-код-ридеров, основной наш пользователь — интранет Windows, иногда offline, иногда интернет.

                                            Здесь, возможности deploymentа Silverlight приложений, автоматических обновлений, локального хранилища, возможности работы оффлан — вот что нужно пользователю. Javascript такого не потянет.
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                          +1
                                          Точно таким-же. Только пока даже Мигель с тысячами обезьян ( у него эмблемы такие) пока мунлайт не доделал.
                                        +1
                                        надо подкрутить приоритетность клеток, но, в целом, неплохо :)
                                          0
                                          AI хорош, но ему не хватает знания тактик описанных в книжках. сначало оно меня выигрывало, потом я увиднл, что алгоритм не ставит фишки в угол, даже когда это выгодно, ну воспользовавшись этим выиграл 3 раза.
                                            0
                                            игрушка затягивает))

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

                                            Самое читаемое