c# 实现康威生命游戏(细胞自动机)的示例
作者:鱼小淮 发布时间:2022-01-08 04:36:22
目录
规则(来自百度百科,康威生命游戏词条)
控制台实现的关键接口
代码实现
规则(来自百度百科,康威生命游戏词条)
游戏开始时,每个细胞随机地设定为“生”或“死”之一的某个状态。然后,根据某种规则,计算出下一代每个细胞的状态,画出下一代细胞的生死分布图。
应该规定什么样的迭代规则呢?需要一个简单的,但又反映生命之间既协同又竞争的生存定律。为简单起见,最基本的考虑是假设每一个细胞都遵循完全一样的生存定律;再进一步,把细胞之间的相互影响只限制在最靠近该细胞的8个邻居中。
也就是说,每个细胞迭代后的状态由该细胞及周围8个细胞状态所决定。作了这些限制后,仍然还有很多方法来规定“生存定律”的具体细节。例如,在康威的生命游戏中,规定了如下生存定律。
(1)当前细胞为死亡状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖);若原先为生,则保持不变。
(2)当前细胞为存活状态时,当周围的邻居细胞低于两个(不包含两个)存活时,该细胞变成死亡状态(模拟生命数量稀少)。
(3)当前细胞为存活状态时,当周围有两个或3个存活细胞时,该细胞保持原样。
(4)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态(模拟生命数量过多)。
控制台实现的关键接口
设置控制台游标的函数:public static void SetCursorPosition (int left, int top); 其中left参数是列,top参数是行。
设置控制台背景色的属性:public static ConsoleColor BackgroundColor { get; set; } 黑色用来表示生存的细胞,白色用来表示死亡的细胞。
代码实现
using System;
using System.Threading;
namespace CellularAutomata
{
class Program
{
private static int gridRowCol = 32;
private static Cell[,] grid = new Cell[gridRowCol, gridRowCol];
private static int sleepMs = 33;
private static int initAlivePossibility = 4; // 4 means 1/4
static void Main(string[] args)
{
try
{
Init();
// Main loop
while (true)
{
Update();
Thread.Sleep(sleepMs);
}
}
catch (Exception e)
{
Console.WriteLine(e);
Console.ReadKey();
}
}
private static void Init()
{
// Set Console Size
Console.BufferHeight = 256;
Console.BufferWidth = 256;
Console.WindowWidth = 256;
Console.WindowHeight = 80;
Random random = new Random();
for (int i = 0; i < grid.GetLength(0); i++)
{
for (int j = 0; j < grid.GetLength(1); j++)
{
grid[i, j] = new Cell();
int value = random.Next(0, initAlivePossibility);
if (value == 0)
{
grid[i, j].Value = true;
}
else
{
grid[i, j].Value = false;
}
}
}
}
private static void Update()
{
for (int i = 0; i < grid.GetLength(0); i++)
{
for (int j = 0; j < grid.GetLength(1); j++)
{
int aliveCount = NeighborAliveCount(i, j);
if (grid[i, j].Value) // Alive
{
if (aliveCount < 2 || aliveCount > 3)
{
grid[i, j].Value = false;
}
}
else // Death
{
if (aliveCount == 3)
{
grid[i, j].Value = true;
}
}
if (grid[i, j].Value)
{
SetAlive(i, j);
}
else
{
SetDeath(i, j);
}
}
}
}
private static int NeighborAliveCount(int i, int j)
{
int count = 0;
for (int m = i - 1; m <= i + 1; m++)
{
for (int n = j - 1; n <= j + 1; n++)
{
if (m == i && n == j) continue;
if (m < 0 || m >= grid.GetLength(0)) continue;
if (n < 0 || n >= grid.GetLength(1)) continue;
if (grid[m, n].Value) count++;
}
}
return count;
}
private static void SetAlive(int i, int j)
{
string aliveStr = " ";
Console.SetCursorPosition(j * aliveStr.Length, i);
Console.BackgroundColor = ConsoleColor.Black;
Console.Write(aliveStr);
}
private static void SetDeath(int i, int j)
{
string deathStr = " ";
Console.SetCursorPosition(j * deathStr.Length, i);
Console.BackgroundColor = ConsoleColor.White;
Console.Write(deathStr);
}
}
public class Cell
{
public bool Value { get; set; }
}
}
完整代码:https://github.com/jingjiangtao/CellularAutomata
Cell类是细胞类,其中有一个bool属性Value,true表示存活,false表示死亡。将细胞单独写成类而不是一个bool值是为了后续可能的扩展。
grid变量是一个二维数组,代表格子,大小可以通过gridRowCol设置,默认32,不宜太大。
sleepMs变量是循环之间的间隔时间,单位是毫秒,默认33ms.
initAlivePossibility变量决定格子中的细胞初始化时存活的概率,计算方式为 1/initAlivePossibility,如initAlivePossibility=4,表示初始化时每个细胞的存活概率是1/4.
Main()函数中先初始化了格子中的细胞和控制台大小。设置控制台大小这一步可能会抛出越界异常,如果出现的话需要修改这个值。 接着是主循环,每次循环的间隔是sleepMs。
Update()就是实现规则的函数。
NeighborAliveCount()函数获取指定细胞的相邻细胞存活数。
SetAlive()函数和SetDeath()函数设置控制台上的显示。
如有错误,欢迎指正,谢谢!
来源:https://www.cnblogs.com/jingjiangtao/p/14439868.html


