2013-03-14 14 views
6

Pracuję nad grą planszową z moim przyjacielem. Udało nam się uzyskać większość z nich działa. Gra nazywa się "jeu de barykada". Może to wiesz.Algorytm ruchu pionkowego gry planszowej

Cała plansza jest tworzona przy użyciu listy połączonej, więc każde pole ma zmienną "LinkNorth", "LinkEast", "LinkSouth" i "LinkWest".

Oto tablica informująca o tym, jak to wygląda.

Board Screen
Teraz jest jedna rzecz, po prostu nie możemy się dowiedzieć, jak to zrobić. Obecnie można wybrać pionka i można go przenieść do dowolnego pola na planszy. To oczywiście nie jest dobre. To, co musimy teraz zrobić, to napisać metodę z jakimś algorytmem, który zwraca tablicę lub listę pól, do których pionek może się przenieść. W ten sposób możemy sprawdzić, czy wybrany pionek jest w stanie przenieść się na pole, na które kliknąłeś, wraz z wyrzuconym numerem kości. (generowana jest liczba losowa od 1 do 6)
Jeszcze jedno. Każda klasa "Field" ma zmienną BarricadePawn. Kiedy ta zmienna zawiera obiekt BarricadePawn. (barricadePawn! = null) pionek nie powinien się nad nim poruszać. Pion powinien mieć możliwość przejścia na to pole, ale nie dalej. (kiedy gracz ląduje dokładnie na barykadzie, może go przenieść, ale już to zaimplementowaliśmy, więc nie martw się o to)

Krótko mówiąc.
- Chcę utworzyć metodę w naszej klasie "Pion", która zwraca tablicę lub listę wszystkich pól, do których pionek powinien się dostać.
- Pionek powinien być w stanie poruszać się na barykadach, ale NIE nad nimi.
- Pionek musi przesunąć dokładnie tyle, ile rzuca kostka. Tak więc, aby dostać się do mety lub na barykadę, musisz wyrzucić dokładnie taką ilość.

Mamy je w naszej klasie "Pawn":
"currentLocation" zawiera pole, na którym aktualnie stoi pionek.

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

I to jest nasz „Pole” klasa:

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

Jeśli ktoś może nam w tym pomóc, to byłoby bardzo mile widziane. Nie byliśmy w stanie wymyślić niczego.

+0

powinna to zrobić funkcja iteracyjna. Będę musiał wyjaśnić zasady dotyczące kości, czy możesz przenieść dowolną liczbę pól do wartości kości lub tylko liczbę pól określoną przez kościę, chyba że napotkasz pionek barykady? – Jodrell

Odpowiedz

4

Spróbuj utworzyć metodę rekursywną.

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

Spowoduje to wyświetlenie listy (gdzie spot jest klasą reprezentującą pozycję na planszy), która zawiera wszystkie potencjalne pozycje końcowe. Oczywiście musisz być nieco bardziej dokładny w upewnianiu się, że Spot.North jest odpowiednim miejscem, ale jest to dla Ciebie podstawowy pomysł.

Powyższa metoda nie pozwoli użytkownikowi na przejście w to samo miejsce dwa razy w jednym ruchu, ale nie szuka barykad ani innych przeszkód. Nie obsługuje również żadnych miejsc, które zatrzymują ruch lub nie mają możliwości ruchu w określonym kierunku.

Powinien jednak dać ci wyobrażenie, jak powinien się udać.

+0

Zaktualizowałem metodę getPossibleMoves() za pomocą Twojej metody. (zobacz główny post) Mam dobre przeczucie, ale kompilator daje mi błąd, że nie wszystkie możliwe ścieżki dają wartość zwracaną. Masz pomysł, jak to naprawić? – Snowy007

+0

Tak. Nie wszystkie ścieżki kodu zwracają wartość. Nic nie jest zwracane w bloku "else", prawda? Coś powinno zostać zwrócone na końcu tego bloku. Spróbuj zwrócić retMoves w bloku else lub na samym końcu metody. – Jeff

+0

@ Snowy007 Należy również pamiętać, że nic nie stoi na przeszkodzie, aby ta sama pozycja znajdowała się wielokrotnie w zestawie zwrotów, tak jak obecnie. Prawdopodobnie będziesz chciał coś zrobić na liście, aby uzyskać różne obiekty. – Jeff

0

Coś jak to powinno wystarczyć,

To recusively wylicza każdy link i dodaje Field s do HashSet aby zapobiec duplikaty. Rekursja zatrzymuje się, gdy worp liczy się od 0, jest to łącze null lub 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; 
    } 
} 

To może być zoptymalizowane przez pominięcie obliczenie zacofanych ruchów, które uniemożliwiałyby dużo Add s pozostawaniem od HashSet.