C#+WPF的 生命游戏机的实现

本文实现的生命游戏机(元胞自动机)有如下规则:

  • 在100x100的方格中,蓝色代表存活,白色代表无;
  • 每个T时间后根据规则修改每个元胞的状态;
  • 对一个活的元胞,如果它的邻居中有两个或三个元胞是活的,那么该元胞将继续生存下去,否则死亡。
  • 繁衍:对一个空的元胞,如果它的邻居中有且仅有3个存活的元胞,则变成存活

一次随机中,有三个种子存活。左上的不断扩张,中间的达到平衡,不增加也不减少。右下的则是不断循环。效果图如下:

一段时间后,扩张的也停下来了。

wpf 界面代码:

<Window x:Class="CellularAutomata.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CellularAutomata"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <UniformGrid Name="grid0">
    </UniformGrid>
</Window>

C# 后端实现代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace CellularAutomata
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        static SolidColorBrush LiveColor = Brushes.Blue;
        static SolidColorBrush DeadColor = Brushes.White;

        const int ColCount = 100;
        const int RowCount = 100;
        const int MinNum_Live = 2;
        const int MaxNum_Live = 6;
        const int MinNum_Procreation = 3;
        /// <summary>
        /// 空白出自然产生的概率
        /// </summary>
        const double Probability_Birth = 1E-3;
        static readonly int[][] AroundIdxList = new int[][]
        {
            new int[]{ -1,-1},
            new int[]{ -1,0},
            new int[]{ -1,1},
            new int[]{ 0,-1},
           //new int[]{ 0,0},
            new int[]{ 0,1},
            new int[]{ 1,-1},
            new int[]{ 1,0},
            new int[]{ 1,1},
        };

        int[,] list;
        Border[,] ctrllist;
        DispatcherTimer timer;
        int showTurn = 0;
        Random random = new Random(DateTime.Now.Millisecond);
        public MainWindow()
        {
            InitializeComponent();

            this.grid0.Width = 400;
            this.grid0.Columns = 1;
            ctrllist = new Border[ColCount, RowCount];
            list = new int[ColCount, RowCount];
            for (int i = 0; i < ColCount; i++)
            {
                UniformGrid ugrid = new UniformGrid();
                ugrid.Rows = 1;
                for (int j = 0; j < ColCount; j++)
                {
                    Border b = new Border();
                    b.Width = 5;
                    b.Height = 5;
                    ugrid.Children.Add(b);
                    ctrllist[i, j] = b;
                }
                this.grid0.Children.Add(ugrid);
            }
            // 洒下N个种子
            int seedCount = (int)Math.Ceiling((double)ColCount / 20);
            for (int i = 0; i < seedCount; i++)
            {
                int r = random.Next(0, RowCount - 1);
                int c = random.Next(0, ColCount - 1);
                for (int j = 0; j < 3; j++)
                {
                    int randomNum = random.Next(-3, 3);
                    if (r + randomNum >= RowCount)
                        break;

                    list[r + randomNum, c] = 1;
                }
                for (int j = 0; j < 3; j++)
                {
                    int randomNum = random.Next(-3, 3);
                    if (c + randomNum >= ColCount)
                        break;

                    list[r, c + randomNum] = 1;
                }
            }
            UpdateCtrl();


            timer = new DispatcherTimer();
            timer.Interval = new TimeSpan(0, 0, 0, 1, 10);
            timer.Tick += Timer_Tick;
            timer.Start();
        }
        private void Timer_Tick(object sender, EventArgs e)
        {
            //1 计算上一轮存活格是否继续存活,以及繁衍
            int[,] templist = new int[ColCount, RowCount];
            for (int i = 0; i < ColCount; i++)
            {
                for (int j = 0; j < RowCount; j++)
                {
                    if (list[i, j] == 1)
                    {
                        // 是否继续存活
                        templist[i, j] = IsLived(i, j) ? 1 : 0;
                    }
                    else
                    {
                        // 繁衍
                        templist[i, j] = IsProcreation(i, j) ? 1 : 0;
                    }
                }
            }
             2 计算是否有新的诞生
            //for (int i = 0; i < ColCount; i++)
            //{
            //    for (int j = 0; j < RowCount; j++)
            //    {
            //        if (templist[i, j] == 0)
            //        {
            //            if (IsBirth())
            //            {
            //                templist[i, j] = 1;
            //            }
            //            else
            //            {
            //                templist[i, j] = 0;
            //            }
            //        }
            //    }
            //}

            list = templist;
            // 每演变N轮更新一次界面
            //if (showTurn++ >= 10)
            {
                showTurn = 0;
                UpdateCtrl();
            }
        }

        public bool IsLived(int colIdx, int rowIdx)
        {
            int num_Lived = GetAroundNum_lived(colIdx, rowIdx);
            if (num_Lived < MinNum_Live || num_Lived > MaxNum_Live)
                return false;
            else
                return true;
        }

        /// <summary>
        /// 是否产生新的存活格
        /// </summary>
        public bool IsProcreation(int colIdx, int rowIdx)
        {
            int num_Lived = GetAroundNum_lived(colIdx, rowIdx);
            return num_Lived == MinNum_Procreation;
        }

        public bool IsBirth()
        {
            int max = (int)(1 / Probability_Birth);

            return random.Next(1, max) == 1;
        }

        public int GetAroundNum_lived(int colIdx, int rowIdx)
        {
            int num = 0;
            foreach (var item in AroundIdxList)
            {
                int tempCIdx = colIdx + item[0];
                if (tempCIdx < 0 || tempCIdx >= RowCount)
                {
                    continue;
                }
                int tempRIdx = rowIdx + item[1];
                if (tempRIdx < 0 || tempRIdx >= ColCount)
                {
                    continue;
                }
                if (list[tempCIdx, tempRIdx] == 1)
                {
                    num++;
                }
            }
            return num;
        }

        public void UpdateCtrl()
        {
            for (int i = 0; i < ColCount; i++)
            {
                for (int j = 0; j < ColCount; j++)
                {
                    if (list[i, j] == 0)
                    {
                        ctrllist[i, j].Background = DeadColor;
                    }
                    else
                    {
                        ctrllist[i, j].Background = LiveColor;

                    }
                }

            }
        }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值