2016-09-15 79 views
2

我已經創建了一個模擬團隊間整個足球賽季的程序。用戶輸入團隊的姓名和技能等級。然後它使用泊松分佈來比較他們的技能評分並計算兩隊之間的結果。每場比賽後,相關名單會更新:獲勝隊獲得3分(如果是第三支隊伍,那麼索引[2]的價值增加3)。我有一個單獨的名單,積分,進球,失球,比賽和比賽失敗(注意 - 有沒有更高效的方式來做這件事?) 我在賽季結束時遇到了問題:每個團隊都按照團隊最初輸入的順序輸出數據。這是通過使用「名稱」列表中的團隊名稱與「點數」列表中的點數相同的索引來完成的。所以問題是,如果我點「點」列表,那麼他們將與他們的名字不同步。我希望這是有道理的,但這裏是一個賽季的示例輸出:在Python中生成排序的足球聯盟表

Enter number of teams in league: 4 
Enter team 1 name: a 
Enter team 2 name: b 
Enter team 3 name: c 
Enter team 4 name: d 
Enter a skill: 1 
Enter b skill: 3 
Enter c skill: 5 
Enter d skill: 8 
=========================================== 
a's home games: 
=========================================== 

a 2 - 0 b 

a 0 - 2 c 

a 0 - 0 d 

=========================================== 
b's home games: 
=========================================== 

b 2 - 3 a 

b 1 - 0 c 

b 0 - 0 d 

=========================================== 
c's home games: 
=========================================== 

c 1 - 0 a 

c 1 - 0 b 

c 0 - 1 d 

=========================================== 
d's home games: 
=========================================== 

d 4 - 0 a 

d 2 - 0 b 

d 0 - 0 c 

Final table: 
a    Skill: 1  Points: 7  For: 5  Against: 9  Goal difference: -4 Wins: 2  Draws: 1  Losses: 3  
b    Skill: 3  Points: 4  For: 3  Against: 8  Goal difference: -5 Wins: 1  Draws: 1  Losses: 4  
c    Skill: 5  Points: 10 For: 4  Against: 2 Goal difference: 2  Wins: 3  Draws: 1  Losses: 2  
d    Skill: 8  Points: 12 For: 7  Against: 0 Goal difference: 7  Wins: 3  Draws: 3  Losses: 0  
[4, 7, 10, 12] 

所以我現在想要做的是能夠打印在降分才能最終排名表,而不是它的方式現在只按索引順序打印。

很抱歉,如果這是措辭很差 - 我的程序代碼可能會更加有用的話那就是:

import math 
import random 
#Lambda value in Poisson distribution for higher rated team 
lambOne = 1.148698355 
#Lambda value for lower rated team 
lambTwo = 0.8705505633 

#Poisson distribution calculating goals scored by the home team 
def homeMatch(homeRating,awayRating): 
    global lambOne 
    global x 
    global y 
    if x == y: 
     raise ValueError 
    else: 
     lamb = lambOne**(int(homeRating)-int(awayRating)) 
     homeScore = 0 
     z = random.random()  
     while z > 0: 
      z = z - ((lamb**homeScore * math.exp(lamb * -1))/(math.factorial(homeScore))) 
      homeScore += 1 
     return (homeScore-1) 

#Poisson distribution calculating goals scored by away team 
def awayMatch(homeRating,awayRating): 
    global lambTwo 
    global x 
    global y 
    #This check is to stop a team playing itself 
    if x == y: 
     raise ValueError 
    else: 
     lamb = lambTwo**(int(homeRating)-int(awayRating)) 
     awayScore = 0 
     z = random.random()  
     while z > 0: 
      z = z - ((lamb**awayScore * math.exp(lamb * -1))/(math.factorial(awayScore))) 
      awayScore += 1 
     return (awayScore-1) 

#Selecting number of teams in league 
leagueSize = int(input("Enter number of teams in league: ")) 

#Initialising empty lists 
teamNames = [] 
teamSkill = [] 
teamPoints = [] 
teamFor = [] 
teamAgainst = [] 
teamWins = [] 
teamDraws = [] 
teamLosses = [] 

#Populating lists with number of zeroes equal to the number of teams (one zero for each) 
for x in range(leagueSize): 
    teamPoints += [0] 
    teamFor += [0] 
    teamAgainst += [0] 
    teamWins += [0] 
    teamDraws += [0] 
    teamLosses += [0] 

#Entering names and skill ratings for each team 
for i in range(leagueSize): 
    teamNames += [input("Enter team "+str(i+1)+" name: ")] 
for j in range(leagueSize): 
    teamSkill += [input("Enter "+teamNames[j]+" skill: ")] 

#Initialising variables 
homeScore = 0 
awayScore = 0 

#The season begins - each team plays all of its home games in one go 
for x in range(leagueSize): 
    #input("Press enter to continue ") 
    print("===========================================") 
    print(teamNames[x]+"'s home games: ") 
    print("===========================================\n") 
    for y in range(leagueSize): 
     error = 0 
     try: 
      homeScore = homeMatch(teamSkill[x],teamSkill[y]) 
     #Skipping a game to stop a team playing itself 
     except ValueError: 
      pass 
      error += 1 
     try: 
      awayScore = awayMatch(teamSkill[x],teamSkill[y]) 
     except ValueError: 
      pass 
     if error == 0: 
      #Updating lists 
      print(teamNames[x],homeScore,"-",awayScore,teamNames[y],"\n") 
      teamFor[x] += homeScore 
      teamFor[y] += awayScore 
      teamAgainst[x] += awayScore 
      teamAgainst[y] += homeScore 
      if homeScore > awayScore: 
       teamWins[x] += 1 
       teamLosses[y] += 1 
       teamPoints[x] += 3 
      elif homeScore == awayScore: 
       teamDraws[x] += 1 
       teamDraws[y] += 1 
       teamPoints[x] += 1 
       teamPoints[y] += 1 
      else: 
       teamWins[y] += 1 
       teamLosses[x] += 1 
       teamPoints[y] += 3 
     else: 
      pass 

#Printing table (unsorted) 
print("Final table: ") 
for x in range(leagueSize): 
    #Lots of formatting 
    print(teamNames[x]+(15-len(teamNames[x]))*" "+" Skill: "+str(teamSkill[x])+(5-len(str(teamSkill[x])))*" "+" Points: "+str(teamPoints[x])+(5-len(str(teamPoints[x])))*" "+" For: "+str(teamFor[x])+(5-len(str(teamFor[x])))*" "+" Against: "+str(teamAgainst[x])+(5-len(str(teamPoints[x])))*" "+" Goal difference: "+str(teamFor[x]-teamAgainst[x])+(5-len(str(teamFor[x]-teamAgainst[x])))*" "+" Wins: "+str(teamWins[x])+(5-len(str(teamWins[x])))*" "+" Draws: "+str(teamDraws[x])+(5-len(str(teamDraws[x])))*" "+" Losses: "+str(teamLosses[x])+(5-len(str(teamLosses[x])))*" ") 
teamPoints.sort() 
print(teamPoints) 

對不起,這是很長,可能措辭不當,效率不高,但我希望有人會能夠幫助我!非常感謝:)

+1

您應該考慮使用不同的數據結構。而不是試圖保持3個同步列表,你可以保留所有的數據字典字典:'{'team_name':{'wins':1,'draws':1,'loses':0,'points':4 }}'等 – DeepSpace

+0

啊好吧,這是一個好主意,謝謝! –

回答

3

雖然您目前的方法(幾乎不可行),但卻很難(例如)更改您想要存儲的有關每個團隊的信息。您可以考慮定義一個Team類,其中的每個實例都存儲有關特定團隊的所有信息。

class Team: 
    def __init__(self, name, skill): 
     self.name = name 
     self.skill = skill 
     self.points = self.goals_for = self.goals_against = \ 
        self.wins = self.draws = self.losses = 0 

這可讓您通過傳遞一個名字和技能水平,以這種方式創建一個新的團隊對象:

t1 = Team("Bradford City", 3) 

T1現在有屬性nameskill與給定值,以及其他值(points,goals_for等)的值都爲零。

然後你就可以很容易地初始化聯賽:

league_size = 4 
teams = [] 
for _ in range(league_size): 
    teams.append(Team(input("Name of team "+str(_)+": "), 
         int(input("Team "+str(_)+"'s skill level: "))) 

然後打印各隊的技術水平,你可以遍歷列表:

for team in teams: 
    print(team.name, team.skill) 

我希望這給你一些想法你的方法如何被簡化。您的比賽功能也可以將球隊當作參數,並根據計算出的結果直接修改球隊對象。

要得到你想要的答案,一旦你有團隊的名單,你可以打印出來的點數來分類的,他們持有相當容易:

for team in sorted(teams, key=lambda t: t.points): 
    print(team.name, team.skill, team.points, ...) 

據我所看到的,沒有你的global聲明是必要的(如果名稱沒有在本地定義,Python將查找全局名稱以滿足引用)。除此之外,一個函數的輸入通常應該作爲參數來傳遞,而從環境中獲取東西是一種相當糟糕的做法!

我希望這足以讓您重寫您的程序更加易於理解。作爲一名初學者,我會說你已經做得非常好,可以將這一切做得更好。接下來的步驟將會讓你興奮!

以後添加:您的所有播放都可以更容易編程的結果:

for home in teams: 
    for away in teams: 
     if home is away: # Teams don't play themselves 
      continue 
     play_match(home, away) 

play_match功能會模擬比賽和調整各支球隊的統計。當然你可以用另一行模擬客場比賽

  play_match(away, home) 

雖然我不確定你的算法是否對稱。

+0

非常感謝您提供這樣詳細而有用的答案!我會盡力實現所有這些儘快!在計算機科學課上我們沒有學過類,所以我從來沒有嘗試過。但是,看起來這會使程序簡化很多!哈哈謝謝你,這個程序從第一個版本中得到了很大改進,這個版本有數百行無效率......無論如何,非常感謝你:) –

+0

最好等到了解類,直到你發現其他方式代表一個問題可能有缺點。你當然知道,在黑桃! – holdenweb