首页 > > 详细

讲解 COMP 202 - Foundations of programming Assignment 3 - Minesweeper Winter 2025调试Python程序

COMP 202 - Foundations of programming

Assignment 3 - Minesweeper

Winter 2025

Due: November 7 2025 11:59 pm

Late Penalty:  10% per day and up to 2 late days

Important Notice

Make sure that all file names and function names are spelled exactly as described in this docu- ment. Otherwise, a 50% penalty per question will be applied. You may make as many submis- sions as you like prior to the deadline, but we will only grade your final submission (all prior ones are automatically deleted). The following instructions are important:

•  Please read the entire assignment guidelines and this PDF before starting.  You must do this assignment individually.

•  The work submitted for this assessment is expected to be your own. The use of technologies such as ChatGPT is prohibited and will be considered a violation of the Code of Student Conduct.

• You must respect the prescribed return types.  For example, do not return a list if the instructions say to return None. Otherwise, no credit will be awarded for that question.

•  For this assignment, you aren’t allowed to use any of the list or string methods.  There are only two exceptions:  you may use  . append  and  . join.   Please  do  not ask for more exceptions.

 Do not use functions that we didnt mention in class.

 Do not use break or continue statements.

Directions:

To get full marks, you must follow all directions below:

•  Make sure that all file names and function names are spelled exactly as described in this document. Otherwise, a 50% penalty per question will be applied.

•  Make sure that your code runs without errors.  Code with errors will receive a very low mark.

 Write your name and student ID in a comment at the top of your program.

•  Name your variables appropriately.  The purpose of each variable should be obvious from the name.

•  Comment your code.  A comment every line is not needed, but there should be enough comments to fully understand your program.

• Avoid writing repetitive code, but rather call helper functions!  You are welcome to add additional functions if you think this can increase the readability of your code.

 Lines of code should NOT require the TA to scroll horizontally to read the whole thing.

• Vertical spacing is also important when writing code.  Separate each block of code (also within a function) with an empty line.

•  Up to 30% can be removed for bad indentation of your code, omission of comments, and/or poor coding style (as discussed in class).

 You can lose up to 30% for not respecting the following requirements:

–  Calling functions outside the code (it is ok to call a function inside another function but not outside)

 Not following functions names

–  Using material not seen in class or using break or continue

Hints & tips

•  Start early. Programming projects always take more time than you estimate!

• Do not wait until the last minute to submit your code.  Submit early and often—a good rule of thumb is to submit every time you finish writing and testing a function.

• Write your code incrementally.  Don’t try to write everything at once.  That never works well. Start off with something small and make sure that it works, then add to it gradually, making sure that it works every step of the way.

•  Read these instructions and make sure you understand them thoroughly before you start. Ask questions if anything is unclear!

•  Seek help when you get stuck!  Check our discussion board first to see if your question has already been asked and answered.  Ask your question on the discussion board if it hasn’t been asked already. Talk to your TA during office hours if you are having difficulties with programming. Go to an instructor’s office hours if you need extra help with understanding a part of the course content.

At the same time, beware not to post anything on the discussion board that might give away any part of your solution—this would constitute plagiarism, and the consequences would be unpleasant for everyone involved.   If you  cannot think of a way to ask your question without giving away part of your solution, then please drop by our office hours.

•  If you come to see us in office hours, please do not ask “Here is my program. What’s wrong with it?” We expect you to at least make an effort to start to debug your own code, a skill which you are meant to learn as part of this course. And as you will discover for yourself, reading through someone else’s code is a difficult process—we just don’t have the time to read through and understand even a fraction of everyone’s code in detail.

However, if you show us the work that you’ve done to narrow down the problem to a specific section of the code, why you think it doesn’t work, and what you’ve tried to fix it, it will be much easier to provide you with the specific help you require and we will be happy to do so.

Learning Objectives:

The main learning objectives for this assignment are:

•  Correctly create and use variables.

•  Learn how to build expressions containing different type of operators.

  Get familiar with string concatenation.

  Correctly use print to display information.

