6

友達と一緒にボードゲームに取り組んでいます。私たちはそれのほとんどをうまく機能させることができました。ゲームは「jeudebarricade」と呼ばれます。多分あなたはそれを知っています。

ボード全体がリンクリストを使用して作成されるため、すべてのフィールドに「LinkNorth」、「LinkEast」、「LinkSouth」、および「LinkWest」変数があります。

これがどのように見えるかをあなたに知らせるためのボードです。

ボード画面
さて、どうすればいいのかわからないことが1つあります。現在、ポーンを選択でき、ボード上の任意のフィールドに移動できます。もちろんこれは良くありません。ここで行う必要があるのは、ポーンが移動できるフィールドの配列またはリストを返す、ある種のアルゴリズムを使用してメソッドを作成することです。このようにして、選択したポーンが、投げられたサイコロ番号を使用して、クリックしたフィールドに実際に移動できるかどうかを確認できます。(1から6までの乱数が生成されます)
ただし、もう1つ。すべての「Field」クラスにはbarricadePawn変数があります。この変数にbarricadePawnオブジェクトが含まれている場合。(barricadePawn!= null)ポーンはその上を移動できないはずです。ポーンはそのフィールドに移動できるようにする必要がありますが、それ以上は移動できません。(プレイヤーがバリケードに正確に着地した場合、彼はそれを動かすことができます。しかし、私たちはすでにそれを実装しているので、それについて心配しないでください)

つまり、要するに。
-'Pawn'クラスにメソッドを作成します。このメソッドは、ポーンが移動できるすべてのフィールドの配列またはリストを返します。
-ポーンはバリケード上を移動できる必要がありますが、バリケード上を移動することはできません。
-ポーンは、サイコロが投げた量を正確に移動する必要があります。したがって、フィニッシュまたはバリケードに乗るには、正確に適切な量を投げる必要があります。

これらは「ポーン」クラスにあります。
「currentLocation」には、選択したポーンが現在立っているフィールドが含まれています。

private Model.Field startLocation;
private Model.Field currentLocation; 

public List<Model.Field> getPossibleMoves(Model.Field curSpot, int remainingMoves, List<Model.Field> moveHistory)
    {
        List<Model.Field> retMoves = new List<Model.Field>();
        if( remainingMoves == 0 )
        {
            retMoves.Add(curSpot);
            return retMoves;
        }
        else
        {
            moveHistory.Add(curSpot);
            if( curSpot.LinkNorth != null && !moveHistory.Contains(curSpot.LinkNorth) )
            {
                retMoves.AddRange( getPossibleMoves( curSpot.LinkNorth, remainingMoves - 1, moveHistory ));
            }

            if (curSpot.LinkEast != null && !moveHistory.Contains(curSpot.LinkEast))
            {
                retMoves.AddRange( getPossibleMoves( curSpot.LinkEast, remainingMoves - 1, moveHistory ));
            }

            if (curSpot.LinkSouth != null && !moveHistory.Contains(curSpot.LinkSouth))
            {
                retMoves.AddRange( getPossibleMoves( curSpot.LinkSouth, remainingMoves - 1, moveHistory ));
            }

            if (curSpot.LinkWest != null && !moveHistory.Contains(curSpot.LinkWest))
            {
                retMoves.AddRange( getPossibleMoves( curSpot.LinkWest, remainingMoves - 1, moveHistory ));
            }
        }
    }

そして、これは私たちの「フィールド」クラスです:

public class Field
    {
        protected Field linkNorth, linkEast, linkSouth, linkWest;
        protected Controller.Pawn pawn;
        protected Model.BarricadePawn barricadePawn;
        protected int x, y;

        //Properties:
        public Field LinkNorth
        {
            get { return linkNorth; }
            set { linkNorth = value; }
        }
        public Field LinkEast
        {
            get { return linkEast; }
            set { linkEast = value; }
        }
        public Field LinkSouth
        {
            get { return linkSouth; }
            set { linkSouth = value; }
        }
        public Field LinkWest
        {
            get { return linkWest; }
            set { linkWest = value; }
        }
        public Controller.Pawn Pawn
        {
            get { return pawn; }
            set { pawn = value; }
        }
        public BarricadePawn Barricade
        {
            get { return barricadePawn; }
            set { barricadePawn = value; }
        }
        public int X
        {
            get { return x; }
            set { x = value; }
        }
        public int Y
        {
            get { return y; }
            set { y = value; }
        }
    }

誰かがこれで私たちを助けることができれば、それは大いにありがたいです。私たちは何も思い付くことができませんでした。

4

2 に答える 2

4

再帰的なメソッドを作成してみてください。

List<Spot> CheckMoves(Spot curSpot, int remainingMoves, List<Spot> moveHistory)
{
    List<Spot> retMoves = new List<Spot>();
    if( remainingMoves == 0 )
    {
        retMoves.Add(curSpot);
        return retMoves;
    }
    else
    {
        moveHistory.Add(curSpot);
        if( !moveHistory.Contains(Spot.North) )
        {

            retMoves.AddRange( CheckMoves( Spot.North, remainingMoves - 1, moveHistory );
        }
        /* Repeat for E, W, S */
    }
}

これにより、すべての潜在的な最終位置を含むリスト(スポットはボード上の位置を表すクラス)が返されます。もちろん、Spot.Northが有効なスポットであることを確認するには、もう少し徹底する必要がありますが、これは基本的な考え方です。

上記の方法では、ユーザーは1回の移動で同じ場所に2回移動することはできませんが、バリケードやその他の障害物を探すことはできません。また、動きを止めたり、特定の方向への動きがないスポットも処理しません。

しかし、それはあなたにそれがどうあるべきかについての考えを与えるはずです。

于 2013-03-14T17:33:54.467 に答える
0

このような何かがそれを行う必要があります、

各リンクを再帰的に列挙し、重複を防ぐためにFieldsをaに追加します。HashSet再帰は、までworpカウントダウンするか0、リンクが存在するnullか、またはが検出されると停止しbarrier pawnます。

public IList<Field> GetPossibleMoves(int worp)
{
    var valid = new HashSet<Field>();

    foreach (var f in GetPossibleMoves(current.LinkNorth, worp))
    {
        valid.Add(f);
    }

    foreach (var f in GetPossibleMoves(current.LinkEast, worp))
    {
        valid.Add(f);
    }

    foreach (var f in GetPossibleMoves(current.LinkSouth, worp))
    {
        valid.Add(f);
    }

    foreach (var f in GetPossibleMoves(current.LinkWest, worp))
    {
        valid.Add(f);
    }

    return valid.ToList();
}

private static IEnumerable<Field> GetPossibleMoves(Field current, int worp)
{
    if (current == null)
    {
        yield break;
    }

    yield return current;

    if (worp == 0 || current.BarricadePawn) // is that a bool?
    {
        yield break;
    } 

    foreach (var f in GetPossibleMoves(current.LinkNorth, nextWorp))
    {
        yield return f;
    }

    foreach (var f in GetPossibleMoves(current.LinkEast, nextWorp))
    {
        yield return f;
    }

    foreach (var f in GetPossibleMoves(current.LinkSouth, nextWorp))
    {
        yield return f;
    }

    foreach (var f in GetPossibleMoves(current.LinkWest, nextWorp))
    {
        yield return f;
    }
}

後方への移動の計算を省略することで最適化できます。これにより、から多くのAddsが破棄されるのを防ぐことができますHashSet

于 2013-03-14T17:46:03.780 に答える