猜你喜欢
- 一.内容抽象类当编写一个类时,常常会为该类定义一些方法,这些方法用于描述这个类的行为。但在某些情况下只需要定义出一些方法,而不需要具体的去实
- 1.DRUID连接池介绍Druid是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面
- 使用java基础类写的一个简单的zip压缩解压工具类package sun.net.helper;import java.io.*;impo
- 线程安全当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协调,这个类
- switch语句的格式如下:(它的功能是选出一段代码执行) switch(整数选择因子) { case 整数值1 : 语句; break;
- 第一个SpringMvc HelloWorld无启动类springboot才有启动类前端操作访问项目名进入默认主页,显示一个链接点击链接后请
- 引言在第一篇文章中我们分析了协程启动创建过程启动过程,在本文中,我们将着重剖析协程中协程调度的逻辑流程。主要是分析解答如下2个问题:涉及到协
- idea手动刷新git分支相信很多小伙伴都遇到过这样的问题,在git上新建的分支却在idea的git分支中找不到又不知在哪里刷新,博主最近也
- Service概念及用途:Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序,如果我们
- 前言大家都知道,不少仪器工作站可xls文件和2007+的xl以将数据导出为Excel文件,包括97-2003版本的sx文件。采集Excel文
- 新建一个集合List<Bill> billList = new ArrayList<>();将订单中所有物品的名称提
- 本文实例讲述了Java编程调用微信分享功能。分享给大家供大家参考,具体如下:这篇文章介绍如何使用java开发微信分享功能,因为工作,已经开发
- 一、作用和区别 break的作用是跳出当前循环块(for、while、do while)或程序块(switch)。在循环块中的作用
- 1.问题项目中有自己企业的通讯录,但是在应用中拨打公司通讯录的联系人,由于手机通讯录中没有相应的信息,只显示一串电话号2 .目的监听系统来电
- 本文实例为大家分享了C#实现会移动的文字效果的具体代码,供大家参考,具体内容如下1 题目描述(1)Form1窗体设计界面如下:(2)窗体左侧
- java jpa自定义sql语句本篇只是为了再次记录自己又学习了jpa的使用,框架原生的通过解析方法名多适用于单表操作,自定义的sql查询则
- 1.pom.xml<?xml version="1.0" encoding="UTF-8"?&
- C#剪切板Clipboard类我们现在先来看一下官方文档的介绍位于:System.Windows.Forms 命名空间下Provides m
- 面试题1:你们是怎样保存用户密码等敏感数据的?本题回答参考朱晔的《Java业务开发常见错误100例》我们知道,用户名、密码、身份证等都属于用
- 一、程序的三种结构顺序结构分支结构循环结构二、条件语句if 语句是最有用的控制结构之一。 if … else …语句的语法:if (布尔表达