Ejemplo n.º 1
0
        /// <summary>
        /// 移動経路となるマスを返します
        /// </summary>
        /// <returns>The route cells.</returns>
        /// <param name="startCell">Start cell.</param>
        /// <param name="moveAmount">Move amount.</param>
        /// <param name="endSquare">End cell.</param>
        public CheckerSquare[] CalculateRouteCells(int x, int y, int moveAmount, CheckerSquare endSquare)
        {
            //スタート位置の取得
            var startSquare = checkerSquares.First(c => c.X == x && c.Y == y);
            //移動可能範囲の計算
            var infos = GetRemainingMoveAmountInfos(startSquare, moveAmount);

            //ゴールの移動可能判定
            if (!infos.Any(info => info.coordinate.x == endSquare.X && info.coordinate.y == endSquare.Y))
            {
                throw new ArgumentException(string.Format("endCell(x:{0}, y:{1}) is not movable.", endSquare.X, endSquare.Y));
            }

            var routeSquares = new List <CheckerSquare>();

            //ゴール地点の登録
            routeSquares.Add(endSquare);
            while (true)//この中のルート検索部分がうまく動いてない模様 7/27
            {
                //移動範囲内とルートの最新で一致するものを取り出す
                var currentSquareInfo = infos.First(info => info.coordinate.x == routeSquares[routeSquares.Count - 1].X && info.coordinate.y == routeSquares[routeSquares.Count - 1].Y);
                //
                var currentSquare      = checkerSquares.First(square => square.X == currentSquareInfo.coordinate.x && square.Y == currentSquareInfo.coordinate.y);
                var previousMoveAmount = currentSquareInfo.value + currentSquare.Cost + 1;
                var previousSquareInfo = infos.FirstOrDefault(info => (Mathf.Abs(info.coordinate.x - currentSquare.X) + Mathf.Abs(info.coordinate.y - currentSquare.Y)) == 1 && info.value == previousMoveAmount);
                if (null == previousSquareInfo)
                {
                    break;
                }
                routeSquares.Add(checkerSquares.First(c => c.X == previousSquareInfo.coordinate.x && c.Y == previousSquareInfo.coordinate.y));
            }
            routeSquares.Reverse();
            return(routeSquares.ToArray());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 指定位置までの移動ルートと移動コストを計算して返す
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public List <CoordinateAndValue> CalcurateRouteCoordinatesAndMoveAmount(CheckerSquare from, CheckerSquare to)
        {
            //コスト算出
            var costs = GetMoveCostToAllSquares(from);

            if (!costs.Any(info => info.coordinate.x == to.X && info.coordinate.y == to.Y))
            {
                //移動不可
                throw new ArgumentException(string.Format("x:{0}, y:{1} is not movable.", to.X, to.Y));
            }
            //ゴール地点の登録
            var toCost = costs.First(info => info.coordinate.x == to.X && info.coordinate.y == to.Y);
            var route  = new List <CoordinateAndValue>();

            route.Add(toCost);
            //スタート地点までのルート検索
            while (true)
            {
                var currentCost  = route.Last();
                var currentCell  = checkerSquares.First(cell => cell.X == currentCost.coordinate.x && cell.Y == currentCost.coordinate.y);
                var prevMoveCost = currentCost.value - currentCell.Cost;
                var previousCost = costs.FirstOrDefault(info => (Mathf.Abs(info.coordinate.x - currentCell.X) + Mathf.Abs(info.coordinate.y - currentCell.Y)) == 1 && info.value == prevMoveCost);
                if (null == previousCost)
                {
                    break;
                }
                route.Add(previousCost);
            }
            route.Reverse();
            return(route.ToList());
        }
Ejemplo n.º 3
0
 /// <summary>
 /// 指定マスまでの距離を算出
 /// </summary>
 /// <param name="baseSquare"></param>
 /// <param name="distanceMin"></param>
 /// <param name="distanceMax"></param>
 /// <returns></returns>
 public CheckerSquare[] GetCellsByDistance(CheckerSquare baseSquare, int distanceMin, int distanceMax)
 {
     return(checkerSquares.Where(x =>
     {
         var distance = Math.Abs(baseSquare.X - x.X) + Math.Abs(baseSquare.Y - x.Y);
         return distanceMin <= distance && distance <= distanceMax;
     }).ToArray());
 }
Ejemplo n.º 4
0
        /// <summary>
        /// 指定座標から各マスまでの移動コストの算出
        /// </summary>
        /// <param name="from"></param>
        /// <returns></returns>
        public List <CoordinateAndValue> GetMoveCostToAllSquares(CheckerSquare from)
        {
            var infos = new List <CoordinateAndValue>();

            infos.Add(new CoordinateAndValue(from.X, from.Y, 0));
            var i = 0;

            while (true)
            {
                var appendInfos = new List <CoordinateAndValue>();
                foreach (var calcTargetInfo in infos.Where(info => info.value == i))
                {
                    // 四方のマスの座標配列を作成
                    var calcTargetCoordinate  = calcTargetInfo.coordinate;
                    var aroundCellCoordinates = new Coordinate[]
                    {
                        new Coordinate(calcTargetCoordinate.x - 1, calcTargetCoordinate.y),
                        new Coordinate(calcTargetCoordinate.x + 1, calcTargetCoordinate.y),
                        new Coordinate(calcTargetCoordinate.x, calcTargetCoordinate.y - 1),
                        new Coordinate(calcTargetCoordinate.x, calcTargetCoordinate.y + 1),
                    };
                    // 四方のマスの残移動力を計算
                    foreach (var aroundCellCoordinate in aroundCellCoordinates)
                    {
                        var targetCell = checkerSquares.FirstOrDefault(c => c.X == aroundCellCoordinate.x && c.Y == aroundCellCoordinate.y);
                        if (null == targetCell ||
                            infos.Any(info => info.coordinate.x == aroundCellCoordinate.x && info.coordinate.y == aroundCellCoordinate.y) ||
                            appendInfos.Any(info => info.coordinate.x == aroundCellCoordinate.x && info.coordinate.y == aroundCellCoordinate.y))
                        {
                            // マップに存在しない、または既に計算済みの座標はスルー
                            continue;
                        }
                        var remainingMoveAmount = i + targetCell.Cost;
                        appendInfos.Add(new CoordinateAndValue(aroundCellCoordinate.x, aroundCellCoordinate.y, remainingMoveAmount));
                    }
                }
                infos.AddRange(appendInfos);

                i++;
                if (i > infos.Max(x => x.value < 999 ? x.value : 0))
                {
                    break;
                }
            }
            return(infos.Where(x => x.value < 999).ToList());
        }
Ejemplo n.º 5
0
        /// <summary>
        /// 攻撃可能範囲の計算を行います
        /// </summary>
        /// <returns>The remaining move amount infos.</returns>
        /// <param name="startSquare">Start cell.</param>
        /// <param name="moveAmount">Move amount.</param>
        CoordinateAndValue[] GetRemainingAccountRangeInfos(CheckerSquare startSquare, int attackRangeMin, int attackRangeMax)
        {
            var infos = new List <CoordinateAndValue>();

            infos.Add(new CoordinateAndValue(startSquare.X, startSquare.Y, attackRangeMax));
            for (var i = attackRangeMax; i >= 0; i--)
            {
                var appendInfos = new List <CoordinateAndValue>();
                foreach (var calcTargetInfo in infos.Where(info => info.value == i))
                {
                    // 四方のマスの座標配列を作成
                    var calcTargetCoordinate  = calcTargetInfo.coordinate;
                    var aroundCellCoordinates = new Coordinate[]
                    {
                        new Coordinate(calcTargetCoordinate.x - 1, calcTargetCoordinate.y),
                        new Coordinate(calcTargetCoordinate.x + 1, calcTargetCoordinate.y),
                        new Coordinate(calcTargetCoordinate.x, calcTargetCoordinate.y - 1),
                        new Coordinate(calcTargetCoordinate.x, calcTargetCoordinate.y + 1),
                    };
                    // 四方のマスの残攻撃範囲を計算
                    foreach (var aroundCellCoordinate in aroundCellCoordinates)
                    {
                        var targetSquare = checkerSquares.FirstOrDefault(c => c.X == aroundCellCoordinate.x && c.Y == aroundCellCoordinate.y);
                        if (null == targetSquare ||
                            infos.Any(info => info.coordinate.x == aroundCellCoordinate.x && info.coordinate.y == aroundCellCoordinate.y) ||
                            appendInfos.Any(info => info.coordinate.x == aroundCellCoordinate.x && info.coordinate.y == aroundCellCoordinate.y))
                        {
                            // マップに存在しない、または既に計算済みの座標はスルー
                            continue;
                        }
                        var remainingMoveAmount = i - 1;
                        appendInfos.Add(new CoordinateAndValue(aroundCellCoordinate.x, aroundCellCoordinate.y, remainingMoveAmount));
                    }
                }
                infos.AddRange(appendInfos);
            }
            // 攻撃範囲内のマスの情報だけを返す
            return(infos.Where(x => 0 <= x.value && x.value <= (attackRangeMax - attackRangeMin)).ToArray());
        }
Ejemplo n.º 6
0
        /// <summary>
        /// 移動力を元に移動可能範囲の計算を行います
        /// </summary>
        /// <returns>The remaining move amount infos.</returns>
        /// <param name="startSquare">Start cell.</param>
        /// <param name="moveAmount">Move amount.</param>
        CoordinateAndValue[] GetRemainingMoveAmountInfos(CheckerSquare startSquare, int moveAmount)
        {
            var infos = new List <CoordinateAndValue>();

            infos.Add(new CoordinateAndValue(startSquare.X, startSquare.Y, moveAmount));
            for (var i = moveAmount; i >= 0; i--)
            {
                var appendInfos = new List <CoordinateAndValue>();
                foreach (var calcTargetInfo in infos.Where(info => info.value == i)) //コスト計算の部分が不完全なので修正を行う 7/26
                {
                    // 四方のマスの座標配列を作成
                    var calcTargetCoordinate  = calcTargetInfo.coordinate;
                    var aroundCellCoordinates = new Coordinate[]
                    {
                        new Coordinate(calcTargetCoordinate.x - 1, calcTargetCoordinate.y),
                        new Coordinate(calcTargetCoordinate.x + 1, calcTargetCoordinate.y),
                        new Coordinate(calcTargetCoordinate.x, calcTargetCoordinate.y - 1),
                        new Coordinate(calcTargetCoordinate.x, calcTargetCoordinate.y + 1),
                    };
                    // 四方のマスの残移動力を計算
                    foreach (var aroundCellCoordinate in aroundCellCoordinates)
                    {
                        var targetSquare = checkerSquares.FirstOrDefault(c => c.X == aroundCellCoordinate.x && c.Y == aroundCellCoordinate.y);
                        if (null == targetSquare ||
                            infos.Any(info => info.coordinate.x == aroundCellCoordinate.x && info.coordinate.y == aroundCellCoordinate.y) ||
                            appendInfos.Any(info => info.coordinate.x == aroundCellCoordinate.x && info.coordinate.y == aroundCellCoordinate.y))
                        {
                            // マップに存在しない、または既に計算済みの座標はスルー
                            continue;
                        }
                        var remainingMoveAmount = i - 1;
                        appendInfos.Add(new CoordinateAndValue(aroundCellCoordinate.x, aroundCellCoordinate.y, remainingMoveAmount));
                    }
                }
                infos.AddRange(appendInfos);
            }
            // 残移動力が0以上(移動可能)なマスの情報だけを返す
            return(infos.Where(x => x.value >= 0).ToArray());
        }