Программирование - это просто
Advertisement
Главная arrow Искусственный интеллект arrow Экспериментальный проект "Эволюция". arrow Экспериментальный проект "Эволюция". Шаг 2. Упрощенная модель. Игра "Жизнь".
25.04.2024 г.
Главное меню
Главная
Интернет магазин
Программные продукты
Биржевые роботы
Искусственный интеллект
Математика и информатика
1С:Предприятие
Уроки C#
Уроки Delphi
Уроки программирования
Web-программирование
Дизайн и графика
Компьютер для блондинок
Исходники
Статьи
Платный раздел
Рассказы про компьютеры
Хитрости и секреты
Системный подход
Размышления
Наука для чайников
Друзья сайта
Excel-это не сложно
Все о финансах
.
Экспериментальный проект "Эволюция". Шаг 2. Упрощенная модель. Игра "Жизнь". Печать E-mail
Автор megabax   
29.09.2014 г.
Структура программы на примере простейшей программы

Экспериментальный проект "Эволюция". Шаг 2. Упрощенная модель. Игра "Жизнь".

Исходники к уроку можно скачать здесь.

На прошлом шаге я придумал модель, на которой буду проводить виртуальные эксперименты. К сожалению, разработка программы по этой модели весьма трудоемкий процесс. Более того, в процессе написания я вдруг понял, что в данной модели имеется ряд недостатков. В частности, если генетический код виртуальной бактерии подвергнется мутации, то та с очень большой вероятностью окажется нежизнеспособной. Но в природе это не так. В природе каждая особь подвергается множеству мутаций, по большему счету, нейтральных. Но, накапливаясь, эти мутации создают изменчивость, которая и является двигателем эволюции. Исходя из этих соображений я решил упростить модель, а что бы не изобретать  велосипед, решил взять за основу игру "Жизнь" (см. описание в википедии).

И так, описание игры (цитата из википедии):

"Место действия этой игры — «вселенная» — это размеченная на клетки поверхность или плоскость — безграничная, ограниченная, или замкнутая (в пределе — бесконечная плоскость). Каждая клетка на этой поверхности может находиться в двух состояниях: быть «живой» или быть «мёртвой» (пустой). Клетка имеет восемь соседей (окружающих клеток). Распределение живых клеток в начале игры называется первым поколением. Каждое следующее поколение рассчитывается на основе предыдущего по таким правилам:

  • в пустой (мёртвой) клетке, рядом с которой ровно три живые клетки, зарождается жизнь;

  • если у живой клетки есть две или три живые соседки, то эта клетка продолжает жить;

  • в противном случае (если соседей меньше двух или больше трёх) клетка умирает («от одиночества» или «от перенаселённости»).

Игра прекращается, если на поле не останется ни одной «живой» клетки, если при очередном шаге ни одна из клеток не меняет своего состояния (складывается стабильная конфигурация) или если конфигурация на очередном шаге в точности (без сдвигов и поворотов) повторит себя же на одном из более ранних шагов (складывается периодическая конфигурация)."
 

Для реализации этой игры я создал простенький класс Universe (Вселеная):

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Drawing;

 

namespace GameLive

{

    /// <summary>

    /// Вселенная игры

    /// </summary>

    public class Universe

    {

        /// <summary>

        /// Местположение на экране в окне коордианта x

        /// </summary>

        public int beg_x_screen = 15;

 

        /// <summary>

        /// Местположение на экране в окне коордианта y

        /// </summary>

        public int beg_y_screen = 50;

 

        /// <summary>

        /// Ширина на экране

        /// </summary>

        public int width_screen = 600;

 

        /// <summary>

        /// Высота на экране

        /// </summary>

        public int height_screen = 600;

 

        /// <summary>

        /// Размер одной ячейки

        /// </summary>

        public int cell_size = 6;

 

        /// <summary>

        /// Живущие во "Вселенной" бактерии

        /// </summary>

        //public List<Bacterium> bacteriums;

 

        /// <summary>

        /// Максимальный размер по X

        /// </summary>

        public int maxX = 100;

 

        /// <summary>

        /// Максимальный размер по Y

        /// </summary>

        public int maxY = 100;

 

        public bool[,] bacteriums;

 

        public Actions[,] actions;

 

        private Random rnd = new Random();

 

        public Universe()

        {

            bacteriums=new bool[maxX,maxY];

            actions = new Actions[maxX, maxY];

 

            //иницаилизация массива

            for (int x = 0; x < maxX; x++)

            {

                for (int y = 0; y < maxY; y++) if (rnd.NextDouble()>0.5)

                {

                    bacteriums[x, y] = true;

                }

            }

 

        }

 

        /// <summary>

        /// Нарисовать на экране

        /// </summary>

        /// <param name="gr">Объект графики</param>

