2016-03-03 9 views
0

我正在寫一個Java算法,它可以讓一個遊戲中的六個玩家分別擲出一個骰子和最高的擲骰子等等。我已經編寫了骰子滾動方法,它以<String playerName, Player player>的形式接收玩家地圖,並且讓每個玩家擲骰子,其中玩家是存儲遊戲必需的許多玩家屬性的類。努力保持一個算法,通過骰子訂購玩家整齊

問題我在訂購玩家時遇到了麻煩,如果兩個玩家擲出相同的數字,他們會再次擲出,以便看到誰先走到另一個玩家的前面。下面是一個例子情形:

位置:播放器(數軋)

1:湯姆(5)

2:傑裏(4)

= 3:插孔(3)

= 3:吉爾(3)

5:哈里(2)

6:羅恩(1)

So傑克和吉爾再次滾動。傑克擲出6分,吉爾擲出3分。傑克現在位於第三位,吉爾在第四位。

我已經開始寫快速的任何策略變得看起來過於複雜,非常不整潔,難以閱讀。這是由於必須檢查是否有任何重複的捲筒在任何數量的捲筒上,同時以正確的順序存儲每個捲筒,如果存在重複的捲筒,允許兩個或更多個位置。 任何人都可以想出一個整齊的結構,其中可以確定和存儲此訂單?

Player的每個實例都有一個nextPlayer變量,它指向後面的位置的玩家。這也可能是最好的,也存儲numberRolled在課堂上。任何滾動相同編號的玩家都可以存儲在新地圖中,然後再次傳入rollDice方法。

編輯

感謝安迪·特納,這裏是我的解決方案:

private Player[] playerOrder = new Player[ModelConstants.NUM_PLAYERS_PLUS_NEUTRALS]; 

playerOrder = getPlayerOrder(); 

Player[] getPlayerOrder() { 
     Player[] players = ModelConstants.PLAYERS.values().toArray(new Player[ModelConstants.PLAYERS.size()]); 
     String[] playerNames = ModelConstants.PLAYERS.keySet().toArray(new String[ModelConstants.PLAYERS.size()]); 
     getPlayerOrder(playerNames, players, 0, players.length); 
     return players; 
    } 

void getPlayerOrder(String[] playerNames, Player[] players, int start, int end) { 
    // Get all players between players[start] (inclusive) and 
    // players[end] (exclusive) to re-roll the dice. 
    for (int i = start; i < end; ++i) { 
     players[i].setDiceNumberRolled(rollDice(playerNames[i], players[i])); 
    } 

    // Sort this portion of the array according to the number rolled. 
    Arrays.sort(players, start, end, new Comparator<Player>() {  
     @Override public int compare(Player a, Player b) { 
      return Integer.compare(a.getDiceNumberRolled(), b.getDiceNumberRolled()); 
     } 
    }); 

    for (int i = 0; i < playerNames.length; i++) { 
     playerNames[i] = HashMapUtilities.getKeyFromValue(ModelConstants.PLAYERS, players[i]); 
    } 

    // Look for players who rolled the same number. 
    int i = start; 
    while (i < end) { 
     // Try to find a "run" of players with the same number. 
     int runStart = i; 
     int diceNumberRolled = players[runStart].getDiceNumberRolled(); 
     i++; 
     while (i < end && players[i].getDiceNumberRolled() == diceNumberRolled) { 
      i++; 
     } 

     if (i - runStart > 1) { 
      // We have found more than one player with the same dice number. 
      // Get all of the players with that dice number to roll again. 
      addMessageToLog(MessageType.INFO, "There has been a tie." , 2000); 
      tiedPlayers = true; 
      getPlayerOrder(playerNames, players, runStart, i); 
      tiedPlayers = false; 
     } 
    } 
} 

private int rollDice(String playerName, Player player) { 
    int numberRolled = 0; 
    if (player.getPlayerType().equals(PlayerType.HUMAN)) { 
     boolean diceRolled = false; 
     while (!diceRolled) { 
      String message = ", roll the dice"; 
      if (tiedPlayers == true) { 
       message += " again."; 
      } 
      else { 
       message += "."; 
      } 
      String userInput = getCommand(playerName + message, "Invlaid command. Type \"Roll Dice\" or something similar.", 2000); 
      if (userInput.equalsIgnoreCase("Roll Dice") || userInput.equalsIgnoreCase("roll the dice") || userInput.equalsIgnoreCase("Roll")) { 
       numberRolled = dice.rollDice(); 
       diceRolled = true; 
      } 
      else { 
       addMessageToLog(MessageType.ERROR, "Invlaid command. Type \"Roll Dice\" or something similar.", 0); 
      } 
     } 
    } 
    else { 
     String message = " is now rolling the dice"; 
     if (tiedPlayers == true) { 
      message += " again..."; 
     } 
     else { 
      message += "..."; 
     } 
     addMessageToLog(MessageType.INFO, playerName + message, 2000); 
     numberRolled = dice.rollDice(); 
    } 
    player.setDiceNumberRolled(numberRolled); 
    addMessageToLog(MessageType.SUCCESS, playerName + " rolled a " + numberRolled, 1000); 
    addDicePanel(numberRolled); 
    return numberRolled; 
} 

