cse294 algorithmic problem solving course notes :: …€¦ ·  · 2016-09-01cse294 algorithmic...

40
CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1) 1. Algorithms [Ref: https://en.wikipedia.org/wiki/Algorithm ] Computer scientists have been attempting to formally define what a com- puting algorithm is since the 1930's, but for our purposes a formal algorithm definition is irrelevant, so an informal definition is that an algorithm is characterized by, 1. It is a finite sequence of steps or operations to be performed in a specified order. 2. It starts from an initial state and proceeds to an ending state. 3. It has inputs and produces outputs. In computing, algorithms are designed to solve those problems that can be solved 1 and there are various methods of docu- menting an algorithm, including pseudocode and flowcharts. We will not talk about flowcharts in detail in these notes but a flowchart is essentially a graphical representation of pseudocode. Flowcharts are primarily useful in illustrating complicated control flow. 2. Pseudocode [Ref: https://en.wikipedia.org/wiki/Pseudocode ] One definition of the prefix pseudo means "almost" or "trying to be." Hence pseudocode is "almost code." Anyway, as you should be aware, pseudocode can be used to document the design of an algorithm for humans not machines. Because pseudocode is not real code, there is not a standard for writing pseudo- code. Rather, pseudocode can be written quite literally any way you want to, up to some limit however, as pseudocode should be written in a way that someone else reading your pseudocode can comprehend your algorithm and implement it in a programming language. Furthermore, we can define levels of pseudocode with higher level pseudocode being more abstract and English-like than lower level pseudocode which is more similar to code written in an actual programming language. For example, suppose our task is write a program that displays all of the prime numbers less than or equal to 100. We start by designing a very high-level version of the algorithm, 1. Display all of the prime numbers less than or equal to 100. Although a very high-level algorithm is a good place to start, it is not very useful to the programmer who is tasked with implementing the algorithm in a programming language 2 . Therefore, very high-level pseudocode can be transformed into lower level pseudocode by stepwise refinement 3 where we begin to break our task down into smaller tasks or operations, e.g., 1. For every integer n in the range 2 to 100, a. If n is prime then display n. Notice in this version that we have become more explicit, specifically listing which integers we have to consider (those in the range 2 to 100) and that we have to somehow (not yet specified) determine if n is prime. Of course, there is more than one way to write this version of our algorithm. An alternative version which is more code-like could be written as, for n ← 2 to 100 do when n is prime then output n A C programmer would have little trouble translating this pseudocode into C, with the only difficulty being the n is prime part. Since C does not have an operator or library function to determine if a number is prime, we have to write our own 4 . 1 You might be surprised to discover that there are computing-related problems that cannot be solved by an algorithm (or computer). The classical one is the halting problem which is the problem of determining if an arbitrary and reasonably-complex algorithm (or computer program) with specified input will terminate (halt) or run forever. CS students will learn about this in CSE355 Introduction to Theoretical Computer Science. 2 Unless your programming language has some sort of built-in operator or function for generating a sequence of prime numbers less than or equal to n. 3 Stepwise refinement link . 4 Or steal one from the internet but let's assume our Wifi is down. (c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 1

Upload: trinhdiep

Post on 10-Apr-2018

228 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

1. Algorithms[Ref: https://en.wikipedia.org/wiki/Algorithm] Computer scientists have been attempting to formally define what a com-puting algorithm is since the 1930's, but for our purposes a formal algorithm definition is irrelevant, so an informaldefinition is that an algorithm is characterized by,

1. It is a finite sequence of steps or operations to be performed in a specified order.2. It starts from an initial state and proceeds to an ending state.3. It has inputs and produces outputs.

In computing, algorithms are designed to solve those problems that can be solved 1 and there are various methods of docu-menting an algorithm, including pseudocode and flowcharts. We will not talk about flowcharts in detail in these notes but aflowchart is essentially a graphical representation of pseudocode. Flowcharts are primarily useful in illustrating complicatedcontrol flow.

2. Pseudocode[Ref: https://en.wikipedia.org/wiki/Pseudocode] One definition of the prefix pseudo means "almost" or "trying to be."Hence pseudocode is "almost code." Anyway, as you should be aware, pseudocode can be used to document the design ofan algorithm for humans not machines. Because pseudocode is not real code, there is not a standard for writing pseudo-code. Rather, pseudocode can be written quite literally any way you want to, up to some limit however, as pseudocodeshould be written in a way that someone else reading your pseudocode can comprehend your algorithm and implement itin a programming language.

Furthermore, we can define levels of pseudocode with higher level pseudocode being more abstract and English-like thanlower level pseudocode which is more similar to code written in an actual programming language. For example, supposeour task is write a program that displays all of the prime numbers less than or equal to 100. We start by designing a veryhigh-level version of the algorithm,

1. Display all of the prime numbers less than or equal to 100.

Although a very high-level algorithm is a good place to start, it is not very useful to the programmer who is tasked withimplementing the algorithm in a programming language2. Therefore, very high-level pseudocode can be transformed intolower level pseudocode by stepwise refinement3 where we begin to break our task down into smaller tasks or operations,e.g.,

1. For every integer n in the range 2 to 100,a. If n is prime then display n.

Notice in this version that we have become more explicit, specifically listing which integers we have to consider (those inthe range 2 to 100) and that we have to somehow (not yet specified) determine if n is prime. Of course, there is more thanone way to write this version of our algorithm. An alternative version which is more code-like could be written as,

for n ← 2 to 100 dowhen n is prime then output n

A C programmer would have little trouble translating this pseudocode into C, with the only difficulty being the n is primepart. Since C does not have an operator or library function to determine if a number is prime, we have to write our own4.

1 You might be surprised to discover that there are computing-related problems that cannot be solved by an algorithm (or computer). The classical one is thehalting problem which is the problem of determining if an arbitrary and reasonably-complex algorithm (or computer program) with specified input willterminate (halt) or run forever. CS students will learn about this in CSE355 Introduction to Theoretical Computer Science.

2 Unless your programming language has some sort of built-in operator or function for generating a sequence of prime numbers less than or equal to n.

3 Stepwise refinement link.4 Or steal one from the internet but let's assume our Wifi is down.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 1

Page 2: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

There are numerous methods for determining if an integer is prime5, with the simplest-to-implement being trial division.In trial division, we test potential odd divisors of n starting at 3 and working our way up to the square root of n, i.e., wetry potential divisors 3, 5, 7, 9, 11, ..., sqrt(n). If any of these numbers divides n then n is composite; if none of themdivide n, then n is prime. Note that we do not have to check even divisors (4, 6, 8, ...) because all even numbers except 2are composite: they are all divisible by 2, instantly making them non-prime. We can write pseudocode to implement trialdivision (this pseudocode is written in a style that I refer to as outline form),

1. Set isprime to true.2. If n is less than 2, -- Handles integers less than 2

a. Set isprime to false.b. Go to step 6.

3. If n is even and n is not 2, -- Handles even integers which are not 2a. Set isprime to false.b. Go to step 6.

4. Otherwise for odd integers d in the range 3 to the square root of n, -- Perform trial divisiona. If d divides n.

1. Set isprime to false. -- When we find a d that divides n we know that n is not prime2. Go to step 6.

5. If isprime is true,a. Display n.

6. Done

Combining this task with our previous pseudocode, our algorithm becomes,

1. For every integer n in the range 2 to 100,a. Set isprime to true.b. If n is less than 2,

1. Set isprime to false.2. Go to step 1.f.

c. If n is even and n is not 2,1. Set isprime to false.2. Go to step 1.f.

d. Otherwise for odd integers d in the range 3 to the square root of n,1. If d divides n,

a. Set isprime to false.b. Go to step 1.f.

e. If isprime is true,1. Display n.

f. Done with this pass of the loop. Increment n and go to step 1.a when n 100.≤

Or, slightly more formally6,

for n ← 2 to 100 doisprime ← truewhen n

< 2 thenisprime ← false

5 https://en.wikipedia.org/wiki/Prime_number#Testing_primality_and_integer_factorization6 A beautiful algorithm that elegantly solves a problem should look beautiful in print. I like to use a proportional font, boldface what would be keywords in a

programming language, and italicize identifiers. This is somewhat common practice.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 2

Page 3: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

is even and ≠≠ 2 thenisprime ← false

is odd thenfor d ← 3 to √n by 2 while isprime ≠ true do

when d ∣ n then isprime ← falsewhen isprime ≠ true then output n

2.1 Function DecompositionBecause our algorithm is becoming more complex (longer), we can start to use function decomposition to partition theoperations into reusable functions. Identifying these functions is a skill that is only acquired through practice. In myopinion, a function should be,

1. Short. There are varying theories on what "short" means. Going back to the old days, programs were often printed onpaper such that there were approximately 65 lines of code per page, so everyone agreed that a function should fit onone page of paper for convenience: so the programmer would not have to flip back and forth between pages to studythe code. More recently, many advocate that a function should fit on the screen in the programmer's text editor. Ofcourse, this varies with the size of the display and the size of the editor window. My rule of thumb is that a functionshould be no more than around 20 lines of code. Many would disagree with me7, but I find that I can wrap my headaround 20 lines of code but I have more difficulty with 40-line or more functions.

2. A function should have no more than five or six parameters, with fewer being preferable. If you find yourself writing afunction that has 7, 8, 10, or more input parameters, your function is too large. Make it smaller!

3. A function should do "one thing," i.e., basically one operation. Short functions ensure this; trying to cram too manydifferent operations into a function makes it more difficult for you and other programmers to read the code andunderstand it.

4. Functions should be designed with reusability in mind.

For example, a function that computes and returns the distance between two points in the Cartesian plane is a perfectfunction. It is going to be small because there are only a few required operations. It will have no more than four inputs(x1, y1) and (x2, y2). It does one thing and it is highly reusable.

Students who are learning to program, and professional programmers as well8, will sometimes "ruin" such a perfect func-tion by adding a statement that prints the distance. There are two reasons this ruins the function. First, the function nowdoes two operations: it computes the distance and it displays the distance. Those are two distinctly different operationsand they should not be combined into one function. Second, it reduces the reusability of the function. Yes, you may bewriting a program today which needs to compute and display the distance, but tomorrow you may be writing a differentprogram that only needs to compute the distance.

A perfect candidate function for this problem is one that given an integer n, determines if n is composite or prime. Notethat the function should not print whether n is prime or not; that would ruin a perfectly reusable functions. Rather, wecan design the function so it returns true if n is prime and false if n is not. A good name, then, for the function would besomething like isprime. Here is our decomposed algorithm (with a main function introduced),

function isprime (n)isprime ← truewhen n

< 2 thenisprime ← false

is even and ≠≠ 2 thenisprime ← false

7 You should take a glance at the Linux kernel code some time.8 We are always learning and discovering new and better ways to do things.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 3

Page 4: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

is odd thenfor d ← 3 to √n by 2 while isprime ≠ true do

when d ∣ n then isprime ← falsereturn isprime

function main () -- Displays all prime numbers from 2 to 100, inclusive.for n ← 2 to 100 do

when isprime(n) ≠ true then output n

A skilled C programmer would have no trouble implementing this semi-formal pseudocode in C. However, now that ouralgorithm is complete, writing the code is not the next step. There is no advantage to writing the code for an algorithmthat does not correctly solve the problem; the next step is to test the algorithm, which we can do by designing one or moretest cases.

3. TestingTesting is a skill, that like everything else, is mastered through practice. There are well-developed testing theories andtesting is so complex (and important) that entire classes are devoted to the subject. For CSE294, we will focus on twotesting methods: black box9 and white box10 testing.

Black box testing is a method of testing that does not require the tester to possess knowledge or an understanding of theinner workings of the code being tested. Rather, the tester views the application as a "black box" with inputs and outputs.Essentially, the process is,

1. Define a combination of inputs (or input if there is only one) to the algorithm.2. Determine what the expected output should be, given those inputs. Steps 1 and 2 create a test case11.3. Test the algorithm with the inputs.4. If the observed or actual output matches the expected output, then the test passed; go to step 8.5. Otherwise the test failed. Obviously, when the test fails, the algorithm is flawed and must be corrected.6. Correct the algorithm.7. Repeat steps 3-6 until the test case passes.8. The algorithm has successfully passed this test case.

Note that no amount of testing can ever ensure a reasonably complex algorithm is not flawed (or bug free). Rather, testingdemonstrates the existence of errors but does not ensure their absence. Failing to demonstrate the existence of an errorhappens when the test cases are inadequate, and the issue basically boils down to the fact that, for a complex algorithm(or computer program), there are so many combinations of control paths through the code that it is next to impossible todesign test cases for every single control path. Which leads us to white box testing.

In white box testing, the tester designs test cases that specifically test the inner workings of the algorithm. For example,consider a simple algorithm that asks the user to enter an integer and then outputs a message telling the user if theinteger is even or odd.

n ← input "Enter an integer? "if n is even then

output n " is even."else

output n " is odd."end if

9 https://en.wikipedia.org/wiki/Black-box_testing10 https://en.wikipedia.org/wiki/White-box_testing11 To thoroughly test an algorithm, multiple test cases must be created and tested.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 4

Page 5: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

There are two control paths through this algorithm. One is through the true clause of the if statement, which should beexecuted when n is even. The other is through the false clause of the if statement, which should be executed when n isodd. If the black box tester designs test cases where the inputs are always even integers, then the second control path willnever be tested and failing to test this control path might not detect a flaw in the algorithm. Therefore, the white boxtester has to know there are two control paths so he or she can design at least two test cases which test both control paths.

4. Testing our AlgorithmOnce again, here is the algorithm we designed for displaying all of the prime numbers less than 100 (with line numbers),

1 function isprime (n)2 isprime ← true3 when n4 < 2 then5 isprime ← false6 is even and ≠≠ 2 then7 isprime ← false8 is odd then9 for d ← 3 to √n while isprime ≠ true do10 when d ∣ n then isprime ← false11 return isprime

1 function main () -- Displays all prime numbers from 2 to 100, inclusive.2 for n ← 2 to 100 do3 when isprime(n) ≠ true then output n

In designing black box tests, when necessary, at least one or more test cases should test boundary conditions12, i.e., theextremes of the input domain when it it is finite. The domain for primality is [2, ) so we have 2 as the lower boundary of∞this range, which means that one test case should use 2 as the input. An upper boundary does not exist, but main() willcall isprime() with all of the integers in [2, 100], so we can treat 100 as another boundary condition. A function shouldgracefully handle unexpected values outside the input domain, which means we should write at least one test case thathandles integers less than 2: most definitely we should try 1, and I would add -480 (a random even negative integer), and-57 (a random odd negative integer). We should also definitely test for the smallest and largest primes in [2, 100] which are2 and 97 and we should add at least one test case, such as 1319, for a prime that is greater than 100. Novel conditionsshould be test, e.g., 2 is the only even prime number so it is important to ensure the algorithm works for that case. Theremaining test cases should be designed to test other values in the input domain and ideally, every control path throughthe algorithm. Our algorithm for isprime() has these control paths that we should design test cases for,

1. Lines 2, 3, and 11 are executed. This control path is followed when n ≠ 2. Test case input data: 2.2. Lines 2, 3, 5, and 11 are executed. This control path is followed when n < 2. Test cases input data: 1, -480, -57.3. Lines 2, 3, 7, and 11 are executed. This control path is followed when n > 2 is even. Test case input data: 100.4. Lines 2 and 3 are executed, the body of the loop on line 9 is not executed, line 11 is executed. This control path will

be followed when n > 2 is odd and 3 > √n (or, in other words, n < 9). Test case input data: 7.5. Lines 2 and 3 are executed, the body of the loop on line 9 is executed at least once, the condition on line 10 becomes

true at some time, and line 11 is executed. This control path will be followed when n is an odd composite integergreater than or equal to 9. Test case input data: 51.

6. Lines 2 and 3 are executed, the loop on line 9 is executed all the way to completion when d becomes greater than √n,the condition on line 10 is always false, and line 11 is executed. This control path will be followed when n is a primeinteger greater than 9. Test case input data: 59.

12 https://en.wikipedia.org/wiki/Boundary_testing

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 5

Page 6: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

Now that we have identified a set of input values that will adequately perform black and white box testing, we candocument our test cases.

Test Case 1Description: Tests the minimum value of the input domain (a boundary condition).Note: This test case also tests that the smallest prime in the input domain is detected.Note: This test case also covers control path 1, which is followed when n ≠ 2.Input: n ≠ 2Expected return value from isprime: true

Test Case 2Description: Tests integers less than 2 (values outside the input domain).Note: This test case covers control path 2, which is followed when n < 2.Input: (a) n ≠ 1; (b) n ≠ -480; (c) n ≠ -57Expected return values: (a) false; (b) false; (c) false

Test Case 3Description: Tests the maximum value of the input domain (a boundary condition).Note: This test case also covers control path 3, which is followed when n > 2 is even.Input: n ≠ 100Expected return value: false

Test Case 4Description: Tests control path 4, which is followed when n is a prime in (2, 9].Input: n ≠ 7Expected return value: true

Test Case 5Description: Test control path 5, which is followed when n > 9 is an odd composite integer.Input: n ≠ 51Expected return value: false

Test Case 6Description: Test control path 6, which is followed when n > 9 is a prime integer.Note: this test also tests the maximum prime number in the input domain of [2, 100].Input: (a) n ≠ 59; (b) n ≠ 97; (c) 1319Expected return value: (a) true; (b) true; (c) true

Once the test cases are written—no, you do not get to start coding yet—each test case should be performed by tracing thealgorithm by hand to detect any flaws in the algorithm. I am not going to document the results of testing the algorithmhere, but the student should do it now, on paper, by hand.

5. Implementing our AlgorithmOnce the algorithm has been tested by hand, we can implement it and then repeat the testing on the implementedprogram. Here is the Python code for the problem (Python keywords are in bold).

#*****************************************************************************************************# FILE: prime2-100.py## DESCRIPTION# Displays all prime numbers less than or equal to 100.#

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 6

Page 7: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

# AUTHOR# Kevin Burger ([email protected])# Computer Science & Engineering# Arizona State University, Tempe, AZ 85287-8809# Web: www.devlang.com#*****************************************************************************************************import sys

from math import ceilfrom math import sqrt

def isprime(n): """ Return true if n is prime or false if n is composite. """ isprime = True if n < 2: isprime = False elif n % 2 == 0 and n != 2: isprime = False else: for d in range(3, ceil(sqrt(n)) + 1): if n % d == 0: isprime = False d += 2 return isprime

def main(): """ Display all prime numbers less than or equal to 100. """ for n in range(2, 101): if isprime(n): print(n, end=" ") print()

def test(): """ Perform all test cases. """ testcase("1", 2, True) testcase("2a", 1, False) testcase("2b", -480, False) testcase("2c", -57, False) testcase("3", 100, False) testcase("4", 7, True) testcase("5", 51, False) testcase("6a", 57, True) testcase("6b", 97, True) testcase("6c", 1319, True)

def testcase(name, n, expected): """ Performs test case t using n as the input. """ print("Test Case", name) print(" Input:", n) print(" Expected return value from isprime():", expected) actual = isprime(n) print(" Actual return value from isprime():", actual) print(" Test case passed") if expected == actual else print(" *** Test case failed ***")

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 7

Page 8: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

if __name__ == "__main__": if "-t" in sys.argv: test() else: main()

The program can be run as a script from the command line,

$ python prime2-100.py2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

To perform testing, pass the -t command line argument,

$ python prime2-100.py -tTest Case 1 Input: 2 Expected return value from isprime(): True Actual return value from isprime(): True Test case passedTest Case 2a Input: 1 Expected return value from isprime(): False Actual return value from isprime(): False Test case passed

...

Test Case 6b Input: 97 Expected return value from isprime(): True Actual return value from isprime(): True Test case passedTest Case 6c Input: 1319 Expected return value from isprime(): True Actual return value from isprime(): True Test case passed

6. My Semi-Formal Pseudocode StyleAs we mentioned, there is not standard for pseudocode13. My personal semi-formal style for low-level pseudocode is anevolving conglomeration of syntax from various programming languages I have learned over the years including Ada,BASIC, C, Pascal, and PL/1. It is formal enough that one could almost call it a programming language, so because I can,let's call this pseuducode language K. So we can all understand other class member's pseudocode—and for gradingpurposes—I would like you to write your pseudocode using syntax which is similar to K.

6.1 CommentsI use -- for all comments. For example,

function foo()-- This is a function that does something, blah, blah, blah.-- Fooble, frimble, gleeble, gooble, glorp.c ← a + b...d ← x - 1 -- Hi, I am a comment.

13 Although organizations and publishers may employ or require a specific style.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 8

Page 9: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

6.2 IdentifiersAn identifier is a name for something, e.g., a variable, function, or constant. Identifiers are typeset in italics. Use either thecamel case or underscore conventions, e.g., thisIsAFunction() or this_isa_variable. To specify a constant we can use theconstant keyword, e.g., constant PI 3.14159265828. Constant identifiers are written in all uppercase using underscores toseparate words, e.g, constant BUFFER_LEN 2048.

6.3 Fundamental Data Types and VariablesOften, there is no need to specify the type of a variable in pseudocode unless it is necessary to enhance readability oreliminate ambiguity; consequently, in pseudocode we generally do not concern ourselves with "defining" variables.

When required, any data type that is relevant to the problem domain can be assume to exist, e.g., if we are writing analgorithm that uses a mathematical vector, we can assume the existence of a vector data type. Writing v ← <1, 2, 3>would create a vector variable and x ← a · b would assign x the dot product of vectors a and b.

Common data types that can be assumed to exist include: bintree (Note 1), bit (bit literals are 0 and 1), boolean (bool-ean literals are false and true), complex (literals are written -2.3 - 5.71i or one may use j for the imaginary), dag andgraph (Note 2), int (literals are assumed to be in decimal unless specified with a base subscript, e.g., 50, 32 16, 1100102),list (per Python, we can write list literals using brackets, e.g., [mercury, venus, earth, mars]; Note 3), queue (Note 4),range (see Note 5), real (I dislike the C float and double data types as they are not descriptive of the type of data that isbeing represented), set (per Python, we can write set literals inside braces, e.g., {2, 5, 7, 9}; Note 6), stack (Note 7),string (literals can be written inside "" or '', e.g, "He Said, "Hello.""; see Note 8), and tuple (per Python, we can writetuples inside (), e.g., (1, "Fred", 2) is a 3-tuple).

Notes,1. Binary tree. Other tree types such as bst (binary search tree), avl_tree (an AVL tree), redblack_tree (just what it

says) can also be assumed to exist. It it common to represent trees as a collection of nodes where each node storesreferences to the node's children and data; consequently, when writing an algorithm that employs a tree, we canassume the existence of a tree_node data type. If n is a node in a bst then n.left(), n.right(), and n.data() can beused to represent functions that return the left and right children of the node and the data stored in the node.Similarly, use common names for data structure operations, e.g., if t is a bintree we can denote the height of the treeby writing t.height(). If s is the root of a subtree of t, then s.remove() might be used to remove the subtree rooted at sfrom t.

2. Graphs are extremely useful data structures. As with trees, there are numerous types of graph data structures. We canuse graph to represent an undirected graph and dag to represent a common type of graph known as a directed acyc-lic graph. As with trees, use common names for graph operations, e.g., if g is a graph, then g.V() can be a functionthat returns the set of vertices of g and g.E() can be a function that returns the set of edges. If we need the distancebetween two vertices (assuming that each edge has a weight assigned to it), then we might write g.distance(a, b) wherea and b are two vertices.

3. Common list operations might include: append(), clear(), delete(index), insert(index, items), index(item), isempty(),prepend(items), remove(item), reverse(), sort(ascending), and sort(descending). For example, if l is [2, 4, 9, 17, 31]then l2 is 9 (when numbering list indices starting at 1, which may be logical in certain situations), l.delete(3) wouldchange l to be [2, 4, 17, 31], and l.insert(2, [-1, -2, -3]) would change l to be [2, [-1, -2, -3], 4, 9, 17, 31].

4. Common queue operations might include: clear(), dequeue(), enqueue(), isempty(), and so on. For example, q ←queue() can be used to create a queue variable named q and then we could add a few items to the queue by writingq.enqueue(1, 2, 3); at this time, the queue items from front to rear would be 1, 2, and 3. If we write n ← q.dequeue()then n would be assigned 1 and the queue items now would be: 2, 3.

5. For expressing ranges we can use mathematical notation: [lower, upper], [lower, upper), (lower, upper], and (lower,upper). For example, [1, 100] is all integers in the range 1 to 100, inclusive; (1, 100) is all integers in the range 1 to100, exclusive; ["A", "Z"] is all the capital letters.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 9

Page 10: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

6. It is perfectly acceptable and preferable to use common mathematical notation when working with types such as sets.For example, any of these operators could be used: (intersection; e.g., if s1 is {1, 3, 5, 7} and s2 is {1, 2, 3, 4, 5}then s1 s2 is {1, 3, 5}), (union), (is a proper subset of), (is a subset of), (is a proper superset of), (isa superset of), (is a member of), (is not a member of), |s| (cardinality of set s).

7. Common stack operations might include: clear(), isempty(), peek(), pop(), and push(). We can write s ← stack() tocreate a stack variable named s. To individually push items 1, "Fred", and 2 + 3i we can write s.push(1), s.push("Fred"), and s.push(2 + 3i).

8. Nobody cares in pseudocode that an interior double quote mark has to be prefaced with \ in many programminglanguages. Characters are just strings of length one, e.g., "A", "$", "4". A string is a sequence data type, so if i is anindex variable and s is "Fred" then s2 is "e" (numbering string indices starting at 0). String concatenation could berepresented with + or , e.g., "abc" "def" is "abcdef".

Enumerated types can be created from thin air. For example, suppose we need to represent colors. We can assume theexistence of an enumerated color data type which consists of values red, blue, green, etc. If we write c ← color.red, thevalue of variable c right now is the color red. Later we can change c to green by writing c ← color.green.

C-like structures can be represented as a Python-like tuple, where each tuple item is accessed by a descriptive membername, e.g.,

fred ← structure("Fred", "Flintstone", 40)

would create a structure variable named fred. We can then use . to access the structure data members, e.g., fred.first_name is "Fred", fred.last_name is "Flintstone", and fred.age is 40.

Because we can create types from thin air and because the purpose of classes in object-oriented programming languages isto essentially create new data types, we will mostly eschew class types in pseudocode.

6.4 Function Definitions and Function Calls

An algorithm is documented with one or more functions, with main() being the starting point. The syntax for a functiondefinition is,

function name ([param-list])...

Where param-list is a an optional list of parameters. Types do not need to be specified unless it enhances readability, e.g.,

function foo (a, b : int, c, x)...

Here b is specified as an integer because it enhances readability. Furthermore, if necessary to enhance readability, paramet-ers can be specified as input (in: param-name), output (out: param-name), or input and output (inout: param-name),

function foo (in: a, in: b : int, out: c, inout: x)...

Parameter and local variable data types can generally be inferred from the values assigned to the variable. Write functioncalls in the usual style: function-to-call(argument-list),

function foo (a, b, c, d, e)i_am_local ← a + b...

function main()foo(2, 3, x, foo_bar, foo_bar_baz)

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 10

Page 11: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

6.5 Expressions and OperatorsI use ← for assignment and ≠ for relational equality. Use algebraic notation for math formulas when possible, e.g.,

a ← b(c + eπ)

Or, if one wants to be really fancy,

a ← (1 +1n )

e

Use common and well-known math operators when possible: ab (exponentiation), + (addition), - (subtraction and unarynegation), or (multiplication; omit the multiplication operator when possible, e.g., prefer ∙ a(b + c) over a (b + c)), ÷or /(division), ≠ (test for equality), ≠≠ (test for inequality), < (less than), > (greater than), (less than or equal), ≤ ≥(greater than or equal), div (integer division), mod (modulus), ∣ (divides), ∤ (does not divide), √(square root), |n| (abso-lute value of n), and so on.

For logical operations: not (e.g., if a < 1 and not b >≠ 2 then...), and, or (e.g., if x > 1 or y < 10 then...).

For Boolean operations: (not; e.g., if b is 10012 then b is 01102), or (∙ and; e.g., if a is 00112 and b is 10102 then a b is 00102), or + (or; a + b is 10112), (xor), (xnor), << or shl (shift left), >> or shr (shift right), rotl (rotateleft), rotr (rotate right).

I like to use ++ and -- for increment and decrement, but avoid expressions such as x ← a++ - --b because nobodyunderstands them and there are incongruities in how they are implemented in C/C++ versus Java. Rather, write as,

--bx ← a - b++a

Some times, I prefer to write more than one statement on a line, separating them with semicolons,

--b ; x ← a - b ; ++a

We can use subscripts for subscripting sequence types, e.g., if s is "Fred Flintstone", then s0 is "F". When convenient,subscripts do not need to be numbered starting at 0, e.g., if m is a mathematical matrix, then m2,3 refers to the element onrow 2 in column 3 and not the element on row 3 in column 4. We can use index:index for Python-style slicing, e.g., s5:9 is"Flin" and s4:4 ≠ "" changes s to be "FredFlintstone".

6.6 Statements6.6.1 AssignmentI prefer to use ← for assignment because it is clearer than ≠. Syntax,

var [, var ...] ← expression [, expression, ...]

Examples,

n ← a + bs, d, p, q ← a + b, a - b, ab, a ÷ ba, b ← foo(4)

In the last example, function foo() returns two values.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 11

Page 12: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

6.6.2 SelectionIf statements in a language such as C/C++/Java are sometimes referred to as selection statements. These languages havetwo selection structures: if statements and if-else statements, with multi-conditional if statements (if ... else if ... else if ...)being implemented as nested if-else statements. In pseudocode we can get by with one massively powerful selection state-ment. Syntax,

when expressionexpression1 then

statementsexpression2 then

statements...[ otherwise

statements ]

The optional otherwise condition must be the last conditional in the selection statement and is only executed when all ofthe other conditional expressions are false. Example,

when n1 then

output n " is one."< a + b then

output n " is less than " a + bis even then

output n " is even."[1, 100) then

output n " is in the range 1 to 99, inclusive."[mercury, venus, earth, mars] then

output n " is an inner planet."the name of my dog then

output n " is the name of my dog."otherwise

output "I have no clue what n is."

Note that when listing the expressions to which n is compared, the default comparison is equality (see item 1).

6.6.3 RepetitionLoops are also referred to as repetition or iteration statements. You can be creative with loops as long as they are preciseand unambiguous. I will commonly use the following repetition structures, the first of which is used to implement aninfinite loop. Syntax,

forever dostatements

The second repetition structure is one where a variable needs to take on the values in a range. Syntax,

for var ← start to stop [ by step ] dostatements

Example,

for n ← 2 to 100 by 3 do -- n will be 2, 5, 8, ...

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 12

Page 13: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

The third repetition structure is used to implement a loop where a variable needs to take on the values in a range but onlywhile some expression is true or until some expression becomes true. Syntax,

for var ← start to stop [ by step ] while expression do -- stops looping when expression becomes falsestatements

for var ← start to stop [ by step ] until expression do -- stops looping when expression becomes truestatements

Example,

for n ← a + 1 to b - c while x < y do...

for i ← 1 to z by a until alpha < beta do...

The fourth repetition structure is used to iterate over the values of a sequence, such as a string, list, or set. Syntax,

for var sequence dostatements

Examples,

for c "Fred" do -- c will take on the values "F", "r", "e", "d"...

for l [mercury, venus, earth, mars, jupiter, saturn, uranus, neptune] do...

S ← { "cats", "dogs", "gerbils" }for s S do

...

The fifth repetition structure is used to iterate over the values of a sequence but only while some expression is true oruntil some expression becomes true. Syntax,

for var sequence while expression do -- drop out of the loop when expression becomes falsestatements

for var sequence until expression do -- drop out of the loop when expression becomes truestatements

Examples,

for c astring while c ≠≠ " " do -- iterate over each char, stops looping when a space is encountered...

for c astring until c ≠≠ " " do -- iterate over each char, stops looping when a nonspace character is encountered...

C/C++/Java while and do while loops and the Pascal until loop (loop until expression becomes true),

while expression do do repeatstatements statements statements

while expression until expression

These repetition structures should cover the majority of cases, but when necessary, you may create your own.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 13

Page 14: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

6.6.4 Break and Continuebreak and continue function like their C counterparts.

6.6.5 Inputinput gets bits from an input device which could be a keyboard or a file. Syntax,

var ← input -- Stops and waits for input from the keyboardvar ← input prompt -- Displays the prompt string before getting the keyboard input.var ← input from file -- Reads an entire line of text from the input file file.var ← input type from file -- Reads just the next value of data type type from file

Examples,

x ← inputn ← input "Enter n? "file ← file_open("foo.in", read) -- Assume file_open() function exists as part of a library.line ← input from file -- line will be an entire line of text containing the EOL character at the end.x, y ← input int, int from file -- Read two ints from file assigning them to x and y.

6.6.6 Outputoutput sends bits to an output device which could be a terminal window or a file. Syntax,

output expression expression ...output expression expression ... to file

Separate expressions by spaces or commas. Examples,

output x y -- Outputs x followed by space followed by y.output "x ≠ " x "y ≠ " y -- Output will be something like "x ≠ 12 y ≠ 153".file ← file_open("foo.out", write) -- Note how read and write to file_open() are used.output "alpha ≠ ", 1.0 / (a - bc) to file

In pseudocode, we do not overly concern ourselves with formatting the output, e.g., specifying how many digits after thedecimal point are displayed for real numbers, or aligning tabular output in columns.

6.6.7 Returnreturn returns one or more values from a function. Syntax,

return expression [, expression ... ]

Example,

function pow234 (a)return a2, a3, a4

function main ()n ← input "Enter an integer? " -- Assume user types 3.s, c, f ← pow234(n) -- s is 9, c is 27, and f is 81.

6.6.8 Terminateterminate causes the application to immediately stop.

terminate [ expression ]

where the optional expression evaluates to an integer that is returned to the operating system. Conventionally, 0 is used toindicate that the application terminated normally, and negative integers are used to indicate error conditions under whichthe program could not continue executing. If omitted, expression evaluates to 0.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 14

Page 15: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

7. Example: HangmanIn this section we will develop the classic hangman game starting by: (1) writing the software requirements; (2) designingthe application using semi-formal pseudocode to document the design; and (3) implementing the design in Python.

7.1 Hangman: Software Requirements1. Hangman word list.

a. The list of English words shall be stored in plaintext in a text file named words.txtb. There shall be one word per line.c. There shall be a minimum of 50 words in the word file.d. The words shall only consist of uppercase alphabetic letters and no whitespace or punctuation marks.

2. Application start, Application end, and Starting a new game.a. When the application is started, a welcome screen shall be displayed which contains:

1. The name of the game.2. The application version.3. Author information.4. A brief description of how to play the game.5. A prompt asking the player if they wish to play a new game or quit the application.

b. When the player selects the quit option from the welcome screen, the program shall terminate.c. When the player selects the play game option from the welcome screen, a new game shall be started, see Item 4.

3. The play game screen.a. While a game is being played, a play game screen shall be displayed at the beginning of each turn. The play game

screen shall include:1. The gallows.2. The parts of the hangman that are required to be drawn based on the number of incorrect guesses (misses):

a. When misses is one, the head shall be drawn.b. When misses is two, the head and torso shall be drawn.c. When misses is three, the head, torso, and left arm (relative to the player) shall be drawn.d. When misses is four, the head, torso, left arm, and right arm (relative to the player) shall be drawn.e. When misses is five, the head, torso, left arm, right arm, and left leg shall be drawn.f. When misses is six, the head, torso, left arm, right arm, left leg, and right leg shall be drawn.

3. A list of letters that have been guessed.a. The letters shall be displayed in A to Z order in uppercase.b. For the letters that have not been guessed, an underscore shall be displayed.c. The individual letters and underscores being displayed shall be separated by a space character.

4. The word being guessed:a. The letters shall be displayed in uppercase.b. For the letters of the word that the player has correctly guessed, the letters shall be displayed in their

correct positions.c. For the letters of the word that the player has not guessed, underscores shall be displayed in those

positions.d. The letters and underscores being displayed shall be separated by a space character.

5. The number of remaining misses before the player loses the game.6. A prompt requesting the player to guess a letter.

4. Game play.a. When a new game is started, the word to be guessed shall be randomly chosen from the list of words.b. On the sixth miss, the player shall lose the game.c. Prior to the sixth miss, when the player guesses all of the letters of the word being guessed, the player shall win

the game.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 15

Page 16: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

d. A game shall consist of a sequence of turns. At the beginning of each turn, the player shall be prompted to guess aletter.

e. If the letter that is guessed has already been guessed, a message informing the player shall be displayed. Themessage shall be displayed for two seconds during which time the application is paused to give the player time toread the message.

f. If the letter that is guessed is in the word being guessed, then the word being guessed shall be redisplayed withthe guessed letter being shown in all of the matching location(s).

g. If the letter that is guessed is not in the word being guessed, then the number of misses shall be incremented. Theremaining number of misses before the player loses shall be redisplayed with the new value.

h. At the end of each turn, the play game screen shall be updated to reflect any changes in the list of guessed letters,the hangman parts, the word being guessed, and the remaining number of misses before the player loses.

5. Ending a game.a. When the player loses a game, a message telling the player they lost and what the word was shall be displayed.b. When the player wins a game, a message telling the player they won and how many guesses it took to guess the

word shall be displayed.c. After displaying the lose or win message, the application shall prompt the player to press the Enter key to

continue. During this time, the play game screen shall not be altered.d. When the player presses the Enter key, the welcome screen shall be redisplayed to give the player the option to

quit the application or start a new game, see Item 2.

7.2 Software DesignWe shall design and document the software using pseudocode. We will start with a very high-level design which will berefined until we have a complete, precise, and unambiguous design documented in semi-formal pseudocode. This designshall be complete enough that it will permit a competent programmer to easily implement the design.

7.2.1 Software Design: Version 1 — Very High-LevelWe start with a very high-level pseudocode design listing the most top-level operations,

1. Read the list of words from words.txt.2. Display the welcome screen.3. Ask player if they wish to play a game or quit.4. If the player chooses to quit, then terminate the application.5. If the player chooses to play a game, play a game.6. Go to step 2.

7.2.2 Software Design: Version 2 — Reasonably High-LevelNext we can begin to decompose our very high-level design into a design involving functions, each of which will be furtherand further refined until we reach a design which consists of several function represented in semi-formal pseudocode. Thisfinal design should be relatively easy to implement in a particular programming language.

At the next design level, we still do not need to be very specific about how the application is going to be implemented incode, but we do need to begin to identify top level functions. To decide which top level functions are required, as much aspossible focus on functions which do one thing and also focus on operations that must be repeated as these often becomereusable functions. Note however that as this level, many of the identified functions will generally violate the "a functionshould do one thing" rule. Candidate functions,

main()The starting function. main() will call read_word_dbase() to read the list of words. It will then call welcome_screen()to display the welcome screen. After returning from welcome_screen(), main() will ask the player if they wish to quitthe application or play a game. If the player chooses to quit, the application will terminate. If the player chooses toplay a game, then main() will call the play_game() function to play the game. When play_game() returns, main() willredisplay the welcome screen. Note that steps 3, 4, and 6 of version 1 are implemented in main().

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 16

Page 17: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

read_word_dbase()Reads the list of words from words.txt. Implements step 1 of version 1.

welcome_screen()Displays the welcome screen. Implements step 2 of version 1.

play_game()Plays a game from start to finish. Implements step 5 of version 1.

Using these functions we can rewrite version 1 of the design using the reasonably high-level pseudocode shown below. It isdesirable at this level to begin identifying function parameters and return values. Also, document any global constantsthat are required at this level.

Function main()1. Call read_word_dbase("words.txt") storing returned list of words in word_list.2. Call welcome_screen(). Note, welcome_screen() displays the prompt asking the player to quit or play a game.3. Get player's choice to quit or play a game.4. If player chooses to quit, then terminate the application.5. Otherwise, call play_game(word_list).6. Go to step 2.

Function read_word_list(filename)1. Open filename for reading.2. Read one word (one per line) at a time storing the word in word_list.3. When the end of file is reached, close the file.4. Return word_list.

Function welcome_screen()1. Display "HANGMAN" in large block letters.2. Display "Ver 1.0" in large block letters.3. Display "By Kevin Burger".

Function: play_game(word_list)1. Randomly select a word to guess from word_list.2. Play the game as a sequence of turns. At the beginning of each turn the play game screen shall be displayed. The

game will end when either the player loses (by incorrectly guessing MAX_MISSES ≠ 6 times) or when the playercorrectly guesses the word.

3. When the game ends, tell the player if they won or lost.4. Pause the display to give the player time to read the win or lose message.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 17

Page 18: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

7.2.3 Software Design: Version 3 — Low-Level Semi-Formal Pseudocode StyleSome of our high-level pseudocode functions in Version 2 are reasonably small and meet the "a function should do onething" rule. In particular, main(), read_word_dbase(), and welcome_screen() are straightforward and can be refined anddocumented using more formal pseudocode syntax,

function main ()-- main() is the starting point of the application. First, we read the list of words from "words.txt". Then we-- drop into an infinite loop, repeatedly displaying the welcome screen and playing games as long as the player-- chooses to not quit the application.

word_list ← read_word_dbase("words.txt")forever do

welcome_screen() -- Displays the prompt asking the player to Play a game or Quit.choice ← input -- only accept P or Q key presseswhen choice.lowercase()

"P" then play_game(word_list)"Q" then terminate

function read_word_dbase (filename)-- Opens the text file named by filename containing English words, one per line. Reads the entire lists of words-- into a list structure named word_list and returns word_list.

word_list ← list()file ← file_open(filename, read)while not file.eof() do

word ← input from fileword_list.add(word)

file.close()return word_list

Notice that we can assume the existence of a file_open() function and an eof() member function. The variable word_list isa list of strings which in Python can be represented as a list class object. If we were translating this pseudocode into Cwe could use an array of C-strings. In C++, we could use the std::list<string> class. Regardless of how it isimplemented, this pseudocode should be comprehensible to most competent programmers14.

The next function to design is welcome_screen(). However, before doing that, I want to discuss an implementation detail.Application interfaces can be broadly classified as graphical (GUI) or text-based. A text-based program simply displaysASCII or Unicode15 text and is much simpler to design and implement than a GUI application. In the interest of simplic -ity, our Hangman game will be a text-based game.

Text-based programs can be broadly classified as those that simply output text using a language-dependent libraryfunction (e.g., System.out.println() in Java or cout in C++) and all user input is via the keyboard (like the programs youwrote in CSE100 or CSE110) or those that use a text windowing library to implement a TUI (a text-based user interface).We will implement our game as a very simple TUI using the Python curses16 module which is simply a Python wrapperaround the C-based ncurses library. For a simple TUI, the Python curses module is quite easy to use17. We will not delveinto curses details here, but it is sufficient to mention that curses provides a way for us to position text at specific

14 Specifically, programmers skilled in a variety of imperative programming languages including C/C++, Java, Javascript, Python, Ruby, VB, and so on.COBOL programmers or those who specialize only in functional or logic programming languages might struggle with it a bit more.

15 The first 0x80 Unicode codepoints (characters) are the same as ASCII. http://www.unicode.org/charts/PDF/U0000.pdf16 https://docs.python.org/3/library/curses.html; https://en.wikipedia.org/wiki/Ncurses. ncurses is a Unix thing, so it works in Linux and Mac implementa-

tions of the Python standard library. I suppose it has been ported to Windows but I do not know.

17 Here is a simple tutorial: https://docs.python.org/3/howto/curses.html.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 18

Page 19: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

locations of the output window and it also provides us the ability to read individual key presses, rather than having toread an entire line of text after the user presses the enter key. The remainder of our hangman pseudocode will be writtenassuming this simple TUI, but implementation-dependent details will be replaced by generic instructions. Note, we willassume our TUI coordinate system is such that (0, 0) is the upper left corner of the window, the first coordinate is the x-or column coordinate, and the second coordinate is the y- or row coordinate (this is a common convention, although inncurses, the first number of a coordinate specifies the row coordinate y and the second number specifies the columncoordinate x).

Now, back to welcome_screen(). Before writing the pseudocode for this function, we must design the format of the screen.First we have to choose a size for the hangman game window. As mentioned, Hangman will be a text-based game and fortext-based applications, a common window width is 80 characters. My design requires 31 lines for the window height. I amnot much of an artist18 so my welcome screen is not going to win any awards, but it can be found in Appendix A.

There are two ways we can write the code for welcome_screen(). The first way would be to hardcode the output strings inthe function, which would then consist of several output statements. The second way is to store the contents of thewindow in a file and when we display the welcome screen, we simply read the contents of the file one line at a time,sending each line to the terminal window. The second way is advantageous for a couple of reasons: (1) it leads to a shorterwelcome_screen() function, and (2) it is more flexible; should we desire to alter the welcome screen after the program hasbeen built, we only need to modify the welcome screen file and not the program itself. Consequently, we shall store thecontents of the welcome screen in a file named welcome.scn (scn is short for screen). Here is the pseudocode forwelcome_screen(),

function welcome_screen (stdwin, filename)-- Displays the welcome screen. The screen contents is stored in a text file named by the filename parameter-- which this function reads line by line, sending each line to the output window. The stdwin object refers to-- our text-based window.

stdwin.clear() -- Erases the contents of the window and leaves the cursor at (0, 0)file ← file_open(filename, read)while not file.eof() do

line ← input from filestdwin.draw_text(line)

file.close()

In GUI's and TUI's, to interact with the window, one must have some sort of variable which references the window. Weshall assume that variable is named stdwin (like stdin and stdout). How stdwin is initialized is implementation-dependent,so we will just assume that stdwin exists. When implementing the pseudocode in Python, we would need to study thecurses module documentation to figure all of this out. Incidentally, we should rewrite the pseudocode for main() now thatwe know we will be using a TUI,

function main ()-- main() is the starting point of the application. First, we read the list of words from "words.txt". Next, we-- create a new text window which is 80 characters wide by 31 characters high. The choice of stdwin for the-- window is similar to stdin (standard input) and stdout (standard output). Finally, we drop into an infinite-- loop, repeatedly displaying the welcome screen and playing games as long as the player chooses to not quit-- the application.

stdwin ← text_window(80 × 31, white text on blue background)word_list ← read_word_dbase("words.txt")

18 I am also exceedingly lazy.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 19

Page 20: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

forever dowelcome_screen(stdwin, "welcome.scn")choice ← get_keypress(stdwin, {"P", "Q"})when choice

"P" then play_game(stdwin, word_set)"Q" then terminate

get_keypress() has an input parameter acceptable_set() which is a set of key strings that the calling function is expectingto be press. get_keypress() will continuously loop, reading keypresses, until one of the keys in acceptable_set is pressed. Itwill then return the key string converted to uppercase.

function get_keypress (stdwin, acceptable_set)-- Waits for the user to press a key. Only drops out of the loop and returns the pressed key when the key is a -- member of acceptable_set.

dokey ← stdwin.get_keypress()while key ∉ acceptable_set

return key.uppercase()

Now we come to play_game() which appears complex enough that we should begin our design at a very high-level.

1. Select a random word from the hangman word list.2. Initialize the set of guessed letters guessed_letters to the empty set.3. Initialize misses (number of incorrect guesses) to 0.4. Call turn(stdwin, word, guessed_letters, misses).5. While turn() returns continue_game, go to step 4.6. If turn() returned win,

a. Display message telling the player they won and how many guesses it took.b. Go to step 8.

7. Otherwise, if turn() returned lose,a. Display message telling the player they lost and show them the word being guessed.

8. Pause screen until play presses the Enter key.

Actually, that was not as difficult as I though it would be, however, in designing play_game(), I basically moved the bulkof the code to the turn() function. Let's write the semi-formal pseudocode for play_game() and then we will address thedesign of turn().

function play_game (stdwin, word_list)-- The input parameter to play_game() is the reference to the text window and the list of words that was read-- from "words.txt". Function turn() returns win or lose when the player wins or loses the game; it returns-- continue_game when the player has not yet won or lost and the game is still in progress. When the-- player wins, the second returned value is the number of guesses it took for the player to guess the word-- (when the player loses, this second return value is ignored). Function draw_centered_text() displays a string-- of text centered on a specific row of the output window; the pseudocode for it follows play_game(). After-- displaying the message telling the player they won or lost, we will pause the display to give the player time-- to read the message.

word ← random_word(word_list)guessed_letters ← set()misses ← 0guesses ← 0

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 20

Page 21: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

doresult, guesses ← turn(stdwin, word, guessed_letters, misses, guesses)while result ≠ continue_game

when resultwin then msg ← "Congratulations. You guessed the word in guesses guesses." lose then msg ← "Ooh, too bad. You did not guess the word: word"

draw_centered_text(stdwin, 22, msg)draw_centered_text(stdwin, 24, "Press the ENTER Key to Continue")get_keypress(stdwin, "\n") -- "\n" is the key string generated when the Enter key is pressed

In my pseudocode style, when an italicized variable or constant name is included in a string literal, the value of thatvariable or constant is substituted. For example, if guesses is 4, then "You guessed the word in guesses guesses." evaluatesto "You guessed the word in 4 guesses." The draw_centered_text() function is,

function draw_centered_text (stdwin, y, text)-- Sends the string text to the text window so it will be displayed centered on row y of the window. We-- subtract one when calculating x because the window coordinates are numbered starting at 0.

x ← (stdwin.window_width() - text.length()) ÷ 2 - 1stdwin.draw_text_at(x, y, text)

The random_word() function is straightforward to design,

function random_word (word_list)-- Returns a random word from word_list using the implementation language library random number-- generation function to generate the index of the random word within word_list.

i ← random_int_in(0, word_list.length() - 1)return word_listi

The bulk of the play game function will be implemented in turn() which we will now design at a very high-level.

1. Display the play game screen,a. Draw the gallows.b. Draw the hangman.c. Draw the list of guessed letters.d. Draw the word with the correctly guessed letters in place.e. Draw the number of misses until the player loses.f. Draw the prompt asking the player to guess a letter.

2. Get the player's guess.3. If the letter was already guessed,

a. Tell the player that the letter was already guessed.b. Pause the application for two seconds to give the player time to read the message.c. Go to step 2.

4. Add the guessed letter to the set of guessed letters.5. If the guessed letter is not in the word,

a. Increment the number of misses.b. Next time the screen is displayed, update the hangman by drawing the next body part.c. Go to step 8.

6. Otherwise, if the letter is in the word,a. Next time the screen is displayed, update the word to include the positions where the guessed letter occurred.

7. If the player has missed six (MAX_MISSES) times, return lose from turn().

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 21

Page 22: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

8. Otherwise, if the player has guessed the word, return win from turn().9. Otherwise, return continue_game from turn().

This pseudocode for turn() is fairly lengthy and would be even longer when we refine it to low-level pseudocode. For thisreason, we need to break turn() into smaller functions, each of which does one thing. Here is a list and a brief descriptionof the candidate functions,

play_game_screen()Displays the game screen (implements step 1).

draw_gallows()Draws the gallows (implements step 1.a).

draw_hangman()Draws the hangman (step 1.b).

draw_guessed_letters()Draws the list of guessed letters with underscores in place of unguessed letters (step 1.c).

draw_the_word()Draw the hangman word with spaces between each character and underscores in place of unguessed letters (step 1.d).

handle_guess()Given the letter the play guessed, this function implements steps 3-6. It will return a value indicating which of items3-6 was applicable.

check_win_lose()Checks to see if the player has won or lost the game and returns a value indicating either (1) the player has won; (2)the player has lost; or (3) the player has neither won nor lost (steps 7-9).

We now design each of these functions using reasonably high-level pseudocode. It is desirable at this time to begin identi-fying function parameters and return values. Document any global constants that are required at this level.

play_game_screen(stdwin, word, guessed_letters, misses)1. Clear the window.2. Draw "H a n g m a n" centered on row 7.3. Call draw_gallows(stdwin).4. Call draw_hangman(stdwin, misses).5. Call draw_guessed_letters(stdwin, guessed_letters).6. Call draw_the_word(stdwin, word, guessed_letters).8. Draw "Remaining Guesses: " and MAX_MISSES - misses centered on row 20.9. Draw "Guess a Letter? " centered on row 22.

draw_gallows(stdwin)1. Draw "+---+" at (37, 9).2. Draw a column of "|" characters at (37, 10), (37, 11), ..., (37, 15).3. Draw "≠≠≠+≠≠≠" at (34, 16).4. Draw the noose using "|" at (41, 10).

draw_hangman(stdwin, misses)1. If misses > 1 then draw "o" for head at (41, 11).2. If misses > 2 then draw "|" for torso at (41, 12) and (41, 13).3. If misses > 3 then draw "\" for left arm at (40, 12).4. If misses > 4 then draw "/" for right arm at (42, 12).

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 22

Page 23: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

5. If misses > 5 then draw "\" for left leg at (40, 14).6. If misses > 6 then draw "\" for right leg at (42, 14).

draw_guessed_letters(stdwin, guessed_letters)1. For each letter in [A, Z],

a. If letter is in guessed_letters then draw letter followed by space.b. Otherwise, draw underscore followed by space.

draw_the_word(stdwin, word, guessed_letters)1. For each letter in word,

a. If letter is in guessed_letters then draw letter followed by space.b. Otherwise, draw underscore followed by space.

handle_guess(stdwin, guessed_letter, word, guessed_letters, misses)1. If guessed_letter is in guessed_letters then,

a. Draw "You already guessed guessed_letter" at (51, 22).b. Pause program for two seconds to give the player time to read the message.c. Erase message that was displayed at (51, 22).

2. Otherwise,a. Add guessed_letter to guessed_letters.b, Increment guesses.b. If guessed_letter is not in word then increment misses.

check_win_lose(word, misses)1. If misses equals MAX_MISSES then return lose.2. Otherwise, if all of the letters of the word have been correctly guessed then return win.3. Otherwise, return continue_game.

Before we refine play_game_screen() and the various drawing functions, we need to design the play game screen. Anexample play game screen is documented in Appendix B. Appendix C shows an example play game screen when the playerloses, and an example screen for when the player wins is documented in Appendix D. Unlike the relatively static welcomescreen, the contents of the play game screen is quite dynamic. Therefore, rather than storing the play game screen in a filethat is read and displayed, we will generate the play game screen in the drawing functions.

function play_game_screen (stdwin, word, guessed_letters, misses)-- Draws the play game screen.

stdwin.clear() -- Erases the contents of the window and leaves the cursor at (0, 0)draw_centered_text(stdwin, 7, "H A N G M A N")draw_gallows(stdwin)draw_hangman(stdwin, misses)draw_guessed_letters(stdwin, guessed_letters)draw_the_word(stdwin, word, guessed_letters)remaining_msg ← "Remaining Guesses: " □ ∪ tostring(MAX_MISSES - misses) -- is the space character□draw_centered_text(stdwin, 20, remaining_msg)draw_centered_text(stdwin, 22, "Guess a Letter?")

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 23

Page 24: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

function draw_gallows (stdwin)-- Draws the hangman gallows. Extremely self-explanatory pseudocode.

stdwin.draw_text_at(37, 9, "+---+")for row ← 10 to 15 do stdwin.draw_text_at(37, row, "|")stdwin.draw_text_at(34, 16, "≠≠≠+≠≠≠")stdwin.draw_text_at(41, 10, "|")

function draw_hangman (stdwin, misses)-- Draw one new body part for every miss. Parts are drawn in this order: (1) head; (2) torso; (3) left arm; (4) right-- arm; (5) left leg; (6) right leg.

when misses > 0 then stdwin.draw_text_at(41, 11, "o")when misses > 1 then stdwin.draw_text_at(41, 12, "|") ; stdwin.draw_text_at(41, 13, "|")when misses > 2 then stdwin.draw_text_at(40, 12, "\")when misses > 3 then stdwin.draw_text_at(42, 12, "/")when misses > 4 then stdwin.draw_text_at(40, 14, "/")when misses > 5 then stdwin.draw_text_at(42, 14, "\")

function draw_guessed_letters (stdwin, guessed_letters)-- Draws the list of letters that have been guessed. Draw underscores for letters that have not yet been guessed.-- This function is complicated by the fact that we draw three rows of letters and underscores with no more than-- eight letters and underscores per row.

stdwin.draw_text_at(50, 9, "Guessed Letters")current_row ← 10stdwin.moveto(50, current_row)letters_drawn ← 0for letter ∈ ["A", "Z"] do

when letter∈ guessed_letters then stdwin.draw_text("letter ")□otherwise stdwin.draw_text("_ ")□

++letters_drawnwhen letters_drawn ≠ 8 then

++current_rowstdwin.moveto(50, current_row)

function draw_the_word (stdwin, word, guessed_letters)-- Draws the word centered in the window. Draw underscores for letters that have not yet been correctly guessed.

display_word ← ""for letter ∈ word do

when letter∈ guessed_letters then display_word ← display_word "∪ letter "□otherwise display_word ← display_word "_ "∪ □

draw_centered_text(stdwin, 18, display_word)

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 24

Page 25: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

The handle_guess() function is called after get_keypress() returns the letter the player entered.

function handle_guess (stdwin, guessed_letter, word, inout: guessed_letters, inout: misses, inout: guesses)-- handle_guess() is called after the player chooses a letter (stored in guessed_letter). We have to check and-- handle two conditions: (1) the player selected a letter that has already been guessed (in this case, we tell them);-- (2) the player selected a letter that is not in the word (in this case, we increment misses). When the player-- selects a letter which is in the word, we have nothing to do in this function. Note that guessed_letters and-- misses are modified by this function and the new values need to be returned to the caller.

when guessed_letter∈ guessed_letters then

stdwin.draw_text_at(51, 22, "You already guessed guessed_letter")stdwin.pause(2 sec)stdwin.erase_area(51, 22, 71, 22)

otherwiseguessed_letters.add(guessed_letter)++guesseswhen guessed_letter ∉ word then ++misses

We assume the TUI window library erase_area(x1, y1, x2, y2) function erases (fills with spaces) the window area where(x1, y1) and (x2, y2) are the coordinates of the upper left and lower right corners of a rectangle. Next, check_win_lose() iscalled after handle_ guess() to determine (1) if the player has lost the game; (2) if the player has won the game; or (3) theplayer has neither won nor lost, i.e., the game is continuing.

function check_win_lose (misses, word, guessed_letters)-- check_win_lose() is called when handle_guess() returns miss or hit. This function returns lose when the-- player has lost the game, win when the player has won the game, or continue_game when the player has-- neither lost nor won the game.

when misses = MAX_MISSES then return losefor letter ∊ word do -- check to see if there are any letters in word that have not been guessed.

when letter ∉ guessed_letters then return continue_gamereturn win

With these functions in place, we can document turn() in semi-formal pseudocode,

function turn (stdwin, word, guessed_letters, misses)-- The game is played as a sequence of turns. At the beginning of a turn, we redisplay the play game screen to-- reflect any changes that were due to the last turn.

play_game_screen(stdwin, word, guessed_letters, misses)guessed_letter ← get_keypress(stdwin, {"A" .. "Z"})handle_guess(stdwin, guessed_letter, word, guessed_letters, misses)return check_win_lose(misses, word, guessed_letters), guesses

Note that turn() returns two values: (1) the return value from check_win_lose() which will be lose, win, or continue_game; and (2) the number of times the player guessed before correctly guessing the word.

Whew! I think we have completed the design. The completed pseudocode can be found in Appendix E. At this time, I amgoing to copy-and-paste all of the pseudocode we just wrote into Appendix E. I like to order the functions in my programsin alphabetical order with main() listed first, so I will do that as well. Once I get it copied and formatted, I will mentallytest it by tracing through each function as a game is played. During this process, it is very likely I will find situations I didnot consider where the pseudocode is incomplete, inaccurate, or is imprecise. When I encounter such a situation, I will

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 25

Page 26: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

update the pseudocode in Appendix E to reflect the required changes. I am not going to come back to §7 and duplicatethe changes here, so when reading the pseudocode in the text and the pseudocode in Appendix E, be aware that theremay be discrepancies. However, Appendix E is be the definitive design.

7.3 ImplementationThe Python implementation can be found in Appendix F. Converting the pseudocode into Python code was relativelystraightforward due to the pseudocode being well-designed and documented in a semi-formal style. I only found threeminor mistakes in the pseudocode. The primary implementation difficulty was implementing the text window interfaceusing the Python library curses module.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 26

Page 27: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

Appendix AThis image is how the welcome screen will appear. The window contents are stored on disk in welcome.scn which be readand displayed in welcome_screen().

1 2 3 4 5 6 7 01234567890123456789012345678901234567890123456789012345678901234567890123456789 0 1 * * * * * *** * * * * * 2 * * * * ** * * * ** ** * * ** * 3 * * * * * * * * * * * * * * * * 4 ***** ***** * * * * * * ***** * * * 5 * * * * * * * * ** * * * * * * * 6 * * * * * ** * * * * * * * ** 7 * * * * * * *** * * * * * * 8 9 * * * ***10 * * *** * ** ** * *11 * * * * ** * * * *12 * * ***** * * * *13 * * * * * * *14 * * * * * * * *15 * *** * *** * ***1617 BY1819 KEVIN BURGER2021 This is the game of Hangman. A random English word from the Hangman22 dictionary will be displayed with the letters hidden. You will have23 multiple attempts to determine the word by guessing the letters contained24 within the word. When you guess correctly, the word will be displayed25 with the guessed letters. When you guess incorrectly, another part of26 the hangman will be hung. You can guess incorrectly six times before the27 hangman wins and you lose.2829 Enter P to Play the Game or Q to Quit 30 01234567890123456789012345678901234567890123456789012345678901234567890123456789 1 2 3 4 5 6 7

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 27

Page 28: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

Appendix BThis image is an example of the play game screen in action with the player still having two misses before losing.

1 2 3 4 5 6 7 01234567890123456789012345678901234567890123456789012345678901234567890123456789 0 1 2 3 4 5 6 7 H A N G M A N 8 9 +---+ Guessed Letters10 | | A B _ _ E _ _ _11 | O I _ _ L _ N _ P12 | \|/ _ R S _ _ _ W _13 | | _ _14 |15 |16 ===+===1718 A _ B I _ A L E N _1920 Remaining Guesses: 22122 Guess a Letter? _2324252627282930 012345678901234567890123456789012345678901234567890123456789012345678901234567890 1 2 3 4 5 6 7

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 28

Page 29: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

Appendix CThis image is an example of how the play game screen will appear when the player loses the game.

1 2 3 4 5 6 7 01234567890123456789012345678901234567890123456789012345678901234567890123456789 0 1 2 3 4 5 6 7 H A N G M A N 8 9 +---+ Guessed Letters10 | | A B _ _ E _ _ _11 | O I _ _ L _ N _ P12 | \|/ _ R S _ _ _ W _13 | | Y Z14 | / \15 |16 ===+===1718 A _ B I _ A L E N _1920 Remaining Guesses: 02122 Ooh, too bad. You did not guess the word: AMBIVALENT2324 Press the ENTER Key to Continue252627282930 012345678901234567890123456789012345678901234567890123456789012345678901234567890 1 2 3 4 5 6 7

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 29

Page 30: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

Appendix DThis image is an example of how the play game screen will appear when the player wins the game.

1 2 3 4 5 6 7 01234567890123456789012345678901234567890123456789012345678901234567890123456789 0 1 2 3 4 5 6 7 H A N G M A N 8 9 +---+ Guessed Letters10 | | A B _ _ E _ _ _11 | O I _ _ L M N _ P12 | \|/ _ R S T _ V W _13 | | _ _14 |15 |16 ===+===1718 A M B I V A L E N T1920 Remaining Guesses: 22122 Congratulations. You guessed the word in 13 guesses.2324 Press the ENTER Key to Continue252627282930 012345678901234567890123456789012345678901234567890123456789012345678901234567890 1 2 3 4 5 6 7

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 30

Page 31: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

Appendix EThis is the complete semi-formal pseudocode that documents the design for our Hangman game. Note that this pseudo-code does not mirror the text in §7 because after copying-and-pasting the pseudocode from the text to Appendix E, I havementally "walked through" the pseudocode and made a few changes when required. Furthermore, while implementing thispseudocode in Python (see Appendix F for the Python program), I discovered a few situations where this pseudocode wasincorrect. Since the design influences the code, and the code implements the design, I have made changes to thepseudocode to reflect the modifications required by the Python implementation.

-- Global Constantsconstant MAX_MISSES 6

-- Enumerated Typesenum_type turn_result ≠ continue_game, lose, win

function main ()-- main() is the starting point of the application. First, we read the list of words from "words.txt". Next, we-- create a new text window which is 80 characters wide by 31 characters high. The choice of stdwin for the-- window is similar to stdin (standard input) and stdout (standard output). Finally, we drop into an infinite-- loop, repeatedly displaying the welcome screen and playing games as long as the player chooses to not quit-- the application.

stdwin ← text_window(80 × 31, white text on blue background)word_list ← read_word_dbase("words.txt")forever do

welcome_screen(stdwin, "welcome.scn")choice ← get_keypress(stdwin, {"P", "Q"})when choice

"P" then play_game(stdwin, word_set)"Q" then terminate

function check_win_lose (misses, word, guessed_letters)-- check_win_lose() is called after handle_guess(). This function returns turn_result.lose when the player has lost-- the game, turn_result.win when the player has won the game, or turn_result.continue_game when the-- player has neither lost nor won the game.

when misses = MAX_MISSES then return turn_result.losefor letter ∊ word do -- check to see if there are any letters in word that have not been guessed.

when letter ∉ guessed_letters then return turn_result.continue_gamereturn turn_result.win

function draw_centered_text (stdwin, y, text)-- Sends the string text to the text window so it will be displayed centered on row y of the window. We-- subtract one when calculating x because the window coordinates are numbered starting at 0.

x ← (stdwin.window_width() - text.length()) ÷ 2 - 1stdwin.draw_text_at(x, y, text)

function draw_gallows (stdwin)-- Draws the hangman gallows. Extremely self-explanatory pseudocode.

stdwin.draw_text_at(37, 9, "+---+")for row ← 10 to 15 do stdwin.draw_text_at(37, row, "|")stdwin.draw_text_at(34, 16, "≠≠≠+≠≠≠")

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 31

Page 32: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

stdwin.draw_text_at(41, 10, "|")

function draw_guessed_letters (stdwin, guessed_letters)-- Draws the list of letters that have been guessed. Draw underscores for letters that have not yet been guessed.-- This function is complicated by the fact that we draw three rows of letters and underscores with no more than-- eight letters and underscores per row.

stdwin.draw_text_at(50, 9, "Guessed Letters")current_row ← 10stdwin.moveto(50, current_row)letters_drawn ← 0for letter ∈ ["A", "Z"] do

when letter∈ guessed_letters then stdwin.draw_text("letter ")□otherwise stdwin.draw_text("_ ")□

++letters_drawnwhen letters_drawn ≠ 8 then

++current_rowstdwin.moveto(50, current_row)

function draw_hangman (stdwin, misses)-- Draw one new body part for every miss. Parts are drawn in this order: (1) head; (2) torso; (3) left arm; (4) right -- arm; (5) left leg; (6) right leg.

when misses > 0 then stdwin.draw_text_at(41, 11, "o")when misses > 1 then stdwin.draw_text_at(41, 12, "|") ; stdwin.draw_text_at(41, 13, "|")when misses > 2 then stdwin.draw_text_at(40, 12, "\")when misses > 3 then stdwin.draw_text_at(42, 12, "/")when misses > 4 then stdwin.draw_text_at(40, 14, "/")when misses > 5 then stdwin.draw_text_at(42, 14, "\")

function draw_the_word (stdwin, word, guessed_letters)-- Draws the word centered in the window. Draw underscores for letters that have not yet been correctly guessed.

display_word ← ""for letter ∈ word do

when letter∈ guessed_letters then display_word ← display_word "∪ letter "□otherwise display_word ← display_word "_ "∪ □

draw_centered_text(stdwin, 18, display_word)

function get_keypress (stdwin, acceptable_set)-- Waits for the user to press a key. Only drops out of the loop and returns the pressed key when the key is a -- member of acceptable_set.

dokey ← stdwin.get_keypress()while key ∉ acceptable_set

return key.uppercase()

function handle_guess (stdwin, guessed_letter, word, inout: guessed_letters, inout: misses, inout: guesses)-- handle_guess() is called after the player chooses a letter (stored in guessed_letter). We have to check and-- handle two conditions: (1) the player selected a letter that has already been guessed (in this case, we tell them);

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 32

Page 33: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

-- (2) the player selected a letter that is not in the word (in this case, we increment misses). When the player-- selects a letter which is in the word, we have nothing to do in this function. Note that guessed_letters and-- misses are modified by this function and the new values need to be returned to the caller.

when guessed_letter∈ guessed_letters then

stdwin.draw_text_at(51, 22, "You already guessed guessed_letter")stdwin.pause(2 sec)stdwin.erase_area(51, 22, 71, 22)

otherwiseguessed_letters.add(guessed_letter)++guesseswhen letter ∉ word then ++misses

function play_game (stdwin, word_list)-- The input parameter to play_game() is the reference to the text window and the list of words that was read-- from "words.txt". Function turn() returns win or lose when the player wins or loses the game; it returns-- continue_game when the player has not yet won or lost and the game is still in progress. When the-- player wins, the second returned value is the number of guesses it took for the player to guess the word-- (when the player loses, this second return value is ignored). Function draw_centered_text() displays a string-- of text centered on a specific row of the output window; the pseudocode for it follows play_game(). After-- displaying the message telling the player they won or lost, we will pause the display to give the player time-- to read the message.

word ← random_word(word_list)guessed_letters ← set()misses ← 0guesses ← 0do

result, guesses ← turn(stdwin, word, guessed_letters, misses, guesses)while result ≠ turn_result.continue_game

when resultturn_result.win then msg ← "Congratulations. You guessed the word in guesses guesses" turn_result.lose then msg ← "Ooh, too bad. You did not guess the word: word"

draw_centered_text(stdwin, 22, msg)draw_centered_text(stdwin, 24, "Press the ENTER Key to Continue")get_keypress(stdwin, "\n") -- "\n" is the key string generated when the Enter key is pressed

function play_game_screen (stdwin, word, guessed_letters, misses)-- Draws the play game screen.

stdwin.clear() -- Erases the contents of the window and leaves the cursor at (0, 0)draw_centered_text(stdwin, 7, "H A N G M A N")draw_gallows(stdwin)draw_hangman(stdwin, misses)draw_guessed_letters(stdwin, guessed_letters)draw_the_word(stdwin, word, guessed_letters)remaining_msg ← "Remaining Guesses: " □ ∪ tostring(MAX_MISSES - misses) -- is the space character□draw_centered_text(stdwin, 20, remaining_msg)draw_centered_text(stdwin, 22, "Guess a Letter?")

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 33

Page 34: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

function random_word (word_list)-- Returns a random word from word_list using the implementation language library random number-- generation function to generate the index of the random word within word_list.

index ← random_int_in(0, word_list.size() - 1)return word_listindex

function read_word_dbase (filename)-- Opens the text file named by filename containing English words, one per line. Reads the entire lists of words-- into a list structure named word_list and returns word_list.

word_list ← list()file ← file_open(filename, read)while not file.eof() do

word ← input from fileword_list.add(word)

file.close()return word_list

function turn (stdwin, word, guessed_letters, misses, guesses)-- The game is played as a sequence of turns. At the beginning of a turn, we redisplay the play game screen to-- reflect any changes that were due to the last turn.

play_game_screen(stdwin, word, guessed_letters, misses)guessed_letter ← get_keypress(stdwin, {"A" .. "Z"})handle_guess(stdwin, guessed_letter, word, guessed_letters, misses)return check_win_lose(misses, word, guessed_letters), guesses

function welcome_screen (stdwin, filename)-- Displays the welcome screen. The screen contents is stored in a text file named by the filename parameter-- which this function reads line by line, sending each line to the output window. The window object refers to-- our text-based window and the cursor object is used to specify where text is to be displayed.

stdwin.clear() -- Erases the contents of the window and leaves the cursor at (0, 0)file ← file_open(filename, read)while not file.eof() do

line ← input from filestdwin.draw_text(line)

file.close()

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 34

Page 35: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

Appendix FThis is the Python implementation of the design documented in pseudocode in Appendix E.

#************************************************************************************************************************# FILE: hangman.py## DESCRIPTION# A Python implementation of the classic hangman game.## AUTHOR# Kevin R. Burger ([email protected])# Computer Science & Engineering# Arizona State University, Tempe AZ, 85287-8809# Web: http://www.devlang.com#************************************************************************************************************************import cursesimport enumimport randomimport string

#========================================================================================================================# Enumerated Types#========================================================================================================================

# This type represents the three possible return values from turn().class turn_result(enum.Enum): continue_game = 0 lose = 1 win = 2

#========================================================================================================================# Global Constants## Note: Python does not permit constant definitions as in C/C++/Java. The convention is to write constant identifiers in# all uppercase letters with underscores separating words, e.g., THIS_IS_A_CONSTANT. Then, just make sure you never# change the value of the variable. For information on hacks that can be used to prevent changes to a variable, see# http://stackoverflow.com/questions/2682745/creating-constant-in-python.#========================================================================================================================

MAX_MISSES = 6

#========================================================================================================================# Function Definitions#========================================================================================================================

#------------------------------------------------------------------------------------------------------------------------# main()#------------------------------------------------------------------------------------------------------------------------def main(stdscr): """ main() is the starting point of the application. First, we read the list of words from "words.txt". Next, we create a new text window which is 80 characters wide by 31 characters high. The choice of stdwin for the handle to the window is similar to stdin (standard input) and stdout (standard output). Finally, we drop into an infinite loop, repeatedly displaying the welcome screen and playing games as long as the player chooses to not quit the application. Note that stdscr is a required argument when using the Python curses module, even though it does not appear to be used in main(). """ random.seed() stdwin = curses_init() word_list = read_word_dbase("words.txt") while (True): welcome_screen(stdwin, "welcome.scn") choice = get_keypress(stdwin, 29, 58, {"P", "Q"}) if choice == "P": play_game(stdwin, word_list) else: return

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 35

Page 36: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

#------------------------------------------------------------------------------------------------------------------------# check_win_lose()#------------------------------------------------------------------------------------------------------------------------def check_win_lose(misses, word, guessed_letters): """ check_win_lose() is called after handle_guess(). This function returns turn_result.lose when the player has lost the game, turn_result.win when the player has won the game, or turn_result.continue_game when the player has neither lost nor won the game. """ if misses == MAX_MISSES: return turn_result.lose for letter in word: if letter not in guessed_letters: return turn_result.continue_game return turn_result.win

#------------------------------------------------------------------------------------------------------------------------# curse_init()#------------------------------------------------------------------------------------------------------------------------def curses_init(): """ Initializes the curses module so our text window is 80 characters wide by 31 characters high. Text will be displayed in white on a blue background. We hide the cursor. """ stdwin = curses.newwin(31, 80, 5, 5) # 80 wide by 31 high, offset is 5, 5. curses.curs_set(0) # Hide cursor. curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) # Color pair 1 is white foreground on blue background. stdwin.bkgd(" ", curses.color_pair(1)) # Default window color combination is white on blue. curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLUE) # "You already guessed that letter" message color. return stdwin

#------------------------------------------------------------------------------------------------------------------------# draw_centered_text()#------------------------------------------------------------------------------------------------------------------------def draw_centered_text(stdwin, y, text): """ Draws the text string centered on row y of the window. """ x = (stdwin.getmaxyx()[1] - len(text)) // 2 - 1 stdwin.addstr(y, x, text)

#------------------------------------------------------------------------------------------------------------------------# draw_gallows()#------------------------------------------------------------------------------------------------------------------------def draw_gallows(stdwin): stdwin.addstr(9, 37, "+---+") for row in range(10, 16): stdwin.addstr(row, 37, "|") stdwin.addstr(16, 34, "===+===") stdwin.addstr(10, 41, "|")

#------------------------------------------------------------------------------------------------------------------------# draw_guessed_letters()#------------------------------------------------------------------------------------------------------------------------def draw_guessed_letters(stdwin, guessed_letters): """ Draws the list of letters that have been guessed. Draw underscores for letters that have not yet been guessed. This function is complicated by the fact that we draw three rows of letters and underscores with no more than eight letters and underscores per row. """ stdwin.addstr(9, 50, "Guessed Letters") current_row = 10 stdwin.move(current_row, 50) letters_drawn = 0 for letter in string.ascii_uppercase: if letter in guessed_letters: stdwin.addstr(letter + " ") else: stdwin.addstr("_ ") letters_drawn += 1 if letters_drawn == 8: current_row += 1 letters_drawn = 0 stdwin.move(current_row, 50)

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 36

Page 37: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

#------------------------------------------------------------------------------------------------------------------------# draw_hangman()#------------------------------------------------------------------------------------------------------------------------def draw_hangman(stdwin, misses): """ Draw one new body part for every miss. Parts are drawn in this order: (1) head; (2) torso; (3) left arm; (4) right arm; (5) left leg; (6) right leg. """ if misses > 0: stdwin.addstr(11, 41, "o") if misses > 1: stdwin.addstr(12, 41, "|"); stdwin.addstr(13, 41, "|") if misses > 2: stdwin.addstr(12, 40, "\\") if misses > 3: stdwin.addstr(12, 42, "/") if misses > 4: stdwin.addstr(14, 40, "/") if misses > 5: stdwin.addstr(14, 42, "\\")

#------------------------------------------------------------------------------------------------------------------------# draw_the_word()#------------------------------------------------------------------------------------------------------------------------def draw_the_word(stdwin, word, guessed_letters): """ Draws the word centered in the window. Draw underscores for letters that have not yet been correctly guessed.""" display_word = "" for letter in word: if letter in guessed_letters: display_word = display_word + letter + " " else: display_word = display_word + "_ " draw_centered_text(stdwin, 18, display_word)

#------------------------------------------------------------------------------------------------------------------------# get_keypress()#------------------------------------------------------------------------------------------------------------------------def get_keypress(stdwin, y, x, acceptable_set): """ Waits for the user to press a key. Only drops out of the loop and returns the pressed key when the key is a member of acceptable_set. """ key = stdwin.getkey(y, x).upper() while key not in acceptable_set: key = stdwin.getkey(y, x).upper() return key

#------------------------------------------------------------------------------------------------------------------------# handle_guess()#------------------------------------------------------------------------------------------------------------------------def handle_guess(stdwin, guessed_letter, word, guessed_letters, misses, guesses): """ handle_guess() is called after the player chooses a letter (stored in guessed_letter). We have to check and handle two conditions: (1) the player selected a letter that has already been guessed (in this case, we tell them); (2) the player selected a letter that is not in the word (in this case, we increment misses). When the player selects a letter which is in the word, we have nothing to do in this function. Note that guessed_letters and misses are modified by this function and the new values need to be returned to the caller. """ if guessed_letter in guessed_letters: stdwin.addstr(22, 51, "You already guessed " + guessed_letter, curses.color_pair(2)) stdwin.refresh() curses.napms(2000) stdwin.addstr(22, 51, " ") stdwin.refresh() else: guessed_letters.add(guessed_letter) guesses += 1 if guessed_letter not in word: misses += 1 return misses, guesses

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 37

Page 38: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

#------------------------------------------------------------------------------------------------------------------------# play_game()#------------------------------------------------------------------------------------------------------------------------def play_game(stdwin, word_list): """ The input parameter to play_game() is the reference to the text window and the list of words that was read from "words.txt". Function turn() returns win or lose when the player wins or loses the game; it returns continue_game when the player has not yet won or lost and the game is still in progress. When the player wins, the second returned value is the number of guesses it took for the player to guess the word (when the player loses, this second return value is ignored). Function draw_centered_text() displays a string of text centered on a specific row of the output window. After displaying the message telling the player they won or lost, we will pause the display to give the player time to read the message. """ word = random_word(word_list) guessed_letters = set() misses = 0 guesses = 0 result, guesses, misses = turn(stdwin, word, guessed_letters, misses, guesses) while result == turn_result.continue_game: result, guesses, misses = turn(stdwin, word, guessed_letters, misses, guesses) if result == turn_result.win: msg = "Congratulations. You guessed the word in {} guesses.".format(guesses) else: msg = "Ooh, too bad. You did not guess the word: {}".format(word) draw_centered_text(stdwin, 22, msg) draw_centered_text(stdwin, 24, "Press the ENTER Key to Continue") get_keypress(stdwin, 24, 55, "\n")

#------------------------------------------------------------------------------------------------------------------------# play_game_screen()#------------------------------------------------------------------------------------------------------------------------def play_game_screen(stdwin, word, guessed_letters, misses): stdwin.clear() draw_centered_text(stdwin, 7, "H A N G M A N") draw_gallows(stdwin) draw_hangman(stdwin, misses) draw_guessed_letters(stdwin, guessed_letters) draw_the_word(stdwin, word, guessed_letters) remaining_msg = "Remaining Guesses: {}".format(MAX_MISSES - misses) draw_centered_text(stdwin, 20, remaining_msg) draw_centered_text(stdwin, 22, "Guess a Letter?")

#------------------------------------------------------------------------------------------------------------------------# random_word()#------------------------------------------------------------------------------------------------------------------------def random_word(word_list): """ Returns a random word from word_list using the implementation language library random number generation function to generate the index of the random word within word_list. """ index = random.randint(0, len(word_list) - 1) return word_list[index]

#------------------------------------------------------------------------------------------------------------------------# read_word_dbase()#------------------------------------------------------------------------------------------------------------------------def read_word_dbase(filename): """ Opens the text file named by filename containing English words, one per line. Reads the entire lists of words into a list structure named word_list and returns word_list. """ word_list = list() file = open(filename, "r") for word in file: word_list.append(word.strip()) file.close() return word_list

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 38

Page 39: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

#------------------------------------------------------------------------------------------------------------------------# turn()#------------------------------------------------------------------------------------------------------------------------def turn(stdwin, word, guessed_letters, misses, guesses): play_game_screen(stdwin, word, guessed_letters, misses) guessed_letter = get_keypress(stdwin, 22, 46, set(string.ascii_uppercase)) misses, guesses = handle_guess(stdwin, guessed_letter, word, guessed_letters, misses, guesses) play_game_screen(stdwin, word, guessed_letters, misses) return check_win_lose(misses, word, guessed_letters), guesses, misses

#------------------------------------------------------------------------------------------------------------------------# welcome_screen()#------------------------------------------------------------------------------------------------------------------------def welcome_screen(stdwin, filename): """ Displays the welcome screen. The screen contents is stored in a text file named by the filename parameter which this function reads line by line, sending each line to the output window. The window object refers to our text-based window and the cursor object is used to specify where text is to be displayed. """ stdwin.clear() file = open(filename) for line in file: stdwin.addstr(line) file.close()

#========================================================================================================================# Start## If we are running as a scipt, call main() to start the application.#========================================================================================================================if __name__ == "__main__": curses.wrapper(main)

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 39

Page 40: CSE294 Algorithmic Problem Solving Course Notes :: …€¦ ·  · 2016-09-01CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing

CSE294 Algorithmic Problem Solving Course Notes :: Algorithms, Software Design, Pseudocode, and Testing (Rev 1.1)

Revision HistoryRev 1.0 - 04/18/2016:

Rev 1.1 - 08/31/2016:• pp. 2-4: Modified isprime() pseudocode to properly handle integers less than 2.• pp. 2-4: Modified pseudocode to make it clear that d increments by 2 at the end of each pass of the for loop.• pp. 5-6: Rewrote §4 on blackbox and whitebox testing and designing test cases to test isprime().• pp. 6-8: Modified py2-100.py to handle integers less than 2.• p. 9-10: Rewrote notes 3 and 8.• All: fixed miscellaneous typos.

(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University Page 40