•  Understand the difference between inputs to a function and inputs to a program (received from the user through the function input).

•  Correctly use and manipulate inputs received by the program from the function input.

•  Correctly use simple conditional statements.

•  Correctly use Loops

•  Correctly define and use simple functions.

•  Correctly define docstrings for each function

•  Solidify your understanding of how executing instructions from the shell differs from run- ning a program. Note that this assignment is designed for you to be practicing what you have learned up to and including Lecture 13 (topics:  Lists, Nested Loops and Nested Lists, Strings, Deep/Shallow copy, Raising Exceptions).  For this reason, you are NOT allowed to use anything seen after Lecture 13 or not seen in class at all.  You will be heavily penalized if you do so.  Also, you are not allowed to use  break  and  continue keywords.  For full marks, in addition to the points listed here, make sure to add the ap- propriate documentation string (docstring) to all the functions you write. The docstrings must contain the following:

• The type contract of the function.

• A description of what the function is expected to do.

• At least three (3) examples of calls to the function.  You are allowed to use at most one example per function from this PDF.

Minesweeper

For this assignment, you will design a basic version of Minesweeper and a (very simplified) bot that will automatically play Minesweeper for you. Write all your code in minesweeper. py.

How to Play Minesweeper

Minesweeper is played on a rectangular grid of cells.  Some of these cells contain  “mines”, and the player’s goal is to “sweep” all cells that do not contain a mine. At first, all cells are hidden (i.e.  the player does not know which cells contain a mine).  The player can then reveal cells by left-clicking on them.  If a cell does not contain a mine and is clicked, that cell will show a number representing the number of adjacent cells with mines:  an adjacent cell is a cell touching the current cell vertically, horizontally, or diagonally.  The player can also flag cells by right- clicking on them (the player will usually want to do this if they believe that there’s a mine at a specific cell).  If the player left-clicks a cell that contains a mine, the mine goes off and the player loses.  If instead the player reveals all cells that do not contain a mine (without clicking a mine along the way), the player wins.

Of course,  the easiest way to understand the game is to play it yourself!   There are many websites/mobile apps/etc. available to play Minesweeper. One of the simpler options is to Google search “Minesweeper”, then play the interactive that shows before the search results.

Minesweeper Board Representation

The instructions for specific functions will explain the implementation in greater detail, but hopefully this section will help with a general intuition for how we will code our version of Minesweeper. We will represent the board with two 2D lists.

Game Board

One of the boards will be a 2D list of characters (strings with length 1) representing the cells that the user sees. We will use '?' to represent unrevealed cells, '\u2691' to represent flagged cells, and the string representation of the corresponding integer to represent revealed cells.  (Unfortunately, we could not render the flag character in our text-editing software,  but  ,\u2691 , should look like a flag in Python.) We will generally call the 2D list of characters the  “game” board.

Figure 1: The '\u2691' character

Helper Board

We will need another 2D list to represent the actual positions of the mines (we will generally call this the “helper” board).  The helper board will hold integers at each position: mines will be represented with -1, while every non-mine position will hold an integer representing the number of adjacent cells with mines. It will take a bit of work to generate the helper board, as we will need to randomly generate mine positions, then ensure that the non-mine positions are correctly updated.  Once the helper board is correctly generated, it should be straightforward to update the game board every time the user reveals or flags a cell.

In fig. 2, we include 3 screenshots of the same board from different perspectives.  The first board is a Minesweeper game played in Google’s interactive, the second board is what we will show the user (a formatted version of the game board), and the third board is the helper board in its matrix form.

Figure 2: Minesweeper Board Representations

Note that our version of Minesweeper is simplified, so there are some small changes in behaviour from most implementations of Minesweeper. When you are unsure about the expected behaviour, first review the instructions carefully, then feel free to ask on Ed if something is unclear.

Safe Assumptions

 You may assume that inputs given to a function will match the expected type.

 You may assume that any list that is given as input is nonempty.

