2013-03-14 135 views
6

我一直在和我的一位朋友一起玩棋盘游戏。我们已经设法使其大部分工作。这场比赛被称为'jeu de barricade'。也许你知道。棋盘游戏典当运动算法

使用链接列表创建整个董事会,所以每个字段都有一个'LinkNorth','LinkEast','LinkSouth'和'LinkWest'变量。

这是董事会给你一个它的样子。

Board Screen
现在,有一件事我们似乎无法弄清楚如何去做。目前,可以选择一个棋子,并将其移动到棋盘上的任何区域。这当然不好。 我们现在需要做的是编写一种方法,用某种算法返回一个数组或列表中的棋子能够移动到的字段。这样,我们可以检查选中的棋子是否实际上能够移动到你点击的区域,掷出的骰子号码。 (从1到6的随机数生成)
但还有一件事。每个'Field'类都有一个barricadePawn变量。当这个变量包含一个barricadePawn对象时。 (barricadePawn!= null)典当不应该移动它。棋子应该被允许移动到该场地上,但不能进一步。我们已经实现了,所以不用担心)

因此,简而言之,
- 我想在我们的'Pawn'类中创建一个方法,它返回一个数组或列表中所有可以移动的棋子。
- 棋子应该能够在路障上移动,但不能在路障上移动。
- 棋子必须移动骰子投掷的数量。所以,要完成或在路障上,你必须投入恰到好处的量。

我们在我们的'典当'类中有这些:
'currentLocation'包含所选pawn当前站在的字段。

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

如果有人可以帮助我们解决这个,这将是大加赞赏。我们一直未能拿出任何东西。

+0

一个迭代函数应该这样做。我需要澄清模具周围的规则,你可以移动领域的任何数字到模值,或仅由模具指定的字段数量,除非你遇到路障棋子? – Jodrell 2013-03-14 17:27:47

回答

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 */ 
    } 
} 

这将返回一个包含所有潜在最终位置的List(其中spot是表示在棋盘上的位置的类)。当然,在确保Spot.North是一个有效位置时,您需要更加全面,但这是您的基本想法。

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

但是,它应该让你知道它应该如何去。

+0

我用你的方法更新了我的getPossibleMoves()方法。 (请参阅主文章)我对它有很好的感觉,但编译器给我一个错误,并不是所有可能的路径都会返回值。任何想法如何我可以解决这个问题? – Snowy007 2013-03-14 20:32:19

+0

是的。并非所有的代码路径都返回一个值。 'else'块中没有返回,是吗?应该在该块的结尾处返回一些东西。尝试返回else块中的retMoves,或者在方法的最后。 – Jeff 2013-03-14 20:38:02

+0

@ Snowy007另外请注意,没有什么能够像在目前的情况下一样停止多次返回集。你可能想要对列表做些什么来获得不同的对象。 – Jeff 2013-03-14 20:40:19

0

像这样的东西应该这样做,

它recusively列举每一个环节,并增加了Field s到一个HashSet,以防止重复。时,在worp递减计数至0,链接nullbarrier 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; 
    } 
} 

它可以通过省略的向后移动这样可以防止大量的Add■从HashSet被丢弃的计算来优化。