2016-03-03 10 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