private void setPlayerOrder() { 
    for (int i = 0; i < playerOrder.length; i++) { 
     if (i == (playerOrder.length - 1)) { 
      playerOrder[i].setNextPlayer(playerOrder[0]); 
     } 
     else { 
      playerOrder[i].setNextPlayer(playerOrder[i + 1]); 
     } 
    } 
    activePlayer = playerOrder[0]; 
} 

private void changePlayer() { 
    activePlayer = activePlayer.getNextPlayer(); 
} 
+1

請出示你是如何存儲和基於骰子的第一輥分發代碼。 –

+0

@AndyTurner我不在我存儲程序的計算機上,所以我在我的文章 – KOB

+1

中添加了一個(未測試的)我的樣本解決方案(int i = 6; i <1; i--){ ':這個for循環將永遠不會執行。 –

回答

0

您可以將所有玩家放入數組中 - 玩家在數組中的順序可以用來指示玩的順序。

讓他們全部選擇一個骰子卷;然後按它們滾動的數字對它們進行排序(使用自定義比較器)。

現在,請查找2個或更多玩家相同的號碼 - 這些玩家彼此相鄰,因爲數組已排序。現在,你可以遞歸地調用相同的邏輯來讓那些玩家重新擲出,但只能在陣列中那些玩家擲出相同骰子的部分。

例如:

Player[] getPlayerOrder() { 
    Player[] players = playerMap.values().toArray(new Player[playerMap.size()]); 
    getPlayerOrder(players, 0, players.length); 
    return players; 
} 

void getPlayerOrder(Player[] players, int start, int end) { 
    // Get all players between players[start] (inclusive) and 
    // players[end] (exclusive) to re-roll the dice. 
    for (int i = start; i < end; ++i) { 
    // Logic to roll dice... 
    players[i].setDiceNumberRolled(...); 
    } 

    // Sort this portion of the array according to the number rolled. 
    Arrays.sort(players, start, end, new Comparator<Player>() { 
    @Override public int compare(Player a, Player b) { 
     return Integer.compare(b.getDiceNumberRolled(), a.getDiceNumberRolled()); 
    } 
    }); 

    // Look for players who rolled the same number. 
    int i = start; 
    while (i < end) { 
    // Try to find a "run" of players with the same number. 
    int runStart = i; 
    int diceNumberRolled = players[runStart].getDiceNumberRolled(); 
    ++i; 
    while (i < end && players[i].getDiceNumberRolled() == diceNumberRolled) { 
     ++i; 
    } 

    if (i - runStart > 1) { 
     // We have found more than one player with the same dice number. 
     // Get all of the players with that dice number to roll again. 
     getPlayerOrder(players, runStart, i); 
    } 
    } 
} 
+0

這是一種全新的觀察方式,我現在正在嘗試實施並進行測試。首先,在附註中,當我使用第二行代碼作爲'Player [] players = ModelConstants.PLAYERS.values()。toArray();''public static Map PLAYERS = new HashMap <>();',我得到一個錯誤來投射PLAYERS.values()。toArray()來鍵入Player [],爲什麼會這樣呢? – KOB

+0

哦,這是因爲['Collection.toArray()'](https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#toArray())返回Object [] '。呼叫另一個過載,例如'playerMap.values()。toArray(new Player [playerMap.size()])''。 –

0

我學嘗試將讓大家擲骰子,只是它沒有存儲任何類型。然後檢查重複項,並讓具有相同數字的玩家再次滾動。之後當每個玩家滾動並且不再複製時,只需使用一些排序算法即可。最簡單的一個就是BubbleSort,因爲排序時你沒有時間問題。看看這個enter link description here

+0

這個解決方案的問題在於,如果一個玩家擲出最高數量5,然後兩個玩家擲出一個4.兩個玩家4現在再次滾動,其中一個滾動一個6,另一個2.現在,在第二輪擲出6的玩家在整場比賽中處於第一位,而他應該在第二位(在初始擲出5的玩家之後) – KOB

2

有兩種方法可以解決這個問題。

1)簡單的事情是忘記「擲骰子」。爲每個玩家生成32個隨機(一個int)位並用於排序。如果他們碰巧選擇了任何你想要的球員。這將是非常罕見的,它並不重要(40億中有1個數字是相同的)。

2)如果你想堅持擲骰子。創建一個獲取球員列表的函數,在內部滾動骰子並返回正確排序的骰子。每當你有相同的名次時,請與等於的球員創建一個較小的名單,並遞歸地調用該函數,以便爲您提供這些球員的排序。當它返回時將其複製到結果中並繼續。你可以從數學上證明,這是不可能的(不可能),這將導致無限循環。

+0

A骰子模擬必須用於選項1不能使用。我編輯了我原來的帖子,並提供了一個類似於您的選項2的可能解決方案。這對您有什麼樣的看法? – KOB

+0

@CornOnTheKob是的,我認爲這看起來不錯。 – Sorin

1

要整理東西,嘗試創建一個單獨的方法爲每個「動作」,你需要 - 滾動骰子一個方法,另外找到重複的,而另一個排序。這裏的步驟:

  1. 擲骰子所有玩家,存放在List
  2. 找到重複
  3. 對於所有重複,重複步驟1和2,直到沒有重複被發現。
  4. 排序玩家。

3種方法。 4個步驟。邏輯上執行你需要的。

public int rolldice(Player player); 
public List<Player> findDuplicates (List<Player> players); 
public void sortPlayers(List<Player> players); 

您可以使用這3種方法。希望這會有所幫助

+0

感謝@Andy Turner,我對我的解決方案的工作方式非常滿意,但不滿意它的繁瑣難度。這絕對有助於清理事情! – KOB

0

迭代解決方案並不像我第一次想到的那麼簡單!

我最初發布了一個解決方案,使用基本詮釋數組玩家&骰子。 但是這對代碼來說是不必要的複雜。更容易使用複合類,PlayerDice。根據爲PlayerDice定義的compareTo(。)方法,可以使用Arrays.sort(...)方法對數組的所需範圍對數組進行排序。

當一組玩家綁定在同一個骰子上時,你必須小心地存儲結束索引。我把這些東西放進了一個堆棧中 - 除了整團隊員在滾降時擲出相同的骰子。

總體完成條件是當沒有關係並且起始索引大於結束索引時。

package snakesAndLadders; 

import java.util.Arrays; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.Stack; 

public class PlayOrderTest6 
{ 
    private final static int numPlayers = 16; 
    private PlayerDice[] playersDice = new PlayerDice[numPlayers]; 

    /** Composite class to enable sorting of players according to dice they throw.*/ 
    public static class PlayerDice implements Comparable<PlayerDice> 
    { 
     private int player; 
     private int dice; 

     public PlayerDice(int player, int dice) 
     { 
      this.player = player; 
      this.dice = dice; 
     } 

     public int getPlayer() 
     { 
      return player; 
     } 

     public void setPlayer(int player) 
     { 
      this.player = player; 
     } 

     public int getDice() 
     { 
      return dice; 
     } 

     public void setDice(int dice) 
     { 
      this.dice = dice; 
     } 

     public String toString() 
     { 
      return "Player# " + player + " | Dice: " + dice; 
     } 


     @Override 
     public int compareTo(PlayerDice pd) 
     { 
      // Default comparison is on basis of dice value descending: 
      return pd.getDice() - this.dice; 
     } 

} 

    /** Main method basically runs the getPlayOrder(.) method for the number of 
    players involved in this game, i.e. the attribute players.     */ 
    public static void main(String[] args) 
    { 
     int[] playOrder = new int[numPlayers]; // Holds final play order 

     // Initialize playerDice array and give each player a number between 1 .. players : 
     for(int i = 0; i < numPlayers; i++) 
     { 
      playersDice[i] = new PlayerDice(i + 1, 1); 
      playOrder[i] = i + 1; 
     } 
     // Generate the order of play by rolling dice & re-rolling for tied players : 
     getPlayOrder(playersDice); 
     // Extract play order : 
     for(int i = 0; i < numPlayers; i++) 
      playOrder[i] = playersDice[i].getPlayer(); 
     System.out.println("\n\nFinal Player Order is : " + Arrays.toString(playOrder)); 
    } 


    public static void getPlayOrder(PlayerDice[] p) 
    { 
     int start = 0,         // Start index of unsorted PlayerDice array 
      end = numPlayers - 1;      // End index of unsorted PlayerDice array 
     Integer[] sdInds = new Integer[2];    // For start & end indices of first group of tied players. 
     Stack<Integer> endStack = new Stack<Integer>(); // Holds end index when a dice-roll to sort a tie produces another tie. 

     while (start < numPlayers && end > start) 
     { 
      // Roll dice for players in index range between start & end : 
      for(int i = start; i < end + 1; i++) 
       p[i].setDice((int) (6 * Math.random() + 1)); 

      // Output player/dice values : 
      System.out.print("\n\nPlayer Order:\t\t"); 
      for(int i = 0; i < numPlayers; i++) 
       System.out.print(p[i].getPlayer() + "\t"); 
      System.out.print("\nDice Rolled:\t\t"); 
      for(int i = 0; i < numPlayers; i++) 
       System.out.print(p[i].getDice() + "\t"); 

      // Sort players between start & end indices by their dice number descending : 
      Arrays.sort(p, start, end + 1); // Uses PlayerDice compareTo(.) method, i.e. by dice value descending. 

      // Output player/dice values : 
      System.out.print("\n\nSorted Player Order:\t"); 
      for(int i = 0; i < numPlayers; i++) 
       System.out.print(p[i].getPlayer() + "\t"); 
      System.out.print("\nSorted Dice Rolled:\t"); 
      for(int i = 0; i < numPlayers; i++) 
       System.out.print(p[i].getDice() + "\t"); 

      // Find first group of players (from leftmost element of p) on the same dice : 
      sdInds[0] = -1; 
      sdInds[1] = -1; 
      findTiedPlayers(p, start, end, sdInds); 
      System.out.print("\nsdInds[0]: " + sdInds[0]); 
      System.out.print("\nsdInds[1]: " + sdInds[1]); 
      // Where tied players are found ... 
      if (sdInds[0] != -1) 
      { // Re-set start and end indices and re-roll dice to sort the tied group : 
       start = sdInds[0]; 
       if (sdInds[1] != end) 
       { 
        endStack.push(end); // Keeps priority of tied players over those on lower first dice roll 
        end = sdInds[1]; 
       } 

      } 
      else // Where no ties, reset start & end indices till ties found or all players sorted. 
       while (sdInds[0] == -1 && end >= start) 
       { 
        start = end + 1; 
        if(!endStack.isEmpty()) 
         end = endStack.pop(); 
        else 
         break;  // When no more players to be checked ! 
        // Get indices of first tied group in remaining players : 
        sdInds[0] = -1; // Initializing start- ... 
        sdInds[1] = -1; // ... and end-indices before tie search. 
        findTiedPlayers(p, start, end, sdInds); 
        if (sdInds[0]!= -1) // If ties found, adjust start & end indices before tie-breaker roll 
        { 
         start = sdInds[0]; 
         endStack.push(end); // Store old end index 
         end = sdInds[1]; 
        } 
       } 

      System.out.print("\nstart: " + start); 
      System.out.print("\nend: " + end); 
     } 
    } 

    /** Method to find first group of tied players in an array holding player & dice data. 
    * @param pt - a PlayerDice array; 
    * @param st - an int holding the start index of the range of pt being examined; 
    * @param en - an int holding the end index of the range of pt being examined; 
    * @param tInds - an int array holding the start & end index of the 

first group of tied players. 
This parameter also acts as a return parameter since it's a reference type, 
tInds[0] holding the index of the first tied player and tInds[1] the index of 
the last. Where no ties are found, both tInds elements retain their received 
values of -1 which signifies no ties. */ 
    public static void findTiedPlayers(PlayerDice[] pt, int st, int en, Integer[] tInds) 
    { 
     for(int i = st; i < en; i++) 
     { 
      for(int j = i + 1; j < en + 1; j++) 
       if (pt[i].getDice() == pt[j].getDice()) 
       { 
        tInds[0] = i; 
        tInds[1] = j; 
       } 
      if (tInds[0] != -1)  // First group of tied players found ... 
       break;    // ... finish search ! 
     } 
    } 
} 

OUTPUT:

Player Order:  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 
Dice Rolled:  4 4 6 5 2 1 3 6 1 3 4 4 1 2 1 3 

