6

I've been working on a board game with a friend of mine. We have managed to get most of it working. The game is called 'jeu de barricade'. Maybe you know it.

The whole board gets created using a Linked List so every field has a 'LinkNorth', 'LinkEast', 'LinkSouth' and 'LinkWest' variable.

Here is the board to give you an idea of how it looks like.

Board Screen
Now, there is one thing we just can't seem to figure out how to do. Currently, a pawn can be selected, and it can be moved to any field on the board. This of course is not good. What we need to do now, is write a method with some sort of algorithm that returns an array or list of the fields the pawn is able to move to. This way, we can check if the selected pawn is actually able to move to the field you clicked on, with the thrown dice number. (a random number from 1 till 6 is generated)
One more thing though. Every 'Field' class has a barricadePawn variable. When this variable contains a barricadePawn object. (barricadePawn != null) the pawn should not be able to move over it. The pawn should be allowed to move onto that field, but not any further. (when the player lands exactly on a barricade, he can move it. But we already implemented that, so don't worry about that)

So, in short.
- I want to create a method in our 'Pawn' class, which returns an array or list of all the fields that the pawn should be able to move to.
- The pawn should be able to move on barricades but NOT over them.
- The pawn has to move exactly the amount thrown by the dice. So, to get on the finish or on a barricade, you have to throw exactly the right amount.

We have these in our 'Pawn' class:
'currentLocation' contains the field that the selected pawn is currently standing on.

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 ));
            }
        }
    }

And this is our 'Field' class:

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; }
        }
    }

If anyone could help us with this, it would be much appreciated. We haven't been able to come up with anything.

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 是代表棋盘上位置的类),其中包含所有潜在的最终位置。当然,您需要更加彻底地确保 Spot.North 是一个有效的地点,但这对您来说是一个基本的想法。

上述方法不允许用户一次移动两次进入同一地点,但不会寻找路障或其他障碍物。它也不处理任何停止运动或在特定方向上不可能运动的点。

但是,它应该让您了解它应该如何进行。

于 2013-03-14T17:33:54.467 回答
0

这样的事情应该这样做,

它递归地枚举每个链接并将Fields 添加到 aHashSet以防止重复。当worp倒计时到0,链接 isnull或 a时递归停止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 回答