Skip to content

Instantly share code, notes, and snippets.

@eliotb
Created April 17, 2018 21:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eliotb/82d970d48f283ae4b01ff8940e05734f to your computer and use it in GitHub Desktop.
Save eliotb/82d970d48f283ae4b01ff8940e05734f to your computer and use it in GitHub Desktop.
import logging
import string
def is_yes(prompt="", default=True):
"""Ask user to enter Y or N in response to a prompt.
returns True if answer is Y, Falseif N or default if answer is empty"""
if default:
prompt += " [Y/n]"
else:
prompt += " [y/N]"
while True:
response = input(prompt).upper()
if len(response) == 0:
return default
elif response.startswith("Y"):
return True
elif response.startswith("N"):
return False
else:
print("Please enter Y or N")
def input_positive(prompt="Enter a number:"):
"""Get a number from the user. Keep retrying until one is entered"""
while True:
response = input(prompt)
try:
num = int(response)
except ValueError:
print("Oops, please enter a number")
if num >= 0:
break
else:
print("Please enter a positive number")
return num
def print_player_list(pl, title="Player Pool"):
print()
if title is not None:
print(title)
if not pl:
print("[empty]")
for i, n in enumerate(pl):
print(i + 1, n)
def print_team(team):
print_player_list(team[1], 'Team: ' + team[0])
def add_players(players):
"""Add players to the player pool"""
while True:
while True:
player = input("Name of player to add (empty to finish): ")
if player in players:
print("There is already a player with that name."
" Try a different one.")
else:
break
if player == "":
break
players.append(player)
return players
def remove_players(players, num_teams):
"""Remove a specified number of players from the member_list
"""
# This is simpler than add_players, because there is aready a player
# list to validate input against
# Ensure we retain at least one player per team!
player = "nobody"
while len(players) > num_teams and player != "":
players, player = select_player(
players,
"Remove a player (empty to finish)",
allow_empty=True)
return players
def edit_player_list(players, num_teams):
"""Allow user to add and remove players, ensuring that the final number
of players available is a multiple of the number of teams.
"""
while True:
print("Player list must finish up with a multiple of %d players"
" so the teams can be even." % num_teams)
players = add_players(players)
players = remove_players(players, num_teams)
print_player_list(players)
num_players = len(players)
# Must have same number of players per team
if num_players % num_teams == 0:
break
print("Player list not multiple of %d"
" Add or remove some more players:" % num_teams)
assert(num_players % num_teams == 0)
return players
def select_player(players, prompt="", remove=True, allow_empty=False):
"""Prints the player list, then
asks the user to select a player by number or name.
returns remaining player list, selected player name.
If remove==true, selected player is removed from players list
If allow_empty==true, and empty player name can be returned, the
player list is unchanged.
"""
if len(players) > 1:
while True:
print_player_list(players)
response = input(
(prompt +
". Choose a player by name or number: ")
)
if response == "" and allow_empty:
return players, ""
if response in players:
selected_player = response
break
else:
try:
selected_player = players[int(response) - 1]
break
except (IndexError, ValueError) as e:
pass
print("\n*** Oops, that player is not in the list. Try again. ***")
else:
selected_player = players[0]
print("And finally", selected_player, "goes to", prompt)
logging.debug("Selected %s", selected_player)
if remove:
players.remove(selected_player)
return players, selected_player
def select_players(players, teams):
"""The teams take turns to choose players until there are none left.
Returns list of teams
"""
print("Ok teams - let's begin selecting players")
while len(players):
for team in teams:
players, selected_player = select_player(players, "Team " + team[0])
team[1].append(selected_player)
print_player_list(team[1], "Team " + team[0])
return teams
def get_team_name(prompt, teams):
while True:
team_name = input(prompt)
if len(team_name) < 1:
print("Oops, you must enter some letters")
elif (team_name[0] in string.whitespace or
team_name[0] not in string.printable):
print("Oops, name must start with something sensible")
elif team_name in [team[0] for team in teams]:
print("Oops, that name has already been taken")
else:
break
return team_name
def initialise_teams(num_teams):
"""Initialise team list. Each team is a tuple (team_name, member_list)
The member list starts off empty.
"""
teams = []
for i in range(num_teams):
team_name = get_team_name(
"What is the name of team#%d? " % (i + 1), teams)
teams.append((team_name, []))
return teams
def build_teams(players, num_teams):
teams = initialise_teams(num_teams)
teams = select_players(players, teams)
return teams
def game(players=[], num_teams=0):
print_player_list(players, "Initial Player Pool")
if not num_teams:
num_teams = input_positive("How many teams do you want to make? ")
players = edit_player_list(players, num_teams)
num_players = len(players)
print("There are %d players to sort into %d teams of %d ..." %
(num_players, num_teams, num_players / num_teams))
teams = build_teams(players, num_teams)
print('=' * 40)
print("\nThe teams have been selected!")
for t in teams:
print_team(t)
if __name__ == '__main__':
logging.basicConfig(level=logging.WARNING)
# Note: The number of players must be even. Two per row makes this clear
players = [
"Thor", "Odin",
"Frigg", "Balder",
"Tyr", "Freyr",
"Freyja", "Loki",
"Bragi", "Forsetti",
"Jones", "Mozart"
]
game(players, num_teams=2)
#game([])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment