Skip to content

Instantly share code, notes, and snippets.

@bmontana
Last active April 23, 2018 13:34
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 bmontana/42bbd39bb29a09a49b6de1df9cc67060 to your computer and use it in GitHub Desktop.
Save bmontana/42bbd39bb29a09a49b6de1df9cc67060 to your computer and use it in GitHub Desktop.
Dice Poker Game with splash screen, help, and high score features
# button.py
from graphics import *
from time import sleep
class Button:
"""A button is a labeled rectangle in a window.
It is activated or deactivated with the activate()
and deactivate() methods. The clicked(p) method
returns true if the button is active and p is inside it."""
def __init__(self, win, center, width, height, label):
"""
Creates a rectangular button, eg:
qb = Button(myWin, centerPoint, width, height, 'Quit')
:param win: GraphWin -> graphics window object
:param center: Point -> point object for center of button
:param width: int/float -> width for button
:param height: int/float -> height for button
:param label: str -> button label
"""
self.win = win
w,h = width/2.0, height/2.0
x,y = center.getX(), center.getY()
self.xmax, self.xmin = x+w, x-w
self.ymax, self.ymin = y+h, y-h
p1 = Point(self.xmin, self.ymin)
p2 = Point(self.xmax, self.ymax)
self.rect = Rectangle(p1,p2)
self.rect.setFill('lightgray')
self.draw_shadow()
self.rect.draw(self.win)
self.label = Text(center, label)
self.label.draw(self.win)
self.deactivate()
def clicked(self, p):
"""
Determines if button was clicked
:param p: Point -> point object for location of mouse click
:return: boolean -> true if button active and p is inside
"""
if (self.active and
self.xmin <= p.getX() <= self.xmax and
self.ymin <= p.getY() <= self.ymax):
self.shadow_out1.undraw()
self.shadow_out2.undraw()
self.draw_depressed()
return True
else:
return False
def getLabel(self):
"""
:return: str -> label of button
"""
return self.label.getText()
def activate(self):
"""
Sets button to 'active.'
"""
self.label.setFill('black')
self.rect.setWidth(2)
self.active = True
def deactivate(self):
"""
Sets button to 'inactive.'
"""
self.label.setFill('darkgrey')
self.rect.setWidth(1)
self.active = False
def draw_shadow(self):
"""Shadow for button when not pressed"""
b = self.rect
p1 = Point(b.getP2().getX()+2, b.getP1().getY()+2) # top right outside shadow point
p2 = Point(b.getP2().getX()+2, b.getP2().getY()+2) # bottom right outside shadow point
p3 = Point(b.getP1().getX()+2, b.getP2().getY()+2) # bottom left outside shadow point
self.shadow_out1 = Line(p1, p2)
self.shadow_out1.setFill('black')
self.shadow_out1.setWidth(2)
self.shadow_out2 = Line(p3, p2)
self.shadow_out2.setFill('black')
self.shadow_out2.setWidth(2)
self.shadow_out1.draw(self.win)
self.shadow_out2.draw(self.win)
def draw_depressed(self):
"""Depressed buttons lose the outside shadow and get an inside shadow"""
b = self.rect
p1 = Point(b.getP1().getX()+3, b.getP1().getY()+3) # top left inside shadow point
p2 = Point(b.getP1().getX()+3, b.getP2().getY()-0) # bottom left inside shadow point
p3 = Point(b.getP2().getX()-0, b.getP1().getY()+3) # top right inside shadow point
shadow_in1 = Line(p1, p2)
shadow_in1.setFill('darkgrey')
shadow_in1.setWidth(2)
shadow_in2 = Line(p1, p3)
shadow_in2.setFill('darkgrey')
shadow_in2.setWidth(2)
self.shadow_out1.undraw()
self.shadow_out2.undraw()
b.move(1, 1)
shadow_in1.draw(self.win)
shadow_in2.draw(self.win)
sleep(0.07)
shadow_in1.undraw()
shadow_in2.undraw()
b.move(-1, -1)
self.shadow_out1.draw(self.win)
self.shadow_out2.draw(self.win)
# cdieview.py
from dieview import DieView
class ColorDieView(DieView):
"""
Implementation of a DieView with changeable forground color
Illustrates inheritance
"""
def setValue(self, value):
"""
Overrides DieView.setValue(), saving value locally first, then calling DieView.setValue()
:param value: int -> value to set for die
"""
self.value = value # remember this value
DieView.setValue(self, value) # call setValue from parent class
def setColor(self, color):
"""
Sets foreground color of die
:param color:
"""
self.foreground = color
self.setValue(self.value)
# dice.py
from random import randrange
class Dice:
"""
Representation of five dice
"""
def __init__(self):
"""
Create five dice and rolls to set random values
"""
self.dice = [0]*5
self.rollAll()
def roll(self, which):
"""
Rolls dice specified in which
:param which: list -> integers representing which dice to roll
"""
for pos in which:
self.dice[pos] = randrange(1,7)
def rollAll(self):
"""
Calls self.roll() to roll all dice
"""
self.roll(range(5))
def values(self):
"""
Values of all dice
:return: list -> copy of self.dice[] containing die values
"""
return self.dice[:]
def score(self):
"""
Determines score of hand
:return: str, int -> name of hand, if any; score of hand in dollars as integer
"""
# Create the counts list
counts = [0] * 7
for value in self.dice:
counts[value] = counts[value] + 1
# score the hand
if 5 in counts:
return "Five of a Kind", 30
elif 4 in counts:
return "Four of a Kind", 15
elif (3 in counts) and (2 in counts):
return "Full House", 12
elif 3 in counts:
return "Three of a Kind", 8
elif not (2 in counts) and (counts[1]==0 or counts[6] == 0):
return "Straight", 20
elif counts.count(2) == 2:
return "Two Pairs", 5
else:
return "Garbage", 0
# dieview.py
from graphics import *
class DieView:
""" DieView is a widget that displays a graphical representation
of a standard six-sided die."""
def __init__(self, win, center, size):
"""
Create a view of a die, e.g.:
d1 = GDie(myWin, Point(40,50), 20) creates a die centered at (40,50) having sides of length 20.
:param win: GraphWin -> graphics window
:param center: Point -> center of die
:param size: int/float -> length of a side of the die
"""
# first define some standard values
self.win = win # save this for drawing pips later
self.background = "white" # color of die face
self.foreground = "black" # color of the pips
self.psize = 0.1 * size # radius of each pip
hsize = size / 2.0 # half the size of the die
offset = 0.6 * hsize # distance from center to outer pips
# create a square for the face
cx, cy = center.getX(), center.getY()
p1 = Point(cx-hsize, cy-hsize)
p2 = Point(cx+hsize, cy+hsize)
# draw a shadow for each die
shadow = Rectangle(Point(p1.getX()+2, p1.getY()+2), Point(p2.getX()+2, p2.getY()+2))
shadow.draw(win)
shadow.setFill('black')
rect = Rectangle(p1,p2)
rect.draw(win)
rect.setFill(self.background)
# Create 7 circles for standard pip locations
self.pip1 = self.__makePip(cx-offset, cy-offset)
self.pip2 = self.__makePip(cx-offset, cy)
self.pip3 = self.__makePip(cx-offset, cy+offset)
self.pip4 = self.__makePip(cx, cy)
self.pip5 = self.__makePip(cx+offset, cy-offset)
self.pip6 = self.__makePip(cx+offset, cy)
self.pip7 = self.__makePip(cx+offset, cy+offset)
# Draw an initial value
self.setValue(1)
def __makePip(self, x, y):
"""
Internal helper method to draw a pip at (x,y)
:param x: int/float -> x-coordinate for center of pip
:param y: int/float -> y-coordinate for center of pip
:return: Circle -> a pip is a Circle object
"""
pip = Circle(Point(x,y), self.psize)
pip.setFill(self.background)
pip.setOutline(self.background)
pip.draw(self.win)
return pip
def setValue(self, value):
"""
Set this die to display value.
:param value: int -> value for this die
"""
# turn all pips off
self.pip1.setFill(self.background)
self.pip2.setFill(self.background)
self.pip3.setFill(self.background)
self.pip4.setFill(self.background)
self.pip5.setFill(self.background)
self.pip6.setFill(self.background)
self.pip7.setFill(self.background)
# turn correct pips on
if value == 1:
self.pip4.setFill(self.foreground)
elif value == 2:
self.pip1.setFill(self.foreground)
self.pip7.setFill(self.foreground)
elif value == 3:
self.pip1.setFill(self.foreground)
self.pip7.setFill(self.foreground)
self.pip4.setFill(self.foreground)
elif value == 4:
self.pip1.setFill(self.foreground)
self.pip3.setFill(self.foreground)
self.pip5.setFill(self.foreground)
self.pip7.setFill(self.foreground)
elif value == 5:
self.pip1.setFill(self.foreground)
self.pip3.setFill(self.foreground)
self.pip4.setFill(self.foreground)
self.pip5.setFill(self.foreground)
self.pip7.setFill(self.foreground)
else:
self.pip1.setFill(self.foreground)
self.pip2.setFill(self.foreground)
self.pip3.setFill(self.foreground)
self.pip5.setFill(self.foreground)
self.pip6.setFill(self.foreground)
self.pip7.setFill(self.foreground)
# guipoker.py
from graphics import *
from pokerapp import PokerApp
from button import Button
from cdieview import ColorDieView
from U12_Ex01_SplashScreen import SplashScreen
from U12_Ex01_HelpScreen import HelpScreen
from shadowtext import *
from Chapter12.U12_Ex01_DicePoker.U12_Ex01_HighScore import HighScore
from Chapter12.U12_Ex01_DicePoker.shadowtext import ShadowText
class GraphicsInterface:
"""
GUI for dice poker game
"""
def __init__(self, hi_scores):
"""
Set up graphical interface
:param hi_scores: obj -> HighScore object
"""
self.win = GraphWin("Dice Poker", 600, 400)
self.win.setBackground("green4")
banner = Text(Point(300,30), "Python Poker Parlor")
banner.setSize(24)
banner.setFill("yellow2")
banner.setStyle("bold")
banner_shadow = ShadowText(banner)
banner_shadow.draw(self.win)
banner.draw(self.win)
self.msg = Text(Point(300,380), "Welcome to the Dice Table")
self.msg.setSize(18)
self.msg.draw(self.win)
self.createDice(Point(300,100), 75)
self.buttons = []
self.addDiceButtons(Point(300,170), 75, 30)
b = Button(self.win, Point(300, 230), 400, 40, "Roll Dice")
self.buttons.append(b)
b = Button(self.win, Point(300, 280), 150, 40, "Score")
self.buttons.append(b)
b = Button(self.win, Point(30,375), 40, 30, "Help")
self.buttons.append(b)
b = Button(self.win, Point(570,375), 40, 30, "Quit")
self.buttons.append(b)
self.money = Text(Point(300,325), "$100")
self.money.setSize(18)
self.money.draw(self.win)
self.hi_scores = hi_scores # added for high score feature
def createDice(self, center, size):
"""
Creates five dice (in self.dice[]), each of which is an instance of ColorDieView
:param center: Point -> center of window (???)
:param size: int/float -> length of an edge of a die
"""
center.move(-3*size,0)
self.dice = []
for i in range(5):
view = ColorDieView(self.win, center, size)
self.dice.append(view)
center.move(1.5*size,0)
def addDiceButtons(self, center, width, height):
"""
Creates a button for each die
:param center: Point -> center of window (???)
:param width: int/float -> width of each button
:param height: int/float -> height of each button
"""
center.move(-3*width, 0)
for i in range(1,6):
label = "Die {0}".format(i)
b = Button(self.win, center, width, height, label)
self.buttons.append(b)
center.move(1.5*width, 0)
def setMoney(self, amt):
"""
Changes money text for GUI
:param amt: int -> amount to display
"""
self.money.setText("${0}".format(amt))
def showResult(self, msg, score):
"""
Show result of latest roll
:param msg: str -> hand that was rolled
:param score: int -> score associated with hand, if any
"""
if score > 0:
text = "{0}! You win ${1}".format(msg, score)
else:
text = "You rolled {0}".format(msg)
self.msg.setText(text)
def setDice(self, values):
"""
Sets values of dice
:param values: list -> integer values for each die
"""
for i in range(5):
self.dice[i].setValue(values[i])
def wantToPlay(self):
"""
Queries if user wants to keep playing
:return: boolean -> true if wants to play; false otherwise
"""
while True:
# added choice for Help
ans = self.choose(["Roll Dice", "Quit", "Help"])
if ans == "Help":
self.show_help()
else:
self.msg.setText("")
return ans == "Roll Dice"
def close(self):
"""
Close-up shop...app exit
"""
self.win.close()
def chooseDice(self):
"""
Allows individual dice to be chosen for re-roll
:return: list -> integer list of dice to re-roll
"""
# choices is a list of the indexes of the selected dice
choices = [] # No dice chosen yet
while True:
# wait for user to click a valid button
# added choice for Help
b = self.choose(["Die 1", "Die 2", "Die 3", "Die 4", "Die 5",
"Roll Dice", "Score", "Help"])
if b[0] == "D": # User clicked a die button
i = int(b[4]) - 1 # Translate label to die index
if i in choices: # Currently selected, unselect it
choices.remove(i)
self.dice[i].setColor("black")
else: # Currently unselected, select it
choices.append(i)
self.dice[i].setColor("gray")
elif b == "Help": # choice added for Help
self.show_help()
else: # User clicked Roll or Score
for d in self.dice: # Revert appearance of all dice
d.setColor("black")
if b == "Score": # Score clicked, ignore choices
return []
elif choices != []: # Don't accept Roll unless some
return choices # dice are actually selected
def choose(self, choices):
"""
Modal method to get user choice from choices parameter
:param choices: list -> str label values for buttons to activate
:return: str -> label of chosen button
"""
buttons = self.buttons
# activate choice buttons, deactivate others
for b in buttons:
if b.getLabel() in choices:
b.activate()
else:
b.deactivate()
# get mouse clicks until an active button is clicked
while True:
p = self.win.getMouse()
for b in buttons:
if b.clicked(p):
return b.getLabel() # function exit here.
def show_help(self):
"""
Creates HelpScreen object (which displays help screen) and waits for response.
:return:
"""
help_screen = HelpScreen([
["Rules of the Game", 24],
["Click the 'Roll Dice' button to start. ", 12],
["The goal is to make the best poker hand", 12],
["with five dice. Up to two re-rolls are ", 12],
["allowed per turn. Click on the 'Die #' ", 12],
["button below each die you wish to re- ", 12],
["roll. Then click 'Roll Dice' to re-roll", 12],
["only those dice. If you like your hand ", 12],
["before using both re-rolls, click the ", 12],
["'Score' button to end the turn. If all ", 12],
["re-rolls are used, the score is updated", 12],
["automatically. Good Luck!", 12],
["", 12],
["Payout Table", 18],
["Hand\t\tPayout", 14],
["Five of a Kind\t\t$30", 12],
["Straight (1-5 or 2-6)\t$20", 12],
["Four of a Kind\t\t$15", 12],
["Full House\t\t$12", 12],
["Three of a Kind\t\t$8", 12],
["Two Pairs\t\t$5", 12],
]
)
help_screen.get_response()
def enter_score(self, amt):
"""
Screen for user to enter their name when their score is in the top ten.
:param amt: int -> score (amount of money)
"""
winW = 600
winH = 300
win = GraphWin("High Score!", winW, winH) # creates a separate window
win.setBackground(color_rgb(80, 0, 0))
sep_shadow = Line(Point(300, 21), Point(300, 279)) # vertical separator line
sep_shadow.setFill('darkgrey')
sep_shadow.draw(win)
sep_pt1 = Point(300, 20)
sep_pt1.setFill('white')
sep_pt1.setOutline('white')
sep_pt1.draw(win)
separator = Line(Point(301, 20), Point(301, 280))
separator.setFill('white')
separator.draw(win)
sep_pt2 = Point(300, 180)
sep_pt2.setFill('white')
sep_pt2.setOutline('white')
sep_pt2.draw(win)
self.display_msg(win, 150, 30, "Congratulations!", 18) # left side of screen for name entry
self.display_msg(win, 150, 54, "You're TOP TEN!", 14)
self.display_msg(win, 150, 119, "Enter your name.", 14)
name_entry = Entry(Point(150, 150), 20)
name_entry.setSize(14)
name_entry.setTextColor(color_rgb(80, 0, 0))
self.display_msg(win, 450, 30, "High Scorers", 18) # right side of screen for high scores list
if len(hi_scores.scores) == 0: # no high scores, yet
self.display_msg(win, 450, 150, "You're the first!", 14)
else:
# display scores
line_pos = 30
hi_scores.set_pointer(0)
while True:
score_info = hi_scores.get_next_score()
name = score_info[0]
hi_score = score_info[1]
if name == None:
break
line_pos += hi_scores.get_scores_fontsize() * 1.3
self.display_msg(win, 450, line_pos+hi_scores.get_scores_fontsize() * 1.3,
'{}\t{}'.format(name, hi_score),
hi_scores.get_scores_fontsize())
name_entry.draw(win)
self.button_ok = Button(win, Point(95, 260), 75, 35, "OK")
self.button_cancel = Button(win, Point(207, 260), 75, 35, "Cancel")
self.button_ok.activate()
self.button_cancel.activate()
response = self.get_response(win)
if response:
hi_scores.set_score(name_entry.getText(), amt)
win.close()
def display_msg(self, win, x, y, m, s, c='white', o='white'):
"""
Helper method to display a message
:param win: obj -> GraphWin object in which to display message
:param x: int/float -> x coordinate for center point of message
:param y: int/float -> y coordinate for center point of message
:param m: str -> message to display
:param s: int -> size of message text
:param c: str -> fill color of message (default: white)
:param o: str -> outline color of message (default: white)
"""
msg = Text(Point(x, y), m)
msg.setFill(c)
msg.setOutline(o)
msg.setSize(s)
msg_shadow = ShadowText(msg, offset_x=2, offset_y=2)
msg_shadow.draw(win)
msg.draw(win)
def get_response(self, win):
"""
Event loop to get response from user (clicking a button or pressing Return or Escape)
:return: boolean -> True if OK is selected; otherwise False
"""
while True:
p = win.checkMouse()
k = win.checkKey()
if p and self.button_ok.clicked(p) or k == "Return":
win.close()
return True
if p and self.button_cancel.clicked(p) or k == "Escape":
win.close()
return False
hi_scores = HighScore() # create HighScore object for application
splash = SplashScreen(hi_scores) # display splash screen
if splash.get_response():
inter = GraphicsInterface(hi_scores) # create interface object for application
app = PokerApp(inter, hi_scores) # create app object
app.run() # Play!
Bill,120
Joe,110
Jack,110
Jad,102
Jarod,102
Julie,102
Bill,98
Jen,95
Justin,95
Mason,90
# pokerapp.py
from dice import Dice
class PokerApp:
"""
Play dice poker
"""
def __init__(self, interface, hi_scores):
"""
Initialize dice, money, and interface (could be text or GUI)
:param interface: obj -> interface object
:param hi_scores: obj -> high scores object
"""
self.dice = Dice()
self.money = 100
self.interface = interface
self.hi_scores = hi_scores # added for high score feature
self.played_once = False # added for high score feature
def run(self):
"""
Runs game continuously until quit or no money left
"""
while self.money >= 10 and self.interface.wantToPlay():
self.playRound()
# if played at least once, compare score to high score list, add to list if high scorer
if self.played_once and self.hi_scores.is_top_ten(self.money):
self.interface.enter_score(self.money)
self.interface.close()
def playRound(self):
"""
Handles all aspects of a round
"""
self.money = self.money - 10
self.interface.setMoney(self.money)
self.doRolls()
result, score = self.dice.score()
self.interface.showResult(result, score)
self.money = self.money + score
self.interface.setMoney(self.money)
self.played_once = True # added for high score feature
def doRolls(self):
"""
Handles all rolls, both initial and any re-rolls
"""
self.dice.rollAll()
roll = 1
self.interface.setDice(self.dice.values())
toRoll = self.interface.chooseDice()
while roll < 3 and toRoll != []:
self.dice.roll(toRoll)
roll = roll + 1
self.interface.setDice(self.dice.values())
if roll < 3:
toRoll = self.interface.chooseDice()
# shadowtext.py
from graphics import *
class ShadowText(Text):
"""
ShadowText class for creating shadow for Text. Inherits from Text
"""
def __init__(self, txtobj, fill='black', offset_x=2, offset_y=2):
"""
Set some instance variables before calling superclass constructor
:param txtobj: Text -> text object needing a shadow
:param fill: str -> fill color
:param offset_x: int/float -> shadow offset in x direction
:param offset_y: int/float -> shadow offset in y direction
"""
self.obj = txtobj.clone() # clone the original Text object
self.center = self.obj.getAnchor()
self.text = self.obj.getText()
self.obj.setFill(fill)
self.offsetX = offset_x
self.offsetY = offset_y
Text.__init__(self, self.center, self.text)
def draw(self, win):
"""
Overrides Text.draw()
:param win: GraphWin -> window in which to draw text shadow
"""
self.obj.move(self.offsetX, self.offsetY)
self.obj.draw(win)
# U12_Ex01_HelpScreen.py
#
# Author: Bill Montana
# Course: Coding for OOP
# Section: A3
# Date: 18 Apr 2018
# IDE: PyCharm Community Edition
#
# Assignment Info
# Exercise: 1
# Source: Python Programming
# Chapter: 12
#
# Program Description
# Adds a help screen to the GUI Dice Poker game
#
# Algorithm (pseudocode)
# see comments
from graphics import *
from button import Button
class HelpScreen():
def __init__(self, msg_list):
"""
HelpScreen class for the GUI Dice Poker game
:param msg: list -> lines of text to display [[line 1, font size], [line 2, font size], ...]
"""
winH = 0
winW = 400
for line in msg_list:
winH += line[1] + line[1] / 2 # font size plus half for line spacing
winH += 70 # to allow for close button
self.win = GraphWin("Help for Dice Poker", winW, winH)
self.win.setBackground(color_rgb(80, 0, 0))
# display lines of help text
line_pos = 30
prev_line_ht = msg_list[0][1]
# first line is heading
self.display_msg(winW/2, line_pos, msg_list[0][0], 'white', 'white', prev_line_ht)
prev_line_ht = prev_line_ht / 2
for line in msg_list[1:]:
line_pos += prev_line_ht/3 + line[1]
self.display_msg(winW/2, line_pos+prev_line_ht+line[1], line[0], 'white', 'white', line[1])
prev_line_ht = line[1]
self.button_close = Button(self.win, Point(winW/2, winH-40), 75, 35, "Close")
self.button_close.activate()
def display_msg(self, x, y, m, c, o, s):
"""
Helper method to display a message
:param x: int/float -> x coordinate for center point of message
:param y: int/float -> y coordinate for center point of message
:param m: str -> message to display
:param c: str -> fill color of message
:param o: str -> outline color of message
:param s: int -> size of message text
"""
msg = Text(Point(x, y), m)
msg.setFill(c)
msg.setOutline(o)
msg.setSize(s)
msg.draw(self.win)
def get_response(self):
"""
Event loop to get response from user (clicking the button or pressing Return or Escape)
:return: boolean -> True when Close is selected
"""
while True:
p = self.win.checkMouse()
k = self.win.checkKey()
if p and self.button_close.clicked(p) or k == "Return" or k == "Escape":
self.win.close()
return True
# U12_Ex01_HighScore.py
#
# Author: Bill Montana
# Course: Coding for OOP
# Section: A3
# Date: 18 Apr 2018
# IDE: PyCharm Community Edition
#
# Assignment Info
# Exercise: 1
# Source: Python Programming
# Chapter: 12
#
# Program Description
# Adds a high score feature to the GUI Dice Poker game
#
# Algorithm (pseudocode)
# see comments
from graphics import *
from button import Button
class HighScore():
"""
HighScore class for GUI game
"""
def __init__(self):
self.heading = "High Scores"
self.heading_fontsize = 18
self.scores = []
self.get_scores() # populate self.scores from high scores file
self.scores_fontsize = 12
self.list_pointer = 0 # current item index in self.scores
def display_msg(self, x, y, m, c, o, s):
"""
Helper method to display a message
:param x: int/float -> x coordinate for center point of message
:param y: int/float -> y coordinate for center point of message
:param m: str -> message to display
:param c: str -> fill color of message
:param o: str -> outline color of message
:param s: int -> size of message text
"""
msg = Text(Point(x, y), m)
msg.setFill(c)
msg.setOutline(o)
msg.setSize(s)
msg.draw(self.win)
def get_heading(self):
return self.heading
def get_heading_fontsize(self):
return self.heading_fontsize
def get_scores_fontsize(self):
return self.scores_fontsize
def get_next_score(self):
"""
Gets next score from list, using self.list_pointer to know the current index
:return: str, int -> name, score (score is stored as a string in file)
"""
if self.list_pointer < len(self.scores):
score_info = self.scores[self.list_pointer]
self.list_pointer += 1
return score_info[0], int(score_info[1])
return None, None
def get_scores(self):
"""
High scores are stored in a file. Each line is in Name, Score order.
"""
try:
file = open('hi-scores.txt', 'r')
for line in file:
self.scores.append(line[:-1].split(","))
file.close()
except FileNotFoundError:
pass
def scores_exist(self):
"""
:return: boolean -> True if scores exist; False otherwise
"""
return len(self.scores) > 0
def is_top_ten(self, score):
"""
Is this score in the top ten?
:param score: int -> score to check
:return: True if score is in the top ten
"""
return len(self.scores) < 10 or score > int(self.scores[-1][1])
def set_score(self, name, score):
"""
Writes top ten scores to hi-scores.txt
:param name: str -> name of user
:param score: int -> user's score
"""
self.scores.append([name, score]) # append score to list
self.scores.sort(key=self.__get_score, reverse=True) # sort in descending order
range_len = min(10, len(self.scores)) # only take top ten
outfile = open('hi-scores.txt', 'w')
for i in range(range_len):
print("{},{}".format(self.scores[i][0], self.scores[i][1]), file=outfile)
def __get_score(self, entry):
"""
Internal helper method to return score from entry
:param entry: list -> [name], [entry]
:return: int -> score
"""
return int(entry[1])
def set_pointer(self, idx):
"""
Sets self.list_pointer to idx
:param idx: int -> new index value
"""
self.list_pointer = idx
# U12_Ex01_SplashScreen.py
#
# Author: Bill Montana
# Course: Coding for OOP
# Section: A3
# Date: 18 Apr 2018
# IDE: PyCharm Community Edition
#
# Assignment Info
# Exercise: 1
# Source: Python Programming
# Chapter: 12
#
# Program Description
# Adds a splash screen to the GUI Dice Poker game
#
# Algorithm (pseudocode)
# see comments
from graphics import *
from Chapter12.U12_Ex01_DicePoker.button import Button
from Chapter12.U12_Ex01_DicePoker.shadowtext import ShadowText
class SplashScreen():
"""
SplashScreen class for the GUI Dice Poker game
"""
def __init__(self, hi_scores):
"""
The splash screen is set up and displayed in the constructor.
High scores are displayed in the splash screen. Screen height
is dynamically determined based on the length of the high score list.
:param hi_scores: obj -> HighScore object
"""
winW = 300
winH = 200
if hi_scores.scores_exist:
for score in hi_scores.scores:
winH += hi_scores.get_scores_fontsize() * 1.5 # font size plus half for line spacing
winH += hi_scores.get_heading_fontsize() * 1.3 # allow for heading and space after
self.win = GraphWin("Dice Poker", winW, winH)
self.win.setBackground(color_rgb(80, 0, 0))
self.display_msg(150, 40, "Welcome to Dice Poker", 'white', 'white', 24)
self.display_msg(150, 80, "Play poker using five dice.", 'white', 'white', 12)
self.display_msg(150, 100, "Up to two re-rolls are allowed.", 'white', 'white', 12)
if hi_scores.scores_exist():
# display high scores list
line_pos = 150
# first line is heading
self.display_msg(winW/2, line_pos, hi_scores.get_heading(),
'white', 'white', hi_scores.get_heading_fontsize())
# display scores
while True:
score_info = hi_scores.get_next_score()
name = score_info[0]
hi_score = score_info[1]
if name == None:
break
line_pos += hi_scores.get_scores_fontsize() * 1.1
self.display_msg(winW/2, line_pos+hi_scores.get_scores_fontsize(),
'{}\t{}'.format(name, hi_score),
'white', 'white', hi_scores.get_scores_fontsize())
self.button_play = Button(self.win, Point(95, winH - 40), 75, 35, "Let's Play")
self.button_exit = Button(self.win, Point(207, winH - 40), 75, 35, "Exit")
self.button_play.activate()
self.button_exit.activate()
def display_msg(self, x, y, m, c, o, s):
"""
Helper method to display a message
:param x: int/float -> x coordinate for center point of message
:param y: int/float -> y coordinate for center point of message
:param m: str -> message to display
:param c: str -> fill color of message
:param o: str -> outline color of message
:param s: int -> size of message text
"""
msg = Text(Point(x, y), m)
msg.setFill(c)
msg.setOutline(o)
msg.setSize(s)
msg_shadow = ShadowText(msg, offset_x=2, offset_y=2)
msg_shadow.draw(self.win)
msg.draw(self.win)
def get_response(self):
"""
Event loop to get response from user (clicking a button or pressing Return or Escape)
:return: boolean -> True if Play is selected; otherwise False
"""
while True:
p = self.win.checkMouse()
k = self.win.checkKey()
if p and self.button_play.clicked(p) or k == "Return":
self.win.close()
return True
if p and self.button_exit.clicked(p) or k == "Escape":
self.win.close()
return False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment