生命模拟
界面:
<DockPanel Background="#EEEEEE">
<WrapPanel DockPanel.Dock="Top">
<Border Background="Green" Width="20" Height="20" VerticalAlignment="Center"/>
<TextBlock Text="新生" VerticalAlignment="Center"/>
<Border Background="DarkGreen" Width="20" Height="20" VerticalAlignment="Center"/>
<TextBlock Text="不变" VerticalAlignment="Center"/>
<Border Background="Gray" Width="20" Height="20" VerticalAlignment="Center"/>
<TextBlock Text="低密度死亡" VerticalAlignment="Center"/>
<Border Background="DarkGray" Width="20" Height="20" VerticalAlignment="Center"/>
<TextBlock Text="高密度死亡" VerticalAlignment="Center"/>
<Border Width="50"/>
<TextBlock Text="行数:"/>
<TextBox x:Name="txtRow" Text="90" Width="50"/>
<TextBlock Text="列数:"/>
<TextBox x:Name="txtCell" Text="150" Width="50"/>
<Button Content="初始化" Click="InitLifWorld"/>
<TextBlock Text="周期(ms):"/>
<TextBox x:Name="txtEllips" Text="300" Width="50"/>
<Button x:Name="btnLifStart" Content="开始" Click="BtnStartLifeWorld"/>
<Button x:Name="btnLifStop" Content="停止" Click="BtnStopLifeWorld" IsEnabled="False"/>
<TextBlock x:Name="txtStatu" Text="已停止"/>
</WrapPanel>
<Grid>
<UniformGrid x:Name="LifeWorld" HorizontalAlignment="Center" VerticalAlignment="Center">
</UniformGrid>
</Grid>
</DockPanel>
代码:
private void BtnStartLifeWorld(object sender, RoutedEventArgs e)
{
try
{
ellipes = Convert.ToInt32(this.txtEllips.Text);
StartLifeWorld();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void InitLifWorld(object sender, RoutedEventArgs e)
{
try
{
maxRow = Convert.ToInt32(this.txtRow.Text);
maxCell = Convert.ToInt32(this.txtCell.Text);
this.LifeWorld.Rows = maxRow;
this.LifeWorld.Columns = maxCell;
this.LifeWorld.Children.Clear();
bodys = new Body[maxRow, maxCell];
for (int r = 0; r < maxRow; r++)
{
for (int c = 0; c < maxCell; c++)
{
bodys[r, c] = new Body(r, c, LifeStatu.Old);
bodys[r, c].Background = Brushes.Black;
this.LifeWorld.Children.Add(bodys[r, c]);
}
}
}catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void BtnStopLifeWorld(object sender, RoutedEventArgs e)
{
Stop();
}
int ellipes = 300;
int maxRow = 100;
int maxCell = 150;
Body[,] bodys = null;
List<Body> editItems = null;
bool isStop = false;
public void StartLifeWorld()
{
this.txtStatu.Text = "正进行";
this.btnLifStart.IsEnabled = false;
this.btnLifStop.IsEnabled = true;
Task.Run(() =>
{
try
{
isStop = false;
while (!isStop)
{
Thread.Sleep(ellipes);
Dispatcher.Invoke(() => ElliseTime());
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
});
}
public void ElliseTime()
{
editItems = new List<Body>();
for (int r = 0; r < maxRow; r++)
{
for (int c = 0; c < maxCell; c++)
{
var roundItems = GetRoundItems(bodys[r,c]);
int whiteCount = roundItems.Count(f => f.Statu == LifeStatu.Born || f.Statu == LifeStatu.Live);
var statu = GetStatu(whiteCount, bodys[r,c].Statu);
var b = bodys[r, c];
if(statu != b.Statu)
editItems.Add(new Body(b.Row, b.Cell, statu));
}
}
if(editItems.Count <= 0)
{
Stop();
return;
}
foreach (var item in editItems)
{
bodys[item.Row, item.Cell].ChangeStatu(item.Statu);
}
}
void Stop()
{
isStop = true;
this.txtStatu.Text = "已停止";
this.btnLifStart.IsEnabled = true;
this.btnLifStop.IsEnabled = false;
}
/// <summary>
/// 获取当前个体周围所有相邻个体
/// </summary>
/// <param name="body"></param>
/// <returns></returns>
public List<Body> GetRoundItems(Body body)
{
var items = new List<Body>();
int row = body.Row;
int cell = body.Cell;
//从左到右,从上到下
////靠上边
if (row == 0)
{
//靠左上角
if (cell == 0)
{
items.Add(new Body(1, 0, bodys[1,0].Statu));
items.Add(new Body(1, 1, bodys[1,1].Statu));
items.Add(new Body(0, 1, bodys[0,1].Statu));
}
////靠上边
else if (cell > 0 && cell < maxCell - 1)
{
int r = row;
int c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = cell;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = cell + 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row;
c = cell + 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
}
//右上角
else if (cell == maxCell - 1)
{
int r = 0;
int c = maxCell - 2;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = 1;
c = maxCell - 2;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = 1;
c = maxCell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
}
}
//靠下方
else if (row == maxRow - 1)
{
//靠右下角
if (cell == maxCell - 1)
{
int r = maxRow - 2;
int c = maxCell - 2;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = maxRow - 1;
c = maxCell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = maxRow - 1;
c = maxCell - 2;
items.Add(new Body(r, c, bodys[r,c].Statu));
}
////左下角
else if (cell == 0)
{
int r = row - 1;
int c = 0;
items.Add(new Body(r, c, bodys[r, c].Statu));
r = row - 1;
c = 1;
items.Add(new Body(r, c, bodys[r, c].Statu));
r = row;
c = 1;
items.Add(new Body(r, c, bodys[r, c].Statu));
}
//下方
else if (cell < maxCell - 1)
{
int r = row - 1;
int c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row - 1;
c = cell;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row - 1;
c = cell + 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row;
c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row;
c = cell + 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
}
}
else
{
////靠左边
if (cell == 0)
{
int r = row - 1;
int c = 0;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row - 1;
c = 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row;
c = 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = 0;
items.Add(new Body(r, c, bodys[r,c].Statu));
}
////靠右边
else if (cell == maxCell - 1)
{
int r = row - 1;
int c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row - 1;
c = cell;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row;
c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = cell;
items.Add(new Body(r, c, bodys[r,c].Statu));
}
else
{
//上
int r = row - 1;
int c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row - 1;
c = cell;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row - 1;
c = cell + 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
//中
r = row;
c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row;
c = cell + 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
//下
r = row + 1;
c = cell - 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = cell;
items.Add(new Body(r, c, bodys[r,c].Statu));
r = row + 1;
c = cell + 1;
items.Add(new Body(r, c, bodys[r,c].Statu));
}
}
return items;
}
public LifeStatu GetStatu(int whiteCount, LifeStatu statu)
{
int a = 3;
if (whiteCount == a)
{
if (statu == LifeStatu.Old || statu == LifeStatu.Young)
return LifeStatu.Born;
else
return LifeStatu.Live;
}
else if (whiteCount == a - 1)
{
if (statu == LifeStatu.Live || statu == LifeStatu.Born)
return LifeStatu.Live;
}
else if (whiteCount < a - 1)
{
if (statu == LifeStatu.Live || statu == LifeStatu.Born)
return LifeStatu.Young;
}
else if (whiteCount > a)
{
if (statu == LifeStatu.Live || statu == LifeStatu.Born)
return LifeStatu.Old;
}
return statu;
//黑格当周围有2个,则变白
//当周围超过3个则变黑
//当周围少于2个或有3个则不变
//if (whiteCount > 3)
// return LifeStatu.Old;
//if (whiteCount == 3)
//{
// if (statu == LifeStatu.Old || statu == LifeStatu.Young)
// return LifeStatu.Born;
//}
//switch (statu)
//{
// case LifeStatu.Born: return LifeStatu.Live;
// case LifeStatu.Live:
// case LifeStatu.Young:
// case LifeStatu.Old:
// default:
// return LifeStatu.Old;
//}
}
}
//
public enum LifeStatu
{
/// <summary>
/// 诞生
/// </summary>
Born,
/// <summary>
/// 活着
/// </summary>
Live,
/// <summary>
/// 低密度而亡
/// </summary>
Young,
/// <summary>
/// 高密度而亡
/// </summary>
Old
}
public class Body : Button
{
public LifeStatu Statu { get; set; }
public int Row { get; set; }
public int Cell { get; set; }
public Body(int row, int cell, LifeStatu statu)
{
this.Width = 10;
this.Height = 10;
this.Style = null;
this.BorderThickness = new Thickness(0);
this.Click += (s, e) => ChangeStatu((int)Statu >= 0 ? (Statu == LifeStatu.Old ? LifeStatu.Born :(LifeStatu)((int)Statu + 1)) : LifeStatu.Born);
this.Row = row;
this.Cell = cell;
ChangeStatu(statu);
}
public void ChangeStatu(LifeStatu statu)
{
Dispatcher.Invoke(() =>
{
this.Statu = statu;
switch (statu)
{
case LifeStatu.Born:
this.Background = Brushes.White;
break;
case LifeStatu.Live:
this.Background = Brushes.White;
break;
case LifeStatu.Young:
this.Background = Brushes.Black;
break;
case LifeStatu.Old:
this.Background = Brushes.Black;
break;
default:
break;
}
});
}
}