Last active
April 23, 2018 13:34
-
-
Save bmontana/42bbd39bb29a09a49b6de1df9cc67060 to your computer and use it in GitHub Desktop.
Dice Poker Game with splash screen, help, and high score features
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Bill,120 | |
Joe,110 | |
Jack,110 | |
Jad,102 | |
Jarod,102 | |
Julie,102 | |
Bill,98 | |
Jen,95 | |
Justin,95 | |
Mason,90 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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