Вывести шахматную доску с заданными размерами по принципу

Обновлено: 29.04.2024

Какие структуры данных вы бы использовали для представления шахматной доски в компьютерной шахматной программе?

Обычно он известен как Презентация доски.

Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно.

Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей.

Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.

У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то.

Ответы 14

Самый простой подход - использовать целочисленный массив 8x8. Используйте 0 для пустых квадратов и присвойте значения фигурам:

Ход фигур можно рассчитать, используя индексы массива. Например, белые пешки перемещаются путем увеличения индекса строки на 1 или на 2, если это первый ход пешки. Таким образом, белая пешка на [2] [1] может перейти на [3] [1] или [4] [1].

Однако это простое представление массива 8x8 имеет несколько проблем. В частности, когда вы перемещаете «скользящие» фигуры, такие как ладьи, слоны и ферзи, вам необходимо постоянно проверять индексы, чтобы видеть, не сдвинулась ли фигура с доски.

Большинство шахматных программ сегодня, особенно те, которые работают на 64-битном процессоре, используют растровый подход для представления шахматной доски и генерации ходов. x88 - это альтернативная модель платы для машин без 64-битных процессоров.

Как вы отслеживаете с помощью этой модели, сделал ли конкретный король или ладья ход или нет в отношении рокировки? Пешковые движения относительно взятия на проходе?

+1 стивет45. Очевидно, что каждая работающая шахматная программа имеет идентификаторы отдельных фигур, а не только целые числа, представляющие их характер, тип или значение. Конечно, предметы тоже имеют ценность, но, прежде всего, у них есть уникальный идентификатор.

Массив, вероятно, подойдет. Если вам нужны более удобные средства «обхода» доски, вы можете легко создать методы, абстрагирующие детали реализации структуры данных.

используйте положительные вставки для белого и отрицательные для черного

Первоначально используйте 8 * 8 целочисленный массив для представления шахматной доски.

Вы можете начать программировать, используя эту нотацию. Дайте баллы за фигуры. Например:

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

После того, как вы разработаете базовые основы своего приложения и четко поймете работу используемых алгоритмов, попробуйте улучшить производительность с помощью битовых плат.

Битовые доски могут значительно улучшить производительность вашего приложения, потому что манипулировать деталями с битовыми досками очень легко и быстро.

Как вы отметили,

Most chessprograms today, especially those that run on a 64 bit CPU, use a bitmapped approach to represent a chessboard and generate moves. x88 is an alternate board model for machines without 64 bit CPUs.

Как отличить слона от коня, если они оба представлены целым числом 3?

Нет, они не представлены числом 3. Это их материальная ценность (слон и кони стоят примерно 3 пешки).

Я бы использовал многомерный массив, чтобы каждый элемент в массиве представлял собой сеточную ссылку на квадрат на доске.

Тогда доска [A] [1] - это доска A1.

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

Конечно, есть несколько разных способов изобразить шахматную доску, и лучший из них будет зависеть от того, что для вас наиболее важно.

У вас есть два основных варианта: скорость и ясность кода.

Если скорость является вашим приоритетом, вы должны использовать 64-битный тип данных для каждого набора фигур на доске (например, белых пешек, черных ферзей, проходных пешек). Затем вы можете воспользоваться преимуществами собственных побитовых операций при генерации ходов и проверке законности перемещения.

Если ясность кода является приоритетом, забудьте о перетасовке битов и перейдите к хорошо абстрактным типам данных, как уже предлагали другие. Просто помните, что если вы пойдете этим путем, вы, вероятно, быстрее достигнете потолка производительности.

Не уверен, что это помогает, но Deep Blue использовал одно 6-битное число для обозначения определенной позиции на доске. Это помогло сэкономить место на кристалле по сравнению с его конкурентом, который использовал 64-битную битовую плату.

Это может быть неактуально, поскольку есть вероятность, что у вас уже есть 64-битные регистры на вашем целевом оборудовании.

Использование битовой доски было бы эффективным способом представления состояния шахматной доски. Основная идея состоит в том, что вы используете 64-битные биты для представления каждого квадрата на доске, где первый бит обычно представляет A1 (нижний левый квадрат), а 64-й бит представляет H8 (диагонально противоположный квадрат). Каждый тип фигуры (пешка, король и т. д.) Каждого игрока (черный, белый) получает свою битовую доску, и все 12 этих досок составляют состояние игры. Для получения дополнительной информации ознакомьтесь с этой Википедией статья.

На самом деле я бы не моделировал шахматную доску, я просто моделировал положение фигур. Тогда у вас могут быть границы для шахматной доски.

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

При создании своего шахматного движка я изначально использовал подход [8] [8], однако недавно я изменил свой код, чтобы представить шахматную доску с использованием массива из 64 элементов. Я обнаружил, что эта реализация была примерно на 1/3 эффективнее, по крайней мере, в моем случае.

Одна из вещей, которую вы хотите учитывать при использовании подхода [8] [8], - это описание позиций. Например, если вы хотите описать допустимый ход для шахматной фигуры, вам потребуется 2 байта для этого. В то время как с массивом элементов [64] вы можете сделать это с одним байтом.

Чтобы преобразовать позицию на доске [64] в доску [8] [8], вы можете просто использовать следующие вычисления:

Строка = (байт) (индекс / 8)

Col = (байт) (индекс% 8)

Хотя я обнаружил, что вам никогда не нужно делать это во время рекурсивного поиска перемещения, который зависит от производительности.

Массив 120 байт.

Это шахматная доска 8x8, окруженная контрольными квадратами (например, 255, чтобы указать, что фигура не может перейти на это поле). Стражи имеют глубину два, так что рыцарь не может перепрыгнуть.

Для перемещения вправо добавьте 1. Для перемещения влево добавьте -1. Вверх 10, вниз -10, вверх и вправо по диагонали 11 и т. д. Квадрат A1 - это индекс 21. H1 - это индекс 29. H8 - это индекс 99.

Все сделано для простоты. Но он никогда не будет таким быстрым, как битборды.

Для серьезного шахматного движка использование битовых досок - эффективный способ представить шахматную доску в памяти. Битовые доски быстрее, чем любое представление на основе массивов, особенно в 64-битных архитектурах, где битовая доска может уместиться в одном регистре ЦП.

Битборды

Теперь, например, если вы хотите переместить ладью с a2 на g2 в приведенном выше примере, все, что вам нужно сделать, это выполнить XOR для битовой доски:

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

Дальнейшее чтение

Битовые доски быстрее, чем представление массива, но не по указанным вами причинам. Как вы утверждаете, они имеют меньший вес на нет (массив 8x8 char составляет всего 64 байта), и сделать один ход на самом деле не быстрее. Основное преимущество заключается в том, что вы можете анализировать несколько позиций платы за одну операцию, используя битовые маски и сдвиги. Это позволяет намного быстрее генерировать и оценивать ходы.

Ссылка на хеш-таблицу без блокировки не работает. Еще одна хорошая ссылка была бы отличной!

Альтернативой стандартному Доска 8x8 является почтовый ящик 10x12 (так называемый, потому что, я думаю, он похож на почтовый ящик). Это одномерный массив, который включает часовые вокруг своих «границ», чтобы помочь с генерацией перемещения. Это выглядит так:

Вы можете сгенерировать этот массив следующим образом (в JavaScript):

Конечно, в реальной реализации вы бы поместили фактические объекты на место меток платы. Но вы бы оставили отрицательные (или что-то подобное). Эти места делают создание ходов намного менее болезненным, потому что вы можете легко определить, когда вы сбежали с доски, проверив это специальное значение.

Давайте сначала посмотрим на создание допустимых ходов для коня (не скользящей фигуры):

Мы знаем, что допустимые ходы коня находятся на фиксированном расстоянии от начальной точки фигуры, поэтому нам нужно было только проверить, что эти местоположения действительны (то есть не сигнальные квадраты).

Скользящие детали не намного сложнее. Посмотрим на епископа:

Вот некоторые примеры:

Обратите внимание, что функция slide является общей реализацией. Вы должны легко смоделировать допустимые ходы других скользящих фигур.

Я знаю, что это очень старый пост, на который я наткнулся несколько раз, когда гуглил шахматное программирование, но я чувствую, что должен упомянуть, что вполне возможно смоделировать шахматную доску с 1D-массивом, например. шахматная доска [64];

Я бы сказал, что это самый простой подход к представлению на шахматной доске . но, конечно, это базовый подход.

Является ли структура массива одномерной шахматной доски более эффективной, чем двумерный массив (которому требуется вложенный цикл for для доступа и управления индексами)?

Также можно использовать одномерный массив с более чем 64 квадратами для представления квадратов OffBoard, например, шахматная доска [120]; (с правильной инициализацией контрольного массива и игровых полей на доске).

Наконец и еще раз для полноты этого поста, я считаю, что должен упомянуть представление массива платы 0x88. Это довольно популярный способ изобразить шахматную доску, на которой также учитываются внешние квадраты.

Было ли вам когда-либо интересно написать свою шахматную программу? Настраивать и развивать её, проверять её на знакомых любителях шахмат и радоваться её победам. Но как написать такую программу? Об этом я и расскажу в этой статье.

Сначала я хотел дать полное описание своей реализации шахматного движка (я назвал его Centurion). Но тут я вдруг понял, что на эту тему пишут книжки, а не статьи. В формате статьи просто невозможно описать детально все компоненты шахматной программы с подробностями реализаций. Поэтому я решил ограничиться общим описанием моего шахматного движка и дать ссылку на его исходный код и саму программу. Выглядит программа для Windows так:



Программа для Windows.
Ходить можно как вводом хода в поле (E2-E4), так и мышкой — левая кнопка откуда, правая — куда.

Итак, начнём.
Для начала, стоит поискать специальную литературу о том, как же писать шахматные программы. Я из таковых использовал книжку Корнилова “Программирование шахмат и других логических задач” 2005 года. Одной этой книжки оказалось мало – автор не акцентировал внимание на кое-чём важном, а кое-что просто не рассказал. А это кое-что, между прочим, сильно сокращает дерево перебора. Сразу же предупреждаю, что в моём движке не используется генератор ходов на базе битовых массивов. Этот уровень мне пока недоступен. Впрочем, я особо и не пытался разобраться с ними, предпочитая написать как можно более прозрачный (для меня) механизм работы с ходами фигур, пусть даже в ущерб быстродействию (движок получился не очень быстрый, но вполне работоспособный).

Первое, о чём нам нужно подумать, так это о том, как мы будем представлять игровое поле. Оказывается, очень удобно каждую клетку представлять целым числом, отдельные биты которого отвечают за параметры этой клетки. Я для клеток задал макрос

А сама клетка у меня представлена битами как AHIIIIEWB0MFFF, где:

W-фигура белая
B-фигура чёрная
F-тип фигуры (0-фигуры нет)
M-ходила ли фигура
E-край доски
I-индекс фигуры в массиве для поиска фигур (0-15)
H-была короткая рокировка (флаг ставится только у короля и ладьи)
A-была длинная рокировка (флаг ставится только у короля и ладьи)

Чем удобно представление с помощью битов? Наложение маски позволяет быстро определять, что это за клетка. Специально для этого у меня были заданы маски:


Дальше следует решить, какого размера будет доска. 8x8 неудобно для анализа выхода за пределы доски. Гораздо удобнее задать массив 16x16 с доской посередине, задав для всех тех клеток, которые не являются доской, флаг границы. В этом случае изменение координаты по X происходит изменением координаты X на нужный шаг, а по Y на шаг*16. Доска задаётся как

Некоторые параметры в дальнейшем будет удобно задавать для поля 8x8, для этой цели стоит завести массив перекодировки координат из поля 16x16 в поле 8x8.

Кстати, чтобы не пришлось сканировать всю доску, стоит помнить, где на доске находятся фигуры. Например, так:

Теперь определимся с тем, как мы будем задавать ходы. Очень удобно сделать так:

