首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >设计二维世界的最佳解决方案--生命游戏

设计二维世界的最佳解决方案--生命游戏
EN

Stack Overflow用户
提问于 2014-03-21 16:49:19
回答 3查看 962关注 0票数 4

我需要创建一个应用程序来模拟食肉动物与猎物的关系。我可以使用一些框架(例如。,但我想知道从头开始编写应用程序的问题。

对我来说,最大的问题是如何用食物、食肉动物和猎物来表示地图。

非常简单的模型

我在考虑二维数组,比如说Cell。单元格将具有布尔字段predatorfoodprey以及相应的设置器和getter。食肉动物和被捕食者会在特定半径(视线范围)内四处游荡和观察细胞。如果捕食者发现猎物,它就会向它移动。如果被捕食者发现捕食者,它就会向相反的方向移动。不受干扰的猎物在找到食物来源之前一直在游荡。

Moving/Wandering

在本例中,动物被转到目的地。

代码语言:javascript
复制
   _ _ _ _ _ _      _ _ _ _ _ _                _ _ _ _ _ _
0 |_|_|_|_|_|_|    |_|_|_|_|_|_|              |_|_|_|_|_|_|
1 |_|A|_|_|_|_|    |_|_|_|_|_|_|              |_|_|_|_|_|_|
2 |_|_|x|x|_|_| -> |_|_|A|x|_|_|    . . .     |_|_|_|_|_|_|
3 |_|_|_|_|x|_|    |_|_|_|_|x|_|              |_|_|_|_|_|_|
4 |_|_|_|_|_|D|    |_|_|_|_|_|D|              |_|_|_|_|_|D|
   0 1 2 3 4 5

这一步消耗了5个移动,动物将有一定的速度(2移动/秒)。在每次移动中,一个单元格将predator设置为false,另一个单元格将其设置为true。通过编程,它将如下所示(当然会有方法moveTo(x,y)):

代码语言:javascript
复制
Animal animal = new Animal(1,1);
animal.setPosition(2,2);
animal.setPosition(3,2);
animal.setPosition(4,3);
animal.setPosition(5,4);

观测

样本捕食者观察的最大范围为3。我已经用x标记了观察细胞。观察只是简单的检查是否getPrey()返回true

代码语言:javascript
复制
   _ _ _ _ _ _ _      _ _ _ _ _ _ _      _ _ _ _ _ _ _          
0 |_|_|_|_|_|_|_|    |_|_|_|_|_|_|_|    |_|_|_|x|_|_|_|      
1 |_|_|_|_|_|_|_|    |_|_|_|x|_|_|_|    |_|x|x|x|x|x|_|        
2 |_|_|_|x|_|_|_|    |_|_|x|x|x|_|_|    |_|x|x|x|x|x|_| 
3 |_|_|x|A|x|_|_| -> |_|x|x|A|x|x|_| -> |x|x|x|A|x|x|x|       
4 |_|_|_|x|_|_|_|    |_|_|x|x|x|_|_|    |_|x|x|x|x|x|_|
5 |_|_|_|_|_|_|_|    |_|_|_|x|_|_|_|    |_|x|x|x|x|x|_|
6 |_|_|_|_|_|_|_|    |_|_|_|_|_|_|_|    |_|_|_|x|_|_|_|
   0 1 2 3 4 5 6

最好的方法是观察周围区域的每一步(移动),但这似乎是大量的计算(检查条件)。我现在说的对不对?

这是一种将大部分数据保存在二维数组中的好方法吗?如果有建设性的回答,我将不胜感激。

这只是一个示例。在未来,我想添加复制,情绪,智慧等。

谢谢。

编辑

我忘了提这个问题的规模。

我认为捕食者和猎物的数量将少于100只。但这只是猜测。地图的大小将是500×500,甚至更小。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-03-21 18:03:13

要求最好的解决方案总是意味着不舒服的压力。为了正确回答这样的问题并真正给出最好的解决方案,我们需要在问题说明中给出一定程度的细节,这是很难理解的。呃..。在问答网站上传达信息。

但不仅仅是因为回答这个问题的困难,我建议首先将它建模为一个接口。假设您已经有了一个Cell接口,您可以将这个世界表示为

代码语言:javascript
复制
interface World {
    Cell get(int x, int y);
    int getSizeX();
    int getSizeY();
}

根据内存消耗和效率之间的权衡,您可以提供各种实现。对于“密集”(且非常高效)实现,可以使用数组:

代码语言:javascript
复制
class ArrayWorld implements World {
    private Cell cells[][] = ...

    @Override
    public Cell get(int x, int y) {
        return cells[x][y];
    }
    ...
}

对于“稀疏”实现(尽管效率稍低),可以使用类似于

代码语言:javascript
复制
class MapWorld implements World {

    // Assuming a class "IntPair" which encapsulates
    // two int values, with proper implementation 
    // of hashCode and equals:
    private Map<IntPair, Cell> map = new HashMap<IntPair, Cell>();

    @Override
    public Cell get(int x, int y) {
        return map.get(new IntPair(x,y));
    }
    ...
}

这里最巧妙的一点是,您可以很容易地实现在此类元胞自动机中经常使用的世界属性:即具有“圆环”拓扑的世界,其中坐标在边界处“环绕”:

代码语言:javascript
复制
class TorusWorld implements World {
    private World delegate = ...

    @Override
    public Cell get(int x, int y) {
        int wrappedX = ((x % getSizeX()) + getSizeX()) % getSizeX();
        int wrappedY = ((y % getSizeY()) + getSizeY()) % getSizeY();
        return delegate.get(wrappedX, wrappedY);
    }
}

然后,这个"Torus世界“可以得到World接口的任何其他实现的支持。

但是:您还提到了一个Animal类,所以还不完全清楚您的Cell类应该是什么样子:Cell真的包含Animal吗?还是只有一组旗子显示细胞中是否含有食物、猎物或其他东西?细胞是否可能包含两种(例如食饵和食物,它们很可能不会相互作用)?在规范阶段,这些都是应该尽早回答的问题。

票数 3
EN

Stack Overflow用户

发布于 2014-03-21 16:57:02

这实际上取决于矩阵的大小和它的稀疏性。但是单元模型应该是很好的,特别是当你可以随机访问坐标(x,y)并且不想有一个巨大的矩阵的时候。为了获得高效的代码,您可以查看“严肃的”生命游戏实现:

问题主要是内存消耗与速度(嗯.如往常一样)。

你要找的是细胞自动机。从头开始做这些很有趣,也很有趣。

票数 3
EN

Stack Overflow用户

发布于 2014-03-21 17:01:11

您的2d数组方法总是最简单的实现方法。预先考虑一下最大数组大小是多少。

如果你需要使用一个巨大的世界,混合着密集和稀疏的生活,那么有更好的选择,但它们都要复杂得多。

对于动态2d结构,可以查看四叉树,甚至可以将四叉树与2d数组方法混在一起。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22564697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档