生命游戏:如何拥有“实体”并行发展?

好吧标题不清楚,这就是我的意思。 我正在编程某种游戏(比如生命游戏)。例如,有动物(每个动物是一个类的Java实例)。 所有这些动物都在地图上,所有这些“世界”都演变为每个“转向”。 这些动物可以在每个回合动作。 例如:狼杀死了一只羊。 但是,我对在状态之间进行这些演变的“方法”有困难,因为结果将取决于我循环通过动物的顺序。 示例: 狼先:狼杀了羊(然后羊死了,所以没动作) 羊首先:羊吃了一些草,然后狼(转过狼)狼杀了羊 我怎么解决这个问题 ? 多线程? (但我会有很多动物,比如1000甚至更多......)。是否有算法,“方法”来做到这一点? 谢谢     
已邀请:
我认为实体只能在非常简单的场景中并行发展(以康威的生活为例) - 对于你的“狼 - 羊草”世界来说,你越是想到它就越复杂: 考虑两只狼和一只羊的情况。狼一决定吃羊;狼二决定吃羊 - 你怎么决定哪一只羊(让我们假设吃是原子操作 - 狼不能分享他们的饭菜)。所以你仍然需要决定一些顺序,所以说Wolf One得到了一只羊,Wolf Two得不到任何东西(对于Wolf Two来说这是完全出乎意料的 - 一秒钟前有一只羊,它开口了--BAM! - 什么也没有) 有两只狼和两只羊;对于两只狼来说,两只羊的“吸引力”都是一样的,所以他们随机选择猎物。不幸的是,他们选择了同样的绵羊,Wolf One吃了一只羊,Wolf Two尝试吃了一只羊,但它神奇地消失在它的鼻子下面。回合结束。在接下来的转弯中,两只羊跑掉了,狼两只挨饿 - 这完全是不合逻辑的。 因此,我认为只需迭代动物列表并为执行原子动作的每个动物调用一个方法,从而产生更符合逻辑的宇宙。如果你担心之前产生的动物比后来产生的动物有不公平的优势你可以在每次转弯之前随机化动物名单 - 这样,在你的例子中,要么是羊吃了一些草,然后被狼吃了,或者狼在它有机会吃任何草之前吃它。这就是生活。     
你应该正确地模拟转弯,即让每只动物根据世界的当前状态轮流,以便动作的结果更新到世界的下一个状态,而不是当前状态。即 在目前的步骤中,羊吃了一些草,狼杀了它。 在世界的下一个状态,有一只内容狼,没有羊(或羊胴体 - 取决于你的模型)。 这样,评估的顺序不影响结果,这开启了例如并行化执行,最好使用
FutureTask
s和a
ThreadPoolExecutor
。     
线程并发不是这里的主要问题。我认为正确的模型应该允许每个实体在当前回合中决定一个动作。然后,为了确定下一回合的游戏状态,您应该处理操作,并在需要时解决冲突。你应该决定解决两个不同球员采取的各种“冲突”动作组合的规则。     
哦,你不想进入多线程,事情会变得更加混乱。 在这种情况下,迭代所有动物,让他们选择他们的行动。然后更新地图。     
如果您有一个可以接收和发出通知的中央管理器,您可以使用Observer模式。每次转弯进化,动物都会通知它们的位置。管理者通知谁在那里,并根据上下文执行他们的
eat()
方法。当他们吃完饭后,他们会给经理,然后告诉他们该怎么做(例如
sheep.die()
)     
听起来你希望每次像康威的生活一样,让世界以同样的方式进化。在“生活”中,您会查看每个单元格,并根据之前的状态计算出它的结果。如果该小区有两个邻居,那么无论这些邻居是否会在下一代中存在,它都会生活在下一代。原始状态应该是只读的,规则无论如何都应该有效。 例如,如果你在绵羊附近有两只狼,他们都会吃它,还是只吃一只?如果只有一个,那么你需要一个规则,一个人可以吃羊,另一个人需要知道。你可以采取相反的方式,即看看羊,找到一种可以吃它的动物。假设你只想要一只狼吃羊,你说有最低'Y'坐标的狼得到绵羊,或者如果有两只狼有相同的'Y'则说最低的'X'坐标。如果你正在处理一只狼,你需要确保没有其他狼会先吃掉它。这可能会变得更加混乱,因为可能会有另一只绵羊靠近它会吃,所以它不会吃掉第一只... 最简单的方法是说,无论在下一轮的进化过程中发生什么动物或其他动物做什么,所有动物都能做出自己的行动。如果一只绵羊被三只狼包围,它将在下一轮死亡,所有狼将分享这顿饭。如果绵羊旁边有草,即使绵羊被狼群包围,绵羊也会吃它。对于狼来说,他们都会被喂食,因为他们只是一只羊。
public class Cell {
    public int CellType = 0; // 0 == empty, 1 == grass, 2 == sheep, 3 == wolf
    public int Feedings = 0;
}