Здесь в массивах заданы изменения координат в пространстве нашей доски 16x16 для одного шага фигуры. Ходы пешки удобно рассматривать отдельно, так как у неё ходы простые, но есть специфическое взятие на проходе.
Как таким массивом пользоваться? Ну вот, например, составление всех ходов ферзя:

Как видите, всё просто. Для хранения ходов я создал структуру

Хоть массив ходов и задаётся как

, где MAX_PLY – максимальная глубина анализа (а 200 – максимальное число ходов любой фигуры (с запасом)), но указатель на следующий элемент sMove_NextPtr позволяет удобно сортировать ходы (а сортировать их придётся). std::list (или ещё что из stl) я тут не стал использовать – у нас крайне критично быстродействие (да и я не скажу, что мастер в stl и современном Си++, скорее наоборот). Впрочем, вы можете сделать и с помощью stl и сравнить скорость работы программы – я же этого не проверял.

Ну, в целом, с ходами закончили, перейдём к алгоритмам.

Во-первых, нам нужна функция оценки позиции. Тут возможностей просто море. У меня в движке в engine_score.cpp вполне читаемо описано всё то, что я использую для оценки позиции. Там представлены массивы очков за нахождение фигуры в данной клетке поля (для поля 8x8 – так просто удобно задавать).

Во-вторых, нам нужен альфа-бета с амортизацией отказов. Думаю, рассматривать сам альфа-бета алгоритм бессмысленно — на эту тему написано множество статей и книг. Да и в общем, он (или его модификации) в основе множества шахматных программ. Самое интересное в шахматных программах, как сократить число ходов для этого алгоритма.

В-третьих, нам нужна хэш-таблица. Дело в том, что в шахматах позиция при переборе часто повторяется – зачем нам заново анализировать то, что уже мы смотрели? Выявить такую позицию и позволяет хэш-таблица. В ней хранятся “уникальные” значения, отличающие одну позицию от другой. Стоятся эти “уникальные” значения просто выполняя операцию xor для ключей элементов, описывающих позицию. Поэтому нам нужны будут массивы уникальных 64 битных чисел (вы можете и любую другую размерность взять, весь вопрос только в том, как часто будут одинаковым значениям позиции соответствовать разные позиции – ошибки хэша). У меня таблица описана так:

Ещё понадобятся ключи смены хода (так как позиции могут быть и одинаковыми, а вот цвет фигур, которые должны ходить разный). И специальный ключ так называемого нулевого хода (о самом нулевом ходе я расскажу ниже). Насколько я помню, вот об этих последних двух ключах Корнилов в своей книжке умолчал.

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

Теперь смотрите какая штука выходит: если мы изначально позицию получим, выполнив xor всех ключей фигур на доске

, то при выполнении хода, как можно заметить, нам достаточно делать с текущим значением хэша позиции xor ключа фигуры на старом месте, а потом xor ключа фигуры на новом месте. Так же и со взятиями. Это позволяет очень быстро в процессе перебора позиций вычислять значение хэша.

В-четвертых, нам нужна такая штука, как статистика истории. Что это такое? Во время игры можно заметить, что какие-то ходы улучшают оценку позиции. Стоит этот факт отмечать, запоминать и в дальнейшем использовать при сортировке ходов. Как это сделать? Просто завести массив [64][64] ([начальная позиция фигуры на поле 8x8][конечная позиция фигуры на поле 8x8]), обнулить в начале оценки выбора лучшего хода и в дальнейшем просто увеличивать счётчик на 1 в случае хода, улучшающего для нас оценку позиции.

В-пятых, нам нужна сортировка ходов. Самыми первыми должны быть ходы с максимальной выгодой по оценке позиции. Понятно, что ходы взятия приоритетнее обычных “тихих” ходов. Ходы взятия сортируются по принципу MVV/LVA (наиболее ценная жертва – наименее ценный нападающий). При этом стоит продвигать все необычные ходы со взятием (любой ход, который не имеет тип MOVE_TYPE_SIMPLY). Так же вперёд стоит продвинуть и взятие последней ходившей фигуры противника (если взятие будет). Обычные ходы сортируются по возрастанию оценки позиции с учётом эвристики истории. Вся эта сортировка очень важна! Она и сама по себе позволяет сократить обход дерева игры, но более того, на нижних уровнях дерева можно в принципе выбрасывать почти все “тихие” ходы (и если король не под шахом) из рассмотрения без ущерба для качества игры программы! Я увидел такое в коде шахматной программы Ифрит (Ifrit) и, конечно же, применил. Это называется Late Move Reduction, насколько я понимаю.
Для этого используется следующий массив:

Здесь числа означают то, сколько “тихих” ходов анализируется в зависимости от уровня дерева (массив задан в обратном порядке). То есть, на последних для анализа 9 уровнях дерева в рассмотрении будет сначала 259 ходов, потом 131, потом 67 и так далее до 19. Это сильно ускоряет работу программы (а также об этом Корнилов вроде как тоже не рассказал в своей книжке). Разумеется, без сортировки ходов такое отсечение не заработает.

В-шестых, нам нужно обязательно продлевать анализ взятий и шахов. Это позволит увеличить точность оценки позиции.

В-седьмых, нам нужна будет эвристика убийцы. Заключается она в том, чтобы при анализе веток дерева пробовать первым ход, вызвавший отсечение на предыдущей ветке. Такой приём также позволяет сократить перебор. Следует помнить, что такой ход может быть только “тихий”: взятия и необычные ходы использовать для таких проверок нельзя.

В-восьмых, есть такая штука, как нулевой ход. Смысл в том, что можно сделать пропуск хода и посмотреть, насколько всё станет плохо. При этом можно сократить глубину анализа дерева (сделать редукцию) – всё равно оценка предварительная. Главное, не забывать пометить хэш позиции ключом этого самого нулевого хода

В-девятых, есть ещё Futility Prunning. Что это такое? На последних двух полуходах дерева оценка позиции не точна и в ряде случаев (если мы не в нулевом ходе, если ход не является шахом, взятием и ход не продление анализа ветки), а также если разность оценки позиции была больше некоторой небольшой величины, то можно просто вернуть эту оценку и не анализировать глубже. Этот приём также ускоряет работу программы.

В-десятых, для сокращения вариантов придуман ещё и Razoring. Это почти то же самое, что и Futility Prunning, но относится к последним четырём полуходам и граница оценки задаётся в некоторую стоимость допустимых потерь фигур.

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

В-двенадцатых, есть ещё такая штука, как Principal Variation (главное изменение). Это та линия игры, которую программа считает лучшей в данный момент. Эта линия постоянно корректируется во время перебора позиций. Ход из главной линии при сортировке стоит продвигать вперёд.

Ну вот вроде бы и всё из того набора, который использует мой шахматный движок. Надеюсь, я ничего нигде не напутал, так как движку уже два года и я столько же его не касался и вполне мог что-либо забыть.

В архиве лежит сам движок (он поддерживает UCI, так что можете подключить его к Arena), программа под Windows для игры с ним (на скорую руку), шахматы для QNX 6.3. Уровень игры я точно оценить не могу (я не шахматист, как ни странно), но вроде как играет достаточно неплохо.

Если вы начинающий Java программист то вам обязательно нужно ознакомится и выполнить все задания из этого списка.

Условные операторы

1. Найти наибольшее значение из двух переменных, трех, четырех, описать общий принцип для большего числа

2. Если а – четное посчитать а*б , иначе а+б

3. Определить какой четверти принадлежит точка с координатами (х,у)

4. Найти суммы только положительных из трех чисел

5. Посчитать выражение макс(а*б*с, а+б+с)+3

6. Есть два конверта со сторонами (а,б) и (с,д) определить, можно ли один конверт вложить в другой

7. Отсортировать значения двух, трех, четырех переменных используя только условные операторы

8. Написать программу определения оценки студента по его рейтингу, на основе следующих правил:
рейтинг Оценка

9. Проанализируйте следующий фрагмент кода. Какой результат будет при a =2 и b= 4 ?

Путем минимальных изменений модифицируйте код таким образом, чтобы на экране было напечатано

134 (при a =2 и b= 4)
4 (при a =2 и b= 44)
14 (при a =2 и b= 4)
1 (при a =2 и b= 4)

