X the Unknown Becoming an “X'' in an equation.

27九/086

认识迷宫

之前的某篇post上,我提起过我学习过了如何生成迷宫。乘今晚终于把迷宫游戏重新写了一次,来总结一下吧。

至于重新写的目的,皆因想顺便练习巩固一下学习过的设计模式的使用,不过我如今写的这个迷宫还是比较微型的,用到的不多。

来个截图先:

迷宫游戏的截图

迷宫游戏的截图

原理

话说我第一次接触如何生成一个迷宫应该是在初中的时候,因为我记得那个时候我才在我住的地方可以买到电脑报的报摊。看守报摊的是一对老夫妻了,不知道他们现在过得可好?

回到主题。我已经记得不清楚了,好像那时候上面的方法是有一个专门的数组,然后0代表通路1代表是墙的,接下来的就真的不知道了,因为那个时候我还看不懂。完全把迷宫写在一个数组里面应该算不上生成的方法吧,只是表示的方法,因为生成迷宫的是人脑不是电脑。

勉强算得上是方法的,应该是依靠填充0和1的随机数到一个二维的数组,0代表通路1代表墙,然后再图形化出来。不过这样的算法其实很囧,生成出来的能不能叫迷宫……我不知道了。

我不懂定义什么叫迷宫,不过我玩过的迷宫,一般都是只有一条路的,从起点到终点只有唯一一条路径,当然这不是绝对的,不过这种迷宫有一个附带的好处就是,你在迷宫走过的正确路径,可以构成唯一的一幅图画。我想这样的迷宫大家应该都玩过很多的啦。

其实可以让条件更严格:迷宫中任意一点都有且只有一条通往另一点的路径。

考虑一下这样的迷宫其实是什么?任意两点之间都有通路,而且通路唯一,也就是不会构成回路——没错,那就是树。

迷宫可以用树的结构表示这一点其实可以用来解释右手规则(或者左手规则):这所谓的规则其实只是人工地遍历树罢了,迷宫的入口是树的根,出口是树结构中的某一个结点,所以是绝对可以从入口找到出口的。

所以怎样构建迷宫其实就是怎样去构建一棵树。那么有什么方法呢?

最直接的方法就是数据结构书经常有代码例子的直接生成啦,不过我感觉这个方法其实……跟人工生成没太大区别,你觉得呢?

间接生成树的方法就是从一个图中得出,比如说遍历,或者是最小生成树。图是现成的,一个3x3的迷宫完全可以看成是一个由9个顶点构成、每两个相邻的顶点之间就存在边的无向图。然后喜欢深度遍历还是Prim算法还是其他的就是你的选择了。

知道了以上的基本原理,生成一个迷宫就不是难事了。下面的没有什么原理上的东西了,只是我实现的具体细节。

20八/084

Abstract Factory和Factory Method的区别

不得不说这两个囧模式看到我现在都还是不能很确认自己是不是真的了解它们之间的区别了。主要原因估计是Abstract Factory一般通过Factory Method来实现的原因。

(下文中,首字母大写正体的表示一个模式,如Abstract Factory,指的是Abstract Factory这个模式;首字母大写粗斜体的表示一个类,如Factory表示一个Factory的类;小写字母的表示一个对象,如factory表示某个类的一个实例,一个对象;其他的可以通过上下文区分其含义。)

经过多番钻牛角尖和刨书的结果,它们两个的区别,我认为还是比较基本的一点:虽然均属创建型模式,但是Abstract Factory是对象型而Factory Method是类型的(强烈BS一下中译版把这么重要的区别给弄没了)。

更具体一点来说,Abstract Factory把一系列的对象的创建留给了一个factory对象去创建。这里面包含了一个动态的概念:你可以动态地决定你的factory的将创建一堆什么东西(通过选择不同的Concrete Factory)。

而Factory Method则是一个静态的概念,它把一个对象的创建推迟到了子类,我们知道这在C++里面可以通过虚拟函数来实现。之所以说是静态的是因为,Factory Method里面的Product,在你进行类设计的阶段时就已经被固定为是经过Creator通过某个操作来创建的。为了创建一个Product的对象,你必须要通过Creator的这个操作进行。

尽管用什么Creator的子类对象来创建哪个Product的子类对象还是动态的,但是这不是Factory Method关心的范围。这也是因为Factory Method是类创建型模式所决定的:它关心的是CreatorProduct两个类(包括子类)之间的关系:Creator负责了Product的创建,而这种创建将依赖于在Creator上面定义的一个操作(也就是一个factory method,``because it is resposible for "manufacturing" an object'')实现。这其实定义了一个Creator(Factory)->Product的关系。

而Abstract Factory之所以显得和Factory Method很接近——Abstract Factory指定了许多的操作,然后再在Concrete Factory里面定义好这些操作,负责创建对应的Concrete Product——是因为Abstract Factory通过Factory Method来实现的原因(所以,Abstract Factory里面的那些操作都可以称为是factory method)。

但Abstract Factory并非只能通过Factory Method来实现。如果说通过Factory Method来实现Abstract Factory使得Abstract Factory定义的类间和类层次结构与Factory Method很接近的话,通过Prototype来实现的Abstract Factory将可以把这个结构坎掉一大半,让Abstract Factory与Factory Method不再相似,只剩下一堆操作。这堆操作只起到接口的作用,并没有定义像Factory Method中那样的关系:尽管对象还是经由Abstract Factory这些操作产生,但本质上已经不再是Factory->Product的关系了(Prototype模式里面通过拷贝对象原型来产生新的对象,是一种prototype->product的关系。注意字体)。

然而根本不用管是否Factory->Product,因为Abstract Factory关心的只是,提供接口,隐藏内部细节,使得可以通过不同的factory object用相同的接口来产生不同系列的产品对象(其实就是不管如何都是显示为一个factory->product的关系。注意字体)。

这也是为何Abstract Factory定位为一个对象创建型的模式的原因吧。