简体   繁体   中英

Java generating random player pairs

my problem is generating random player pairs with equal number of games, but limiting number of games, so that all players don't have to play with each other.

Think of it as a chess game, where random players are set to games, but every player don't have to play with all the players (it would just take too much time) but they all must have a equal number of games to competition be fair.

So far I generated a unique pairs for game, but all players must play everyone, that takes just too much time. I know that code isn't pretty but it must run once a month, to generate pairs:

    @RequestMapping("/voistlus/{id}")
    public String newGame(Model model, @PathVariable Long id) {
    Stage stage = stageService.findOneById(id);
    if (gameService.findByStage(stage).isEmpty()) {
        List<Paar> paars = paarService.getAllPaar();
        List<Game> pairs = new ArrayList<Game>();
        for (Paar one : paars) {
            for (Paar two : paars) {
                if (!one.equals(two)) {
                    Game newPair = new Game();
                    newPair.setPaar1(one);
                    newPair.setPaar2(two);
                    if (!pairs.contains(newPair)) {
                        if (pairs.isEmpty()) {
                            pairs.add(newPair);
                            newPair.setStage(stage);
                            gameService.save(newPair);
                        } else {
                            boolean exists = false;
                            for (Game game : pairs) {
                                if (game.getPaar1().equals(two) && game.getPaar2().equals(one)) {
                                    exists = true;
                                }
                            }
                            if (!exists) {
                                pairs.add(newPair);
                                newPair.setStage(stage);
                                gameService.save(newPair);
                            }
                        }
                    }
                }
            }
        }
    }
    model.addAttribute("pairs", gameService.findByStage(stage));
    return "newGame";
}

Consider the graph where each player is a vertex, and an edge between players denotes a game between those players. What we want to do is find cycles in this graph, where each cycle goes through all players, ie we want to find Hamiltonian cycles in this graph.

In general, finding out if a graph has a Hamiltonian cycle is NP-complete. However, since the graph we consider in this problem is a complete graph (each vertex has an edge to each other vertex), this problem is quite easy.

We can do this with the following pseudocode

Let V be the empty set
Let E be the empty set

Let init be a random vertex
Add init to V

While V does not contain all players
    Select a random vertex R that is not in V
    Add R to V
    Add the edge (init - R) to E
    Let init = R
End

E now contains the set of games to be played

By doing this multiple times, you will be able to generate multiple hamiltonian cycles, each cycle being a set of games where each player plays against exactly two other different players.

This algorithm has one major disadvantage, which is that it allows the same game to occur multiple times. (It is possible that player 1 and player 2 have to play against each other more than once.)

If we want to avoid this, we have to remove the cycle we found from the graph before searching the next cycle. Doing this however makes determining if there is another cycle, and thus finding it, NP-complete again.

If you wish to solve this, a good starting point would be here and here .

How about iterating over the number of games and each time picking random players?

    int numberOfGames = 10;
    List<Paar> paars = paarService.getAllPaar();
    for (int game = 0; game < numberOfGames; game++) {
        // for each "game day", shuffle the list of players
        Collections.shuffle(paars);
        for (int playerIndex = 0; playerIndex < paars.size(); playerIndex+=2) {
            Game newPair = new Game();
            newPair.setStage(stage);
            newPair.setPaar1(paars.get(playerIndex));
            newPair.setPaar2(paars.get(playerIndex+1));
            gameService.save(newPair);
        }
    }

Downside is that you can't avoid the same player pair playing multiple times against each other;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM