Click here to Skip to main content
15,892,746 members
Articles / Programming Languages / C#

Revisit the Game of Life while Learning about Extension Methods in C#

Rate me:
Please Sign up or sign in to vote.
4.65/5 (8 votes)
24 Aug 2008CPOL11 min read 55.6K   594   40  
A fun variation of the Game of Life re-factored using extension methods
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace LifeSimulation.Extensions
{
    static class ProcessLifeModelExtension
    {
        private enum CellOutcome
        {
            Dies,
            Spawns,
            NoChange
        }

        #region Extension methods

        public static void Process(this LifeModelBase model, World World)
        {
            List<Point> dieList = new List<Point>();
            List<Point> spawnList = new List<Point>();
            for (int i = 0; i < World.Space.GetLength(0); i++)
            {
                for (int j = 0; j < World.Space.GetLength(1); j++)
                {
                    switch (model.GetCellOutcome(World, i, j))
                    {
                        case CellOutcome.Dies:
                            dieList.Add(new Point(i, j));
                            break;
                        case CellOutcome.Spawns:
                            spawnList.Add(new Point(i, j));
                            break;
                    }
                }
            }

            //Die
            foreach (Point point in dieList)
                World.Space[point.X, point.Y] = 0;
            //Spawn
            foreach (Point point in spawnList)
                World.Space[point.X, point.Y] = model.MaximumAge;

            //Age
            for (int i = 0; i < World.Space.GetLength(0); i++)
                for (int j = 0; j < World.Space.GetLength(1); j++)
                    if (World.Space[i, j] > 0)
                        World.Space[i, j]--;
        }

        public static int GetMaximumNeighbours(this LifeModelBase model)
        {
            return GetMaximumNeighbours(model.NeighbourDistance);
        }

        #endregion

        #region Public methods
        /// <summary>
        /// Gets max number of neighbours according to distance indicator as follows...
        /// 
        /// Distance = 1
        /// 00000
        /// 00100
        /// 01X10
        /// 00100
        /// 00000
        /// Distance = 2
        /// 00000
        /// 01110
        /// 01X10
        /// 01110
        /// 00000
        /// Distance = 3
        /// 00100
        /// 01110
        /// 11X11
        /// 01110
        /// 00100
        /// Distance = 4
        /// 01110
        /// 11111
        /// 11X11
        /// 11111
        /// 01110
        /// Distance = 5 or more
        /// 11111
        /// 11111
        /// 11X11
        /// 11111
        /// 11111
        /// </summary>
        /// <param name="neighbourhoodDistance"></param>
        public static int GetMaximumNeighbours(int neighbourhoodDistance)
        {
            switch (neighbourhoodDistance)
            {
                case 1: return 4;
                case 2: return 8;
                case 3: return 12;
                case 4: return 20;
                default: return 24;
            }
        }

        #endregion

        #region Private methods
        private static CellOutcome GetCellOutcome(this LifeModelBase model, World World, int i, int j)
        {
            World.Neighbours[i, j] = World.CountNeighbours(i, j, model.NeighbourDistance);
            if (World.Space[i, j] > 0)
            {
                if (model.CellDeathIndicators.Contains(World.Neighbours[i, j]))
                    return CellOutcome.Dies;
            }
            else
            {
                if (model.CellSpawnIndicators.Contains(World.Neighbours[i, j]))
                    return CellOutcome.Spawns;
            }
            return CellOutcome.NoChange;
        }


        private static int CountNeighbours(this World World, int i, int j, int distance)
        {
            int c = 0;
            int mi = World.Space.GetLength(0) - 1;
            int mj = World.Space.GetLength(1) - 1;
            int mi2 = mi - 1;
            int mj2 = mj - 1;

            if (distance >= 1)
            {
                if (i > 0 && World.Space[i - 1, j] > 0) c++;
                if (i < mi && World.Space[i + 1, j] > 0) c++;
                if (j > 0 && World.Space[i, j - 1] > 0) c++;
                if (j < mj && World.Space[i, j + 1] > 0) c++;
            }
            if (distance >= 2)
            {
                if (i > 0 && j > 0 && World.Space[i - 1, j - 1] > 0) c++;
                if (i > 0 && j < mj && World.Space[i - 1, j + 1] > 0) c++;
                if (i < mi && j > 0 && World.Space[i + 1, j - 1] > 0) c++;
                if (i < mi && j < mj && World.Space[i + 1, j + 1] > 0) c++;
            }
            if (distance >= 3)
            {
                if (i > 1 && World.Space[i - 2, j] > 0) c++;
                if (i < mi2 && World.Space[i + 2, j] > 0) c++;
                if (j > 1 && World.Space[i, j - 2] > 0) c++;
                if (j < mj2 && World.Space[i, j + 2] > 0) c++;
            }
            if (distance >= 4)
            {
                //Left top
                if (i > 1 && j > 0 && World.Space[i - 2, j - 1] > 0) c++;
                if (i > 0 && j > 1 && World.Space[i - 1, j - 2] > 0) c++;
                //Left bottom
                if (i > 1 && j < mj && World.Space[i - 2, j + 1] > 0) c++;
                if (i > 0 && j < mj2 && World.Space[i - 1, j + 2] > 0) c++;
                //Right top
                if (i < mi2 && j > 0 && World.Space[i + 2, j - 1] > 0) c++;
                if (i < mi && j > 1 && World.Space[i + 1, j - 2] > 0) c++;
                //Right bottom
                if (i < mi2 && j < mj && World.Space[i + 2, j + 1] > 0) c++;
                if (i < mi && j < mj2 && World.Space[i + 1, j + 2] > 0) c++;
            }
            if (distance >= 5)
            {
                //Left top
                if (i > 1 && j > 1 && World.Space[i - 2, j - 2] > 0) c++;
                //Left bottom
                if (i > 1 && j < mj2 && World.Space[i - 2, j + 2] > 0) c++;
                //Right top
                if (i < mi2 && j > 1 && World.Space[i + 2, j - 2] > 0) c++;
                //Right bottom
                if (i < mi2 && j < mj2 && World.Space[i + 2, j + 2] > 0) c++;
            }

            return c;
        }
        #endregion

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions