Консультация № 182840
13.04.2011, 14:48
55.00 руб.
0 7 1
Здравствуйте! У меня возникли сложности с таким вопросом:
Реализовать игру "Цепь". В builder 6.5. Парвила игры: играют 2 игрока задача составить из фишек на шашечном поле цепь от нижнего края до верхнего( для одного игрока) и от левого края до правого(для другого). Обязательна проверка выйгрыша.Также ввести таблицу рекордов(сколько использованно фишек и за какое время)

Приложение:
builder 6.5

Обсуждение

Неизвестный
19.04.2011, 13:50
общий
Можно правила игры поподробнее? Что считается цепью, сколько фишек имеется?
Неизвестный
19.04.2011, 14:31
общий
Фишек неограниченное количество(пока не будет построенна цепь), Цепь - фишки стоящие рядом друг с другом или по диагонали, образующие непрерывную линию, от нижнего края поля до верхнего для одного игрока и от левого края до правого для другого.
Да еще забыл предусмотреть до начала игры размерность поля, игрок сам выбирает размерность.
Неизвестный
19.04.2011, 17:31
общий
А ходить можно куда угодно или только рядом со своими фишками? И начинать обязательно снизу/слева или можно ставить первую фишку куда угодно?
Неизвестный
19.04.2011, 20:42
общий
Да ходить можно куда угодно, первую фишку не обязательно ставить снизу\слева.
Неизвестный
20.04.2011, 00:29
общий
Это хорошоПостараюсь завтра сделать эту и вторую (про уголки) - есть наброски.
Неизвестный
20.04.2011, 07:59
общий
Большое спасибо!!!
Неизвестный
20.04.2011, 17:57
общий
это ответ
Здравствуйте, Иванов Иван!
Для ячейки поля будем использовать компонент, наследованный от TSpeedButton, в котором предусмотрен рисунок на кнопке. Мы будем рисовать на ней фишки заданных цветов (я поставила красный и чёрный). Нам даже не придётся перегружать никакие функции исходного класса, достаточно добавить функцию, позволяющую занять клетку (она-то и будет рисовать фишку).
Из алгоритма самое сложное - проверка на выигрыш. Но тут у нас есть преимущество перед задачей поиска пути между границами в массиве - мы можем всегда отталкиваться от последней поставленной фишки. Для этого используем рекурсивную функцию, которая осмотрит всех соседей текущей фишки. Если функция натыкается на край, то выставляет соответствующий флаг. Если после выхода из рекурсии выставлены флаги право-лево или верх-низ, то соответствующий игрок победил.
[code h=100]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; //если пуста или просмотрена - прерываем
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);
}
}[/code]
Обратите внимание, что при ходе я проставляю единицы в матрице flds, а в рекурсивной функции работаю с её копией temp, чтобы можно было помечать просмотренные клетки (это сократит число проходов и исключит зацикление рекурсии).
Максимальное число клеток определено константой, можно менять при необходимости. Число клеток по умолчанию выставляется в конструкторе.
Проект прилагаю, в приложении код класса кнопки.
Удачи!

Приложение:
class BlockControl : public TSpeedButton
{ //кнопка, способная быть занятой фишкой заданного цвета
bool isUsed; //занятость
TColor blockColor; //цвет фона
public:
int i; //расположение на поле
int j;
__fastcall BlockControl (TComponent* owner) : TSpeedButton (owner), isUsed(false){};
void Setup (int w, int ng, int i_, int j_, TColor col);
void SetUsed (bool is, TColor col = clWhite);
bool IsUsed ();
};

void BlockControl::Setup (int w, int ng, int i_, int j_, TColor col)
{ //настроить
this->Width = w;
this->Height = w;
this->Glyph->Width = w;
this->Glyph->Height = w;
this->GroupIndex = ng;
this->AllowAllUp = true;
blockColor = col;
//this->Color = clWhite;
i = i_; j = j_;
}

void BlockControl::SetUsed (bool is, TColor col)
{ //занять или освободить
if (is!=isUsed) {
TRect r = this->ClientRect;
if (is) {
//int r = this->Glyph->Width / 2 - 2;
this->Glyph->Canvas->Brush->Color = col;
this->Glyph->Canvas->Ellipse(r);
} else {
this->Glyph->Canvas->Brush->Color = blockColor;
this->Glyph->Canvas->Ellipse(r);
}
}
isUsed = is;
}

bool BlockControl::IsUsed ()
{
return isUsed;
}
Прикрепленные файлы:
5
Форма ответа