181 lines
5.8 KiB
Python
181 lines
5.8 KiB
Python
|
# Title: Project 3 - Group validation
|
||
|
# Author: Rory Healy
|
||
|
# Date created - 23rd May 2019
|
||
|
# Date modified - 30th May 2019
|
||
|
|
||
|
def is_n_of_a_kind(cards):
|
||
|
'''Takes a list of cards and returns a Boolean value based on if those
|
||
|
cards are said to be "N-of-a-kind".'''
|
||
|
|
||
|
# Analyse the numbers of the cards to determine validity.
|
||
|
numbers_of_cards = []
|
||
|
for i in range(len(cards)):
|
||
|
numbers_of_cards.append(cards[i][:-1])
|
||
|
if numbers_are_same(numbers_of_cards):
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
def numbers_are_same(numbers):
|
||
|
'''Takes a list of strings, "numbers", and returns True if all the numbers
|
||
|
in the list of strings are the same, and False otherwise.'''
|
||
|
original_number = numbers[0]
|
||
|
for i in range(len(numbers)):
|
||
|
if numbers[i] != original_number:
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
def is_run(cards, aces):
|
||
|
'''Takes two lists of cards (represented as strings), cards and aces, and
|
||
|
returns a list of the lists of runs that are possible with all the given
|
||
|
cards.'''
|
||
|
|
||
|
return_list = []
|
||
|
possible_runs = []
|
||
|
original_cards_len = len(cards)
|
||
|
for i in range(1, len(cards)):
|
||
|
current_card = cards[0]
|
||
|
current_run = []
|
||
|
if len(possible_runs) > 0:
|
||
|
# This is to prevent any IndexErrors due to the use of a while
|
||
|
# loop within a for loop.
|
||
|
for run in possible_runs:
|
||
|
if len(run) + len(cards) != original_cards_len:
|
||
|
break
|
||
|
else:
|
||
|
continue
|
||
|
break
|
||
|
n = 1
|
||
|
while n < len(cards):
|
||
|
if len(cards) == 1:
|
||
|
break
|
||
|
# This will check that the cards form a run.
|
||
|
elif int(current_card[:-1]) == int(cards[i][:-1]) - n:
|
||
|
current_run.append(cards[i])
|
||
|
cards.remove(cards[i])
|
||
|
n += 1
|
||
|
if len(current_run) > 0:
|
||
|
current_run.append(current_card)
|
||
|
possible_runs.append(current_run)
|
||
|
cards.remove(current_card)
|
||
|
|
||
|
# Numerically sorts the runs.
|
||
|
for i in range(len(possible_runs)):
|
||
|
current_run = order_a_list(possible_runs[i])
|
||
|
possible_runs.pop(i)
|
||
|
possible_runs.insert(i, current_run)
|
||
|
|
||
|
# Inserts any aces where necessary.
|
||
|
for run in possible_runs:
|
||
|
for i in range(len(run)):
|
||
|
if i == len(run):
|
||
|
break
|
||
|
elif int(run[i][:-1]) != (int(run[i + 1][:-1]) - 1):
|
||
|
if len(aces) > 0:
|
||
|
run.insert(i + 1, aces[0])
|
||
|
aces.pop(0)
|
||
|
break
|
||
|
else:
|
||
|
for card in run:
|
||
|
cards.append(card)
|
||
|
possible_runs.remove(run)
|
||
|
break
|
||
|
|
||
|
# Checks for alternating suits.
|
||
|
for run in possible_runs:
|
||
|
if not suits_are_alternating(run):
|
||
|
for card in run:
|
||
|
cards.append(card)
|
||
|
run.remove(card)
|
||
|
|
||
|
# Returns all the runs and leftover cards.
|
||
|
return_list.append(possible_runs)
|
||
|
return_list.append(cards)
|
||
|
return_list.append(aces)
|
||
|
return return_list
|
||
|
|
||
|
def suits_are_alternating(suits):
|
||
|
'''Takes a string "suits" and returns True if the suits of the string are
|
||
|
alternating, and False otherwise.'''
|
||
|
for i in range(1, len(suits)):
|
||
|
if suits[i] == suits[i - 1]:
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
def convert_0jqk(cards):
|
||
|
'''Takes a list of cards and converts special numbers (0, J, Q, K) to
|
||
|
their respective values (10, 11, 12, 13) respectively.'''
|
||
|
|
||
|
# Replaces letters with numbers.
|
||
|
for i in range(len(cards)):
|
||
|
# Replaces Kings with their numerical value - 13.
|
||
|
if cards[i][0] == 'K':
|
||
|
suit = cards[i][1]
|
||
|
cards[i] = '13' + suit
|
||
|
|
||
|
# Replaces Queens with their numerical value - 12.
|
||
|
elif cards[i][0] == 'Q':
|
||
|
suit = cards[i][1]
|
||
|
cards[i] = '12' + suit
|
||
|
|
||
|
# Replaces Jacks with their numerical value - 11.
|
||
|
elif cards[i][0] == 'J':
|
||
|
suit = cards[i][1]
|
||
|
cards[i] = '11' + suit
|
||
|
|
||
|
# Replaces '0', representing 10, with its numerical value.
|
||
|
elif cards[i][0] == '0':
|
||
|
suit = cards[i][1]
|
||
|
cards[i] = '10' + suit
|
||
|
return cards
|
||
|
|
||
|
def order_a_list(cards):
|
||
|
'''Orders a list of cards based their numerical value with Aces last.'''
|
||
|
ordered_list = []
|
||
|
numbers_of_cards = []
|
||
|
aces = []
|
||
|
for i in range(len(cards)):
|
||
|
if cards[i][:-1] == 'A':
|
||
|
aces.append('A')
|
||
|
else:
|
||
|
numbers_of_cards.append(cards[i][:-1])
|
||
|
|
||
|
numbers_of_cards.sort(key=int)
|
||
|
numbers_of_cards += aces
|
||
|
for number in numbers_of_cards:
|
||
|
for card in cards:
|
||
|
if number == card[:-1]:
|
||
|
if card in ordered_list:
|
||
|
continue
|
||
|
ordered_list.append(number + card[-1])
|
||
|
return ordered_list
|
||
|
|
||
|
def comp10001go_valid_groups(groups):
|
||
|
'''Takes a list of lists of cards (stored as strings) and returns True or
|
||
|
False depending on if it matches the conditions of valiidty as specified
|
||
|
in the rules.'''
|
||
|
|
||
|
# Handles empty lists.
|
||
|
if not groups:
|
||
|
return True
|
||
|
|
||
|
for group in groups:
|
||
|
|
||
|
# Converts all cards in the group to actual numbers (excluding aces)
|
||
|
group = convert_0jqk(group)
|
||
|
group = order_a_list(group)
|
||
|
|
||
|
# Checks if the group is either an n-of-a-kind or a run
|
||
|
if not is_n_of_a_kind(group):
|
||
|
return False
|
||
|
|
||
|
elif len(group) == 1:
|
||
|
aces = []
|
||
|
for card in group:
|
||
|
if card[0] == 'A':
|
||
|
aces.append(card)
|
||
|
group.remove(card)
|
||
|
runs = is_run(group, aces)
|
||
|
if len(runs[0]) == 0 and len(group) != 1:
|
||
|
return False
|
||
|
return True
|