# 450 line Python card game

I have just finished a big project in Python. It is a card game.

Here are the rules:

There are 30 cards in the deck. Before the game starts, the deck is shuffled. Each card has a colour (red, black or yellow) and a number (1-10).

There are 15 rounds in the game. In each round both players take 1 card from the top of the deck.

The winner of each round depends on the colour of the card.

Red beats black. Black beats yellow. Yellow beats red.

If both cards have the same colour than the winner is the card with the highest number.

If both cards have the same colour and the same number then that round is a draw.

The winner of the game is the person with the most cards.

from random import shuffle
from time import sleep
from random import randint

from FileFunctions import *

# Card index constants
COLOUR = 0
NUMBER = 1

# Colour constants
RED = 'red'
BLACK = 'black'
YELLOW = 'yellow'

# Player constants
DRAW = 'draw'
PLAYER1 = '1'
PLAYER2 = '2'

def main():

print('=======================================\n')

print('1 - Play game')
print('2 - Create new deck')
print('3 - Change the speed of the game')
print('5 - Quit')

print('\n=======================================')

play_game()
input('Press enter to continue.')

input('Press enter to continue.')

change_speed()
input('Press enter to continue.')

input('Press enter to continue.')

print('Goodbye.')

else:

# The passcode (for now) is 'Python'.

valid = False

while not valid:

print('Welcome.')
valid = True
else:
print('Incorrect passcode.')

print('\n\n')

# Returns a tuple containing a colour and a number
def new_card(colour):
return (colour, randint(1, 10))

# Creates a new random deck
def new_random_deck():

deck = []

for i in range(10):
deck.append(new_card(RED))
deck.append(new_card(BLACK))
deck.append(new_card(YELLOW))

write_deck(deck)

# Returns the name of the winner of the game and the winning cards as a tuple
def play_game():

print('\n\n')

valid = False

while not valid:
player1_name = input('Enter player 1\'s name: ')
if '_' in player1_name:
print('Names cannot contain underscores.')
else:
valid = True

valid = False

while not valid:
player2_name = input('Enter player 2\'s name: ')
if '_' in player2_name:
print('Names cannot contain underscores.')
elif player2_name == player1_name:
print('Player 1 and player 2 must have different names.')
else:
valid = True

play_again = True

while play_again:

player1_cards = []
player2_cards = []

# Read the deck from the deck file.

shuffle(deck)

game_round = 1

print('\n\n')

while len(deck) > 0:

sleep(round_delay)

player1_card = deck[-1]
player2_card = deck[-2]

deck.pop()
deck.pop()

print('ROUND', game_round, '\n')

display_cards(player1_card, player2_card)

winner = compare_cards(player1_card, player2_card)

if winner == PLAYER1:
print('\nWinner:', player1_name)
elif winner == PLAYER2:
print('\nWinner:', player2_name)
else:
print('\nWinner: draw')

print('\n\n')

if winner == PLAYER1:
player1_cards.append(player1_card)
player1_cards.append(player2_card)

elif winner == PLAYER2:
player2_cards.append(player1_card)
player2_cards.append(player2_card)

game_round += 1

if len(player1_cards) > len(player2_cards):
winner = player1_name
winning_cards = player1_cards

elif len(player1_cards) < len(player2_cards):
winner = player2_name
winning_cards = player2_cards

else:
winner = DRAW

if winner != DRAW:
write_name_and_cards(winner, winning_cards)

print('Winner of game:', winner)

valid = False

while not valid:
yes_or_no = input('\nWould you like to play again? (y/n)').lower()
valid = True
if yes_or_no == 'n':
play_again = False
elif yes_or_no != 'y':
valid = False

print('\n\n')

# Returns the winner of 2 cards
def compare_cards(card1, card2):

if card1[COLOUR] == card2[COLOUR]:

if card1[NUMBER] > card2[NUMBER]:
return PLAYER1
elif card1[NUMBER] < card2[NUMBER]:
return PLAYER2
else:
return DRAW

else:

if card1[COLOUR] == RED:
return PLAYER1 if card2[COLOUR] == BLACK else PLAYER2

elif card1[COLOUR] == BLACK:
return PLAYER1 if card2[COLOUR] == YELLOW else PLAYER2

elif card1[COLOUR] == YELLOW:
return PLAYER1 if card2[COLOUR] == RED else PLAYER2

def display_cards(card1, card2):

print('=======================================')
print('PLAYER 1                 PLAYER 2')
print('=======================================')

print('colour:', card1[COLOUR], end='')
space_length = 17 - len(card1[COLOUR])
print(space_length * ' ', end='')
print('colour:', card2[COLOUR])

print('number:', card1[NUMBER], end='')
space_length = 17 - len(str(card1[NUMBER]))
print(space_length * ' ', end='')
print('number:', card2[NUMBER])

for i in range(len(players)):
score = len(players[i]) - 1
print(str(i+1), ')', players[i][0], '-', score)

print('\n')

print('\n\n')

valid = False

while not valid:

yes_or_no = input('\nCreating a new deck will overwrite the current deck. Do you wish to proceed? (y/n)')
yes_or_no = yes_or_no.lower()

valid = True

if yes_or_no == 'y':
new_random_deck()
print('\nThe new deck has been created.')

elif yes_or_no == 'n':
print('\nCreation of new deck has been cancelled.')

else:
valid = False

print('\n\n')

def change_speed():

valid = False

while not valid:

print('The current round delay is %f.' % (current_delay))

yes_or_no = input('Are you sure you want to change the speed of the game? (y/n)').lower()
valid = True

if yes_or_no == 'y':

global round_delay

input_loop = True

while input_loop:

input_loop = False

try:
seconds = float(input('\nEnter delay between each round in seconds: '))
except ValueError:
input_loop = True
print('Please enter a float or an integer.')

write_round_delay(seconds)

print('\nThe new round delay has been saved.')

elif yes_or_no == 'n':
print('\nChanging of game speed has been cancelled.')

else:
valid = False

if __name__ == '__main__':
main()


FileFunctions.py:

from pickle import load

EmptyLine = IndexError

# Writes deck to deck.txt
def write_deck(deck_array):

with open('deck.txt', 'w') as deck_file:

for card in deck_array:

deck_file.write(card[0])
deck_file.write(',')
deck_file.write(str(card[1]))
deck_file.write('\n')

deck_array = []

with open('deck.txt', 'r') as deck_file:

deck_text = deck_text.split('\n')

for card_string in deck_text:

try:
card = card_string.split(',')
card[1] = int(card[1])
deck_array.append( (card[0], card[1]) )
except EmptyLine:
continue

return deck_array

def get_passcode():
with open('passcode.bin', 'rb') as passcode_file:

# Writes name and cards to win.txt
def write_name_and_cards(name, cards):

with open('win.txt', 'a') as win_file:

win_file.write(name)

for card in cards:

win_file.write('\n')
win_file.write(card[0])
win_file.write(',')
win_file.write(str(card[1]))

win_file.write('_')

# Returns the top 5 players as a tuple

with open('win.txt', 'r') as win_file:

players = players.split('_')

for i in range(len(players)):
players[i] = players[i].split('\n')

try:
while players[-1] == ['']:
players.pop()
except IndexError: # The players array might be empty
pass

# The players variable now stores a 2d array

top5 = []

maximum = 5 if len(players) >= 5 else len(players)

while len(top5) < maximum:

index_of_highest = 0

for i in range(len(players)):

if len(players[i]) > len(players[index_of_highest]):
index_of_highest = i

top5.append(players[index_of_highest])
players.pop(index_of_highest)

def write_round_delay(seconds):
with open('round_delay.txt', 'w') as rd_file:
rd_file.write(str(seconds))

with open('round_delay.txt', 'r') as rd_file:


deck.txt:

red,6
black,5
yellow,6
red,9
black,8
yellow,8
red,5
black,9
yellow,3
red,7
black,2
yellow,9
red,10
black,2
yellow,3
red,5
black,3
yellow,6
red,6
black,3
yellow,7
red,2
black,1
yellow,5
red,3
black,1
yellow,10
red,6
black,10
yellow,2


round_delay.txt:

1


win.txt is empty at first.

passcode.bin contains the string "Python"

Edit: How can I improve the code?