/// <summary> /// 分析を実行します。 /// </summary> /// <returns>分析結果</returns> /// <param name="param">入力情報</param> public FieldContext Analyze(Param param) { var player = param.TargetContext.OperationPlayer; MovableSlime.ForEach(moveble => { if (param.TargetContext.MovableSlimes[player.ToInt()][(int)moveble].Index > FieldContextConfig.MaxHiddenUnitIndex) { throw new InvalidOperationException("移動可能スライムが隠し領域外に存在するときに呼び出されることは想定していません"); } }); var target = param.TargetContext.SlimeFields[param.TargetContext.OperationPlayer.ToInt()]; foreach (var fields in target) { for (var i = 0; i < param.ErasedSlimes.Length; i++) { // 隠し領域は対象外 if (i < FieldContextConfig.MinDisplayUnitIndex) { continue; } fields.Value[i] &= param.ErasedSlimes[i]; } } return(param.TargetContext); }
/// <summary> /// 削除できる可能性のあるスライムの分析する /// </summary> /// <param name="context">フィールド状態</param> /// <param name="player">プレイヤ</param> /// <param name="param">パラメータ</param> /// <returns>削除できる可能性のあるスライム数</returns> public int Analyze(FieldContext context, Player.Index player, Param param) { Debug.Assert(param.TargetSlime != Slime.None, "対象スライムがNoneはありえません"); var _context = context.DeepCopy(); // フィールドから削除対象のスライムを削除する foreach (var slime in param.ErasedSlimes) { if (slime == param.TargetSlime) { continue; } _context.SlimeFields[(int)player][slime] = Enumerable.Range(0, FieldContextConfig.FieldUnitCount).Select(i => 0u).ToArray(); } // 移動可能スライムも落下させたいので、情報のみ場外においやってしまう MovableSlime.ForEach(index => { var movable = _context.MovableSlimes[(int)player][(int)index]; movable.Index = 0; movable.Position = (int)index; }); // 重力ですべて落下させる this.Gravity.Update(_context, player, GravityParam); // スライムを消済にマーキングする this.ErasingMarker.Update(_context, player, ErasingMarkerParam); // 消済スライム数をカウントする return(SlimeCountHelper.GetSlimeCount(_context, player, Slime.Erased)); }
/// <summary> /// 移動可能なスライムの変換を行います。 /// </summary> /// <param name="value">移動可能なスライムの文字列</param> /// <returns>移動可能なスライムの情報</returns> private static MovableSlime[][] ParseMovableSlime(string value) { // 変換を行う Func <List <string>, MovableSlime[]> parse = (lines) => { var slimes = new MovableSlime[MovableSlime.Length]; var movableUnit = MovableSlime.UnitIndex.First; var isEnd = false; foreach (Slime slime in ExtensionSlime.Slimes) { var baseShift = 0; var field = new uint[FieldContextConfig.FieldUnitCount]; var fieldIndex = 0; for (var i = 0; i < SimpleText.Length.Field - 1; i++) { var blocks = lines[i].ToCharArray(); Debug.Assert((blocks.Length == 6), string.Format("状態の長さが不正です。{0}", blocks.Length)); var shift = blocks.Length + 1; for (var j = 0; j < blocks.Length; j++) { if (IsExistsMovableColor(slime, blocks[j])) { var movable = DiProvider.GetContainer().GetInstance <MovableSlime>(); movable.Slime = slime; movable.Index = fieldIndex; movable.Position = (baseShift * 8) + shift; slimes[(int)movableUnit] = movable; if (movableUnit == MovableSlime.UnitIndex.Second) { isEnd = true; break; } movableUnit = MovableSlime.UnitIndex.Second; } shift--; } if (isEnd) { break; } baseShift++; // フィールドの境目か? if (i % FieldContextConfig.FieldUnitLineCount >= (FieldContextConfig.FieldUnitLineCount - 1)) { baseShift = 0; fieldIndex++; } } if (isEnd) { break; } } Debug.Assert(slimes[(int)MovableSlime.UnitIndex.First] != null, "1番目の移動可能スライムがnullです。"); Debug.Assert(slimes[(int)MovableSlime.UnitIndex.Second] != null, "2番目の移動可能スライムがnullです。"); // 移動可能スライムの順番整形 // 横の場合は、2←1とする // 縦の場合は、 // 1 // ↓ // 2 // とする var orderdSlimes = slimes .OrderBy(m => m.Index) .ThenBy(m => m.Position) .ToArray(); return(orderdSlimes); }; var values = SplitNewLine(value); var movableSlimes = new MovableSlime[Player.Length][]; Player.ForEach((player) => { var lines = ExtractOnePlayerFieldLines(values, player); movableSlimes[(int)player] = parse(lines); }); return(movableSlimes); }