Вопрос № 182840: Здравствуйте! У меня возникли сложности с таким вопросом: Реализовать игру "Цепь". В builder 6.5. Парвила игры: играют 2 игрока задача составить из фишек на шашечном поле цепь от нижнего края до верхнего( для одного игрока) и от левого к...
Вопрос № 182840:
Здравствуйте! У меня возникли сложности с таким вопросом: Реализовать игру "Цепь". В builder 6.5. Парвила игры: играют 2 игрока задача составить из фишек на шашечном поле цепь от нижнего края до верхнего( для одного игрока) и от левого края до правого(для другого). Обязательна проверка выйгрыша.Также ввести таблицу рекордов(сколько использованно фишек и за какое время)
Отвечает Киселёва Алёна aka Verena (Профессор) :
Здравствуйте, Иванов Иван! Для ячейки поля будем использовать компонент, наследованный от TSpeedButton, в котором предусмотрен рисунок на кнопке. Мы будем рисовать на ней фишки заданных цветов (я поставила красный и чёрный). Нам даже не придётся перегружать никакие функции исходного класса, достаточно добавить функцию, позволяющую занять клетку (она-то и будет рисовать фишку). Из алгоритма самое сложное - проверка на выигрыш. Но тут у нас есть преимущество перед задачей поиска пути между границами
в массиве - мы можем всегда отталкиваться от последней поставленной фишки. Для этого используем рекурсивную функцию, которая осмотрит всех соседей текущей фишки. Если функция натыкается на край, то выставляет соответствующий флаг. Если после выхода из рекурсии выставлены флаги право-лево или верх-низ, то соответствующий игрок победил.
Код:
bool TForm1::CheckWinner (int x, int y) //проверка, победил ли игрок ходом на x,y { top = false; bottom = false; left = false; rigth = false; //копируем поле во временное поле memcpy (temp[gamer], flds[gamer], MaxBlocks*MaxBlocks*sizeof(bool)); CheckPath (x, y,
-2, -2); //проверяем, есть ли путь от текущей клетки до краёв if (gamer) return left&&rigth; //определяем победителя else return top&⊥ }
void TForm1::CheckPath (int x, int y, int fromx, int fromy) { //рекурсивная функция, которая осматривает ячейки вокруг x,y на занятость if (x>=wfield || y>=wfield || x<0 || y<0) return; if (!temp[gamer][x][y]) return; //если пуста или просмотрена - прерываем<
br> temp[gamer][x][y] = 0; //помечаем как просмотренную if (x==(wfield-1)) {bottom = true;} //проверяем на края if (x==0) {top = true;} if (y==0) {left = true;} if (y==(wfield-1)) {rigth = true;} if (gamer && rigth && left) return; if (!gamer && top && bottom) return; for (int i=-1; i<=1; i++) //просматриваем окружающие, не возвращаясь назад for (int j=-1; j<=1; j++) { if
(!(i==0 && j==0) && !(fromx==x+i && fromy==y+j)) CheckPath (x+i, y+j, x, y); } }
Обратите внимание, что при ходе я проставляю единицы в матрице flds, а в рекурсивной функции работаю с её копией temp, чтобы можно было помечать просмотренные клетки (это сократит число проходов и исключит зацикление рекурсии). Максимальное число клеток определено константой, можно менять при необходимости. Числ
о клеток по умолчанию выставляется в конструкторе. Проект прилагаю, в приложении код класса кнопки. Удачи!
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.