Ігровий Паскаль
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 editor

вологість:
тиск:
вітер:

Огляд джерела безперебійного живлення PowerWalker VFI 2000 AT: такі часи



Джерела безперебійного живлення стали як ніколи актуальними цієї зими. Про досвід використанням в умовах квартири з автономним опаленням, розкажемо на прикладі моделі PowerWalker VFI 2000 AT

Електровелосипед Acer ebii отримав штучний інтелект, який слідкує за безпекою пересування
Acer електротранспорт штучний інтеллектНалаштування реалізовані за допомогою фірмового застосунку ebiiGO: тут можна отримати інформацію про час автономної роботи, рекомендовані маршрути, розблокувати і заблокувати велосипед
Xiaomi представила смартфони серії Redmi Note 12 в чотирьох версіях для європейського ринку
Android MediaTek Qualcomm Redmi Xiaomi смартфонМоделі Redmi Note 12 для китайського ринку подекуди мають відмінності технічного плану і помітно дешевші