c# – 对于水管连接游戏,如何正确检查所有4个相邻的网格而无需回
我正在尝试编码的游戏是一个管道连接游戏,其中有4个水源(左上角,左下角,右上角和右下角),目标是将它们连接到位于最顶行的~11个建筑物的网格.
我设置的网格是一个21 x 9的32x32px正方形列表,每个正方形都包含对null“Pipe”类的引用.我还在Grid< 0>处制作了一个水源(基本上是“hasWater = true”).用于测试目的. 这是我如何做我的Pipe类的插座标记: ` public class Pipe { bool pipehasTop; // Top outlet flag bool pipehasRight; // Right outlet flag bool pipehasBottom; // Bottom outlet flag bool pipehasLeft; // Left outlet flag bool hasWater; // To determine pipe color and whether it can spread to other pipes bool outletCount; // No. of outlets (I pipe has 2,T pipe has 3,etc) bool connectedCount; // No. of outlets connected to adjacent grid's outlet } 旋转是单独完成的,当我按下鼠标中键时,它将根据管道类型(按预期工作)更改标志 当我没有放置管道时,默认情况下实例化的网格方块为空.当前的系统是我将按热键选择管道,如果需要可以旋转它,然后通过单击将管道放置到网格上,将空引用转换为选定的管道变体.因此,在我的代码中几乎无处不在,我需要为管道添加“if!= null”:( 我目前正在使用for循环首先水平遍历每个网格方块然后垂直 – 逻辑是检查每个相邻网格是否匹配标志以及相邻网格是否“hasWater”,如果所有返回true,那么Grid-in-question将现在有了水. for(int y = 0; y < rows; y++) { for(int x = 0; x < columns; x++) { int gridIndex = (y*columns) + x; // Horizontal 0,1,2,etc if(y > 0 && Grid[gridIndex - columns].pipe != null) if(Grid[gridIndex - columns].pipe.pipehasBottom == true // Check if above grid has bottom flag && Grid[gridIndex].pipe.pipehasTop == true // Check if current grid has top flag && Grid[gridIndex - columns].pipe.hasWater == true) { // Check if above grid has water Grid[gridIndex].pipe.hasWater == true; } } } 我重复一遍右边,底部和左边的其他3个相邻的瓷砖. 起初我遇到了一个“鬼”水管问题,当管道链断开时,分离的管道将检查仍然有水的相邻网格并重新获回水,然后整个链条确实每组2个或更多分离的管道将自我维持,除非我自己移除管道,然后只有它没有水网检查,因此没有水. 我通过在检查循环之前运行一个方法将所有pipe.hasWater变为false然后运行相邻检查来进行迷你修复 然而,由于检查循环的水平性质,我坚持使用,当一切都是假的并且它逐行检查时,在一个有水的网格上放置一个新管道将不会检查它并将新管道放置到有水的网格左边也不会检查它.我无法删除“将所有水变为假”的方法,因为它会再次导致“鬼水管”问题. 我已经尝试了几天找到一个解决方法,这是我能想到的最好的…而且大多数管道检查逻辑都在Update()和LateUpdate()下……当我不做的时候它要么中途检查要么在随机的地方休息. 对于这个看似简单的检查,我似乎无法找到平衡的解决方案. 感谢您的阅读,请帮助我了解这个动态管道检查逻辑!我会继续寻找解决方案. 解决方法
您可能需要的是一种更好的算法来检查有水的管道的连通性.我的第一反应是制作一个算法,该算法基本上遵循来自源的水流并填充每个管道的hasWater标志.如果瓷砖被移除/添加到正确重新计算(如果有水),您可能希望运行此项.我在这里伪代码的是
breadth first search.
在伪代码中: reset all hasWater flags to false //Use a queue object to place the pipes that we are declaring as having water //but that we still need to check if they have any neighbors that will get water var pipesWithWaterToProcess = new Queue(); //seed the queue with pipes that connect to a water source (ie. one of the sources in the corners) foreach waterSource in waterSources if exists an adjacent pipe that has an outlet that connects to the water source if pipe does not have water already add pipe to pipesWithWaterToProcess queue flip the has water flag to true end end end while pipesWithWaterToProcess queue has items var currentPipe = pipesWithWaterToProcess.dequeue() for each adjoining tile to the currentPipe if tile has pipe (newPipe) and newPipe connects to currentPipe if newPipe does not have water flip the hasWater flag add newPipe to the pipesWithWaterToProcess queue end end end end 假设您有这样的地图: S-A-B-D- | | C- | (线是连接,S是水源). 这种最终发生的方式是从水源开始并将管道A添加到队列中.然后你看一下队列,看看有什么东西要处理.所以你拿A出去看看它的邻居.如果B和C连接到A,则声明B和C有水并将它们添加到队列中(因为现在需要检查所有邻居).然后你做B. B.添加D.然后你做C,但是没有任何管道连接到C.然后你做D,它也没有添加管道.然后你就完成了,所有相关的东西都会显示为有水. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |