14.3.1 表示仿真的世界
来源:互联网 发布:rar解压密码破解软件 编辑:程序博客网 时间:2024/04/27 23:49
14.3.1 表示仿真的世界
我们的仿真世界是很简单的,它只包含动物和捕食者,因此,可以用两个列表来表示。原则上,我们还应该包括这个世界范围的宽度和高度,但是,我们使用固定的大小来,以使事情更简单。你可以得到有关这个世界更好地了解,我们试图通过图 14.3 来表示,它显示了仿真运行中的一个屏幕快照。
图 14.3 运行中的念真,有 10 个捕食者(大圆圈),在捕猎 100 个动物(小圆圈)
我们来看看在两种语言中,这个仿真中有趣的元素,就像我们在图像应用程序中所做的。我们首先用 F# 版本来说明典型的函数式方法。
用 F# 表示这个仿真的状态
如我们所提到的,仿真的状态会有两个列表,表示动物和捕食者的位置。我们需要用位置来进行计算,比如,计算在两个位置之间的路径上的几个位置。为简化此过程,我们要实现 Vector (向量)类型,使用它来表示动物的位置(相对于原点)。还会实现几个运算符,用于向量的加、减法,以及向量乘以标量的浮点数。
我们将我们的向量实现为简单的不可变的值类型,仿真的状态是一个 F# 的记录类型,有两个字段。你可以在清单 14.20 中看到这个数据结构的声明。
Listing 14.20 Representing the state of the world (F#)
[<Struct>]
type Vector(x:float, y:float) =
member t.X = x
member t.Y = y
static member (+) (vect1:Vector, vect2:Vector) =
Vector(vect1.X + vect2.X, vect1.Y + vect2.Y)
static member (*) (vect:Vector, f) =
Vector(vect.X * f, vect.Y * f)
static member (-) (vect1:Vector, vect2:Vector) =
vect1 + (vect2 * -1.0)
type Simulation =
{ Animals : list<Vector>
Predators : list<Vector> }
位置是用 Struct 属性标记的简单对象,它包含在构造函数中设置的不可变的属性, X 和 Y 坐标,它支持按分量逐位(component-wise)加法,乘以一个标量,向量减法的操作。注意,减法使用另外两个运算符实现的。如你所料,所有的运算符都返回新的值。表示仿真的类型也很简单明了,这个类型也是不可变的,因此,为了处理它,就需要为每一步的仿真,构建一个新的 Simulation 值。
现在,让我们看看 C# 的表示形式。我们主要使用标准 .NET 类型,但是,会以函数的方式处理。
用 C# 表示仿真的状态
在 C# 中,最简单的方法是使用可变类型,表示一些状态,因为,这正是 C# 语言和标准的 .NET 库提供了最大的支持。特别是,.NET 不能提供函数式的列表类型。我们使用以前章节中的 FuncList<T> 类型,这会有两个类似的表示。然而,函数式编程是一种风格,并不是一种技术,因此,我们甚至可以用已有的类,来写函数式代码。只是必须更小心,才能保证做到正确。
清单 14.21 显示了这样的类,我们将用来在 C# 中表示这个仿真。我们省略了 Vector 类型的实现,因为它是一个简单的不可变结构,有重载的运算符,与 F# 版本完全相同。
Listing 14.21 Representing the state of the world (C#)
public class Simulation {
private readonly IEnumerable<Vector> animals;
private readonly IEnumerable<Vector> predators;
public Simulation(List<Vector> animals, List<Vector> predators) {
this.animals = animals;
this.predators = predators;
}
public IEnumerable<Vector> Animals
{ get { return animals; } }
public IEnumerable<Vector> Predators
{ get { return predators; } }
}
在这里,我们使用了两种不同的集合类型,一个用于构造函数的参数,当在其中创建仿真状态时,另一个用于属性。在构造函数中,我们使用List<T>,以确保得到完全计算过的集合,包含所有的位置。因为 IEnumerable<T>是一个延迟序列,我们不可能知道,位置是否已经计算过,或者,是否在以后计算,当我们在以后代码中需要它们的时候。这不是一个大问题,但它会让使测量性能变得困难,因为,我们不可能知道代码何时执行。此外,如果我们运行嘀嗒操作多次,而不强制序列进行计算,它可能会创建一个延迟的序列,将执行后面的工作,在这类应用程序中,这可能会引起混乱。
我们不想把状态公开为 List<T>,因为这是一种可变类型,有人可能会对其进行修改。相反,我们使用 IEnumerable<T>,因此,客户端代码可以对动物和捕食者进行迭代,而不会直接修改现有状态。
现在,我们已经有了表示状态的数据结构,也应该看一下能用它来做什么了。在典型的函数式设计中,这总是下一步要做的事。
- 14.3.1 表示仿真的世界
- 27-《电子入门趣谈》第五章_仿真世界里的电子元器件-第二部分-Mutisim案例1
- 802.11的仿真(1)
- 控制器的仿真电路图-1
- 26-《电子入门趣谈》第五章_仿真世界里的电子元器件-第一部分-Mutisim简介
- Havok_2014-1-0_Pc_Xs_User_Guide(2.2.2-模拟仿真一个Physics2012世界)
- -1的二进制表示
- 数的表示1
- -1 的 二进制表示
- -1的二进制表示
- 在3d世界里 表示 相对屏幕的 上下左右方向
- 影响仿真效率的随机约束写法(多层foreach)和随机数据bit位宽表示
- PPC 仿真环境的搭建(1) --- build_plib
- PID控制的MATLAB仿真(1)
- 世界1%的手机用户用了世界50%的带宽
- 一条狗的世界1
- 平凡的世界---读后感1
- 变化的世界(1)
- android 中stk学习
- 观察者模式
- jquery attr()方法
- 跨浏览器的CSS固定定位{position:fixed}
- [施工中]CentOS5.7 安装 FFMPEG转码MP4
- 14.3.1 表示仿真的世界
- Android自动判定输入的是电话号码还是网址
- Uname
- FIleUpLoad控件的使用(上)
- 备忘:tomcat新增nginx后dwr不正常
- Java程序获得本机的ip+tomcat端口等
- SQL时间格式大全
- Xcode Target (Apple Document) Xcode中的Target含义
- Flex学习笔记_05 使用组件处理数据和交互_02导航类组件