2D Arrays in Python

undefined
 
2-D Arrays in Python
 
And how not to get snake-bitten
 
Bill Emshoff
Software Engineer
Lockheed Martin
Bill.Emshoff@att.net
 
First things first: Start Python!
 
To get the most out of this presentation, follow
along on your own PC in Python.
 
Depending upon your installation, you can get
there by typing “
python
” or “
py
” from a
command window, or better still, “
idle
” from the
search bar to bring up the Python Integrated
Development and Learning Environment (IDLE).
You should see something like this:
Python 3.9.1
Type "help" for more information.
>>>
Don’t be afraid to experiment with the
command-line interface!
 
Motivation: what good is a 2D
array for anyway?
 
 
By Source (WP:NFCC#4), Fair use,
https://en.wikipedia.org/w/index.php?curid=65727752
 
An Excel spreadsheet can be
thought of as a 2D array of rows
and columns, but let’s look at
something more fun, like how
we’d implement the game
Minesweeper in Python, where
each element on the board is
either a bomb (touch it and die!)
or a safe spot, containing a clue
about how many bombs are
nearby.
 
Background: Python lists as arrays
 
Python lists can be used as arrays
>>> shopping_list = [ "bread", "milk", "apples" ]
>>> shopping_list[0] # first item
'bread'
>>> shopping_list[2] # last item
'apples'
>>> shopping_list[-1] # also last item: list indices wrap!
'apples'
>>> len(shopping_list)
3
>>> # lists can be updated a number of ways:
>>> shopping_list.append("oranges")
>>> shopping_list.remove("apples")
>>> shopping_list
['bread', 'milk', 'oranges']
 
 
List of Lists as a 2D Array
 
A Python List can hold anything, so we
can use a List of Lists as a 2D array
>>> the_matrix = [ [1,2,3],
                   [4,5,6] ]
>>> the_matrix[0] # 1st row
[1, 2, 3]
>>> the_matrix[0][2] # element at 1st row, 2nd column
3
The syntax “matrix[row][col]” is the same
used for other languages like Java
 
Creating a zero-filled array of
variable size
 
Our game needs to support variable-sized grids.
Python has shortcuts to create arrays of any
size:
 
Using Python List Multiplication
>>> myArraySize = 4
>>> myArray = [0] * myArraySize
>>> myArray
[0, 0, 0, 0]
 
Using a List Comprehension: “Python’s killer
feature”
>>> myArray = [ 0 for _ in range(myArraySize) ]
>>> myArray
[0, 0, 0, 0]
 
 
Putting it all together: Creating an
empty game grid: 1
st
 attempt
 
Creating a 2D array the WRONG way
Nesting Python list multiplication (don’t do this)
>>> nRows = 3; nCols = 2
>>> myGrid = [ [0]*nCols ] * nRows
>>> myGrid
[[0, 0], [0, 0], [0, 0]]
Looks as expected.  Now set the 1
st
 element:
 
>>> myGrid[0][0] = 'B'
>>> myGrid
[['B', 0], ['B', 0], ['B', 0]]
Say what?  Is Python buggy???
 
Creating an empty game grid: why
the 1
st
 attempt failed
 
Important point to remember about objects
in Python (and languages like Java too!):
Variables are like 
pointers 
to an object, so
copying a variable doesn’t copy data, only a
pointer to the data:
>>> a = [1,2]; b = a
>>> a[0] = 3
>>> b    
# a is just pointer to the same array as b
[3, 2]
Lesson learned: If you want a copy of a list in
Python, you must explicitly copy it
 
Putting it all together: Creating an
empty game grid: The right way
 
Nesting a list comprehension
>>> myGrid = [ [ 0 for c in range(nCols) ]
            for r in range(nRows) ]
>>> myGrid[0][0] = '*'
>>> myGrid
[['*', 0], [0, 0], [0, 0]]
 
Alternative: use the list-multiply shortcut
but for the inner list only:
myGrid = [ [0]*nCols for r in range(nRows) ]
 
 
Printing out our grid
 
For a production-quality game, we’ll want to print our grid using a
graphic library, but for quick testing (and Code Quest
competitions), we’re going to just use text:
 
>>> def printGrid(grid):
    for row in grid:
        for item in row:
            # print each item with no newline between
            print(item, end='')
        print("")    # adds newline at end of row
 
>>> printGrid(myGrid)
B0
00
00
 
 
 
Student Exercise: completing the
Minesweeper grid
 
Next step in implementing the game: for a grid
populated by mines, marked with a “*” at any
selected point, we want a function to count the
adjacent bombs, horizontally, vertically, or diagonally,
e.g.,
>>> printGrid(myGrid)
*0
0*
00
>>> countAdjacentBombs(myGrid,0,1)
2
>>> countAdjacentBombs(myGrid,2,1)
1
Important: your function can’t access points outside the grid,
e.g., to access a row < 0 or a row past the end
 
 
 
 
 
Helpful python functions to help
implement our bomb-counting
function
 
# loop from 0 to the length of an array:
for r in range( len(myGrid) ):
 
# loop from “start” to “stop”:
for r in range(start, stop):
 
min(x,y)    # minimum of 2 numbers
max(x,y)    # maximum of 2 numbers
 
 
 
Filling the grid
 
Now that we can get the count of adjacent
bombs to any square, let’s create a function to
fill up the empty spots on the grid, using that
function we just created, e.g.,
 
>>> populateGrid(myGrid)
>>> printGrid(myGrid)
*2
2*
11
 
Wrap up
 
Today’s
Minesweeper-
themed exercises
were based off a
real recent Code
Quest contest, and
constitute 90% of
the code for this
problem – the rest
being boilerplate.
 
Possible Topics for another
session
 
Formatting / “pretty printing” Text
Regular Expressions
Beyond Lists: Other Python Containers:
Tuples, Sets, and Dictionaries
A Class on Classes in Python
Maze escapes using AI techniques
Handling the Unexpected: Exceptions
Other suggestions?
 
Appendix
A completed Code Quest solution
to the “Minequest” problem using
code written while preparing this
presentation
 
Minesweeper.py – a complete
Code Quest program entry
 
def printGrid(grid):
    for row in grid:
        for item in row:
            # print each item with no newline between
            print(item, end='')
        print("")    # adds newline at end of row
 
def countAdjacentBombs(grid, row, col):
    # count adjacent bombs above, below, left, and right
    numRows=len(grid); numCols=len(grid[0])
    numBombs = 0
    for r in range(max(0,row-1), min(numRows,row+2)):
        for c in range(max(0,col-1), min(numCols,col+2)):
            if grid[r][c] == '*':
                numBombs += 1
    return numBombs
 
 
def populateGrid(grid):
    numRows = len(grid)
    numCols = len(grid[0])    # assuming a rectangular grid
    for row in range(numRows):
        for col in range(numCols):
            if grid[row][col] != '*':
                # count adjacent bombs up, down, left, right
                numBombs = countAdjacentBombs(grid, row, col)
                grid[row][col] = numBombs
import sys  # for stdin
 
# Always start with reading in the number
of test cases from standard input.
cases = int(sys.stdin.readline())
 
# Loop for each test case. This is the
last line common to all problems
for caseNum in range(cases):
    s = sys.stdin.readline().split()
    numRows = int(s[0])
    numCols = int(s[1])
    numBombs = int(s[2])
    grid = [[0 for c in range(numCols)]
 
for r in range(numRows)]
    for bomb in range(numBombs):
        s = sys.stdin.readline().split()
        r = int(s[0])
        c = int(s[1])
 
        grid[r][c] = '*'
 
    populateGrid(grid)
    printGrid(grid)
 
Slide Note
Embed
Share

Explore the concept of 2D arrays in Python through the implementation of the Minesweeper game. Learn how to represent game boards, handle lists as arrays, and work with multi-dimensional data structures for efficient game development.

  • Python Arrays
  • Minesweeper Game
  • 2D Data Structures
  • Python Programming
  • Game Development

Uploaded on Aug 03, 2024 | 8 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. 2-D Arrays in Python And how not to get snake-bitten Bill Emshoff Software Engineer Lockheed Martin Bill.Emshoff@att.net

  2. To get the most out of this presentation, follow along on your own PC in Python. Depending upon your installation, you can get there by typing python or py from a command window, or better still, idle from the search bar to bring up the Python Integrated Development and Learning Environment (IDLE). You should see something like this: Python 3.9.1 Type "help" for more information. >>> Don t be afraid to experiment with the command-line interface! First things first: Start Python!

  3. An Excel spreadsheet can be thought of as a 2D array of rows and columns, but let s look at something more fun, like how we d implement the game Minesweeper in Python, where each element on the board is either a bomb (touch it and die!) or a safe spot, containing a clue about how many bombs are nearby. By Source (WP:NFCC#4), Fair use, https://en.wikipedia.org/w/index.php?curid=65727752 Motivation: what good is a 2D array for anyway?

  4. Python lists can be used as arrays >>> shopping_list = [ "bread", "milk", "apples" ] >>> shopping_list[0] # first item 'bread' >>> shopping_list[2] # last item 'apples' >>> shopping_list[-1] # also last item: list indices wrap! 'apples' >>> len(shopping_list) 3 >>> # lists can be updated a number of ways: >>> shopping_list.append("oranges") >>> shopping_list.remove("apples") >>> shopping_list ['bread', 'milk', 'oranges'] Background: Python lists as arrays

  5. A Python List can hold anything, so we can use a List of Lists as a 2D array >>> the_matrix = [ [1,2,3], [4,5,6] ] >>> the_matrix[0] # 1st row [1, 2, 3] >>> the_matrix[0][2] # element at 1st row, 2nd column 3 The syntax matrix[row][col] is the same used for other languages like Java List of Lists as a 2D Array

  6. Our game needs to support variable-sized grids. Python has shortcuts to create arrays of any size: Using Python List Multiplication >>> myArraySize = 4 >>> myArray = [0] * myArraySize >>> myArray [0, 0, 0, 0] Using a List Comprehension: Python s killer feature >>> myArray = [ 0 for _ in range(myArraySize) ] >>> myArray [0, 0, 0, 0] Creating a zero-filled array of variable size

  7. Creating a 2D array the WRONG way Nesting Python list multiplication (don t do this) >>> nRows = 3; nCols = 2 >>> myGrid = [ [0]*nCols ] * nRows >>> myGrid [[0, 0], [0, 0], [0, 0]] Looks as expected. Now set the 1st element: >>> myGrid[0][0] = 'B' >>> myGrid [['B', 0], ['B', 0], ['B', 0]] Say what? Is Python buggy??? Putting it all together: Creating an empty game grid: 1st attempt

  8. Important point to remember about objects in Python (and languages like Java too!): Variables are like pointers to an object, so copying a variable doesn t copy data, only a pointer to the data: >>> a = [1,2]; b = a >>> a[0] = 3 >>> b # a is just pointer to the same array as b [3, 2] Lesson learned: If you want a copy of a list in Python, you must explicitly copy it Creating an empty game grid: why the 1st attempt failed

  9. Nesting a list comprehension >>> myGrid = [ [ 0 for c in range(nCols) ] for r in range(nRows) ] >>> myGrid[0][0] = '*' >>> myGrid [['*', 0], [0, 0], [0, 0]] Alternative: use the list-multiply shortcut but for the inner list only: myGrid = [ [0]*nCols for r in range(nRows) ] Putting it all together: Creating an empty game grid: The right way

  10. For a production-quality game, well want to print our grid using a graphic library, but for quick testing (and Code Quest competitions), we re going to just use text: >>> def printGrid(grid): for row in grid: for item in row: # print each item with no newline between print(item, end='') print("") # adds newline at end of row >>> printGrid(myGrid) B0 00 00 Printing out our grid

  11. Next step in implementing the game: for a grid populated by mines, marked with a * at any selected point, we want a function to count the adjacent bombs, horizontally, vertically, or diagonally, e.g., >>> printGrid(myGrid) *0 0* 00 >>> countAdjacentBombs(myGrid,0,1) 2 >>> countAdjacentBombs(myGrid,2,1) 1 Important: your function can t access points outside the grid, e.g., to access a row < 0 or a row past the end Student Exercise: completing the Minesweeper grid

  12. # loop from 0 to the length of an array: for r in range( len(myGrid) ): # loop from start to stop : for r in range(start, stop): min(x,y) # minimum of 2 numbers max(x,y) # maximum of 2 numbers Helpful python functions to help implement our bomb-counting function

  13. Now that we can get the count of adjacent bombs to any square, let s create a function to fill up the empty spots on the grid, using that function we just created, e.g., >>> populateGrid(myGrid) >>> printGrid(myGrid) *2 2* 11 Filling the grid

  14. Todays Minesweeper- themed exercises were based off a real recent Code Quest contest, and constitute 90% of the code for this problem the rest being boilerplate. Wrap up

  15. Formatting / pretty printing Text Regular Expressions Beyond Lists: Other Python Containers: Tuples, Sets, and Dictionaries A Class on Classes in Python Maze escapes using AI techniques Handling the Unexpected: Exceptions Other suggestions? Possible Topics for another session

  16. Appendix A completed Code Quest solution to the Minequest problem using code written while preparing this presentation

  17. def printGrid(grid): import sys # for stdin for row in grid: # Always start with reading in the number of test cases from standard input. cases = int(sys.stdin.readline()) for item in row: # print each item with no newline between print(item, end='') # Loop for each test case. This is the last line common to all problems for caseNum in range(cases): s = sys.stdin.readline().split() numRows = int(s[0]) numCols = int(s[1]) numBombs = int(s[2]) grid = [[0 for c in range(numCols)] print("") # adds newline at end of row def countAdjacentBombs(grid, row, col): # count adjacent bombs above, below, left, and right numRows=len(grid); numCols=len(grid[0]) numBombs = 0 for r in range(max(0,row-1), min(numRows,row+2)): for r in range(numRows)] for bomb in range(numBombs): s = sys.stdin.readline().split() r = int(s[0]) c = int(s[1]) for c in range(max(0,col-1), min(numCols,col+2)): if grid[r][c] == '*': numBombs += 1 return numBombs grid[r][c] = '*' populateGrid(grid) printGrid(grid) def populateGrid(grid): numRows = len(grid) numCols = len(grid[0]) # assuming a rectangular grid for row in range(numRows): for col in range(numCols): if grid[row][col] != '*': # count adjacent bombs up, down, left, right numBombs = countAdjacentBombs(grid, row, col) grid[row][col] = numBombs Minesweeper.py a complete Code Quest program entry

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#