Циклы

1. найти сумму четных чисел и их количество в диапазоне от 1 до 99

2. Проверить простое ли число? (число называется простым, если оно делится только само на себя и на 1)

3. Вывести на экран квадрат, со стороной а

4. Вывести шахматную доску с заданными размерами, по принципу:

5. Напишите программу, которая определяет, является ли введенное число палиндромом? (Палиндром – число или текст, которые одинаково читаются слева направо и справа налево)

6. Вывести все простые числа в диапазоне от 2 до n

7. Вывести все натуральные числа, квадрат которых больше меньше заданного числа n

8. Вывести все делители числа

9. Найти корень натурального числа с точностью до целого (рассмотреть переборный вариант, и метод бинарного поиска)

10. Теорема Пифагора: вывести все прямоугольные треугольники, стороны которых – натуральные числа меньше 1000, посчитать их количество(по теореме Пифагора у прямоугольного треугольника сумма квадратов катетов равна квадрату гипотенузы). Подсказка: использовать полный перебор с трижды вложенными циклами.

11. Вычислить факториал числа n. n! = 1*2*…*n-1*n;

12. Вычислить среднее значение чисел, не являющихся простыми, в диапазоне от 1 до n.

13. Посчитать сумму цифр заданного числа

14. Вывести число, которое является зеркальным отображением последовательности цифр заданного числа, например, задано число 123, вывести 321.

Как я могу сделать шахматную доску с переменным размером из текста? Я могу сделать шахматную доску, состоящую из отдельных символов, используя этот код:

Но это дает мне вывод только отдельных символов, как бы я добавил переменные размеры блоков в уравнение?

Например, Учитывая символ (C), длину (L), ширину (W) и размер (N), напишите программу на C ++, чтобы нарисовать доску размером (2N x 2N), состоящую из ячеек, заполненных символом C, длина L и ширина W. Ячейки доски должны быть нарисованы как шахматная доска

Предположим, C = ‘&’, L = 4, W = 6 и N = 3

Выход будет такой (без границ)

http://i.stack.imgur.com/qQk2J.jpg

Решение

Честно говоря, я пытался просмотреть ваш код и найти ошибки, но в итоге я переписал проблему с нуля. Это все о вложенных циклах, и вам нужно довольно много из них для детального контроля.

Код, который помог мне (надеюсь, комментарии полезны):

Компилирование с g++ -o main main.cpp а затем выполнить с некоторыми параметрами, например, echo "X 3 5 2" | ./main дает мне хороший результат:

Другие решения

Способ решения проблемы такого рода состоит в том, чтобы разбить ее на более мелкие проблемы и продолжать разбивать проблему до тех пор, пока вы не получите очень маленькие задачи, которые можно легко перевести в код.

Например, после просмотра вашего плана того, что вы пытаетесь сделать, одна вещь становится совершенно ясной:

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

Таким образом, мы можем с уверенностью сказать, что код для выполнения того, что вы хотите, будет выглядеть примерно так:

Итак, с N = 3 вы получите шахматную доску, состоящую из шести рядов, как в примере с желаемым результатом. С N = 4 вы получите восемь и так далее.

Теперь проблема сводится, в основном, к рисованию одной логической строки шахматной доски. Как бы то ни было, получающийся код будет втиснут в цикл for. Итак, мы можем отложить это.

Второй легко разложимый шаг состоит в том, что каждая строка шахматной доски состоит из L строк физических строк.

Таким образом, код для создания одной логической строки шахматной доски будет выглядеть примерно так:

Это делается для каждого нечетного и четного ряда шахматной доски. Далее, чтобы избежать дублирования кода, вы, возможно, могли бы уточнить конечный результат, но сейчас достаточно дважды продублировать его для цикла for, внутри первого цикла for, один раз для нечетной строки, один раз для четной строки.

На этом этапе исходная проблема теперь разбита на: нарисовать одну физическую строку. Это должно быть достаточно просто, чтобы вы заимствовали код, который вы уже написали в своем вопросе, для реализации окончательного ответа.

Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском.