•  If given a row and column, you may assume that these coordinates represent a valid position (so assume safe coordinates in all functions, only exception: is valid position).

• You may assume that any given 2D list is a matrix, i.e.  each inner list has the same length.

• You may assume that any argument that refers to a “board” represents a valid helper or game board (with the type of board depending on the context).

• You may assume that the user is nice and smart and will only give inputs that make sense.

1    Nested List Functions  [30 Points]

We will start by writing a number of general functions for nested lists that will help us in the later parts.

1.1    init board [5 Points] Inputs:

• nb rows : positive int

• nb   cols : positive int

 value : any immutable type

Returns: 2D list

Description:  Construct and return a 2D list with nb rows rows and nb   cols columns, where each value in the inner lists is the given argument value.

Note: To avoid bugs in later functions, each inner list must be a distinct copy. In other words, the IDs of two inner lists should never match. To ensure this, we require that you use a nested loop to build the board. You may assume that the argument value itself is immutable, so you do not need to make copies of value.

Examples:

>>>  init board(3,  3,  0)

[[0,  0,  0],  [0,  0,  0],  [0,  0,  0]]

>>>  init board(4,  4,  ' 202 ' )

[[ ' 202 ' ,  ' 202 ' ,  ' 202 ' ,  ' 202 ' ],  [ ' 202 ' ,  ' 202 ' ,  ' 202 ' ,  ' 202 ' ],  [ ' 202 ' ,  ' 202 ' ,  ' 202 ' , ' 202 ' ],  [ ' 202 ' ,  ' 202 ' ,  ' 202 ' ,  ' 202 ' ]]

1.2    count total [5 Points]

Inputs:

 board : 2D list

• value : any type

Returns: int

Description: Return an integer representing the number of times that value occurs in board.

Keep in mind that board is a 2D list, so we really want to check how many times value occurs in the inner lists.

Note:  Recall that you  may not use any list or string methods  ( . append and  . join  are not helpful here). You must use a nested loop instead.

Examples:

>>>  count total([[ ' ? ' ,  ' 4 ' ,  ' ? ' ],  [ ' 2 ' ,  ' ? ' ,  ' ? ' ]],  ' ? ' )

4

>>>  count total([[0,  1,  2],  [3,  4,  6],  [7,  8,  9]],  5) 0

1.3    is valid position [5 Points]

Inputs:

 board : 2D list

 row : int

•  col : int

Returns: bool

Description: Return True if (row, col) is a valid position in board, False otherwise.  Although Python supports negative indexing for lists, we will consider a position to be invalid if row or col is negative.

Note: Recall that you may assume that board is a nonempty matrix.

Examples:

>>> board  =  init board(5,  5,  0)

>>>  is valid position(board,  2,  2)

True

>>>  is valid position(board,  5,  5)

False

>>>  is valid position(board,  -1,  2)

False

1.4    get neighbour positions [10 Points]

Inputs:

 board : 2D list

 row : int

  col : int

Returns: 2D list of integers

Description: Given position (row, col), return a list of positions that are adjacent to (row, col) in board. We will represent each position as a 2-element list, i.e. in the form [neighbour row, neighbour   col].   Recall that,  in  Minesweeper,  an adjacent position is considered to be any cell touching the current position: vertically, horizontally, or even diagonally. You will need to use is valid position to determine whether a candidate [neighbour row, neighbour   col] is actually in the board. Do not include the original position [row, col].

Notes: We do not want to write 8 different conditions for the 8 possible neighbours.  Instead, you must figure out a way to use a nested loop to write this function. The order of the positions in the outer list does not matter (but row must come before col in an inner list).  Recall that you may assume that the input (row, col) is a valid position.  Recall that you may not use break or continue statements.

Examples:

>>> board  =  init board(3,  3,  0)

>>>  get neighbour positions(board,  1,  1)

[[0,  0],  [0,  1],  [0,  2],  [1,  0],  [1,  2],  [2,  0],  [2,  1],  [2,  2]]