Sorted Player Order: 3 8 4 1 2 11 12 7 10 16 5 14 6 9 13 15 
Sorted Dice Rolled: 6 6 5 4 4 4 4 3 3 3 2 2 1 1 1 1 
sdInds[0]: 0 
sdInds[1]: 1 
start: 0 
end: 1 

Player Order:  3 8 4 1 2 11 12 7 10 16 5 14 6 9 13 15 
Dice Rolled:  5 6 5 4 4 4 4 3 3 3 2 2 1 1 1 1 

Sorted Player Order: 8 3 4 1 2 11 12 7 10 16 5 14 6 9 13 15 
Sorted Dice Rolled: 6 5 5 4 4 4 4 3 3 3 2 2 1 1 1 1 
sdInds[0]: -1 
sdInds[1]: -1 
start: 3 
end: 6 

Player Order:  8 3 4 1 2 11 12 7 10 16 5 14 6 9 13 15 
Dice Rolled:  6 5 5 2 6 1 1 3 3 3 2 2 1 1 1 1 

Sorted Player Order: 8 3 4 2 1 11 12 7 10 16 5 14 6 9 13 15 
Sorted Dice Rolled: 6 5 5 6 2 1 1 3 3 3 2 2 1 1 1 1 
sdInds[0]: 5 
sdInds[1]: 6 
start: 5 
end: 6 

Player Order:  8 3 4 2 1 11 12 7 10 16 5 14 6 9 13 15 
Dice Rolled:  6 5 5 6 2 4 4 3 3 3 2 2 1 1 1 1 

Sorted Player Order: 8 3 4 2 1 11 12 7 10 16 5 14 6 9 13 15 
Sorted Dice Rolled: 6 5 5 6 2 4 4 3 3 3 2 2 1 1 1 1 
sdInds[0]: 5 
sdInds[1]: 6 
start: 5 
end: 6 

Player Order:  8 3 4 2 1 11 12 7 10 16 5 14 6 9 13 15 
Dice Rolled:  6 5 5 6 2 5 1 3 3 3 2 2 1 1 1 1 

Sorted Player Order: 8 3 4 2 1 11 12 7 10 16 5 14 6 9 13 15 
Sorted Dice Rolled: 6 5 5 6 2 5 1 3 3 3 2 2 1 1 1 1 
sdInds[0]: -1 
sdInds[1]: -1 
start: 7 
end: 9 

Player Order:  8 3 4 2 1 11 12 7 10 16 5 14 6 9 13 15 
Dice Rolled:  6 5 5 6 2 5 1 2 6 3 2 2 1 1 1 1 

Sorted Player Order: 8 3 4 2 1 11 12 10 16 7 5 14 6 9 13 15 
Sorted Dice Rolled: 6 5 5 6 2 5 1 6 3 2 2 2 1 1 1 1 
sdInds[0]: -1 
sdInds[1]: -1 
start: 10 
end: 11 

Player Order:  8 3 4 2 1 11 12 10 16 7 5 14 6 9 13 15 
Dice Rolled:  6 5 5 6 2 5 1 6 3 2 4 6 1 1 1 1 

Sorted Player Order: 8 3 4 2 1 11 12 10 16 7 14 5 6 9 13 15 
Sorted Dice Rolled: 6 5 5 6 2 5 1 6 3 2 6 4 1 1 1 1 
sdInds[0]: -1 
sdInds[1]: -1 
start: 12 
end: 15 

Player Order:  8 3 4 2 1 11 12 10 16 7 14 5 6 9 13 15 
Dice Rolled:  6 5 5 6 2 5 1 6 3 2 6 4 5 4 5 5 

Sorted Player Order: 8 3 4 2 1 11 12 10 16 7 14 5 6 13 15 9 
Sorted Dice Rolled: 6 5 5 6 2 5 1 6 3 2 6 4 5 5 5 4 
sdInds[0]: 12 
sdInds[1]: 14 
start: 12 
end: 14 

Player Order:  8 3 4 2 1 11 12 10 16 7 14 5 6 13 15 9 
Dice Rolled:  6 5 5 6 2 5 1 6 3 2 6 4 6 2 5 4 

Sorted Player Order: 8 3 4 2 1 11 12 10 16 7 14 5 6 15 13 9 
Sorted Dice Rolled: 6 5 5 6 2 5 1 6 3 2 6 4 6 5 2 4 
sdInds[0]: -1 
sdInds[1]: -1 
start: 16 
end: 15 

Final Player Order is : [8, 3, 4, 2, 1, 11, 12, 10, 16, 7, 14, 5, 6, 15, 13, 9] 
+0

感謝編輯,科迪。 – Trunk