Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Копия X3.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
471 Кб
Скачать
☆

Int I; /* индекс ряда */

for(i = 0; i < NY; i++) { /* цикл по рядам игрового поля */

repos(i, 0, 0); /* левый край поля для фишки 0 */

repos(i, (NX − 1), 1); /* правый край поля для фишки Х */

} /* for */

return(0);

} /* restore */

Функцию restore вызывает функция refuse графического модуля по нажатию клавиши ESCAPE, чтобы начать новую партию. Остальные игровые функции явно или косвенно вызывает графическая функция reset для ходов партии или корректировки позиции. В частности, функция remark вызывается для контролируемой перестановки одной из фишек заданного ряда в указанную клетку по щелчку левой или правой кнопки мыши. При вызове в функцию remark передаются соответствующие индексы клетки игрового поля, а также адресуется номер фишки ряда, чтобы вернуть результат ее выбора. Выбор фишки в функции remark зависит от позиции указанной клетки. Если она находится между фишками, то в нее должна быть передвинута фишка, адресованная аргументом функции. Иначе указанную клетку должна занять ближайшая фишка ряда, а ее индекс фиксируется и адресуется аргументом функции remark. В любом случае ее выполнение завершает вызов функции repos для графического позиционирования передвигаемой фишки. Следующий исходный код реализует действие функции remark.

int remark(int i, int j, int* m) {/* Перестановка фишки */

if(j < pos[i][0]) /* перестановка фишки 0 влево */

(*m) = 0; /* фиксировать индекс фишки 0 */

if(j > pos[i][1]) /* перестановка фишки Х вправо */

(*m) = 1; /* фиксировать индекс фишки Х */

if(j != pos[i][(*m)]) /* перестановка фишки к центру */

return(repos(i, j, *m)); /* позиционирование фишки */

return(NY);

} /* remark */

Самой важной для организации игры является функция nim. Она реализует выигрышный ответ фишкой, которую индексирует аргумент ее вызова из функции reset. Выбор выигрышного хода основан на вычислении НИМ-суммы по модулю 2 для разностей номеров фишек по всем рядам игрового поля. Если НИМ-сумма оказалась равна 0, то выигрышный ход невозможен, и следует немедленный возврат числа рядов. Если НИМ-сумма не равна 0, нужно найти ее максимальный значащий бит (MSB), который равен 1. Для ответа выбирается первый по порядку ряд, где разность номеров клеток фишек имеет 1 в разряде MSB. После этого инвертируются все биты разности ряда ответа (0<->1), которые не старше MSB. Результат инверсии дает разность позиций между фишками в этом ряду после выигрышного хода. По этой разности легко вычислить номер новой клетки передвигаемой фишки, относительно позиции парной фишки в том же ряду. Требуемое позиционирование фишки обеспечивается функцией repos с возвратом ряда выигрышного ответа. Выигрышную стратегию функции nim реализует исходный код.

/* Выигрышный ход для фишки m по стратегии NIMM */

int nim(int m) {

unsigned b = 8*sizeof(unsigned); /* старший 1 бит */

unsigned d=0; /* разность позиций (X-0) */

unsigned s=0; /* NIMM-сумма */

int i; /* индекс ряда */

for(i = 0; i < NY; i++) /* Вычисление NIMM-суммы */

s ^= (pos[i][1] − pos[i][0] − 1); /* по (X-0) для всех рядов */

if(s == 0) /* Нет выигрышного хода */

return(NY); /* Идентификация проигрышной позиции */

for( ; b > 0; b >>= 1) /* Поиск MSB */

if(b & s) /* (наибольшего значащего бита 1) */

break; /* NIMM-суммы */

for(i = 0; i < NY; i++) /* Выбрать ряд ответа */

if((d = (pos[i][1] − pos[i][0] − 1)) & b) /* по разности */

break; /* позиций фишек и MSB */

for( ; b > 0; b >>= 1) /* Инверсия */

if(b & s) /* младших битов */

d = (d & b) ? (d ^ b) : (d | b); /* разности ряда ответа */

d = (m > 0) ? (d + 1) : −(d + 1); /* Величина сдвига фишки */

repos(i, pos[i][(m+1)%2] + d, m); /* Позиционирование */

return(i); /* Возврат ряда выигрышного ответа */

} /* nim */

Если в позиции партии нет выигрышного ответа фишкой с заданным индексом, вызывается функция lose, чтобы сделать вынужденный ход. Аналогично функции nim, ее вызывает функция reset графического модуля, а ее аргументом является индекс фишки, которая делает ответный ход. Сначала делается попытка выбрать ряд, где можно сдвинуть фишку с этим индексом навстречу парной фишке ряда на одну клетку, используя функцию repos. Если это не может быть реализовано, выполняется проверка пата функциями lpat или rpat в зависимости от индекса фишки ответа. Если нет пата, то их код возврата идентифицирует ряд, где фишка ответа может отступить на одну клетку к своему краю игрового поля. Передвижение фишки как обычно должно осуществляться функцией repos. При пате функция lose завершается без ответа. Рассмотренный выбор вынужденного хода реализует следующий исходный код функции lose.

/* Вынужденный ответ фишкой m */

int lose(int m) {

int i; /* индекс ряда */

int d = (m == 0) ? 1 : −1; /* оценка направления 1 сдвига */

for(i = 0; i < NY; i++) /* Выбор ряда для сдвига */

if((pos[i][1] − pos[i][0]) > 1) /* по направлению */

break; /* к парной фишке */

if(i < NY) /* Сдвиг вперед на 1 клетку к */

return(repos(i, pos[i][m] + d, m)); /* парной фишке ряда */

i = (m == 0) ? lpat() : rpat(); /* контроль пата */

if(i < NY) /* выбор ряда отступа */

repos(i, pos[i][m] − d, m); /* отступ на 1 клетку к краю */

return(i); /* возврат ряда вынужденного ответа */

} /* lose */

Спецификации игрового модуля завершает исходный код функций проверки патовой позиции lpat и rpat, которые вызываются функцией lose при выборе вынужденного ответного хода. В частности, функция lpat применяется для проверки патовой позиции у левых фишек (0). При левом пате все фишки Х стоят в клетках с индексом 1 (считая с 0) своих рядов, что можно быстро установить по массиву позиций для индекса 1. В этом случае код возврата функции lpat равен числу рядов игрового поля. Если пата нет, возвращается номер ряда, где можно сделать ход фишкой 0. Следующий исходный код реализует рассмотренную проверку левого пата в функции lpat:

/* Контроль пата слева для фишек 0 */

int lpat() {

int i; /* индекс ряда */

for(i = 0; i < NY; i++)

if(pos[i][1] > 1)

break;

return(i);

} /* leftpat */

Функция rpat для проверки пата правых фишек (Х) устроена аналогично функции lpat. Только при правом пате все фишки 0 находятся в предпоследней клетке (NX−2, считая с 0) своих рядов, что легко проверяется по массиву позиций для индекса 0. Очевидно, следующий исходный код функции rpat почти совпадает с lpat.

/* Контроль пата справа для фишек Х */

int rpat() {

int i; /* индекс ряда */

for(i=0; i < NY; i++)

if(pos[i][0] < (NX-1-1))

break;

return(i);

} /* rightpat */

Если исходный код модулей программы игры Норкотта сохранен в файлах xpat0.c и xpat1.c, то для их компиляции и компоновки с графической библиотекой нужно выполнить следующую команду:

$ cc -o xpat xpat0.c xpat1.c –lX11

В результате должен быть получен выполняемый файл xpat. Он может быть вызван с любым реалистичным аргументом в полном или частичном формате спецификации геометрических ресурсов Х-клиентов, а также вообще без аргумента. В частности, следующая командная строка образует в правом верхнем углу экрана графическое окно игрового поля с заголовком "xpat", которое имеет 4 ряда по 32 клетки (цвета циан):

$ xpat 32x4−0+0 &

При вызове программы с аргументом в любом сокращенном формате, например, когда указаны только габариты игрового поля без координатных смещений окна, или только 1 из габаритов, значение недостающих параметров выбираются по умолчанию из строки "16x4+0+0" (4 ряда по 16 клеток в левом верхнем углу +0+0 экрана). Вызов программы без аргумента сопровождает диагностический вывод формата по умолчанию в окне эмулятора терминала.

СПИСОК РЕКОМЕНДУЕМОЙ ЛИТЕРАТУРЫ

1. С.Е. Базаева, В.Б. Бетелин, А.И. Грюнталь, С.Г. Романюк. Технология разработки диалоговых графических систем. − М.: «Наука», 1992. – 207 с.

2. Доценко А.В., Исаков А.Б., Рябов А.Ю. Unix, X Window, Motif. Основы программирования. − М.: АО «Аналитик», 1994. Часть 1 − 252 с., часть 2 − 259 с.

3. В.В. Коннов, Г.И. Клековкин, Л.П. Коннова Геометрическая теория графов. − М.: «Народное образование», 1999. − 240 с.

СОДЕРЖАНИЕ

ВВЕДЕНИЕ ……………………………………………………………………………………..

2

ПРОГРАММИРОВАНИЕ ФОНА ГРАФИЧЕСКИХ ОКОН ………………………………...

4

РАСКРАСКА МНОГОУГОЛЬНЫХ ГРАФОВ ………………………………………………

10

ОКОННАЯ ГРАФИКА ПОЗИЦИОННЫХ ИГР ……………………………………………..

37

СПИСОК РЕКОМЕНДУЕМОЙ ЛИТЕРАТУРЫ …………………………………………….

54