>>>  get neighbour positions(board,  1,  2)

[[0,  1],  [0,  2],  [1,  1],  [2,  1],  [2,  2]]

1.5    count neighbours  [5 points]

Inputs:

 board : 2D list

 row : int

  col : int

• value : any type Returns: int

Description: First, call get neighbour positions to get the positions adjacent to (row, col) in board.  Then, count how many of these positions in board contain value, and return this count.

Notes:  Recall that you may not use any list or string methods  ( . append and  . join are not helpful here). Recall that you may assume that (row, col) is a valid position.

Example:

>>>  count neighbours([[1,  1,  0,  0],  [-1,  2,  1,  1],  [1,  3,  -1,  2],  [0,  2,  -1,  2]], 2,  1,  -1)

3

2    The Helper Board [15 Points]

We will now write a few functions to help us construct a “helper” board. This is not the board that we will show to the user; instead, this board will store an integer at each position.  Each mine position will hold -1, and each non-mine position will hold an integer representing the number of adjacent (vertical, horizontal, or diagonal) mines. We will eventually use this board to help with revealing cells in the game board (the one that we show to the user).

2.1    new mine position [5 points]

Inputs:

• board : 2D list of integers Returns: int, int

Description: Repeatedly generate a random (valid) position, i.e.  a pair of two integers, until the value at that position in board is not -1.  Return these two integers.  (The idea here is to choose a random position that does not already represent a mine.)

Hint: The autograder will set a seed for testing purposes, so you will need to generate a random position in the same way.  We warn you of some possible mistakes in advance:  first, make sure that there are no redundant random . randint calls.   In this case, you may generate a truly random position, but the autograder will get a different result, and redundant code does not merit full credit. Second, do not choose the row, then randomly generate the column until you find a non-mine position. This may appear random, but it does not actually choose each position with equal probability (depending on the number of mines in each row).  Third, while it would still be correct to generate the column before the row, doing this will result in a different position from the autograder, so we ask that you generate the row before the column.

Notes: It is possible to achieve this using random. random, but we ask you to use random . randint for consistency with the autograder. For the docstring examples, we ask that you use random . seed so that the example is always true. You may assume that there is at least one position that does not hold -1. Recall that you may assume that board is a matrix.

Examples:

>>>  random. seed(202)

>>> new mine position([[0,  0,  0],  [0,  0,  0],  [0,  0,  0]])

(1,  2)

>>>  random. seed(202)

>>> new mine position([[0,  1,  1],  [0,  1,  -1],  [0,  1,  1]])

(1,  1)

2.2    new mine [5 points]

Inputs:

 board : 2D list of integers

Returns: None

Description:  First, call new mine position to get a randomly generated new mine position. Then, change the value at this position in board to -1.  Finally, for all adjacent positions (with respect to the random position) that do not hold -1, increase their values by 1.  (The idea here is to update adjacent non-mine values to reflect that they are now beside one more mine.)

Notes:  For the docstring examples, we ask that you use random . seed so that the example is always true. You must not return any value (other than None).  Do not return a list. You may assume that there is at least one position that does not hold -1.  Recall that you may assume that board is a matrix.

Examples:

>>>  random. seed(202)

>>> board  =  init board(3,  3,  0)

>>>  board

[[0,  0,  0],  [0,  0,  0],  [0,  0,  0]]

>>> new mine(board)

>>>  board

[[0,  1,  1],  [0,  1,  -1],  [0,  1,  1]]

>>> new mine(board)

>>>  board

[[1,  2,  2],  [1,  -1,  -1],  [1,  2,  2]]

2.3    generate helper board [5 points]

Inputs:

• nb rows : positive int

• nb   cols : positive int

• nb mines : nonnegative int Returns: 2D list of integers

Description: You now have everything you need to make the helper board.

First, call init board to create a board of 0s with nb rows rows and nb   cols columns.  This essentially represents a board with no mines.  Then, repeatedly call new mine on this board until you get a board with nb mines mines (cells with -1). Return this board.