public class World {
public Cell [] Cells = new Cell[100];
public int Rows = 10, Cols = 10;

public Cell GetCell(x, y) {
    if (x < 0 || x >= Cols || y < 0 || y >= Rows) return null;
    if (Cells[y * Cols + x] == null) {
        Cells[y * Cols + x] = new Cell();
    }
    return Cells[y * Cols + x];
}

public World Evolve() {
    World w = new World();
    for (int y = 0; y < Rows; y++) {
        for (int x = 0; x < Cols; x++) {
            HandleCell(w, x, y);
        }
    }
    return w;
}

public void HandleCell(World newWorld, int x, int y) {
    Cell result = newWorld.GetCell(x, y);

    Cell c = GetCell(x, y);
    if (c.CellType == 2) { // sheep
        bool foundWolf = false;
        bool foundGrass = false;

        // code here to find if a wolf or grass are around the sheep

        if (foundWolf) {
            // default cell type is empty, so leave it be (wolf ate me)
        } else {
            result.cellType = 2; // still a sheep here
            if (foundGrass) {
                result.Feedings = c.Feedings + 1; // and he ate!
            } else {
                result.Feedings = c.Feedings; // or not...
            }
        }
    }

    if (c.CellType == 3) { // wolf
        bool foundSheep = false;

        // code here to find if a sheep is around the wolf

        result.CellType = 3;
        if (foundSheep) {
            result.Feedings = c.Feedings + 1; // ate the sheep!
        } else {
            result.Feedings = c.Feedings;
        }
    }
}
    
在我的头顶,你可能会做这样的事情: 拥有一个管理Player对象列表的World对象。玩家有以下方法: 播放机 public void takeTurn(世界) public boolean isDead() public void kill() 当World实例进入每个玩家时,它会询问它是否已经死亡。如果没有,则调用takeTurn方法。或者,takeTurn可以在内部调用isDead(),如果是,则返回。如果你杀了另一个玩家(或你自己),你只需要调用玩家的杀戮方法。 将世界传递给takeTurn只是为了防止您需要进行回调以更新世界状态。     
一种方法是: 让绵羊做他们的行动并在下一步记录它们。 更新羊的行动板 做每个狼的行动并在下一步记录它们。 为狼行动更新董事会。 两种多线程的方式是: 将董事会划分为不同的区域,并将每个线程分配到一个区域。您将无法确定如何将其从一个区域移动到另一个区域。 另一种方式可能是通过生物打破不同线程的循环。例如
for(w=THREAD_NUM;  w<NUM_OF_WOLVES; w+=NUM_OF_THREADS)
{ 
   w.doAction(); 
}
    
也许你可以完全随意地做到这一点。 第一个随机的例子:羊吃草,然后狼吃羊(羊 - >狼) 第二个随机的例子:狼吃羊,因为可怜的东西太慢而无法到达草地(狼 - > /) 现实世界是确定性的吗? :)     

要回复问题请先登录注册