Представляю Вашему вниманию пример реализации алгоритмической игры «Жизнь» на языке Паскаль. Игра «Жизнь», она же так называемый клеточный автомат, обязана своим появлением английскому математику Джону Конвейю.
Для начала — относительно простой, но одновременно структурированный вариант текста программы (на Free Pascal в самом простом и совместимом исполнении):
program Life;
uses
ptcGraph, ptcCrt;
const
HorSize = 640;
VerSize = 480;
type
TMatrix = array [0..VerSize+1, 0..HorSize+1] of Byte;
var
GraphDriver :Integer;
GraphMode :Integer;
NewArr, OldArr :TMatrix;
{ Процедура очистки массива (заполнения нулями) }
procedure ClearMatrix(var Matrix :TMatrix; VSize, HSize :Integer);
var
i, j :Integer;
begin
for i := 0 to VSize+1 do
for j := 0 to HSize+1 do
Matrix[i, j] := 0;
end;
{ Процедура "вставки" в массив некоторого прямоугольника из единиц }
procedure InitMatrix(var Matrix :TMatrix;
RVpos, RHPos, RVSize, RHSize :Integer);
var
i, j :Integer;
begin
for i := 1 to RVSize do
for j := 1 to RHSize do
Matrix[RVPos+i-1, RHPos+j-1] := 1;
end;
{ Процедура "заворачивания" границ массива для эмуляции "бесконечного" поля }
procedure InfiMatrixEdges(var Matrix :TMatrix; VSize, HSize :Integer);
var
i :Integer;
begin
Matrix[0, 0] := Matrix[VSize, HSize];
Matrix[VSize+1, HSize+1] := Matrix[1, 1];
Matrix[0, HSize+1] := Matrix[VSize, 1];
Matrix[VSize+1, 0] := Matrix[1, HSize];
for i := 1 to VSize do
begin
Matrix[i, 0] := Matrix[i, HSize];
Matrix[i, HSize+1] := Matrix[i, 1];
end;
for i := 1 to HSize do
begin
Matrix[0, i] := Matrix[VSize, i];
Matrix[VSize+1, i] := Matrix[1, i];
end;
end;
{ Процедура реализации игровой логики }
procedure GameLogic(var Source, Dest :TMatrix; VSize, HSize :Integer);
var
i, j :Integer;
around :Byte;
begin
for i := 1 to VSize do
for j := 1 to HSize do
begin
around := Source[i-1, j-1] + Source[i-1, j] + Source[i-1, j+1] +
Source[i, j-1] + Source[i, j+1] +
Source[i+1, j-1] + Source[i+1, j] + Source[i+1, j+1];
case Source[i, j] of
0: if around = 3 then
Dest[i, j] := 1
else
Dest[i, j] := 0;
1: if (around < 2) or (around > 3) then
Dest[i, j] := 0
else
Dest[i, j] := 1;
end;
end;
end;
{ Процедура "визуализации" - отрисовывает игровое поле на экран }
procedure DrawMatrix(var Matrix :TMatrix; VSize, HSize :Integer;
Color, Background :Integer);
var
i, j :Integer;
begin
for i := 1 to VSize do
for j := 1 to HSize do
case Matrix[i, j] of
0: PutPixel(j-1, i-1, Background);
1: PutPixel(j-1, i-1, Color);
end;
end;
begin
ClearMatrix(NewArr, VerSize, HorSize);
ClearMatrix(OldArr, VerSize, HorSize);
InitMatrix(OldArr, 140, 220, 200, 200);
{ DetectGraph(GraphDriver, GraphMode);
WriteLn('Driver: ', GraphDriver, ', Mode: ', GraphMode); }
GraphDriver := VGA;
GraphMode := VGAHi;
InitGraph(GraphDriver, GraphMode, '');
repeat
GameLogic(OldArr, NewArr, VerSize, HorSize);
InfiMatrixEdges(NewArr, VerSize, HorSize);
OldArr := NewArr;
{ Delay(100); }
DrawMatrix(NewArr, VerSize, HorSize, 15, 0);
until KeyPressed;
CloseGraph;
end.
Пояснения по тексту программы ниже, а сейчас — немного о сути игры.
В нашем распоряжении есть игровое поле — двумерный массив ячеек (клеток). Каждая такая ячейка может находиться в одном из двух возможных состояний: «живом» и «неживом». Скажем, пусть состоянию «жив» соответствует численное значение, равное 1, а состоянию «мертв» — численное значение, равное 0. Для образности каждую «живую» ячейку мы можем называть, скажем, бактерией.
В ходе действия игрового алгоритма над игровым полем мы выполняем некоторые манипуляции, результат которых графически отображаем на экране.
Суть игрового алгоритма такова: по очереди «пересматриваем» все клетки и подсчитываем количество «живых соседей» каждой клетки. В зависимости от количества «живых соседей» меняем состояние текущей клетки — «возрождаем» (создаем) нашу «бактерию» либо «убиваем» её. Вот варианты условия:
- если вокруг пустой («мертвой») находятся ровно три непустые («живые») клетки, то данная клетка «оживает» (либо, другими словами, «появляется» — кому как больше нравится);
- состояние непустой («живой») клетки при наличии двух или трех непустых же («живых») соседей не изменяется (клетка продолжает «существовать»);
- если у непустой («живой») клетки меньше двух или больше трех «живых» соседей, то данная клетка «умирает» (перестает «существовать»).
Задав выборочно начальные условия (разместив на игровом поле то или иное количество «живых» клеток) и запустив игровой алгоритм, можно наблюдать за развитием «жизни» в пределах игрового поля — изменением конфигурации и количества «бактерий», их движением. Процесс и результат могут быть довольно любопытными.
И немного по тексту программы-примера. Для реализации игрового поля будем использовать двумерный массив элементов типа Byte, в цикле перебирая все его ячейки (по строкам и столбцам). «Живой» ячейкой будет элемент со значением «1», «мертвой» — со значением «0». Результат работы алгоритма, что естественно, будем помещать в другой идентичного типа двумерный массив, который и отображается графически. После отработки игрового алгоритма в очередном «шаге» первый массив будем обновлять, копируя в него содержимое из второго.
Чтобы сделать игровое поле «бесконечным» (и избавиться от «краевых» эффектов), мы «заворачиваем» края двумерного массива. Для этого добавляем к каждому краю двумерного массива по лишнему элементу, куда копируем значение элемента с противоположенного края. Соответственно, в данном случае каждая ячейка с обычным индексом в массиве «видит» полный набор «соседей» и алгоритм работает корректно (пусть и в «завернутом» пространстве игрового поля).
В тексте программы названия переменных и процедур/функций выбраны таким образом, чтобы можно было максимально быстро понять, для чего они нужны. Например, HorSize и VerSize — задают горизонтальный и вертикальный размеры игрового поля соответственно. Поскольку для реализации применен Free Pascal, графика выполнена с использованием модулей ptcGraph и ptcCrt (последний — для считывания клавиатуры). Но версия Паскаля здесь принципиального значения не имеет — программу легко адаптировать под любой диалект, немного изменится лишь реализация графики.
Скачать текст программы и её модификации с «улучшенной» графикой Вы можете здесь: zip-архив.