Notes:  For the docstring examples, we ask that you use random . seed so that the example is always true. You may assume that nb mines is at most nb rows × nb   cols.

Examples:

>>>  random. seed(202)

>>>  generate helper board(5,  5,  7)

[[0,  0,  2,  -1,  -1],  [1,  1,  3,  -1,  3],  [2,  -1,  4,  2,  2],  [2,  -1,  3,  -1,  2], [1,  1,  2,  2,  -1]]

>>>  generate helper board(7,  7,  0)  ==  init board(7,  7,  0)

True

3    The Game Board  [15 Points]

We will now write some functions to help manage the board that the user sees.  To start, the board will be filled with '?'  characters  (representing cells that the user has yet to reveal).  In Minesweeper, the user typically left-clicks to reveal a cell or right-clicks to place a flag on a cell if they believe that it is a mine.  This part is not too complicated:  for a flag, we can just modify the game board directly, and to reveal a cell, we will use the helper board to determine the correct number.

3.1    flag [5 points]

Inputs:

 board : 2D list of characters

 row : int

  col : int

Returns: None

Description: For this feature, we will use the flag character:  '\u2691'. If the value at position (row, col) in board is '?', switch it to '\u2691'.  Similarly, if the value is '\u2691', switch it to '?'.  For any other value, we would not want to flag a cell that we know is not a mine, so you should not change the value.

Notes: You must not return any value (other than None).  Do not return a list.  Recall that you may assume that (row, col) is a valid position.

Examples:

These examples will be displayed with the actual flag character in Thonny.  It is equivalent to use '\u2691' wherever you see a flag character.

Figure 3: Placing a Flag on a Cell (flag example)

Figure 4: Removing a Flag from a Cell (flag example)

3.2    reveal [5 points]

Inputs:

• helper board : 2D list of integers

•  game board : 2D list of characters

 row : int

  col : int

Returns: None

Description:  First, get the value at position  (row, col) in helper board.  If it is -1, raise an  AssertionError  with  the  message  'BOOM!  You  lost.'.    (You  might  not  have  seen  an AssertionError before, but the syntax is the exact same as when you raise an exception that you have seen, like a TypeError or a ValueError.)  Otherwise, update game board at position (row, col) to be the string representation of the integer you found in helper board.

Notes: Most Minesweeper implementations prevent you from revealing a flagged cell.  However, we are keeping it simple:  the function should behave the same regardless of the value at that position in game board.  You must not return any value (other than None).  Do not return a list. Recall that you may assume that (row, col) is a valid position (in both boards).

Examples:

>>> helper board  =  [[2,  -1,  1],  [-1,  4,  3],  [2,  -1,  -1]]

>>>  game board  =  init board(3,  3,  ' ? ' )

>>>  game board

[[ ' ? ' ,  ' ? ' ,  ' ? ' ],  [ ' ? ' ,  ' ? ' ,  ' ? ' ],  [ ' ? ' ,  ' ? ' ,  ' ? ' ]]

>>>  reveal(helper board,  game board,  1,  1)

>>>  game board

[[ ' ? ' ,  ' ? ' ,  ' ? ' ],  [ ' ? ' ,  ' 4 ' ,  ' ? ' ],  [ ' ? ' ,  ' ? ' ,  ' ? ' ]]

>>>  reveal(helper board,  game board,  2,  2)

Traceback  (most  recent  call  last):

AssertionError:   BOOM! You  lost .

3.3    print board [5 points]

Inputs:

 board : 2D list of characters

Returns: None

Description: Display board such that the elements within a row are separated by a space and each row is separated by a newline.  Do not just write print(board), we do not want to include the brackets and commas. See the example for the exact format.

Hint: Recall that you may use  . join.

Example:

This example will be displayed with the actual flag character in Thonny. It is equivalent to use '\u2691' wherever you see a flag character.

Figure 5: print board example


联系我们
  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp
热点标签

联系我们 - QQ: 99515681 微信:codinghelp
程序辅导网!