Игра Ним
Обратите внимание: константа ТЕХТ3 = 'Ваш ход: имеет длинный "хвост" из пробелов (их 17), поэтому после вывода этого приглашения курсор возвращается влево на 16 позиций оператором:
GotoXY(WhereX-16,Y+2); {курсор влево на 16 позиций}
(Функция WHEREX возвращает текущую горизонтальную координату курсора, а функция WHEREY – его вертикальную координату). Сделано это для того, чтобы в случае, если игрок ввел неверный ход и программа повторяет вывод приглашения, пробелы в константе ТЕХТ3 затерли бы строку предыдущего ввода.
Чтобы завершить создание процедуры GETPLAYERMOVE, нужно спроектировать процедуру GETCHANGE, в которой осуществляется изменение условий игры. Я привожу текст этой процедуры без пояснений и приглашаю Вас самостоятельно разобраться в том, как она работает:
Procedure GetChange; {Устанавливает новую настройку игры (количество рядов и количество фишек в каждом ряду} const t1='HACTPOЙКA ИГРЫ'; t2 ='(ввод количества рядов и количества '+'фишек в каждом ряду)'; var correctly: Boolean; i: Integer; begin {GetChange} ClrScr; GotoXY((80 – Length (tl)) div2,l); Write(tl); GotoXY((80 – Length (t2)) div2.2); Write (t2); repeat GotoXYd, 3); Write ('Введите количество рядов (максимум ', MAXROW, '):'); GotoXY(WhereX-6,WhereY); ReadLn (nrow); correctly: = (nrow <= MAXROW) and (nrow > 1); if not correctly then Write (#7) until correctly; for i: = 1 to nrow do repeat GotoXY(l,i+3); Write (' ряд ',i,', количество фишек (максимум ', MAXCOL, '): '); GotoXY (WhereX – 6, WhereY); ReadLn (ncol [i]); correctly: = (ncol [i] <= MAXCOL) and (ncol[i] > 0); if not correctly then Write (#7) until correctly end; {GetChange}
Переходим к конструированию процедуры SETOWNERMOVE, в которой программа должна проконтролировать текущую ситуацию на игровом поле и выбрать собственный ход. Работа процедуры начинается с подсчета числа непустых рядов. В зависимости от этого подсчета реализуются следующие действия:
- если все ряды пусты, значит предыдущим ходом игрок забрал последнюю фишку и он победил; нужно поздравить его с победой, усложнить игру и предложить сыграть еще раз;
- если есть только один непустой ряд, то очередной ход программы очевиден – забрать все фишки, что означает победу машины: сообщить об этом и предложить сыграть еще раз;
- если осталось два или более непустых ряда, выбрать собственный ход на основе оптимальной стратегии.
Начальный вариант процедуры:
Procedure SetOwnerMove; {Находит и отображает очередной ход программы} {-----------------} Function CheckField: Integer; {Проверяет состояния игры. Возвращает 0, если нет ни одной фишки (победа игрока), 1 – есть один ряд (победа машины) и – количество непустых рядов в остальных случаях} begin {CheckField} end; {CheckField} {-----------------} Procedure PlayerVictory; {Поздравить игрока с победой и усложнить игру} begin {PlayerVictory} end; {PlayerVictory} {-----------------} Procedure OwnVictory; {Победа машины} begin {OwnVictory} end; {OwnVictory} {-----------------} Procedure ChooseMove; {Выбор очередного хода} begin {ChooseMove} end; {ChooseMove} {-----------------} begin {SetOwnerMove} case CheckField of {Проверяем количество непустых рядов} 0: PlayerVictory; {Все ряды пусты – победа игрока} 1: OwnVictory; {Один непустой ряд – победа машины} else ChooseMove; {Выбираем очередной ход} end; {case} end; {SetOwnerMove}