在Django中建模瑞士制比赛

4 投票
2 回答
1861 浏览
提问于 2025-04-15 11:30

我正在尝试创建一些模型,用来表示一种叫做瑞士赛的比赛,这种比赛会有多个回合。在每一回合中,所有的选手都会和其他选手配对,除非有一个选手是单独的,这种情况下他会被称为“轮空”。

我需要记录每对选手的比赛结果,也就是哪个选手赢了。此外,我还想能够方便地查找所有曾经和某个选手对战过的选手。

一些明显的事情:

class Tournament(models.Model):
    name = models.CharField(max_length=80)

class Player(models.Model):
    name = models.CharField(max_length=80)

一开始我打算创建一个叫“TournamentPairing”的类,大概是这样的:

class TournamentPairing(models.Model):
    tournament = models.ForeignKey(Tournament)
    round = models.IntegerKey()
    player1 = models.ForeignKey(Player)
    player2 = models.ForeignKey(Player, null = True) # In case of a bye, this is None.
    outcome = models.CharField(max_length=1) # player1 wins, loses, bye, or tie

但是这样感觉有点不太靠谱,尤其是有时候player2会是None(空值)这一点。而且,我觉得这样不太方便查找(因为我们要找的选手可能在player1或player2的位置上)。

有没有更好的办法?我觉得我在django方面的经验不足,让我找不到合适的解决方案。

2 个回答

1

我觉得你只需要一个玩家列表,不用把它分成玩家1和玩家2,这些可以在每轮开始时再设置。

你的玩家类可以包含一个他们曾经对战过的玩家列表,列表中的最后一个玩家就是他们当前面对的对手。当你选择下一个要对战的玩家时,就把这个玩家加到列表里。

class Player(Models.model):
  name = models.CharField(max_length=80)
  playersPlayed = []

在每一轮中,对于一个玩家,只需遍历所有玩家的全局列表,看看这个玩家是否在他们已经对战过的列表中。如果没有找到,那这个人就可以参赛,然后把他加到列表里。如果在某一轮找不到合适的玩家,那么这个玩家就会被安排休息。

我希望这至少能给你一个起点。

5

你可以对你的TournamentPairing类进行一些调整,让它更关注“轮次”,这样在查询时会更方便。

可选项有:

CHOICES = (

('n', '正常'),

('b', '轮空'),

)

class Round(models.Model):        
    number = models.IntegerField()
    round_type = models.CharField(max_length=1, default="n", choices=CHOICES)
    tournament = models.ForeignKey(Tournament)
    players = models.ManyToManyField(Player, related_name="rounds")
    winner = models.ForeignKey(Player, null=True, related_name="round_winner") 

如果出现平局,可以把赢家字段指向一个叫“平局”的玩家。

然后,关于你的搜索条件,如果你想查看某个玩家对战过的所有玩家,可以使用:

# grab a player 
p = Player.objects.get(name='Tom')

# see what rounds this player played in
rounds_played = p.rounds.all()

# who did this player play against?
[r.players for r in rounds_played]

# to see all rounds this player won
p.round_winner.all()

撰写回答