Throughout the course, you've experimented with various problem solving strategies.
They've included:
stepwise refinement
divide and conquer
working backwards
examples
extreme cases
tables and charts
and everyone's favourite: trial and error
The course began with you using the input-processing-output problem solving model. You've solved problems independently during the course and by the culminating activity, you'll have solved problems as part of a team.
In this unit, we're going to use a formal approach to software development.
The SDLC (Software Development Life Cycle) can be visualized in several ways:
I was taught to visualize the Waterfall model, but in a cycle:
In this unit we will look at a simple problem, and apply the principals of software development to it.
For the purpose of this unit, it doesn't matter which SDLC you choose to follow. What matters is that you learn to follow one. I will go over the phases, but in case you missed it, the phases of the SDLC are also outlined here in this wikipedia.org article.
You can use a Gantt chart, a critical path diagram, or a PERT chart to manage your project for this unit. I recommend a Gantt chart.
Let's look at this sample Gantt chart. The full article is located here.
What are the 4 different 'types' of people doing across the 12 days of this office move?
Are days divided?
A simple Gantt charts in Microsoft Excel tutorial.
A Test Plan is a T-Chart where you break the larger project into smaller chunks. List these smaller problems on the left hand side of your chart. On the right hand side indicate if they are in a state PASS or FAIL. When you first write your chart, most items will be indicated as FAIL - even if you think you know how to do them. Once they are actually done, and in your code, you can mark them as PASS.
Create a test plan to test your program.
Begin by writing a list of scenarios, and then track them by indicating pass or fail. The default state is FAIL, only change to PASS if you actually implement it (code it).
Things to consider: Input, Output, Variables, Functions, Data Structures, Is it usable?, Does it meet the requirements?
Track your expected and actual outcomes.
You have 10 days. Use the course calendar when you are planning.
Play with easyGUI. Try to implement some of the example code. Show me what you built.
Choose an SDLC that you would like to follow. Stick to your plan.
I am your client. How will you clarify program specifications(dialogue, questionnaires, survey, research)? Talk to me.
Create a Gantt chart. Plan your 10 days. Your Gantt chart must show your tasks and milestones. Show it to me.
Create and use a test plan. Show it to me.
Communicate information about the status of your project in writing / orally throughout the project. You should do this during the beginning of each class with me.
Only hand in your documented assignment on the due date. The Gantt, survey, test plan and SDLC will have been checked during class time.
Google Classroom has a 20 file max file limit per submission. If your project requires more than 20 files, see me, and I'll make a secondary folder for the class. Name your files using the class naming convention:
lastname_assignment.py
lastname_assignment.txt
lastname_image1.jpeg
lastname_image2.jpeg
The rubric and complicated rules for this for this unit are located below.
Your client Mr. Liconti wants a Python version of the game of 'rock paper scissors'. Your client would like for his game to not to run in a terminal, but to have a graphical user interface. Because you only have 10 days starting from your first client meeting, a fellow programmer has suggested using the Python library EasyGui to build the graphical user interface. Your client would like a theme and art for his game, but he is uncertain. Your 10 days begin the day of this lesson. See the Calendar for more details.
DO NOT DO THE TASKS IN ORDER. CLEARLY, THE COMMUNICATION TASK HAS TO HAPPEN FIRST.
Choose an SDLC (Prototype, Waterfall, Spiral or Waterfall in a Circle) that you understand to help you plan your project. State which SDLC you are using.
Create a SCHOOL Google Doc
In sentence form, for each heading of the SDLC you chose, answer:
Explain what will happen. 1 - 2 sentences.
Explain why it is happening. 1 - 2 sentences.
Explain how it is happening. 1 - 2 sentences.
This is page 1 of the document you will hand in to your client.
Create a Gantt chart that covers the 10 days of the project. You can do this with ONE of the following:
Hand drawn chart. Use markers, highlighters, pens, pencils, shading, a ruler or anything you have (yes, break out the crayons.). Take a picture of the chart and paste it into page 2 of your document.
SCHOOL Google Sheets. Paste it into page 2 of your document.
No Camera, No Paper, No Crayons? No Problem. Use MS PAINT or MS Excel or Google Drawings. Save as a picture. Paste it into page 2 of your document.
Create a questionnaire / survey for client research. You know your client wants a game, but what kinds of details did you client leave out? Ask the client a variety of questions (both quantity and type) in order to understand what they want in the game.
Make it with your SCHOOL Google Forms
Ask a variety of different TYPES of questions so that you can collect information
Use that information to help shape the game
The last question in your questionnaire must be, " TEACHER FEEDBACK" with the TYPE of 'Long answer text'. This will give me a chance to tell you how effective your questionnaire was. If you want to RESUBMIT your questionnaire, you can only move up 1 level. For example, if your questionnaire has only a few simple questions and no variety of question type, and it is given a Level 1, and you resubmit and it it excellent, your mark will be a Level 2.
Once your questionnaire is ready, send it to MY SCHOOL EMAIL.
Copy and paste the questions and answers from your questionnaire to your document. These are the last page(s) of your document.
Create a Test Plan that covers the programming of the game. Remember, this is ONLY for the programming aspects of this project.
This is page 3 of your document.
One Google Doc. Order your document like this: Knowledge Task, Thinking Task, Application Task, Communication Task.
Make a Google Doc with your SCHOOL ACCOUNT.
Give the file this name: Lastname_Unit2.
Turn it into our Google Classroom by the due date.
Do not hand in a link or share the document with me. Follow these steps 5 steps to hand it in properly: https://support.google.com/edu/classroom/answer/6020285?co=GENIE.Platform%3DDesktop&hl=en
If you can't see the document, please read: You Do Not Need Permission To View Any Documents.
easyGUI is a Python module that lets you quickly build a user interface. easyGUI is installed at school, and you can install it at home as well. Please use the example code provided as a template for your solution.
Steve Ferg's easyGUI is a very simple and effective Python module that allows you to quickly create a GUI for your Python code.
Alex Zawadzki, Horst JENS and Robert Lugg now maintain easyGUI. This primer is written with easyGUI version 0.97.
easyGUI is function driven, not event driven!
When / if you've got the time, run down this rabbit hole, or this one to explore the differences.
All the tutorials, examples and videos for easyGUI can be found on the easyGUI homepage: easyGUI
If you would like to use easyGUI at home, you must follow the download and install instructions found on the easyGUI page. Click on the large orange download button. CHOOSE THE LATEST VERSION. IT HAS THE SETUP.PY FILE THAT YOU NEED.
These instructions are for Python3.X on a PC
Download easygui found on the easyGUI page. CHOOSE THE LATEST VERSION. IT HAS THE SETUP.PY FILE THAT YOU NEED.
Open Windows Explorer, go to where you downloaded easygui, unzip the archive
Open a Command Prompt in that directory (SHIFT + RIGHT CLICK)
Select 'Open Command Window Here'
Use this command: setup.py install
IF # 5 DOES NOT WORK, TRY: python setup.py install (Thanks Alvaro!)
Open IDLE or your Python shell and test it with this command: import easygui
These instructions are for Python3.X on a Mac, not using pip
Download easygui found on the easyGUI page. CHOOSE THE LATEST VERSION. IT HAS THE SETUP.PY FILE THAT YOU NEED.
Unzip the archive
Open a Terminal
Navigate into the unzipped folder like this: cd Downloads/easygui-VERSION#
Use this command: pythonX.X setup.py install
Open IDLE or your Python shell and test it with this command: import easygui
If you really want to use Python 2.X on a Mac and install easygui with pip
pip install --upgrade pip (OPTIONAL STEP)
pip install easygui
From the interpreter, you can always type:
import easygui
help(easygui)
If you know the name of the widget, and want to use help(module name) you will need to import the module first:
from easygui import *
help(msgbox)
The complete set of easyGUI widgets can be found in the easyGUI tutorial
easyGUI has an interesting demo you can run:
from easygui import *
egdemo()
Lexi teaches easyGUI: http://showmedo.com/videotutorials/video?name=pythonJensFromKids2&fromSeriesID=57
Leo teaches easyGUI: http://showmedo.com/videotutorials/video?name=pythonJensFromKids3&fromSeriesID=57
It looks like showmedo.com is gone (as of Semester 1, 2016-17)...
The easiest explanation of:
msgbox(), ynbox(), ccbox(), boolbox(), buttonbox(), indexbox(), choicebox(), enterbox(), passwordbox() and integerbox()
The easyGUI Gallery (OLD) is located: http://easygui.sourceforge.net/sourceforge_site_as_of_2014_11_21/tutorial/gallery.html
The easyGUI Tutorial (CURRENT) has screenshots of some of the widgets: http://easygui.sourceforge.net/tutorial.html
The following examples have been lifted right out of the easyGUI Gallery (OLD). Slight modifications and commenting have been made:
In Python 3 + easyGUI, images are loaded by PIL (old module, not supported) or PILLOW. PILLOW is installed at school. The COMBINATION of Python 3 + easyGUI + PILLOW allows you to load PNG, JPEG and GIF images. The COMMENTS in the next example are OLD! Oh, before I forget: GIF's will not animate.
#
# msgbox()
#
# Don't forget to import the easygui module
from easygui import *
# Let's build a simple Message Box
msgbox("This is my message")
# if you try help(msgbox) from the interpreter, you'll see that a msgbox can do intresting things like,
# return a string and have a title, or display a picture
# you'll need to grab a an image, rename it cat.gif, and put that gif in the same directory as your python script
#easyGUI WILL ONLY LOAD .GIF FILES. Use an editor at school to change file format as needed.
msgbox(msg='I demand you click the button !', title='Orange Kittens Rule ', ok_button='Human, Click Here', image='./cat.gif', root=None)
# Please note that easygui only handles the .gif image file type. You can convert your images at school with Photoshop Elements or MS Paint
#
# choicebox()
#
# import the module
from easygui import *
# build 2 strings variables to hold our display information
msg ="What is your favorite flavor?"
title = "Ice Cream Survey"
# build a list to hold our choices
choices = ["Vanilla", "Chocolate", "Strawberry", "Rocky Road"]
# build a choice box object and use the previous three variables as the parameters
choice = choicebox(msg, title, choices)
# because the variable 'choice' is used in the choicebox() function call, we can then do anything we want with that data
# in this case, i'll display it in a message box
msgbox(choice)
#
# ccbox()
#
# import the module
from easygui import *
import sys # in this example, we'll use the exit button, for that we'll need access to the OS
# the following 5 lines were explained in the previous note
msg ="What is your favorite flavor?"
title = "Ice Cream Survey"
choices = ["Vanilla", "Chocolate", "Strawberry", "Rocky Road"]
choice = choicebox(msg, title, choices)
msgbox(choice)
# note that the strings msg and title will be used when the Continue / Cancel box is created
msg = "Do you want to continue?"
title = "Please Confirm"
if ccbox(msg, title): # show a Continue/Cancel dialog
pass # user chose Continue
else:
sys.exit(0) # user chose Cancel
# pass is a python keyword that is used when you syntactically need a statement, but don't have one
# see help(ccbox) for another variation of this if / else structure
Summative Evaluation
If you can't see the document, please read: You Do Not Need Permission To View Any Documents.
Software Development Life Cycle - SDLC Waterfall by Sophia F.
Software Development Life Cycle - SDLC Cycle by Sophia F.
Software Development Life Cycle - SDLC Spiral by Sophia F.
Software Development Life Cycle - SDLC Prototyping by Sophia F.
Software Development Life Cycle - SDLC Test Plan by Sophia F.
Software Development Life Cycle - SDLC Gantt Chart by Sophia F.
guizero is a Python 3 library for creating simple GUIs.
This tutorial was created by Anisha L. and Chloe C. based on the documentation found on the guizero website.
Guizero uses tkinter to make a simpler way to use GUI?s. This primer was written using guizero version 1.1.0 and Python version 3.7.0.
https://lawsie.github.io/guizero/about/
pip3 install guizero
Widgets are the objects that appear in apps or windows, such as text boxes, buttons, sliders and even plain old pieces of text. Widgets can be used to display information or get an input from a user.
At the top of every program, guizero requires you to choose which widgets from the library you need, and to import them. Each widget only needs to be imported once, regardless of how many times it is used:
from guizero import App, PushButton, ButtonGroup, Slider
To make a program we have to add widgets, starting with the app. The widget that every guizero program needs is the App, the main window which contains all other widgets. You should have only one App in your program.
from guizero import App # import guizero and the widget(s) you want to use
app = App() # define the app
app.display() # display the app
So what happened? A main window was created, but we can't do anything with, so let's add some more widgets to our app.
All widgets that will be used in the program must go between the line of code to create the App, and the app.display() line:
from guizero import App, Text # import guizero library with the widgets needed
my_app = App(title='Welcome to Castelman Tester') # define the app - all widgets go after this line of code
message = Text(my_app, text='Castelman says hi') # define the message with a text widget
my_app.display() # Display the app
In this example we added a Text widget to our app, allowing us to display a message. Let's breakdown the Text widget code:
message - The variable name that we are giving the widget
Text - the widget we choose, in this example it is the Text widget which displays a message
my_app - The container for the widget. Most of the time your widgets will be contained directly inside the app. All widgets must be placed in a container.
text='Castelman says hi' - displayed text, or a parameter we are passing to the widget
You can change the values of many widgets using parameters. Parameters are the different properties we put inside the brackets when we define our widget.
For example, in the earlier example we defined a Text widget:
message = Text(my_app, text = 'Castelman says hi') # define the message with a text widget
In this example, we used the parameter 'text' to assign a value to the variable message. Throughout this tutorial, when we refer to our parameters we are referring to properties being passed to the widget.
Widgets (PushButton, Waffle, CheckBox, etc.) can be given a command in the parameters, which will call a function when the widget is interacted with.
The function that follows 'command=' does not need () brackets. To pass arguments to the function when called, use 'args=[arguments_here]'.
This code will display hello world when the button is pressed:
from guizero import App, Text, PushButton # import the widgets needed
# define a function to be called in our command
def say_hello():
text.value = "hello world" # change the value of our text widget to hello
app = App() # define the app
text = Text(app) # define text and place it in the app
message = 'This is my passed argument.' # define a message to be passed to the command
# define a PushButton, calling a command every time it is used, and passing it the argument message
button = PushButton(app, command=say_hello, args=[message])
app.display() # display the app
What did you notice? The .value property is used to edit the text object. Use object_name.value = new_value any time you want to edit a text object. This also applies to many other widgets, which can be assigned a value from the user, or given a value to display.
Create a guizero app and display a message.
from guizero import App, Text #import App and Text from guizero library
my_app = App()
text = Text(my_app, text="Hello World!") #create text object in app
my_app.display()
Get text input from the user using a TextBox.
from guizero import App, TextBox #import App and TextBox from guizero library
my_app = App()
name = TextBox(my_app, text="Enter your name") #create text object in app
my_app.display()
Use a PushButton to call a command when the button is pressed. In the code below, the text object will be updated when the pushbutton is pressed.
from guizero import App, Text, TextBox, PushButton #import App and Text, TextBox, and PushButton from guizero library
def update_text(): #assign textbox value to text value
label.value = name.value
my_app = App()
label = Text(my_app, text="What's your name?") #create text object in app to display msg
name = TextBox(my_app) #create textbox object in app for user input
update_button = PushButton(my_app, command=update_text) #pushbutton calls update text command when pushed
my_app.display()
What did you notice? The .value property is used to edit the text object. Use object_name.value = new_value any time you want to edit a text object.
Use a Picture object to display an image. Ensure your image files are in the same directory folder as your .py file. By default, images can be either .png or .gif files. To use .jpg images, enter the following command into your Command Prompt:
pip3 install guizero[images]
from guizero import App, Picture #import app and picture from guizero library
my_app = App()
pic = Picture(my_app, image="my_image.gif") #create picture object in app
my_app.display()
Create 2 pushbuttons, start and stop, and have them toggle the enabled state of each other.
When enabled is set to True, the button is clickable. When enabled is set to false, the button is not clickable.
from guizero import App, PushButton #import app and picture from guizero library
def start():
start_button.disable()
stop_button.enable()
def stop():
start_button.enable()
stop_button.disable()
my_app = App()
start_button = PushButton(my_app, command=start, text="Start")
stop_button = PushButton(my_app, command=stop, text="Stop", enabled=False)
my_app.display()
A container that contains other widgets, and the only object other than app which acts as a master for other objects. This means that you can control the layout inside of a box, and can use it to group other objects.
from guizero import App, Box # import the widgets needed
my_app = App() # define the app
box = Box(my_app, layout = 'align') # insert the box inside of the app
button = PushButton(box, align = 'right') # align the new widget inside of the box
my_app.display()
Displays a group of radio buttons which allows the user to choose a single option.
from guizero import App, ButtonGroup # import the widgets needed
my_app = App() # define the app
# define a ButtonGroup inside the app which has 3 options, with option 1 already selected
choice = ButtonGroup(my_app, options=['option 1', 'option 2', 'option 3'], selected='option 1')
my_app.display()
Displays a box with a label, allowing an option to be checked or unchecked.
from guizero import App, CheckBox # import the widgets needed
my_app = App() # define the app
# define a CheckBox inside the app with text
checkbox = CheckBox(my_app, text = 'Check this out!')
my_app.display() # display the app
Displays a drop down box which allows a single option to be selected from a list.
from guizero import App, Combo # import the widgets needed
my_app = App()
# define a combo with 4 options inside the app
combo = Combo(my_app, options=['Waffles', 'Pancakes', 'Eggs', 'French Toast'])
my_app.display()
Displays a list of items, where single or multiple items can be selected.
from guizero import App, ListBox
my_app = App()
# define a listbox with 4 options inside the app
listbox = ListBox(my_app, multiselect = True, items = ['Waffles', 'Pancakes', 'Eggs', 'French Toast'])
my_app.display()
In this example, we gave 'multiselect' the value of true to allow the user to select multiple items in our list, by either holding shift or ctrl on their keyboard. If you don't want that to be true, simply remove that parameter from the brackets.
Allows shapes to be drawn by specifying its parameters in code. To create a drawing, you first define the drawing, then any shapes in the drawing:
from guizero import App, Drawing
app = App()
# define the drawing inside of the app
draw = Drawing(app)
# define a rectangle with the drawing, specifying the coordinates of the 4 coordinates and a colour
draw.rectangle(10, 10, 60, 60, color = 'red')
app.display()
We specified the coordinates of each vertex pixel in our parameters, allowing us to place it in the app. You can also draw triangles and ovals using the same process.
Displays a menu at the top of the app. Each option on the menu can also lead to a submenu.
from guizero import App, MenuBar
def file_function(): # define a function to print that an option from file is selected
print('Option from File')
def edit_function(): # define a function to print that an option from edit is selected
print('Option from Edit')
my_app = App()
# define the MenuBar, setting the app it is located in and the top level menu options
menubar = MenuBar(my_app,toplevel=['File', 'Edit'],
# define the submenu which will be inside each menu option with it's text and command in a list
options=[
[['File option 1', file_function], ['File option 2', file_function]],
[['Edit option 1', edit_function], ['Edit option 2', edit_function]]])
my_app.display()
So what happened here? After we defined the top level of our menu, we had to define the options in each submenu. This means that inside the option list, there are 2 lists: the submenu for file and the submenu for edit. Inside each of these lists is each option in the submenu: a display name and a function name.
Displays a bar and selector which allows the user to specify a value in a range.
If you want the slider to call a function when it's value changes, define a function that accepts the parameter of slider_value. Then call the function as a command in the slider parameters.
Here's an example of using the slider value to update a textbox:
from guizero import App, Slider, TextBox
# define the function which accepts slider_value
def update_text(slider_value):
textbox.value = slider_value # change the value inside the textbox to slider_value
my_app = App()
slider = Slider(my_app, command=update_text, start = 0, end = 100) # define the slider inside the app with the command
textbox = TextBox(my_app) # insert a textbox inside the app
my_app.display()
A widget that displays uneditable text in an app or window.
from guizero import App, Text # import the desired widgets
my_app = App() # define the app
text = Text(my_app, text='This is the text widget') # define the text widget in the app with text
my_app.display() # display the app
A widget which creates a box that the user can type in.
from guizero import App, TextBox
my_app = App()
# insert a TextBox which has starting text, but allows the user to input any value they want
input_box = TextBox(app, text = 'input your text here')
my_app.display()
You can also set 'multiline = True' in the TextBox parameters to create a multiple lines of wrapped text.
Displays a grid of squares which can call a function when clicked.
You can index a waffle by choosing using it's x and y coordinates. The same indexing rules for 2D lists apply to waffles:
from guizero import App, Waffle
my_app = App()
waffle = Waffle(my_app) # define the waffle
waffle[0,2].color = 'red' # use the x coordinate of 0 and the y coordinate of 2 to select a position on the waffle. In this example we change the colour of that box to red
my_app.display()
#Anisha L. & Chloe C.
#December 12, 2019
#Castelman_Connect_Four
#Write a program that will run a game of connect 4 between 2 players using guizero (check horizontal, vertical, and diagonal wins and display winner)
from guizero import App, Window, PushButton, TextBox, Text, Picture, Box, Waffle #import widgets from guizero library
import sys #import system library
import random #import random library
def show_menu(): #create menu box with picture, start button, and rules button
menu = Box(game) #create menu box in game app
menu_pic = Picture(menu, image = 'Castelman_Welcome2.png') #create picture in game app
menu_buttons = Box(menu, layout='align', width = 800, height = 100, align = 'bottom') #create box with grid layout in game app
menu_buttons.text_color = 'white' #assign white to box colour
menu_buttons.text_size = 40
menu_buttons.font = 'Calibri Bold'
start = PushButton(menu_buttons, text = 'Start', width = 13, height = 1, align = 'left', command = show_start, args = [menu]) #create start button in box, calls display board function when clicked
start.bg = p1_colour
rules = PushButton(menu_buttons, text = 'How To Play', width = 14, height = 1, align = 'right', command = show_rules, args = [menu]) #create rules button in box, calls display rules function when clicked
rules.bg = blue
#A.L.
def exit_program():
game.destroy() #destroy app
sys.exit(0) #exit program
#A.L.
def hide_rules(rules, menu): #hide rules box, show menu box
rules.hide() #hide rules window
menu.show() #show game main menu app
#A.L.
def show_rules(menu): #hide menu box, show rules box
menu.hide()
rules = Box(game) #create rules window in game app
rules_pic = Picture(rules, image = 'Castelman_Rules.png')
done = PushButton(rules, width = 28, height = 1, text = 'Done', command = hide_rules, args = [rules, menu]) #create button in rules window
done.font = 'Calibri Bold'
done.text_size = 40
done.text_color = 'white' #assign white to box colour
done.bg = blue #assign hex colour code to box bg
#A.L.
def show_start(menu): #hide menu box and show start box with game board
menu.hide()
start.show()
#A.L.
def edit_waffle(column, row): #passed x and y coordinates from waffle
try: #try statements for when board is clicked
row = get_row(column, current_turn[1]) #get next available row in clicked column
if row < 0: #if row is off board range (row is full), don't drop disk
drop = False #do not drop disk
else: #if column is not yet full, drop disk
drop_disk(column, row, current_turn[1]) #pass function x, y, player colour
win_flag = check_win(current_turn[1]) #pass current player colour to check win
if win_flag: #if player won, display pop-up and destroy game app
display_win(current_turn[0]) #pass current winner name to display pop-up
else:
full_board = check_full_board() #return value to full board as a flag
if full_board == 5: #if value returned is 5 (board is full), destroy app and restart
game.destroy()
else: #if board not full, switch players
if skip_turn_flag[0] == False: #if skip turn is not clicked, switch players
current_turn[0:] = switch_players(current_turn) #pass function current turn list and return to current turn
else:
nothing = 'nothing' #do nothing
update_shop(current_turn[0]) #enable or disable shop buttons based on coin count
update_display(current_turn)#update display text and colours to switch player
skip_turn_flag[0] = False
except KeyError: #exception handling for when edges of board is clicked
nothing = 'nothing' #do nothing
#A.L.
def update_shop(player): # enable and disable the shop buttons depending on the coins the player has
if player == 'Player 1': # if the current player is player 1, pass the change buttons function player 1's coins
coins = p1_coins[0]
elif player == 'Player 2': # if the current player is player 2, pass the change buttons function player 2's coins
coins = p2_coins[0]
if coins >= 20: # if the player has at least 20 coins, enable the skip turn button
skip_turn.enable()
skip_turn.bg = current_turn[1]
else:
skip_turn.disable()
skip_turn.bg = 'SystemButtonFace'
if coins >= 50: # if the player has at least 50 coins, enable the switch disks button
switch_disks.enable()
switch_disks.bg = current_turn[1]
else:
switch_disks.disable()
switch_disks.bg = 'SystemButtonFace'
#C.C
def check_win(colour): # define a function that takes a colour and checks if it has won in the board
win = False # start the variable win at False
# Check for wins
for column in range(6): # go through each column in the board - the x coordinate
for row in range(5): # go through each row in the board - the y coordinate
pos_colour = board[column, row].color # get the colour of the circle in the specified position
if pos_colour == colour: # if the position colour is the same as the player colour
if column < 3 and win == False: # if the chip is in the first 3 columns check three horizontal
win = check_three_horizontal(column, row, board)
if row < 2 and win == False: # if the chip is in the first 2 rows checks three vertical
win = check_three_vertical(column, row, board)
if column < 3 and row > 2 and win == False: # if the chip is in the first 3 columns and the last 2 rows, check three top diagonal
win = check_three_tdiagonal(column, row, board)
if column < 3 and row < 2 and win == False: # if the chip is in the first 3 columns and the first 2 rows, check three bottom diagonal
win = check_three_bdiagonal(column, row, board)
else: # if they are not the same do nothing
win = win
return win #return winning colour and exit function
#C.C.
def add_one(number): # add one to any number given
number += 1
return number
#C.C.
def subtract_one(number): # subtract one from any number given
number -= 1
return number
#C.C.
def display_win(player_name): #display appropriate win info box for the winning player and destroy app to restart
msg = player_name + ' won the game!'
game.info(title = 'Good Game', text = msg) #create info popup to display winner
game.destroy()
#A.L.
def check_three_horizontal(column, row, board): # checks three to the right of a given position
pos_1 = board[column, row].color # define the first position
# add one to each column position to get the next three column positions in the row
col_p1 = add_one(column)
col_p2 = add_one(col_p1)
col_p3 = add_one(col_p2)
# find the colour at each of the next three column positions
pos_2 = board[col_p1, row].color
pos_3 = board[col_p2, row].color
pos_4 = board[col_p3, row].color
# if all the elements in each position are the same return that the win is true
if pos_1 == pos_2 and pos_2 == pos_3 and pos_3 == pos_4:
win = True
else: # if not return that win is false
win = False
return win
#C.C.
def check_three_vertical(column, row, board): # checks three to the bottom of a given position
pos_1 = board[column, row].color # define the first position
# add one to each row position to get the next three row positions
row_p1 = add_one(row)
row_p2 = add_one(row_p1)
row_p3 = add_one(row_p2)
# find the colour at each of the next three column positions
pos_2 = board[column, row_p1].color
pos_3 = board[column, row_p2].color
pos_4 = board[column, row_p3].color
# if all the elements in each position are the same return that the win is true
if pos_1 == pos_2 and pos_2 == pos_3 and pos_3 == pos_4:
win = True
else: # if not return that win is false
win = False
return win
#C.C.
def check_three_tdiagonal(column, row, board): # checks three to the top diagonal of a given position
# checks for upwards/positive sloping wins
pos_1 = board[column, row].color # define the first position
# subtract one to each row position to get the next three row positions
row_s1 = subtract_one(row)
row_s2 = subtract_one(row_s1)
row_s3 = subtract_one(row_s2)
# add one to each column position to get the next three column positions in the row
col_p1 = add_one(column)
col_p2 = add_one(col_p1)
col_p3 = add_one(col_p2)
# find the colour at each of the next three column positions
pos_2 = board[col_p1, row_s1].color
pos_3 = board[col_p2, row_s2].color
pos_4 = board[col_p3, row_s3].color
# if all the elements in each position are the same return that the win is true
if pos_1 == pos_2 and pos_2 == pos_3 and pos_3 == pos_4:
win = True
else: # if not return that win is false
win = False
return win
#C.C.
def check_three_bdiagonal(column, row, board): # checks three to the bottom diagonal of a given position and returns true or false
# checks for downwards/negative sloping wins
pos_1 = board[column, row].color # define the first position
# add one to each row position to get the next three row positions
row_p1 = add_one(row)
row_p2 = add_one(row_p1)
row_p3 = add_one(row_p2)
# add one to each column position to get the next three column positions in the row
col_p1 = add_one(column)
col_p2 = add_one(col_p1)
col_p3 = add_one(col_p2)
# find the colour at each of the next three column positions
pos_2 = board[col_p1, row_p1].color
pos_3 = board[col_p2, row_p2].color
pos_4 = board[col_p3, row_p3].color
# if all the elements in each position are the same return that the win is true
if pos_1 == pos_2 and pos_2 == pos_3 and pos_3 == pos_4:
win = True
else: # if not return that win is false
win = False
return win
#C.C.
def get_row(column, colour): #function must be passed chosen column and current player colour
row = 4 #assign 4 to row
next_row = True #assign true to flag
while next_row: #loop runs while pixel is already occupied by another disk
if board[column, row].color == empty_colour: #statements run if bottom of chosen column is empty
next_row = False #do not go up one column
elif board[column, row].color == coin_colour: #statements run if bottom of chosen column is a coin space
add_coins(colour, 10) #add 10 coins to player's bank (before drop disk so display is updated)
next_row = False #do not go up one column
elif board[column, row].color != 'white': #statements run if bottom of chosen column is occupied
row -= 1 #go up one row
else:
print('Check Column Error')
return row
#A.L.
def drop_disk(column, row, colour): #drop disk of player colour into board
board[column,row].color = colour #assign player colour to indexed pixel on board
#A.L.
def add_coins(player_colour, num): #add coins to player's bank
if player_colour == p1_colour: #if current player is P1, add coins to P1 bank
p1_coins[0] += num
elif player_colour == p2_colour: #if current player is P2, add coins to P2 bank
p2_coins[0] += num
else:
print('Add Coins Error')
#A.L.
def check_full_board(): #display popup and return to menu when board is full
board_list = board.get_all() #return a 2D list of board colours
full_row = 0
for row in board_list: #loop runs for each row in 2D board list
if 'white' not in row and 'gold' not in row: #increase counter if row is full
full_row += 1 #add one to full row counter
else:
nothing = 'nothing' #do nothing
if full_row == 5: #display popup if entire board is full
game.info(title = 'Game Over', text = 'The game board is full. Tie game.')
return full_row #return variable and exit function
else:
nothing = 'nothing' #do nothing
#A.L.
def switch_players(player_list): #switch current_player list from P1 to P1
if player_list == ['Player 1', p1_colour]: #if current player is P1, switch to P2
player_list = ['Player 2', p2_colour]
elif player_list == ['Player 2', p2_colour]: #if current player is P2, switch to P1
player_list = ['Player 1', p1_colour]
else:
print('Switch Player Error')
return player_list[0:] #return the current player list
#A.L.
def update_display(player_list): #update board box border colour & text
player_msg.value = player_list[0] + "'s Move" #update board box title
player_msg.bg = player_list[1] #update board box title bg
board_box.set_border(5, player_list[1]) #update board box border colour
p1_bank.value = 'Player 1 bank: ' + str(p1_coins[0]) + ' coins'
p2_bank.value = 'Player 2 bank: ' + str(p2_coins[0]) + ' coins'
#A.L.
def generate_coins(board): #generate 5 random green pixels (coins) on board
more_coins = True #set flag to true
while more_coins: #loop runs while <5 coins are on board
row = random.randint(0,5) #generate a random integer for row coordinate
column = random.randint(0,4) #generate a random integer for column coordinate
board[row, column].color = coin_colour #assign pixel colour at indexed coordinates to cyan
colours_list = board.get_all() #return a 2D list of all colours on board
count = 0 #assign 0 to coins count
for row in colours_list: #loop runs through each row in colours list
count += row.count(coin_colour) #keep running total of cyan occurences
if count == 5: #loop flag set to false if 5 coins are on board
more_coins = False
else:
more_coins = True
#A.L.
def switch_board_disks(): # define a function to switch the player disks on the board
subtract_coins(50)
for column in range(6): # go through the columns- the x coordinate
for row in range(5): # go through the 5 rows in each column - the y coordinate
if board[column, row].color == p1_colour: # if the color at the specified cooridnate is p1's colour, switch it to p2's colour
board[column, row].color = p2_colour
elif board[column, row].color == p2_colour: # if the color at the specified cooridnate is p2's colour, switch it to p1's colour
board[column, row].color = p1_colour
else: # if none of the above conditions are true keep the colour the same
board[column, row].color = board[column, row].color
#C.C.
def skip_opp_turn(): #skip the opponent's turn
subtract_coins(20) #subtract 20 coins from current player's bank
skip_turn_flag[0] = True #assign skip turn flag to True
#A.L.
def subtract_coins(num): #subtract passed number from current player's bank
if current_turn[0] == 'Player 1': #if current player is P1, subtract coins from P1 bank
p1_coins[0] -= num
elif current_turn[0] == 'Player 2': #if current player is P2, subtract coins from P2 bank
p2_coins[0] -= num
else:
print('Subtract Coins Error')
update_shop(current_turn[0]) #update shop button colours, and coins count
update_display(current_turn)#update display text and colours to switch player
#A.L.
flag = True
while flag:
#define global variables
coin_colour = 'gold'
empty_colour = 'white'
p1_colour = '#ff5757'
p2_colour = '#1de1ce'
blue = '#4120a9'
p1_coins = [0]
p2_coins = [0]
current_turn = ['Player 1', p1_colour]
skip_turn_flag = [False]
#create main 800x600 app
game = App(title = 'Castelman Connect Four', width = 800, height = 600) #create game app with specified dimensions
show_menu() #show menu box
#create start game box with GLOBAL 5x6 waffle
start = Box(game, width = 800, height = 600, layout = 'align') #create start window in game app
start.hide() #hide start box
start_msg = Text(start, text= 'Castelman Connect Four', font = 'Calibri Bold', size = 30, width = 60, height = 1, bg = blue, color ='white', align = 'top') #create text in start window
board_box = Box(start, align = 'left') #create player 1 input box
board_box.set_border(5, current_turn[1])
player_msg = Text(board_box, text = current_turn[0] + "'s Move", bg = current_turn[1], width = 'fill', size = 18, font = 'Calibri Bold')
player_msg2 = Text(board_box, text = 'Click on a column to drop your disk into.', size = 14)
board = Waffle(board_box, width = 6, height = 5, bg= '#4120a9', dim = 88, dotty = True, command = edit_waffle) #create waffle of circles with blue background in start window
generate_coins(board) #generate 5 random coins on board
#create power-ups shop box with buttons and bank text
shop = Box(start, align = 'right', width ='fill', height = 'fill') #create power up shop box
shop.set_border(5, blue)
shop_title = Text(shop, text = 'Power-Ups Shop', bg = blue, width = 'fill', size = 18, font = 'Calibri', color = 'white')
p1_bank = Text(shop, text = 'Player 1 bank: ' + str(p1_coins[0]) + ' coins', font = 'Calibri', size = 16)
p2_bank = Text(shop, text = 'Player 2 bank: ' + str(p2_coins[0]) + ' coins', font = 'Calibri', size = 16)
skip_turn = PushButton(shop, width = 'fill', text = "Skip Opponent's Turn - 20 coins", command = skip_opp_turn) #call skip turn function when clicked and apss current turn list
switch_disks = PushButton(shop, width ='fill', text = 'Switch Disks on Board - 50 coins', command = switch_board_disks)
# disable the shop buttons at the beginning of the game
switch_disks.disable()
skip_turn.disable()
#create return to menu button
back = PushButton(shop, text = 'Return to Menu', width = 'fill', align = 'bottom', command = game.destroy) #back to menu button destroys app and restarts program when clicked
back.bg = p1_colour
back.text_size = 14
back.font = 'Calibri'
#create rules button that hides start box and shows rules box when clicked
rules_button = PushButton(shop, text = 'Rules', width = 'fill', align = 'bottom', command = show_rules, args = [start]) #go to rules when clicked
rules_button.bg = p2_colour
rules_button.text_size = 14
rules_button.font = 'Calibri'
game.when_closed = exit_program #call exit program when app is closed (via red x button)
game.display() #display game app
***************************************************************************
_______ _______ _____ ______ __
| | | ___| |_| __ \__|
| | ___| | __/__
|___|___|_______|_______|___| |__|
Authors: Anisha L. and Chloe C.
Class/Section: ICS3U1-01, CPT
Date: December 16, 2019
Version: 2.0
Unit/Question number: CPT game
Programming Language: Python 3.7.3
Problem Description: To create a game of connect 4 in guizero
Program Assumptions:
- A computer/laptop with an OS of Windows, Mac, or Linux
- The latest version of python installed (3.7.3)
- guizero 1.1.0 installed
Features of Program:
- Added a shop and coins:
- 5 coins are randomly placed on the board, by placing a chip on the coin,
the user gains 10 coins to their bank
- A user can spend 20 coins to skip ther opponents turn, or 50 coins to
switch all the disks colours on the board
Restrictions:
- No known restrictions
Known Errors:
- No known errors
Implementation Details:
1. Download the file Castelman_Connect_Four.py
2. Using IDLE, click open and navigate to the downloaded program, double-
clicking to open
3. Once opened in IDLE and the code is visible, click F5 on your keyboard
to start, then following the on-screen instructions
- Hardware needed:
- A monitor
- A keyboard
- A mouse
- Software needed:
- IDLE (python 3.7.3)
- guizero
Additional Files:
- Castelman_Welcome2.png
- Castelman_Rules.png
You're going to need a copy of this image to play the game.
You're going to need a copy of this image to play the game.