Закрыт 1 год назад .

Требуется нарисовать поле, с которым в последствии можно будет работать через логику, описанную в коде. В логике программы доска и расстановка на ней фигур описана в виде двумерного массива. Есть идея с Canvas и Rectangle , но я не понимаю, как автоматом наклепать этих Rectangle и закрасить их в соответствии с доской, после чего привязать фигуры, основываясь на опять же, двумерном массиве.

1 ответ 1

Этот ответ не зависит от ссылки в вопросе, полноценный пример использования UI в WPF "с нуля".

Я вас огорчу, но в ниже следующем примере не используется ни Canvas , не Rectangle .

  • Нарисовать в интерфейсе шахматную доску с координатными метками
  • Разместить на ней шахматные фигуры
  • Реализовать перемещение шахматных фигур в свободные клетки пользователем с помощью мыши

Выглядит просто, поехали:

Шахматная доска с шахматами в WPF

введите сюда описание изображения

1. MVVM, INotifyPropertyChanged , ICommand

Если кратко, то MVVM (Model View ViewModel) - это шаблон проектирования приложений, позволяющий удобно их разрабатывать за счет полного разделения логики данных (Model), интерфейса (View) и логики взаимодействия данных с интерфейсом (ViewModel). Все эти 3 слоя разрабатываются отдельно. В моем конкретном случае у меня не будет Model как таковой, так что будет немного проще, чем полноценный MVVM.

INotifyPropertyChanged - нужен для того чтобы можно было сообщать интерфейсу о том, что данные поменялись посредством вызова события PropertyChanged . По-началу будет выглядеть как магия, но вся магическая часть здесь в том, что интерфейс сам подписывается на это событие автоматически. Оно зашито в WPF, надо только пользоваться. За реализацию этого интерфейса будет отвечать простой класс, его нужно просто добавить в проект.

ICommand - прощай обработчики событий Click , команда имеет больше возможностей, позже вы увидите их. Для удобного использования команд, был создан вот такой вспомогательный класс. Его тоже просто надо добавить в проект.

2. Структура данных

Ячейка шахматного поля может быть всего в 13 состояниях: пусто или на ней 1 из 12 типов шахматных фигур (6 белых и 6 черных). Чтобы перечислить все состояния, я создам (внезапно) перечисление.

Ячейка, которая содержит это состояние, выглядит так. Кстати, вот он сразу NotifyPropertyChanged и несложный способ его использовать.

Шахматное поле будет "хитрым" классом, с одной стороны это будет двумерный массив состояний State , с другой - поле с ячейками Cell . Первое - для вас, чтобы вы легко могли в коде писать типа Board[0, 0] = State.WhiteQueen . Второе - для интерфейса, чтобы он мог все эти состояния отслеживать.

Здесь все просто, массив, индексатор State и IEnumerable , чтобы интерфейс ( ItemsControl ) мог это прожевать.

Дальше я голопом по европам, потому что кода много, а ответ не резиновый.

3. ViewModel

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

Чтобы прикрутить ViewModel к приложению, нужно, чтобы класс MainWindow выглядел следующим образом:

Да, это весь код класса MainWindow , больше в нём ничего нет :)

4. Интерфейс

Основная часть интерфейса содержит 2 кнопки и рисует шахматную доску на 64 клетки. Для того, чтобы у интерфейса получилось сделать доску из темных и светлых клеток, я написал маленький конвертер. В него передается порядковый номер ячейки 0..63, а он возвращает true или false , где true - темная клетка. Каждая клетка - тоже кнопка.

XAML основного окна получился не сложный.

И я бы закончил на этом, но так как вам будет очень сложно продвинуться дальше с шахматными фигурами не вникнув полностью в суть привязки данных, поэтому я сразу написал UserControl , которому вы передаете State , а он вам выдает картинку. Картинки векторные - Path картинок выдернут из SVG файлов, скачанных с сайта iconfinder. Вбейте там в поиск Chess и вы быстро их найдете.

И разметка юзерконтрола. Здесь я применил все приемы кунгфу при работе со стилями в WPF, которые знаю. :)

Читайте также: