Identifying straight, flush and other categories (from Poker) using Python - python-3.x

I am newbie to python and learning it from books, forums and developers. Recently, I tried to implement various hand-ranking categories in the poker program. The goal is to calculate probabilities and see if it agrees with theoretical poker hand probabilities?
Source: https://en.wikipedia.org/wiki/Poker_probability?oldformat=true
Please find below the code and logic I've used so far to build it. The code contains Card and Deck classes which together implement a deck of standard playing cards used, as well as a sample PyTest test function test_xxx().
So far, I've written hasOnePair, hasTwoPairs, hasThreeOfAKind, hasFullHouse and hasFourOfaKind() functions and it is working fine but I am struggling with Straight, flush, StraightFlush.
Could someone please suggest or give guideline about how to approach straight, flush, royalflush, straightflush cases? Also, any further suggestions to update this code will be great.
import random
SUITS = ["Clubs", "Diamonds", "Hearts", "Spades"]
RANKS = ["", "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"]
# here's two Python classes whose objects represent playing cards and decks thereof
class Card():
"""
Represents a single playing card,
whose rank internally is int _rank: 1..13 => "Ace".."King"
and whose suit internally is int _suit 0..3 => "Clubs".."Spades"
"""
def __init__(self, rank=1, suit=3): # this is the constructor!
'''
Initialize card with given int suit and int rank
:param rank:
:param suit:
:return:
'''
self._rank = rank
self._suit = suit
def __str__(self): # this is the "stringifier"
"""
Return the string name of this card:
"Ace of Spades": translates int fields to strings
:return:
"""
# "Ace of Spades" is string for self._rank==1, self._suit==3
toreturn = RANKS[self._rank] + " of " + SUITS[self._suit]
return toreturn
class Deck():
"""
Represents a deck of 52 standard playing cards,
as a list of Card refs
"""
def __init__(self): # constructor
"""
Initialize deck: field _cards is list containing
52 Card refs, initially
:return: nothing
"""
self._cards = []
for rank in range(1, 14):
for suit in range(4):
c = Card(rank, suit) # create next Card with given value
self._cards.append(c) # add it to this Deck
def __str__(self):
"""
"Stringified" deck: string of Card named,
with \n for easier reading
:return:
"""
toreturn = ''
# for index in range(len(self._cards)):
# self._cards[index]
for c in self._cards:
temp = str(c) # temp is the stringified card
toreturn = toreturn + temp + "\n" # note \n at end
return toreturn
def shuffle(self):
random.shuffle(self._cards) # note random function to do this
def dealCard(self):
toreturn = self._cards.pop(0) # get and remove top card from deck
return toreturn
def buildDict(hand):
dict = {}
for card in hand:
dict[card._rank] = dict.get(card._rank, 0) + 1
return dict
def hasOnePair(dict):
twocount = 0
threecount = 0
for v in dict.values():
if v == 2:
twocount += 1
elif v == 3:
threecount += 1
if twocount==1 and threecount != 1:
return True
else:
return False
def hasTwoPairs(dict):
twocount1 = 0
threecount1 = 0
for v in dict.values():
if v ==2:
twocount1 += 1
elif v == 3:
threecount1 +=1
if twocount1 == 2 and threecount1 != 1:
return True
else:
return False
def hasThreeOfAKind(dict):
twocount = 0
threecount = 0
for v in dict.values():
if v == 2:
twocount += 1
elif v == 3:
threecount += 1
if twocount != 1 and threecount == 1:
return True
else:
return False
def hasFullHouse(dict):
twocount = 0
threecount = 0
for v in dict.values():
if v == 2:
twocount += 1
elif v == 3:
threecount += 1
if twocount == 1 and threecount == 1:
return True
else:
return False
def hasFourOfAKind(dict):
fourcount = 0
onecount = 0
for v in dict.values():
if v ==4:
fourcount += 1
elif v == 1:
onecount +=1
if fourcount == 1 and onecount == 1:
return True
else:
return False
def hasStraight(hand):
return False
def hasFlush(dict):
return False
def hasStraightFlush(dict):
return False
def hasRoyalFlush(dict):
return False
def main():
TRIALS = 1000 # int(input ("Input number of hands to test: "))
hand = [] # list of Card in hand
# accumulators for different counts
onepairCount = 0
twopairCount = 0
threeCount = 0
fourCount = 0
fullHouseCount = 0
StraightCount = 0
for num in range(TRIALS):
# create new Deck and shuffle
d = Deck()
d.shuffle()
# initialize hand as empty list
hand = []
# deal top 5 cards of deck, adding to hand
for count in range(5):
hand.append(d.dealCard())
# build the dictionary of card ranks in hand
dict = buildDict(hand)
# use dictionary to make hand checking easier
if hasOnePair(dict):
onepairCount += 1
elif hasTwoPairs(dict):
twopairCount += 1
elif hasThreeOfAKind(dict):
threeCount += 1
elif hasFourOfAKind(dict):
fourCount += 1
elif hasFullHouse(dict):
fullHouseCount += 1
elif hasStraight(dict):
StraightCount +=1
# add more if needed...
# print out results...
print("Number of one pair hands is: ", onepairCount)
print("% of hands: ", 100.0 * onepairCount / TRIALS)
print("Number of two pair hands is: ", twopairCount)
print("% of hands: ", 100.0 * twopairCount / TRIALS)
print("Number of trips hand is: ", threeCount)
print("% of hands: ", 100.0 * threeCount / TRIALS)
print("Number of quads hand is: ", fourCount)
print("% of hands: ", 100.0 * fourCount / TRIALS)
print("Number of trips hand is: ", fullHouseCount)
print("% of hands: ", 100.0 * fullHouseCount / TRIALS)
print("Number of trips hand is: ", StraightCount)
print("% of hands: ", 100.0 * StraightCount / TRIALS)
def card_example():
card1 = Card() # Card(1,3) => Ace of Clubs
card2 = Card(12, 2) # Card (12,2) => Queen of Hearts
card1._newfield = 47 # we can add new fields to any Python object!
# three ways of printing a Card
#
print(card1.__str__()) # calling the methods against card
print(str(card2)) # type-casting
print(card2) # short-cut: passing obj ref to print does str() automagically
print(card1._newfield) # see the new field value?
print(card1._rank) # see the rank (1..13)
print(card1._suit) # see the suit (0..3)
def deck_example():
"""
Test Deck: create, print then shuffle, print again
Then deal first two cards and print, along with bottom card
"""
deck = Deck()
print(str(deck)) # see entire deck before shuffling
print("Now we shuffle:\n")
deck.shuffle()
print(str(deck)) # see entire deck after shuffling
card1 = deck.dealCard()
card2 = deck.dealCard()
print("The first card dealt is", str(card1), "and the second is", str(card2))
print("Bottom of deck is", deck._cards[-1]) # can't hide the implementation!
if __name__ == "__main__": # only run this if this .py is NOT imported
# pass
# card_example() # uncomment to test creating & calling Card methods
# deck_example() # uncomment to test Deck: create, print, shuffle, print
main() # uncomment to run general poker odds calculations
#
# -------------------------------------------------------------------------
#
#pytest follows...
def test_one_pair():
testhand = [Card(2, 3), Card(1, 2),
Card(3, 1), Card(13, 2),
Card(2, 0)]
dict = buildDict(testhand)
assert hasOnePair(dict) #hasTwoPairs
def test_two_pair():
testhand = [Card(2, 3), Card(1, 2),
Card(3, 1), Card(3, 2),
Card(2, 0)]
dict = buildDict(testhand)
assert hasTwoPairs(dict)
def test_three_pair():
testhand = [Card(1, 3), Card(1, 2),
Card(1, 1), Card(13, 2),
Card(2, 0)]
dict = buildDict(testhand)
assert hasThreeOfAKind(dict)
def has_Four_Of_A_Kind():
testhand = [Card(1, 3), Card(1, 2),
Card(1, 1), Card(1, 0),
Card(2, 0)]
dict = buildDict(testhand)
assert hasFourOfAKind(dict)
def test_full_house():
testhand = [Card(1, 3), Card(1, 2),
Card(1, 1), Card(13, 2),
Card(13, 2)]
dict = buildDict(testhand)
assert hasFullHouse(dict)
def test_Straight():
testhand = [Card(11, 1), Card(10, 3),
Card(9, 2), Card(8, 1),
Card(7, 3)]
dict = buildDict(testhand)
assert hasStraight(dict)

The condition for a straight is for your five cards to have adjacent ranks, such that no two cards have the same rank. You can use two different checks to confirm this:
when sorted, the difference between the top card and the bottom card is equal to the total number of cards minus one(e.g. a 4-8 straight has a difference of 4)
no two cards in the straight have the same rank (thus by pigeonhole principle, all ranks between the minimum and maximum must be present
Here's a sample implementation of that:
def hasStraight(hand):
# account for both low-ace and high-ace
ranks_low = sorted([card._rank for card in hand])
ranks_high = sorted([(14 if card._rank == 1 else card._rank) for card in hand])
return (
(
ranks_low[-1] - (len(hand) - 1) == ranks_low[0]
or ranks_high[-1] - (len(hand) - 1) == ranks_high[0]
) # condition 1
and len(set(hand)) == len(hand) # condition 2
)
You will also have to account for low-aces and high-aces. You can do this by, for example, doing two similar checks, once with the normal card ranks and once by doing something like `if card._rank == 1: card._rank == 14
The condition for a flush is simply that all cards are the same suit. This is easy to verify, by simply making a set of all unique suits in the hand, and returning true if that set has only one element (thus all the suits must be the same):
def hasFlush(hand):
suits_set = set(*[card._suit for card in hand])
return len(suits_set) == 1
Once you have those, straight flush and royal flush are easy:
def hasStraightFlush(hand):
return hasStraight(hand) and hasFlush(hand)
def hasRoyalFlush(hand):
ranks = sorted([14 if card._rank == 1 else card._rank for card in hand])
return (
hasStraightFlush(hand)
and ranks[0] == 10 and ranks[-1] == 14
) # royal flush starts at 10, ends at high-ace

Related

Backtracking problem in Knights tour algorithm

**Edit: I managed to find solution for my problem so i put the correct code in place. Everything works perfect now.
I'm trying to complete the last stage of a project in Jetbrains Academy but I can't make my approach to the problem work:
It gives the user the solution for the knights tour in chess if it exists by taking their inputs. I know that there are working solutions out there, but I would like to make it work with the approach I have taken.
I can't make it work. Although, it works fine when the player plays with and I had cut the extra lines.
Example:
Input: A 4x3 board, and 1 3 (column/row)
My implementation gives 2 possible moves [(3, 2), (2, 1)]. It then continues for the possible values of 2 1 and it goes all the way down until it has no other solutions. Then it stops. Those inputs works because they dont require further search in the inside possible valid move. It doesn't check multiple paths that exist at the deeper level.
I don't understand why this happens. Where is the problem in the code?
Initialization of the board (there are extra variables because of the previous steps):
# Write your code here
from copy import deepcopy
import sys
sys.setrecursionlimit(2000)
# With that recursion limit you can test boards up to 40x40 instantly.
# Without this you can test easily up to 30 x 30 any value
# and up to 35x35 any value except edge columns / rows ex 1 4 / 4 1.
class ChessBoard:
def __init__(self, dimensions: str):
self.game_over = False
self.valid_grid = True
self.dimensions = self.board_validation(dimensions.strip().split())
if self.valid_grid:
self.x = self.dimensions[0]
self.y = self.dimensions[1]
self.cell_length = len(str(self.x * self.y)) # Cell format helper for spaces
self.board = [[(x, y) for x in range(1, self.x + 1)] for y in range(self.y, 0, -1)]
self.visual = [["_" * self.cell_length for _ in range(1, self.x + 1)] for _ in range(self.y, 0, -1)]
self.moves_visit = {key: False for i in range(len(self.board)) for key in self.board[i]}
# We need duplicates to reverse the state of the board if we want:
# to continue the game - try other initial move for the valid movements pool
self.board_duplicate = deepcopy(self.board)
self.visual_duplicate = deepcopy(self.visual)
self.moves_visit_duplicate = deepcopy(self.moves_visit)
self.x_boundaries = {i for i in range(1, self.x + 1)}
self.y_boundaries = {i for i in range(1, self.y + 1)}
self.valid_moves = [] # Helper for getting instant valid_moves for the player.
self.is_first_move = True # With that we make it easier to differentiate the first move from other inputs.
self.movements_made = 0 # Move counter direct connection with the AI solution finder and the AI move
self.board_dimensions = self.x * self.y
self.has_solution = False
self.initial_move_for_ai = None
self.first_valid_move = set({})
self.moves_placed = set({}) # Fast comparison to check if the ai_play function will return from recursion
self.total_moves = 0
self.find_solution_mode = False
def set_first(self):
if self.is_first_move:
self.is_first_move = False
def board_validation(self, board_dimensions):
if len(board_dimensions) != 2:
self.valid_grid = False
return False
try:
x = int(board_dimensions[0])
y = int(board_dimensions[1])
if x <= 0 or y <= 0:
self.valid_grid = False
return False
self.valid_grid = True
return x, y
except ValueError:
self.valid_grid = False
return False
def move_validation(self, move_to_validate):
if isinstance(move_to_validate, tuple) and move_to_validate[0] in self.x_boundaries and \
move_to_validate[1] in self.y_boundaries:
return move_to_validate
values = move_to_validate.split()
if len(values) != 2:
return False
try:
column = int(values[0])
row = int(values[1])
movement = (column, row)
if column not in self.x_boundaries or row not in self.y_boundaries:
return False
if not self.is_first_move and self.moves_visit[movement]:
return False
if not self.is_first_move and movement not in self.valid_moves:
return False
return movement
except ValueError:
return False
# Knight movement. X for player - Movement number for AI
def knight_move(self, movement, solution_mode=False):
if self.movements_made == 0:
self.set_first()
movement = self.move_validation(movement)
for m in range(len(self.board)):
if movement in self.board[m]:
index_of_move = self.board[m].index(movement)
if not self.moves_visit[movement]:
if not solution_mode:
self.visual[m][index_of_move] = " " * (self.cell_length - 1) + "X"
else:
move = "" * (self.cell_length - 3) + str(self.movements_made + 1)
self.visual[m][index_of_move] = move.rjust(self.cell_length)
self.possible_moves(movement)
self.movements_made += 1
self.moves_visit[movement] = True
return movement
return False
# Calculating exact moves to chose from. We return index based values based on visual repr
# and also player based values (2, 1), (3, 2) etc.. columns / rows
def move_calculation(self, movement_to_calc):
movement = movement_to_calc
value_to_process = [(-2, -1), (-2, 1), (-1, 2), (1, 2), (2, 1), (2, -1), (-1, -2), (1, -2)]
possible_calculations = [(movement[0] + value_to_process[i][0], movement[1] +
value_to_process[i][1]) for i in range(len(value_to_process))]
final_possible_indexes = [(r, self.board[r].index(j)) for r in range(len(self.board))
for j in possible_calculations if j in self.board[r] and not self.moves_visit[j]]
final_possible_indexes_translation = [self.board[i][j] for i, j in final_possible_indexes]
return final_possible_indexes, final_possible_indexes_translation
# Function that is used to calculate how many moves we have for the valid placements on board
def depth_calc(self, valid_move):
x, y = self.move_calculation(valid_move)
return len(x)
# Similar to move_calculation but this one is used to register primary valid moves for player on board
# And also to check the state of players game and outputting the depth values for the valid moves.
def possible_moves(self, main_move):
try:
moves, moves_translation = self.move_calculation(main_move)
combined_index_translation = set(zip(moves, moves_translation))
except TypeError:
return False
if not self.find_solution_mode:
for i, j in combined_index_translation:
col, row = i[0], i[1]
if not self.moves_visit[j]:
self.visual[col][row] = f'{" " * (self.cell_length - 1)}{self.depth_calc(j) - 1}'
self.valid_moves = moves_translation
print(self.__str__())
self.board_updater()
self.check_end()
return moves_translation
# Board update based on the moves_visit state True/False (if we visited or not)
def board_updater(self):
for i in range(len(self.board)):
for j in range(len(self.board[i])):
move_to_check = self.board[i][j]
if self.moves_visit[move_to_check]:
self.visual[i][j] = f'{" " * (self.cell_length - 1)}*'
else:
self.visual[i][j] = f'{" " * (self.cell_length - 1)}_'
# Getting all primary valid moves to work with
def get_valid_moves(self, from_move):
valid = self.possible_moves(from_move)
if valid:
return valid
else:
return False
# Key function for the ai_play function. It gives us the valid move with the minimum depth.
def lower_move(self, valid_values):
lengths = {i: self.depth_calc(i) for i in valid_values}
min_depth = min(lengths, key=lengths.get)
return min_depth
# Recursive function that is giving us the solution for the inputted move
def ai_play(self, move, pool, n):
if not self.moves_placed:
self.moves_placed.add(move)
if n == 1:
self.first_valid_move.add(self.lower_move(pool))
if len(self.moves_placed) == self.board_dimensions:
self.has_solution = True
return True
if self.total_moves >= self.board_dimensions ** 4:
return False
self.total_moves += 1
if pool:
best_move = self.lower_move(pool)
ai_move = self.knight_move(best_move, solution_mode=True)
self.moves_placed.add(ai_move)
if ai_move:
possible_moves = self.get_valid_moves(ai_move)
if self.ai_play(ai_move, possible_moves, n + 1):
return True
else:
self.ai_play_reset()
first_move = self.knight_reset()
self.moves_placed.add(first_move)
first_pool = self.get_valid_moves(first_move)
self.first_valid_move.add(first_pool[0])
new_pool = set(first_pool).difference(self.first_valid_move)
try:
self.ai_play(first_move, list(new_pool), 1)
except RecursionError:
self.ai_play_reset()
return False
except IndexError:
print("We tested all initial valid moves and failed.\nChoose one cell higher column and try again")
return False
# Resets the important variables of the board. Crucial if ai_play doesn't find a solution with first try.
def ai_play_reset(self):
self.moves_placed.clear()
self.board = deepcopy(self.board_duplicate)
self.visual = deepcopy(self.visual_duplicate)
self.moves_visit = deepcopy(self.moves_visit_duplicate)
self.movements_made = 0
self.has_solution = False
self.first_valid_move.clear()
# Checks the state of the player's game.
def check_end(self):
if not self.valid_moves:
self.game_over = True
if self.movements_made + 1 == self.board_dimensions:
self.has_solution = True
print("What a great tour! Congratulations!")
return False
else:
print(f"No more possible moves!\nYour knight visited {self.movements_made + 1} squares!")
return False
# Resets the Knight position to the initial for the ai_play function
def knight_reset(self):
main_move = self.knight_move(self.initial_move_for_ai, solution_mode=True)
return main_move
# Helper function that manages the outputs of the ai_play function regarding if player want a solution or not
def ai_solution_test(self, move, for_player=False):
if self.board_dimensions in {16, 4, 9}:
print("No solution exists!")
return False
self.initial_move_for_ai = move
self.find_solution_mode = True
movement = self.knight_move(move, solution_mode=True)
self.set_first()
self.initial_move_for_ai = movement
valid_moves = self.get_valid_moves(movement)
while True:
self.ai_play(movement, valid_moves, 1)
if self.has_solution:
if not for_player:
print("\nHere's the solution!")
print(self.__str__())
break
else:
break
self.find_solution_mode = False
self.ai_play_reset()
return True
def __str__(self):
visualization = [" ".rjust(self.cell_length - 1) + "-" * (self.x * (self.cell_length + 1) + 3)]
for i in range(len(self.visual)):
main_chess = " ".join([str(len(self.visual) - i).rjust(self.cell_length - 1) + "|", *self.visual[i], "|"])
visualization.append(main_chess)
visualization.append(" " * (self.cell_length - 1) + "-" * (self.x * (self.cell_length + 1) + 3))
visualization.append(
" ".rjust(self.cell_length + 2) + " ".join([f"{i}".center(self.cell_length) for i in range(1, self.x + 1)]))
return "\n".join(visualization)
def main():
while True:
board = ChessBoard(input("Enter your board's dimensions: "))
if not board.valid_grid:
print("Invalid dimensions!", end=" ")
continue
while True:
knight_move = board.move_validation(input("Enter the knight's starting position: "))
if not knight_move:
print("Invalid move!", end=" ")
continue
else:
break
while True:
puzzle_try = input("Do you want to try the puzzle? (y/n): ")
if puzzle_try not in {"y", "n"}:
print("Invalid input!", end=" ")
continue
else:
break
if puzzle_try == "y":
check_if_solution = board.ai_solution_test(knight_move, for_player=True)
if check_if_solution:
board.knight_move(knight_move)
while not board.game_over:
next_move = board.knight_move(input("Enter your next move: "))
if next_move:
board.board_updater()
else:
print("Invalid move!", end=" ")
continue
if board.game_over:
break
else:
break
else:
board.ai_solution_test(knight_move)
break
if __name__ == "__main__":
main()

Deep Q learning-Training issue

A snake game was created using Pygame and I tried to solve it using an AI. Initially I didn't increase the body length to check if the snake head moves towards the food. Grid size is 5*5. DDQN network was used. Most of time the head moves towards the wall or gets struck in a continuous loop.The maximum score attained was 4 even if I train it for 5000 episodes.
State: It is an array of size 16. The first 8 values has the distance between the head and wall at 8 directions(left , left top, top, right top, right , right bottom, bottom, left bottom). Next 8 values has the distance between head and food at 8 directions. All the values are in the range 0 to 1. 1 means the object is near and 0 means it is very far.
Action : There are 3 actions 0,1,2. 0- Head moves in same direction. 1- Head turns left. 2- Head turns right.
Reward: Reward of +50 if it collects the food and reward of -200 if it touches the wall.
I am not able to understand why my neural network learns in the wrong way. Please do help me solve this issue. I have attached the code here.
Code:
import pygame
pygame.font.init()
import time
import random
import numpy as np
from math import hypot
from collections import deque
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
import tensorflow as tf
import os
seeds = 1001
os.environ['PYTHONHASHSEED']=str(seeds)
np.random.seed(seeds)
random.seed(seeds)
tf.random.set_seed(seeds)
batch = 16
class Food:
def __init__(self,width,n):
self.width = width
self.n = n
self.size = width //n
self.blocks = self.blocks_total()
def blocks_total(self):# Total available positions
x = y = 0
s=[]
for i in range(self.n):
for j in range(self.n):
s.append([x,y])
y += self.size
x += self.size
y = 0
return s
def food_pos(self,s):# Random food position
food_blocks = self.blocks_total()
try:
for i in self.blocks:
for j in s:
if i[0] == j[0] and i[1] == j[1]:
food_blocks.remove([j[0],j[1]])
break
a = random.choice(food_blocks)
return a
except:
return 0.1,0.1
class Agent:
def __init__(self,width,n,state_size,action_size=3,gamma = 0.98):
self.width = width
self.n = n
self.size = width //n
self.state_size = state_size
self.action_size = action_size
self.gamma = gamma
self.epsilon = 1
self.epsilon_min = 0
self.epsilon_decay = 0.99
self.memory = deque(maxlen=5000)
self.model = self.build_model()
self.train_model = self.build_model()
def reshape(self,state):# Reshaping state for input in nueral network
return np.reshape(state,[1,state.shape[0]])
def build_model(self):# Nueral network
model = Sequential()
model.add(Dense(16,input_shape=(self.state_size,),activation='relu'))
model.add(Dense(12,activation='relu'))
model.add(Dense(12,activation='relu'))
model.add(Dense(3,activation='softmax'))
model.compile(loss='mse',optimizer=Adam(0.0001))
return model
def get_action(self,state):
if np.random.rand() <= self.epsilon:
return random.randint(0,2)
a = self.reshape(state)
p = self.model.predict(a)
return np.argmax(p[0])
def remember(self,state,action,reward,new_state,done): # Saving in memory
self.memory.append((state,action,reward,new_state,done))
def replay(self): # Training of nueral network
minibatch = random.sample(self.memory,batch)
for state,action,reward,new_state,done in minibatch:
target = reward
state = self.reshape(state)
new_state = self.reshape(new_state)
if not done:
target = reward +(self.gamma*(np.max(self.train_model.predict(new_state)[0])))
target_f = self.model.predict(state)
target_f[0][action] = target
self.model.fit(state,target_f,epochs =1, verbose = 0)
if self.epsilon > self.epsilon_min:
self.epsilon *= self.epsilon_decay
def save_model(self):
self.model.save_weights('nn1.h5')
def load_model(self):
self.train_model.load_weights('nn1.h5')
class Game:
def __init__(self,width=500,n=5):
self.width = width
self.n = n
self.size = width//n
self.display = pygame.display.set_mode((width,width))
pygame.display.set_caption('A')
self.food = Food(width,n)
self.agent = Agent(width, n, state_size=16)
self.game_over = False
self.dirc = 'r'# starting direction of snake
self.snake_list = []
self.snake_length = 1
self.wall_touch = False
def display_player(self,disp,s_list,dirc):# displaying the snake head and its eyes
l = len(s_list)
if l > self.snake_length:
del s_list[0]
l -=1
for idx,i in enumerate(s_list):
if idx == l-1:
pygame.draw.rect(disp,(255,255,255),(i[0],i[1],self.size-1,self.size-1))
else:
pygame.draw.rect(disp,(255,165,0),(i[0],i[1],self.size-1,self.size-1))
a = s_list.copy()
x,y = a.pop()
rad = 10
if dirc == 'u':
pygame.draw.circle(disp,(0,0,0),(x+50,y+30),rad)
elif dirc == 'd':
pygame.draw.circle(disp,(0,0,0),(x+50,y+70),rad)
elif dirc == 'r':
pygame.draw.circle(disp,(0,0,0),(x+70,y+49),rad)
elif dirc == 'l':
pygame.draw.circle(disp,(0,0,0),(x+30,y+49),rad)
def move(self,dirc,s_list):# Constantly moving the snake on that particular direction
x,y = s_list.pop()
if dirc == 'l':
x -= self.size
if x <0:
x = 0
self.wall_touch = True
elif dirc == 'r':
x += self.size
if x > self.width - self.size:
x = self.width - self.size
self.wall_touch = True
elif dirc == 'u':
y -= self.size
if y <0:
y = 0
self.wall_touch = True
elif dirc == 'd':
y += self.size
if y > self.width - self.size:
y = self.width - self.size
self.wall_touch = True
self.snake_list.append([x,y])
def check_food_collect(self,fx,fy,s_list):# Check if head position and food position are same
x,y =s_list.pop()
if x == fx and y == fy:
return True
return False
def display_msg(self,msg,font='freesansbold.ttf',size=15,color=(255,255,255),loc=(410,15)):
mymsg = pygame.font.Font(font,size).render(msg,True,color)
self.display.blit(mymsg,loc)
def get_direction(self,change):# Changing the direction of snake based on the current direction
if self.dirc == 'r':
if change == 'r':
self.dirc= 'd'
elif change == 'l':
self.dirc= 'u'
elif self.dirc == 'l':
if change == 'r':
self.dirc= 'u'
elif change == 'l':
self.dirc= 'd'
elif self.dirc == 'd' :
if change == 'r':
self.dirc= 'l'
elif change == 'l':
self.dirc= 'r'
elif self.dirc == 'u':
if change == 'r':
self.dirc= 'r'
elif change == 'l':
self.dirc= 'l'
def near_wall(self,n,s_list): # Distance of nearby wall
a,b = n
x,y = s_list.pop()
i =0
while True:
xx = x +(self.size * i * a)
yy = y +(self.size * i * b)
dis = abs(xx-x)/self.size,abs(yy-y)/self.size
i +=1
if xx <0 or yy <0 or xx > self.width - self.size or yy > self.width - self.size:
return 1/ hypot(dis[0],dis[1])
def get_wall_dis(self,s_list): # Wall distance at 8 direction
j = [[-1,0],[-1,-1],[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1]]
s = []
for i in j:
s.append(self.near_wall(i, s_list.copy()))
s = np.asarray(s)
return s
def near_food(self,fx,fy,n,s_list):# Head looks at 8 direction for the food
a,b = n
x,y = s_list.pop()
i =0
while True:
xx = x +(self.size * i * a)
yy = y +(self.size * i * b)
dis = abs(x-fx)/self.size,abs(fy-y)/self.size
i +=1
if xx <0 or yy <0 or xx > self.width - self.size or yy > self.width - self.size:
return 0
else:
if xx == fx and yy == fy:
if dis[0] ==0 and dis[1] ==0:
return 0
return 1/hypot(dis[0],dis[1])
def get_state(self,fx,fy,s_list,w): # Array of size 16
j = [[-1,0],[-1,-1],[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1]]
s = []
for i in j:
s.append(self.near_food(fx,fy,i, s_list.copy()))
s = np.asarray(s)
a = np.append(w,s)
return a
def reset(self): # Initialising the value when a new game is started
self.agent.load_model()
self.game_over = False
self.wall_touch = False
self.dirc = 'r'
self.snake_length = 1
self.snake_list = []
def startgame(self,e):
sx,sy = 0,0 # Starting position of snake
self.snake_list.append([sx,sy])
fx,fy = 200,200 # Initial position of food
step = 0
action = 0
score = 0
change = None
wall = self.get_wall_dis(self.snake_list.copy())
state = self.get_state(fx, fy, self.snake_list.copy(), wall)
reward = 0
t = 0
save = False
j = 0
while not self.game_over:
j +=1
if j >500: # If snake struck in continuous loop
print('Ended')
break
action = 0
action = self.agent.get_action(state)
if action ==1:
change = 'l'
step = 1
elif action ==2:
change = 'r'
step = 1
else:
action = 0
change = None
if step == 0:
step = 1
else:
t +=1
save = True
self.get_direction(change)
change = None
self.move(self.dirc,self.snake_list.copy())
wall = self.get_wall_dis(self.snake_list.copy())
new_state = self.get_state(fx, fy, self.snake_list.copy(), wall)
if self.wall_touch:
reward = -200
print('Walled')
self.agent.remember(state, action, reward, new_state, True)
break
food_collect = self.check_food_collect(fx, fy, self.snake_list.copy())
if food_collect:
reward += 50
self.agent.remember(state, action, reward, new_state, False)
save = False
score +=1
step = 0
t = 0
reward = 0
fx,fy = self.food.food_pos(self.snake_list.copy())
if fx == 0.1 and fy ==0.1:
print('COMPLETED')
pygame.quit()
if save:
save = False
self.agent.remember(state, action, reward, new_state, False)
self.display.fill((0,0,0))
self.display_msg('Score :'+str(score))
pygame.draw.rect(self.display,(0,255,0),(fx,fy,self.size-1,self.size-1))
self.display_player(self.display, self.snake_list,self.dirc)
pygame.display.update()
#time.sleep(1)
state = new_state
if e > 2500:
time.sleep(0.1)
print('E : {} , Epsilon :{:.2} , Score : {}'.format(e,np.float32(self.agent.epsilon),score))
if e%10 ==0:
self.agent.save_model()
if len(self.agent.memory) > batch:
self.agent.replay()
game = Game()
for e in range(10000):
game.startgame(e)
game.reset()
pygame.quit()
A few things you could try:
The way you have defined your state looks a little complicated. Won't top and bottom give the same information, one being negative of the other? Also if your snake head is at (1,1) and your fruit at (3,4), well then the fruit won't show up in the state at all. There will be very limited times when the snake agent can actually see the fruit. Maybe you can try defining the state another way?
In RL, things go south very frequently so it often makes sense to start with basic agents and basic games and move up the ladder. Try using the same agent for a simple openai gym environment like mountaincar, to check if the agent class works as intended.

Why aren't the values from my arrays passing though my full bit adder

# 8-bit-binary adder
#if you have questions about the code just ask
# arrays and funtions
Array1 = []
Array2 = []
#Input A and Validation
def vaildNumberA():
a = int(input("Enter your A value:"))
if (a < 0):
print("Please Enter A Valid Number For Input A")
elif (a > 255):
print("Please Enter A Valid Number For Input A")
else:
Array1 = [int(x) for x in list('{0:08b}'.format(a))]
#Input B and Validation
def vaildNumberB():
b = int(input("Enter your B value:"))
if (b < 0):
print("Please Enter A Valid Number For Input B")
elif (b > 255):
print("Please Enter A Valid Number For Input B")
else:
Array2 = [int(x) for x in list('{0:08b}'.format(b))]
# and gate
# AND Gate
def AND (a,b):
if (a == 1 and b == 1):
return 1
else:
return 0
# or gate
#OR Gate
def OR(a,b):
if (a == 1 or b == 1):
return 1
else:
return 0
# XOR GATEE
#XOR Gate
def XOR (a,b):
if (a == b):
return 0
else:
return 1
#carry formula
def carryformula(a,b,c,d):
return OR(AND(a,b), AND(c,d))
# this is where the calculation should be done
#formula for sum
def calculateSum(Array1,Array2):
carry = ""
sumof = []
for index, in range(len(Array1)):
list2 = Array2[index]
sec_xor_form = XOR(Array1[index],Array2[index])
sumof.append(XOR(sec_xor_form,carry))
carry = carryformula(Array1[index],Array2[index],sec_xor_form,carry)
return list(reversed(sumof))
calculateSum(Array1,Array2)
def main(Array1,Array2):
vaildNumberA()
vaildNumberB()
while True:
a = Array1
b = Array2
total = calculateSum(list(reversed(Array1)),list(reversed(Array2)))
print(total)
quit = input("if want to quit type q: ")
if quit == 'q':
break
main(Array1,Array2)
in the send it prints 0
The only problem in your code is that you need to return Array1 and Array2 from your functions and assign them inside the while true loop, once you do that the code works fine.
The updated code will be
# 8-bit-binary adder
#if you have questions about the code just ask
# arrays and funtions
Array1 = []
Array2 = []
#Input A and Validation
def vaildNumberA():
Array1 = []
a = int(input("Enter your A value:"))
if (a < 0):
print("Please Enter A Valid Number For Input A")
elif (a > 255):
print("Please Enter A Valid Number For Input A")
else:
Array1 = [int(x) for x in list('{0:08b}'.format(a))]
#Return the array
return Array1
#Input B and Validation
def vaildNumberB():
Array2 = []
b = int(input("Enter your B value:"))
if (b < 0):
print("Please Enter A Valid Number For Input B")
elif (b > 255):
print("Please Enter A Valid Number For Input B")
else:
Array2 = [int(x) for x in list('{0:08b}'.format(b))]
#Return the array
return Array2
# AND Gate
def AND (a,b):
if (a == 1 and b == 1):
return 1
else:
return 0
#OR Gate
def OR(a,b):
if (a == 1 or b == 1):
return 1
else:
return 0
#XOR Gate
def XOR (a,b):
if (a == b):
return 0
else:
return 1
#carry formula
def carryformula(a,b,c,d):
return OR(AND(a,b), AND(c,d))
# this is where the calculation should be done
#formula for sum
def calculateSum(Array1,Array2):
carry = ""
sumof = []
for index in range(len(Array1)):
list2 = Array2[index]
sec_xor_form = XOR(Array1[index],Array2[index])
sumof.append(XOR(sec_xor_form,carry))
carry = carryformula(Array1[index],Array2[index],sec_xor_form,carry)
return list(reversed(sumof))
#No need of a main function
while True:
#Call the function from within the while True loop
Array1 = vaildNumberA()
Array2 = vaildNumberB()
total = calculateSum(list(reversed(Array1)),list(reversed(Array2)))
print(total)
quit = input("if want to quit type q: ")
if quit == 'q':
break
And the output will look like
Enter your A value:5
Enter your B value:5
[0, 0, 0, 0, 1, 0, 1, 1]
if want to quit type q: 7
Enter your A value:9
Enter your B value:8
[0, 0, 0, 1, 0, 0, 0, 1]
....

Greedy Motif Search in Python

I am studying the Bioinformatics course at Coursera, and have been stuck on the following problem for 5 days:
Implement GreedyMotifSearch.
Input: Integers k and t, followed by a collection of strings Dna.
Output: A collection of strings BestMotifs resulting from applying GreedyMotifSearch(Dna, k, t).
If at any step you find more than one Profile-most probable k-mer in a given string, use the
one occurring first.
Here's my attempt to solve this (I just copied it from my IDE, so pardon any print statements):
def GreedyMotifSearch(DNA, k, t):
"""
Documentation here
"""
import math
bestMotifs = []
bestScore = math.inf
for string in DNA:
bestMotifs.append(string[:k])
base = DNA[0]
for i in window(base, k):
newMotifs = []
for j in range(t):
profile = ProfileMatrix([i])
probable = ProfileMostProbable(DNA[j], k, profile)
newMotifs.append(probable)
if Score(newMotifs) <= bestScore:
bestScore = Score(newMotifs)
bestMotifs = newMotifs
return bestMotifs
The helper functions are these:
def SymbolToNumber(Symbol):
"""
Converts base to number (in lexicograpical order)
Symbol: the letter to be converted (str)
Returns: the number correspondinig to that base (int)
"""
if Symbol == "A":
return 0
elif Symbol == "C":
return 1
elif Symbol == "G":
return 2
elif Symbol == "T":
return 3
def NumberToSymbol(index):
"""
Finds base from number (in lexicographical order)
index: the number to be converted (int)
Returns: the base corresponding to index (str)
"""
if index == 0:
return str("A")
elif index == 1:
return str("C")
elif index == 2:
return str("G")
elif index == 3:
return str("T")
def HammingDistance(p, q):
"""
Finds the number of mismatches between 2 DNA segments of equal lengths
p: first DNA segment (str)
q: second DNA segment (str)
Returns: number of mismatches (int)
"""
return sum(s1 != s2 for s1, s2 in zip(p, q))
def window(s, k):
for i in range(1 + len(s) - k):
yield s[i:i+k]
def ProfileMostProbable(Text, k, Profile):
"""
Finds a k-mer that was most likely to be generated by profile among
all k-mers in Text
Text: given DNA segment (str)
k: length of pattern (int)
Profile: a 4x4 matrix (list)
Returns: profile-most probable k-mer (str)
"""
letter = [[] for key in range(k)]
probable = ""
hamdict = {}
index = 1
for a in range(k):
for j in "ACGT":
letter[a].append(Profile[j][a])
for b in range(len(letter)):
number = max(letter[b])
probable += str(NumberToSymbol(letter[b].index(number)))
for c in window(Text, k):
for x in range(len(c)):
y = SymbolToNumber(c[x])
index *= float(letter[x][y])
hamdict[c] = index
index = 1
for pat, ham in hamdict.items():
if ham == max(hamdict.values()):
final = pat
break
return final
def Count(Motifs):
"""
Documentation here
"""
count = {}
k = len(Motifs[0])
for symbol in "ACGT":
count[symbol] = []
for i in range(k):
count[symbol].append(0)
t = len(Motifs)
for i in range(t):
for j in range(k):
symbol = Motifs[i][j]
count[symbol][j] += 1
return count
def FindConsensus(motifs):
"""
Finds a consensus sequence for given list of motifs
motifs: a list of motif sequences (list)
Returns: consensus sequence of motifs (str)
"""
consensus = ""
for i in range(len(motifs[0])):
countA, countC, countG, countT = 0, 0, 0, 0
for motif in motifs:
if motif[i] == "A":
countA += 1
elif motif[i] == "C":
countC += 1
elif motif[i] == "G":
countG += 1
elif motif[i] == "T":
countT += 1
if countA >= max(countC, countG, countT):
consensus += "A"
elif countC >= max(countA, countG, countT):
consensus += "C"
elif countG >= max(countC, countA, countT):
consensus += "G"
elif countT >= max(countC, countG, countA):
consensus += "T"
return consensus
def ProfileMatrix(motifs):
"""
Finds the profile matrix for given list of motifs
motifs: list of motif sequences (list)
Returns: the profile matrix for motifs (list)
"""
Profile = {}
A, C, G, T = [], [], [], []
for j in range(len(motifs[0])):
countA, countC, countG, countT = 0, 0, 0, 0
for motif in motifs:
if motif[j] == "A":
countA += 1
elif motif[j] == "C":
countC += 1
elif motif[j] == "G":
countG += 1
elif motif[j] == "T":
countT += 1
A.append(countA)
C.append(countC)
G.append(countG)
T.append(countT)
Profile["A"] = A
Profile["C"] = C
Profile["G"] = G
Profile["T"] = T
return Profile
def Score(motifs):
"""
Finds score of motifs relative to the consensus sequence
motifs: a list of given motifs (list)
Returns: score of given motifs (int)
"""
consensus = FindConsensus(motifs)
score = 0.0000
for motif in motifs:
score += HammingDistance(consensus, motif)
#print(score)
return round(score, 4)
It seems fine to me. However, when I run this code for quiz problems, it gives an incorrect answer. Their code grading system shows this error:
Failed test #3. Your indexing may be off by one at the beginning of each string in Dna.
I have tried everything I can think of and run this code on all their sample data and debug data, but I simply can't figure out how to make this code work. Please help me with any possible solutions to this.
You have a few problems. I think this should address them all. I've included comments explaining each change along with your original code and a reference to the relevant Pseudocode in the debug data page you linked to.
def GreedyMotifSearch(DNA, k, t):
"""
Documentation here
"""
import math
bestMotifs = []
bestScore = math.inf
for string in DNA:
bestMotifs.append(string[:k])
base = DNA[0]
for i in window(base, k):
# Change here. Should start with one element in motifs and build up.
# As in the line "motifs ← list with only Dna[0](i,k)"
# newMotifs = []
newMotifs = [i]
# Change here to iterate over len(DNA).
# Should go through "for j from 1 to |Dna| - 1"
# for j in range(t):
for j in range(1, len(DNA)):
# Change here. Should build up motifs and build profile using them.
# profile = ProfileMatrix([i])
profile = ProfileMatrix(newMotifs)
probable = ProfileMostProbable(DNA[j], k, profile)
newMotifs.append(probable)
# Change to < rather < = to ensure getting the most recent hit. As referenced in the instructions:
# If at any step you find more than one Profile-most probable k-mer in a given string, use the one occurring **first**.
if Score(newMotifs) < bestScore:
#if Score(newMotifs) <= bestScore:
bestScore = Score(newMotifs)
bestMotifs = newMotifs
return bestMotifs

Python 3 : Object has not attribute

I need your kind assistance on these codes. I am getting this error: 'Card object has no attribute 'equal_rank'. Below are the codes from two files. Basically I am not allowed to modify the cards.py file. My codes are in main.py.
main.py
import cards
#call deck
lmdeck = cards.Deck()
#display message
print("=======messy print a deck========")
#display lDck
print(lmdeck)
#call method
a_card = lmdeck.deal()
#display message
print("Card dealt is:", a_card)
#display message
print('Cards left:', len(lmdeck))
#display message
print("Is deck empty?", lmdeck.is_empty())
#define hand
lHndlist1 = []
#define hand
lHndlist2 = []
#loop
for li in range(5):
#call method
lHndlist1.append(lmdeck.deal())
#call method
lHndlist2.append(lmdeck.deal())
#display message
print("\nHand 1:", lHndlist1)
#display message
print("Hand 2:", lHndlist2)
#display
print()
#define hand 1
lLastCrdHnd1 = lHndlist1.pop()
#define hand 1
lLastCrdHnd2 = lHndlist2.pop()
#display message
print("Hand1 threw down", lLastCrdHnd1, ", Hand2 threw down", lLastCrdHnd2)
#display message
print("Hands are now:", lHndlist1, lHndlist2)
#check condition
if lLastCrdHnd1.equal_rank(lLastCrdHnd2):
#display message
print(lLastCrdHnd1, lLastCrdHnd2, "of equal rank")
#otherwise
elif lLastCrdHnd1.get_rank() > lLastCrdHnd2.get_rank():
#display message
print(lLastCrdHnd1, "of higher rank than", lLastCrdHnd2)
#otherwise
else:
#display message
print(lLastCrdHnd2, "of higher rank than", lLastCrdHnd1)
#check condition
if lLastCrdHnd1.equal_value(lLastCrdHnd2):
#display message
print(lLastCrdHnd1, lLastCrdHnd2, "of equal value")
#otherwise
elif lLastCrdHnd1.get_value() > lLastCrdHnd2.get_value():
#display message
print(lLastCrdHnd1, "of higher value than", lLastCrdHnd2)
#otherwise
else:
#display message
print(lLastCrdHnd2, "of higher value than", lLastCrdHnd1)
#check condition
if lLastCrdHnd1.equal_suit(lLastCrdHnd2):
#display message
print(lLastCrdHnd1, 'of equal suit with', lLastCrdHnd2)
#otherwise
else:
#display message
print(lLastCrdHnd1, 'of different suit than', lLastCrdHnd2)
#define list
foundation_list = [[], [], [], []]
#define column
column = 0
#loop
while not lmdeck.is_empty():
#append
foundation_list[column].append(lmdeck.deal())
#update column
column += 1
#check condition
if column % 4 == 0:
#set value
column = 0
#loop
for li in range(4):
#display message
print("foundation", li, foundation_list[li])
#define function
def lGet1Par(cards):
cards.sort(key=lambda card: card.get_rank())
#loop
for lStrt in range(len(cards) - 2 + 1):
if cards [lStrt].get_rank() == cards[lStrt + 1].get_rank():
return cards[lStrt:lStrt + 2]
return []
#define function
def lGet2Par(cards):
lOnePair = lGet1Par(cards)
if lOnePair:
remaining = [c for c in cards if c not in lOnePair]
another_pair = lGet1Par(remaining)
if another_pair:
lOnePair.extend(another_pair)
return lOnePair
return []
#define function
def lGetstgtflsh(cards):
#sort the cards by their ranks
cards.sort(key=lambda card: card.get_rank())
#check each possibility
for lStrt in range(len(cards) - 5 + 1):
end = lStrt + 1
while end < len(cards):
if cards[end].get_suit() != cards[end - 1].get_suit():
break
if cards[end].get_rank() - cards[end - 1].get_rank() != 1:
break
end = end + 1
if end - lStrt >=5: #found
return cards[lStrt:lStrt + 5]
return
#define function
def lGet4ofKnd(cards):
cards.sort(key=lambda card: card.get_rank())
for lStrt in range(len(cards) - 4 + 1):
if cards[lStrt].get_rank() == cards[lStrt + 3].get_rank():
return cards[lStrt:lStrt + 4]
return []
#define function
def lGet3ofKnd(cards):
cards.sort(key=lambda card: card.get_rank())
for lStrt in range(len(cards) - 3 + 1):
if cards[lStrt].get_rank() == cards[lStrt + 2].get_rank():
return cards [lStrt:lStrt + 3]
return []
#define function
def lGetFllHse(cards):
l3 = lGet3ofKnd(cards)
if l3:
remaining = [c for c in cards if c not in l3]
pair = lGet1Par(remaining)
if pair:
l3.extend(pair)
return l3
return []
#define function
def lGetFlsh(cards):
cards.sort(key=lambda card: card.get_suit())
for lStrt in range(len(cards) - 5 + 1):
if cards[lStrt].get_suit() == cards[lStrt + 4].get_suit():
return cards[lStrt:lStrt + 5]
return []
#define function
def lGetStgth(cards):
cards.sort(key=lambda card: card.get_rank())
for lStrt in range(len(cards) - 5 + 1):
end = lStrt + 1
while end < len(cards):
if cards[end].get_rank() - cards[end - 1]. get_rank() != 1:
break
end = end + 1
if end - lStrt >= 5:
return cards[lStrt:lStrt + 5]
return []
#define function
def test():
c = [cards.Card(1, 1), cards.Card(7, 1), cards.Card(6, 1), cards.Card(8, 1), card.Cards(9, 1), cards.Card(10, 1), cards.Card(3, 1)]
print(lGetstgtflsh(c))
c = [cards.Card(1, 1), cards.Card(7, 1), cards.Card(6, 2), cards.Card(8, 1), cards.Card(9, 1), cards.Card(10, 2), cards.Card(11, 1)]
print(lGetstgtflsh(c))
c = [cards.Card(1, 1), cards.Card(1, 2), cards.Card(1, 3), cards.Card(1, 4), cards.Card(9, 1), cards.Card(10, 2), cards.Card(11, 1)]
print(lGet4ofKnd(c))
c = [cards.Card(3, 1), cards.Card(1, 2), cards.Card(1, 3), cards.Card(1, 4), cards.Card(9, 1), cards.Card(10, 2), cards.Card(11, 1)]
print(lGet4ofKnd(c))
print (lGet3ofKnd(c))
c = [cards.Card(3, 1), cards.Card(3, 2), cards.Card(1, 3), cards.Card(1, 4), cards.Card(9, 1), cards.Card(10, 2), cards.Card(11, 1)]
print(lGet2Par(c))
print(lGet1Par(c))
c = [cards.Card(3, 1), cards.Card(3, 2), cards.Card(1, 3), cards.Card(1, 1), cards.Card(9, 1), cards.Card(10, 1), cards.Card(11, 1)]
print(lGetFlsh(c))
c = [cards.Card(1, 1), cards.Card(7, 2), cards.Card(6, 1), cards.Card(8, 1), cards.Card(9, 1), cards.Card(10, 1), cards.Card(3, 1)]
print(lGetStgth(c))
c = [cards.Card(1, 1), cards.Card(1, 2), cards.Card(1, 3), cards.Card(8, 1), cards.Card(9, 1), cards.Card(10, 1), cards.Card(8, 2)]
print(lGetFllHse(c))
c = [cards.Card(1, 1), cards.Card(1, 2), cards.Card(2, 3), cards.Card(8, 1), cards.Card(9, 1), cards.Card(10, 1), cards.Card(8, 2)]
print(lGetFllHse(c))
print(lGet2Par(c))
#define function
def get(player1, player2, category):
if category == 'straight flush':
return(lGetstgtflsh(player1), lGetstgtflsh(player2))
if category == '4 of a kind':
return(lGet4ofKnd(player1), lGet4ofKnd(player2))
if category == 'full house':
return(lGetFllHse(player1), lGetFllHse(player2))
if category == 'flush':
return(lGetFlsh(player1), lGetFlsh(player2))
if category == 'straight':
return(lGetStgth(player1), lGetStgth(player2))
if category == '3 of a kind':
return(lGet3ofKnd(player1), lGet3ofKnd(player2))
if category == '2 pair':
return(lGet2Par(player1), lGet2Par(player2))
if category == '1 pair':
return(lGet1Par(player1), lGet1Par(player2))
return (player1, player2)
#define main function
def main():
lDck = cards.Deck()
lDck.shuffle()
while True:
print("---------------------------")
print("Let's play poker!")
community_cards = []
player1_cards = []
player2_cards = []
player1_cards.append(lDck.deal())
player2_cards.append(lDck.deal())
player1_cards.append(lDck.deal())
player2_cards.append(lDck.deal())
for li in range(5):
community_cards.append(lDck.deal())
print()
print("Community cards: %s" % (community_cards))
print("Player 1: %s" % (player1_cards))
print("Player 2: %s" % (player2_cards))
print()
player1_cards.extend(community_cards)
player2_cards.extend(community_cards)
for category in ('straight flush', '4 of a kind', 'full house', 'flush', 'straight', '3 of a kind', '2 pair', '1 pair', 'high card'):
player1, player2 = get(player1_cards, player2_cards, category)
if player1 and player2:
print("TIE with a %s: %s" % (category, player1))
break
elif player1 and not player2:
print("Player %d wins with a %s: %s" % (1, category, player1))
break
elif not player1 and player2:
print("Player %d wins with a %s: %s" % (2, category, player2))
break
if lDck.cards_count() < 9:
print("Deck has too few cards so game is done.")
break
print()
c = input("Do you wish to play another hand? (Y or N")
if c not in ('y', 'Y'):
break
if __name__ == '__main__':
main()
cards.py
import random
class Card( object ):
# Rank is an int (1-13), where aces are 1 and kings are 13.
# Suit is an int (1-4), where clubs are 1 and spades are 4.
# Value is an int (1-10), where aces are 1 and face cards are 10.
# List to map int rank to printable character (index 0 used for no rank)
rank_list = ['x','A','2','3','4','5','6','7','8','9','10','J','Q','K']
# List to map int suit to printable character (index 0 used for no suit)
# 1 is clubs, 2 is diamonds, 3 is hearts, and 4 is spades
# suit_list = ['x','c','d','h','s'] # for systems that cannot print Unicode symbols
suit_list = ['x','\u2663','\u2666','\u2665','\u2660']
def __init__( self, rank=0, suit=0 ):
""" Initialize card to specified rank (1-13) and suit (1-4). """
self.__rank = 0
self.__suit = 0
self.__face_up = None
# Verify that rank and suit are ints and that they are within
# range (1-13 and 1-4), then update instance variables if valid.
if type(rank) == int and type(suit) == int:
if rank in range(1,14) and suit in range(1,5):
self.__rank = rank
self.__suit = suit
self.__face_up = True
def rank( self ):
""" Return card's rank (1-13). """
return self.__rank
def value( self ):
""" Return card's value (1 for aces, 2-9, 10 for face cards). """
# Use ternary expression to determine value.
return self.__rank if self.__rank < 10 else 10
def suit( self ):
""" Return card's suit (1-4). """
return self.__suit
def is_face_up( self ):
""" Returns True if card is facing up."""
return self.__face_up
def flip_card( self ):
""" Flips card between face-up and face-down"""
self.__face_up = not self.__face_up
def __str__( self ):
""" Convert card into a string (usually for printing). """
# Use rank to index into rank_list; use suit to index into suit_list.
if self.__face_up:
return "{}{}".format( (self.rank_list)[self.__rank], \
(self.suit_list)[self.__suit] )
else:
return "{}{}".format( "X", "X")
def __repr__( self ):
""" Convert card into a string for use in the shell. """
return self.__str__()
def __eq__( self, other ):
""" Return True, if Cards of equal rank and suit; False, otherwise. """
if not isinstance(other, Card):
return False
return self.rank() == other.rank() and self.suit() == other.suit()
class Deck( object ):
# Implement the deck as a list of cards. The last card in the list is
# defined to be at the top of the deck.
def __init__( self ):
""" Initialize deck--Ace of clubs on bottom, King of spades on top. """
self.__deck = [Card(r,s) for s in range(1,5) for r in range(1,14)]
def shuffle( self ):
""" Shuffle deck using shuffle method in random module. """
random.shuffle(self.__deck)
def deal( self ):
""" Return top card from deck (return None if deck empty). """
# Use ternary expression to guard against empty deck.
return self.__deck.pop() if len(self.__deck) else None
def is_empty( self ):
""" Return True if deck is empty; False, otherwise """
return len(self.__deck) == 0
def __len__( self ):
""" Return number of cards remaining in deck. """
return len(self.__deck)
def __str__( self ):
""" Return string representing deck (usually for printing). """
return ", ".join([str(card) for card in self.__deck])
def __repr__( self ):
""" Return string representing deck (for use in shell). """
return self.__str__()
def display( self, cols=13 ):
""" Column-oriented display of deck. """
for index, card in enumerate(self.__deck):
if index%cols == 0:
print()
print("{:3s} ".format(str(card)), end="" )
print()
print()
I don't think there are errors inside the cards.py because I am not allowed to modify the file. It could be in main.py but I could not figure out. Any help would be much appreciated. Thank you.
As the error message says, cards.py does not define the attribute (i.e., internal storage) equal_rank, nore is there a functio equal_rank(), so when you try to access its value with lLastCrdHnd1.equal_rank(lLastCrdHnd2) it fails.
card.py does override the equals operator to allow card ranks to be cmpared so you should be able to do something like
if lLastCrdHnd1 == lLastCrdHnd2:

Resources