Игра Ним
Теперь вернемся к процедуре GETPLAYERMOVE. При вводе любого очередного хода игрок должен задать два целых числа X1 и Х2. Первое из них указывает номер ряда, а второе – количество фишек, которые игрок хочет забрать из этого ряда. Программа должна проконтролировать правильность задания этих чисел: X1 должно указывать непустой ряд, Х2 не может превышать количество фишек в этом ряду. Кроме того, мы должны условиться о двух особых случаях:
- пользователь больше не хочет играть и дает команду завершить работу программы;
- пользователь хочет изменить условия игры.
Пусть ввод числа X1 =0 означает команду выхода из программы, а X1 = -1 – команду изменения условий игры. Тогда можно написать такой начальный вариант процедуры:
Procedure GetPlayerMove; {Получает, контролирует и отображает ход игрока} var correctly: Boolean; {Признак правильности сделанного хода} x1,x2: Integer; {Вводимый ход} begin {GetPlayerMove} {Показываем начальное состояние игрового поля} ShowField; {Сообщаем, игроку правила ввода хода} repeat {Приглашаем игрока ввести ход} ReadLn(x1,x2); {Вводим очередной ход} exit: = x1=0; {Контроль команды выхода} change: = x1=-1; {Контроль команды изменения} if not (exit or change) then {Проверить правильность хода и установить нужное значение переменной CORRECTLY. Если ход правильный, сделать нужные изменения в раскладке фишек и показать поле.} else correctly: = true {Случай EXIT или CHANGE} until correctly; if change then { Изменить условия игры } end; {GetPlayerMove}
В этом варианте в процедуре GetPlayerMove нет описания процедуры SHOWFIELD. Сделано это не случайно: процедура ShowField может понадобиться также и при реализации процедуры SetOwnerMove, поэтому она должна быть глобальной по отношению и к GetPlayerMove, и к SetOwnerMove, т.е. ее описание должно в тексте программы предшествовать описаниям двух использующих ее процедур.
Действия:
{ Сообщить игроку правила ввода хода }, { Пригласить игрока ввести ход }
И:
{Проверить правильность хода и установить нужное значение переменной Correctly. Если ход правильный, сделать нужные изменения в раскладке фишек и показать поле.}
Не очень сложны в реализации, поэтому их можно осуществить непосредственно в теле процедуры GETPLAYERMOVE. Иное дело – изменение условий игры. Это действие полезно реализовать в отдельной процедуре GETCHANGE. С учетом этого второй вариант процедуры GETPLAYERMOVE примет такой вид:
Procedure GetPlayerMove; {Получает, контролирует и отображает ход игрока} const ТЕХТ1 = 'Введите Ваш ход в формате РЯД КОЛИЧ '; ТЕХТ01= ' (например, 2 3 – взять из 2 ряда 3 фишки) '; ТЕХТ2 = 'или введите 0 0 для выхода из игры; ';. ТЕХТ02= '-1 0 для настройки игры'; ТЕХТ3 = 'Ваш ход: '; Y = 20; {Номер строки для вывода сообщений} var correctly: Boolean; {Признак правильности сделанного хода} x1,x2: Integer; {Вводимый ход} {-----------------} Procedure GetChange; {Устанавливает новую настройку игры (количество рядов и количество фишек в каждом ряду} begin {GetChange} end; {GetChange} {-----------------} begin {GetPlayerMove} ShowField; {Показываем начальное состояние поля} {Сообщить игроку правила ввода хода:} GotoXY((80-Length(TEXT1+TEXT01)) div2,Y); Write(TEXT1+TEXT01); GotoXY((80-Length(TEXT2+TEXT02)) div2,Y+l); Write(TEXT2+TEXT02); repeat {Пригласить игрока ввести ход:} GotoXY(1,Y+2); Write(TEXTS); {Выводим приглашение и стираем предыдущий ход} GotoXY(WhereX-16,Y+2); {Курсор влево на 16 позиций} ReadLn(x1,x2); {Вводим очередной ход} exit: = x1=0; {Контроль команды выхода} change: = x1=-1; {Контроль команды изменения} if not (exit or change) then begin correctly: = (x1 > 0) and (x1 <= nrow) and (x2 <= col[xl]) and (x2 > 0); if correctly then begin {Ход правильный:} col[xl]: = col[xl]-x2; {Изменяем раскладку фишек} ShowField {Показываем поле} end else Write(#7) {Ход неправильный: дать звуковой сигнал} end else correctly: = true {Случай EXIT или CHANGE} until correctly; if change then GetChange end; {GetPlayerMove}