Ігровий Паскаль
24.11.08Насамперед
Для початку давайте передбачимо непередбачуване :-), тобто детально вивчимо всі можливі ігрові ситуації та надзвичайні події, які можуть виникнути в процесі гри — цим треба зайнятись перед початком проектування.
Перше — в нашому варіанті грають двоє людей. Потім, звичайно ж, можна додати в якості суперника комп’ютерного опонента, але це потім. Гра консольна. Проект представлятиме собою класичні хрестики-нулики з розміром ігрового поля 3х3. Виграє той, хто перший закреслить одну з вертикальних, горизонтальних або діагональних ліній. Зверніть увагу на те, що цілком можлива і нічия. Це все, що треба знати перед початком.
Геймплей
Як виглядатиме початковий екран? Можна «розмалювати» його зірочками, доларами, собачками та іншими символами. Я не буду цього зараз робити. Давайте просто дамо зрозуміти користувачу, що за гру він запустив і вкажемо версію програмного продукту. Думаю, цього вистачить. Для більшого реалізму додамо можливість гравцям ввести їхні імена і вибрати, хто чим буде грати. Дефолтний варіант: один грає хрестиками, інший — нуликами. Якщо ж це не задовільнятиме, то буде змога обрати індивідуальний символ. Тут же виникає проблема — а якщо вони виберуть однакові символи для гри? Гра тоді перестане бути грою. Через це необхідно застерегти і заборонити їм вибирати однакові символи. З двома іменами ситуація не буде критичною для програми, та все ж краще також не дати гравцям назвати себе одним і тим же іменем.
Ввели вони імена, обрали значки для гри. Після цього буде показано ігрове поле. Внизу бажано вказати, хто саме здійснює хід в даний момент. А от яким чином ходити? На роль поля 3х3 краще за все підійде «калькуляторна» частина клавіатури. Наприклад, після передачі програмі числа 1 закреслиться ліва нижня клітинка, 9 — права верхня, 5 — центральна і т.д. Приблизний варіант інтерфейсу зображено на рис. 1.
Програмування
Почнемо писати код. Можна сховати все під капотом, винісши процедури в окремий модуль. Глобальні змінні, котрі нам знадобляться для реалізації проекту:
Table:array [1..3,1..3] of char; {ігрове поле у вигляді двовимірного масиву}
Name1, Name2:string; {імена гравців}
Symbol1, Symbol2:char; {символи, якими ці гравці будуть ходити. Змінну Symbol1 ми ще використаємо в інших цілях, про це згодом.}
i,j:integer; {керуючі змінні циклів}
Victory, Player1:boolean; {Victory — для перевірки, чи часом хтось не переміг, Player1 дасть програмі знати, який гравець здійснює хід}
Moves:byte = 0; {лічильник ходів}
Основний текст програми я зробив достатньо лаконічним і зрозумілим:
begin
BeginGame; {початок гри}
while not Victory do {поки не досягнуто перемоги, виконуємо наступне…}
begin
Move; {хід гравця}
CheckVictory; {дивимось, чи хтось не переміг після ходу}
ShowTable; {показуємо поле}
inc(Moves); {збільшуємо на 1 лічильник ходів}
if Victory then EndGame; {якщо перемога, то гра завершується}
if Moves = 9 then Draw {а от якщо після дев’яти ходів виграшу не досягнуто, тоді нічия. 10 ходів на полі 3х3 зробити важкувато 🙂 }
end {кінець циклу}
end.
Тепер розберемо детально процедури Draw, EndGame, Move, ShowTable, CheckVictory, BeginGame. Почнемо з найпростіших — Draw і EndGame, котрі відрізняються тільки тим, що виводять різний текст. Тому приводжу приклад тільки однієї.
procedure EndGame;
begin
writeln(‘***Game Over***’); {виводимо оголошення про закінчення гри (відповідно для іншого випадку повідомляємо про нічию)}
halt {завершуємо виконання програми і передаємо керування операційній системі}
end;
ShowTable це не що інше, як вивід двовимірного масиву на монітор.
procedure ShowTable;
begin
Clrscr; {оскільки поле буде демонструватись більш ніж один раз, непогано би було очистити екран перед наступним показом. І не забудьте підключити модуль Crt!}
for i := 1 to 3 do
begin
for j := 1 to 3 do
write (Table[i,j]:3);
writeln {Стандартний шаблон. Таким чином виводяться всі двовимірні масиви. Формат виводу — три клітинки — я поставив з метою розтягнути поле, щоб воно набуло форми квадрата}
end
end;
Перевіряти перемогу можна двома способами (принаймні ці два видаються найбільш логічними). Перший — математичний підхід — створення ще одного масиву цілочисельних цифр. Заповнюватиметься він паралельно з масивом символів (наше поле). Хрестику відповідатиме одна цифра, нулику — інша. Будуть певні початкові значення елементів поля. А тоді перевірити суму по рядках, стовпцях і діагоналях масиву і, проаналізувавши результат, перевірити істинність перемоги. Такий метод має переваги в швидкості, порівняно з тим, про який піде мова кількома рядками нижче, і займає менший об’єм. Також він є універсальним, тобто підходить для поля 3х3, 10х10 чи навіть 100х100. Єдиний вагомий мінус — потрібно виділяти пам’ять для ще одного масиву.
В моєму варіанті втілено інший варіант. Я просто-напросто перелічив всі можливі виграшні комбінації, і програма щоразу “проганяє” масив, шукаючи переможну комбінацію. Якщо така знайдена, логічна змінна Victory отримує значення true. В основному тексті програма побачить, що настала перемога і перейде до виконання EndGame.
procedure CheckVictory;
begin
if
(Table[1,1] and Table[1,2] and Table[1,3]=Symbol1)
or (Table[2,1] and Table[2,2] and Table [2,3]=Symbol1)
{далі йдуть наступні варіанти, всього їх сім — три вертикалі, три горизонталі і дві діагоналі. Горизонталь, закреслена зліва направо, нічим не відрізняється від такої ж, закресленої справа наліво 🙂 }
then Victory := true;
{Опісля розташований аналогічний блок коду, тільки перевіряємо вже нулики (чи що там буде), тому змінено Symbol1 на Symbol2}
end;
Як користувач ходитиме, я вже пояснив. На рис. 2 показано, як воно виглядає в процесі. Зараз наводжу код підпрограми:
procedure Move;
var MoveDone:boolean = false; coord:byte; {дві змінні, котрі потрібні тільки всередині процедури. MoveDone — процедура не завершиться, доки хід не буде зроблено. coord зберігає в собі цифру від 1 до 9 — координати поля}
begin
В цій процедурі, як і в попередній, є два блоки коду, що відрізняються лише тим, що в другому замість Name1 — Name2, а замість Symbol1 — Symbol2.
if Player1 then {якщо це перший гравець}
repeat {повторювати поки…}
write(Name1,’, номер клітинки: ‘);
readln(coord); {дізнаємось, куди треба ходити}
case coord of
1:if Table[3,1] = ‘.’ then begin Table[3,1] := Symbol1; MoveDone := true end; {такий собі міні-конвертер, який спершу перевірить, чи ніхто до цього не походив на клітинку, а потім відповідно до введеної гравцем цифри замінить певний елемент масиву на інший символ. І врешті-решт підніме наш прапорець, котрий відповідає за завершення циклу repeat … until}
{далі перелік чисел продовжується до 9}
9:if Table[1,3] = ‘.’ then begin Table[1,3] := Symbol1; MoveDone := true end
end; {кінець case-конвертера}
until MoveDone {умова виходу з циклу — вдалий хід гравця}
Повторюсь, далі йде схожий блок і, нарешті, кінець процедури:
MoveDone := false; {опускаємо прапорець в початкове положення}
Player1 := not Player1; {змінюємо гравця на протилежного}
end;
Завершальний етап — опис того, як гра починається :-). В цій процедурі є багато питань, що програма ставитиме гравцям, тут же можна реалізувати псевдографічний інтерфейс, намалювати красиве лого гри, створити меню та багато іншого.
Цю підпрограму пишу від і до, без пропусків частин коду, бо тут все таке важливе, що не можна щось пропустити :-).
procedure BeginGame;
begin
writeln(‘Хрестики-нулики’); {це в мене таке графічне оформлення 🙂 }
writeln(‘версія 0.0.1 альфа’); {продовжуємо оформлення}
writeln;
repeat
repeat
write(‘Ім’я першого гравця: ‘);
readln(Name1); {дізнаємось ім’я}
if length(Name1) > 20 then writeln(‘Ім’я не має перевищувати 20 символів!’);
until length(Name1) <= 20; {я поставив умову на те, що ім’я не може перевищувати 20 символів}
repeat
write(‘Ім’я другого гравця: ‘);
readln(Name2); {ті самі дані питаємо в другого гравця}
if length(Name2) > 20 then writeln(‘Ім’я не має перевищувати 20 символів!’);
until length(Name2) <= 20;
if Name1 = Name2 then writeln(‘Введіть різні імена!’)
until Name1 <> Name2; {бажано, щоб їх звали по-різному. До речі, при вводі двох однакових імен можна перейменувати їх в Коля№1 і Коля№2, але це вже зробите самі}
repeat
write(‘Стандартні значки? (y/n)’);
readln(Symbol1); {поки що змінна Symbol1 без діла, тому доручаємо їй збереження відповіді на запитання}
if (Symbol1 <> ‘y’) and (Symbol1 <> ‘n’) then writeln(‘Некоректна відповідь!’); {захист від хакерів 🙂 }
until (Symbol1 = ‘y’) or (Symbol1 = ‘n’);
if Symbol1 = ‘y’
then begin
Symbol1 := ‘x’;
Symbol2 := ‘o’ {якщо гравці погодились на стандартний варіант, тоді в якості символів будуть букви “х” та “о”}
end
else begin {коли ж дефолтний варіант не влаштовує, вони можуть вибрати собі щось оригінальніше}
repeat
write(‘Значок першого гравця: ‘);
readln(Symbol1);
write(‘Значок другого гравця: ‘);
readln(Symbol2);
if Symbol1 = Symbol2 then writeln(‘Введіть різні значки! Не можна використовувати крапку!’);
until (Symbol1 <> Symbol2) and (Symbol1 <> ‘.’) and (Symbol2 <> ‘.’);
end;
for i :=1 to 3 do
for j := 1 to 3 do
Table[i,j] := ‘.’; {тут у нас лежить важливий вкладений цикл з параметром. Він робить наше поле пустим. Якщо в якості порожня клітинка це крапка, то гравцеві не можна вводити крапку ні в якому разі}
ShowTable {демонструємо щойно створене ігрове поле}
end;
Р.S. Незважаючи на «невеличкість» прикладу, на його основі можна навчитись багато чому, зокрема — плануванню програми, лаконічності написання коду. — Прим. ред.
Web-droid редактор
Не пропустите интересное!
Підписывайтесь на наши каналы и читайте анонсы хай-тек новостей, тестов и обзоров в удобном формате!


Samsung Galaxy A36 и Galaxy A56 — доступные флагманские технологии



У Samsung Galaxy A36 и Galaxy A56 одинаково хорошие дисплеи, емкие аккумуляторы, есть поддержка обновлений софта в течение 6 лет. Расскажем подробнее чем еще они интересны

TWS-навушники Nothing CMF Buds 2 получили ANC и защиту IP55 Bluetooth наушники
Среди ключевых обновлений CMF Buds 2 – поддержка Bluetooth 5.4 с возможностью одновременного соединения с двумя устройствами, а также интеграция с Google Fast Pair и Microsoft Swift Pair
Motorola Edge 60 Stylus впервые в серии получил стилус. Смартфон оснащен Snapdragon 7s Gen 2 Motorola смартфон стилус
Motorola анонсировала новый смартфон Edge 60 Stylus, который станет доступен в Индии с 23 апреля, а затем поступит и на другие рынки.