Игра “Жизнь”

Интегрированные математические пакеты

Юдинцев В. В.

Кафедра теоретической механики. Самарский университет.

Функции

Пример колонии “Глайдер”

Колонию будет задавать списком пар координат "живых" клеток . Например, колония "Глайдер" может быть представлена списком :

colony={{0,0},{1,0},{2,0},{2,1},{1,2}};

Построим изображение этой колонии при помои функции ListPlot.

ListPlot[colony,PlotStyle->PointSize[0.15],PlotRange->{{-1,4},{-1,4}},AspectRatio->1,
Frame->True,GridLines->{Range[-1,4]},FrameTicks->None]

Функция определяет принадлежность клетки колонии

Для проверки принадлежности клетки x колонии col можно использовать функцию MemberQ, которая возвращает True если элемент, указанный вторым аргументом, будет принадлежать списку, указанному первым аргументом. Для рассматриваемого примера колонии:

MemberQ[colony,{1,0}]

MemberQ[colony,{5,0}]

Список смежных клеток (занятых или пустых), включая саму клетку

Для определения количества соседей у некоторой клетки с координатами c = (x, y) необходимо определить список смежных клеток (клеток - соседей) и подсчитать в этом списке количество клеток, которые принадлежат колонии.

Tuples[{{1,2},{3,4,5}}]

Список смещений координат

Tuples[{{-1,0,1},{-1,0,1}}]

Tuples[{-1,0,1},2]

DeleteCases[Tuples[{-1,0,1},2],{0,0}]

{2,3}+#&/@DeleteCases[Tuples[{-1,0,1},2],{0,0}]

Координаты смежных клеток для {2,3}

{x,y}+#&/@DeleteCases[Tuples[{-1,0,1},2],{0,0}]

Какие из них принадлежат колонии

MemberQ[colony,{2,3}+#]&/@DeleteCases[Tuples[{-1,0,1},2],{0,0}]

Функции вычисления количества соседей

countNeighbours[x_,colony_]:=Count[MemberQ[colony,x+#]&/@DeleteCases[Tuples[{-1,0,1},2],{0,0}],True];

countNeighbours[{1,1},colony]

Определение ареала колонии

Outer[f,{a,b},{c,d,e}]

Outer[f,{{1,2},{3,4}},{{10,20}}]

Outer[f,{{1,2},{3,4}},{{10,20}},1]

Flatten[Outer[f,{{1,2},{3,4}},{{10,20}},1]]

Outer[#1+#2&,colony,Tuples[{-1,0,1},2],1]
Flatten[%,1]
Union[%]

colonyArea[colony_]:=Union[Flatten[Outer[#1+#2&,colony,Tuples[{-1,0,1},2],1],1]];

Функция вычисления следующего поколения

{#,countNeighbours[#,colony],MemberQ[colony,#]}&/@colonyArea[colony]

nextGeneration[colony_]:=#[[1]]&/@Select[{#,countNeighbours[#,colony],MemberQ[colony,#]}&/@colonyArea[colony],
#[[2]]==3||(#[[2]]==2&&#[[3]])&]

Формирование массива поколений

Для формирования списка поколений используем функции Nest и NestList. Функция Nest возвращает результат применения функции к аргументу заданное количество раз.

Nest[f,x,4]

Функция NestList[f, x, n] формирует список результатов применения функции f к выражению x от  0 до n раз :

NestList[f,x,4]

Четыре поколения колонии “Глайдер”:

NestList[nextGeneration,colony,4]

Весь код

countNeighbours[x_,colony_]:=Count[MemberQ[colony,x+#]&/@DeleteCases[Tuples[{-1,0,1},2],{0,0}],True];
colonyArea[colony_]:=Union[Flatten[Outer[#1+#2&,colony,Tuples[{-1,0,1},2],1],1]];
nextGeneration[colony_]:=#[[1]]&/@Select[{#,countNeighbours[#,colony],MemberQ[colony,#]}&/@colonyArea[colony],
#[[2]]==3||(#[[2]]==2&&#[[3]])&]

Глайдер

colony={{0,0},{1,0},{2,0},{2,1},{1,2}};
NestList[nextGeneration,colony,5];
ListPlot[%[[#]],PlotStyle->PointSize[0.08],PlotRange->{{-5,5},{-5,5}},AspectRatio->1,Axes->False,Frame->True,FrameTicks->None,GridLines->{Range[-5,5]},ImageSize->150]&/@Range[5]

Ее один пример

colony={{0,0},{1,0},{2,0},{2,1},{1,2},{4,-1},{4,-2},{4,-3}};
ListPlot[colony,PlotStyle->PointSize[0.1],PlotRange->{{-2,6},{-4,5}},AspectRatio->1,
Frame->True,Axes->False,GridLines->{Range[-3,4]},FrameTicks->None]

NestList[nextGeneration,colony,100];
Animate[ListPlot[%[[i]],PlotStyle->PointSize[0.016],PlotRange->{{-30,30},{-20,40}},AspectRatio->1,Axes->False,Frame->True,FrameTicks->None],{i,1,100,1},DisplayAllSteps->True]

Экспорт анимации в файл

SetDirectory[NotebookDirectory[]];

colony={{0,0},{1,0},{2,0},{2,1},{1,2},{4,-1},{4,-2},{4,-3}};
NestList[nextGeneration,colony,100];
ListPlot[%[[#]],PlotStyle->PointSize[0.02],PlotRange->{{-20,30},{-20,30}},AspectRatio->1,Axes->False,Frame->True,FrameTicks->None]&/@Range[100];
Export["GameLife-WolframMathemetica.gif",%]