如何在C#的foreach循环中用递归实现位置校验直到isAllowed为true
解决方案
首先你现存代码里有两个可优化点:
- 重复写了生成随机坐标、赋值、校验的逻辑,完全可以复用
- 每次都重新实例化
Random类,短时间内连续调用会因为系统时间种子相同生成重复随机值,建议全局复用一个Random实例
递归实现代码
首先把生成合法坐标的逻辑抽为单独的递归方法:
// 全局复用的Random实例 private static readonly Random _random = new Random(); private int GetValidCords(Map map, Fleet fleetItem) { // 生成随机坐标 int x = _random.Next(0, 9); int y = _random.Next(0, 9); int cords = int.Parse($"{x}{y}"); // 赋值后校验 map.Location[cords].ActualFleetPosition = fleetItem; if (IsPositionAllowed(map, cords)) { // 合法直接返回坐标 return cords; } // 不合法递归调用自身重新生成 return GetValidCords(map, fleetItem); }
然后改造你原来的循环逻辑,直接调用递归方法即可:
int i = 0; foreach (var fleet in groupedFleetsbySpaceshipCounts) { // 直接调用递归方法获取合法坐标,不需要重复写校验逻辑 var validCords = GetValidCords(map, fleet.Key[i]); i++; }
注意事项
- 递归一定要有明确的终止条件,这里的终止条件就是
IsPositionAllowed返回true,只要地图上还有可用位置就不会出现无限递归 - 如果存在地图全满的可能,建议加递归深度限制,避免栈溢出:可以给递归方法加一个深度参数,调用时累加深度,超过最大深度(比如100次)就抛出异常或者返回错误标识
内容的提问来源于stack exchange,提问作者Piotr Żak
相关产品推荐
相关产品推荐