        public void draw(Graphics gr)

        {

            Brush brush = new SolidBrush(Color.White);

            gr.FillRectangle(brush, beg_x_screen, beg_y_screen, width_screen, height_screen);

            for (int x = 0; x < maxX; x++)

            {

                for (int y = 0; y < maxY; y++) if(bacteriums[x,y])

                {

                    brush = new SolidBrush(Color.Black);

                    int x1 = beg_x_screen + cell_size * x;

                    int y1 = beg_y_screen + cell_size * y;

                    gr.FillRectangle(brush, x1, y1, cell_size, cell_size);

                }

            }

        }

 

        /// <summary>

        /// Посчитать количество соседей у клетки

        /// </summary>

        /// <param name="x">Координата X клетки</param>

        /// <param name="y">Координата Y клетки</param>

        /// <returns>Количество соседних клеток</returns>

        public int get_neighbors_count(int x, int y)

        {

            int res = 0;

            if (is_neighbor(x, y + 1)) res++;

            if (is_neighbor(x + 1, y + 1)) res++;

            if (is_neighbor(x + 1, y)) res++;

            if (is_neighbor(x + 1, y - 1)) res++;

            if (is_neighbor(x, y - 1)) res++;

            if (is_neighbor(x - 1, y - 1)) res++;

            if (is_neighbor(x - 1, y)) res++;

            if (is_neighbor(x - 1, y + 1)) res++;

            return res;

        }

 

        /// <summary>

        /// Проверить, есть ли в этой позиции бактерия

        /// </summary>

        /// <param name="x">Координата X</param>

        /// <param name="y">Координата Y</param>

        /// <returns>true - есть, false - нет</returns>

        public bool is_neighbor(int x, int y)

        {

            int x1, y1;

            x1 = x;

            y1 = y;

            if (x1 < 0) x1 = maxX - 1;

            if (x1 >= maxX) x1 = 0;

            if (y1 < 0) y1 = maxY - 1;

            if (y1 >= maxY) y1 = 0;

            return bacteriums[x1, y1];

        }

 

        /// <summary>

        /// Шаг игры

        /// </summary>

        /// <returns>true - игра продолжается, false - игра окончена (все бактерии вымерли)</returns>

        public bool step()

        {

            bool res=false;

 

            //сначала обежим все клетки и создадим массив изменений

            for (int x = 0; x < maxX; x++)

            {

                for (int y = 0; y < maxY; y++)

                {

                    int count = get_neighbors_count(x,y);

                    if (bacteriums[x, y])

                    {

                        if (count == 2 || count == 3) actions[x, y] = Actions.non; else actions[x, y] = Actions.death;

                    }

                    else

                    {                      

                        if (count == 3) actions[x, y] = Actions.birth; else actions[x, y] = Actions.non;

                    }

                }

            }

 

            //теперь обежим массив изменений и применим их

            for (int x = 0; x < maxX; x++)

            {

                for (int y = 0; y < maxY; y++)

                {

                    switch (actions[x, y])

                    {

                        case Actions.birth:

                            bacteriums[x, y] = true;

                            break;

                        case Actions.death:

                            bacteriums[x,y]=false;

                            break;

                    }

                    if(bacteriums[x,y]) res=true;

                }

            }

 

            return res;

 

        }

 

    }

}

И засунул его в специальную обертку. И так, что же получилось из моего эксперимента? Сначала у нас расположение бактерий выглядит хаотично:

Экспериментальный проект "Эволюция". Шаг 2. Упрощенная модель. Игра "Жизнь".

После запуска начинают формироваться устойчивые фигуры, некоторые из них движутся:

Экспериментальный проект "Эволюция". Шаг 2. Упрощенная модель. Игра "Жизнь".

Движущиеся фигуры сталкиваются с неподвижными, а так же друг с другом, появляются новые фигуры. Дело заканчивается тем, что остаются только устойчивые неподвижные фигуры:

Экспериментальный проект "Эволюция". Шаг 2. Упрощенная модель. Игра "Жизнь".

Как видим, система уперлась в эволюционный тупик - дальше она не развивается. Однако, можно заставить эти фигурки эволюционировать дальше - нужно всего то начать менять внешние условия. Именно так происходит и в природе: меняются обстоятельства, особи начинают к ним приспосабливаться. Нечто подобное задумал и я, но об этом расскажу в следующей статье, до новых встреч.

 

 

 

Последнее обновление ( 29.09.2014 г. )
 
Пред. »
 
© 2024 Программирование - это просто
Joomla! - свободное программное обеспечение, распространяемое по лицензии GNU/GPL.
Русская локализация © 2005-2008 Joom.Ru - Русский Дом Joomla!
Design by Mamboteam.com | Powered by Mambobanner.de
Я принимаю Яндекс.Деньги