Question

In: Computer Science

Python: In the CIS 41A version of Battleship, the user tries to find the computer's battleship...

Python:

In the CIS 41A version of Battleship, the user tries to find the computer's battleship that has been randomly put on a grid of rows and columns (the game board). Here is how the game is played:

  1. The computer asks the user to choose the size of the board, which is a square of 2, 3, or 4 rows and columns.
  2. The computer randomly chooses a spot on the board (r, c) where r = row, c = column, as the location for the battleship
  3. The computer prints the board with the correct size, and asks the user for a row and a column.
  4. If the user row and column matches (r,c), then the computer prints the grid again with an X at the found location. This means the user has found the computer's battleship.
    Otherwise the computer prints the board again with no 'X'
  5. Repeat steps 3 and 4 until the user has found the battleship
  6. Then the computer prints the number tries that the user took.

Implementation

The program has 2 constants:  MIN which is set to 2, and MAX which is set to 4

and the program has 4 functions:

  1. getNum: get a number from the user and return it
    1. prompt the user for the number with an appropriate prompt string
    2. check that the input number is between a given low and high value, inclusive, or print an error message to show the valid range, and then re-prompt until you get a valid number
  2. printBoard: print the grid based on the size from the user
  3. start with a row of column numbers going across
  4. then a row of dashes, which is the top of the board
  5. each row of the board starts with a row number, then multiple patterns of:  '|', 3 spaces, and another '|'
    which makes up each 'square' in the grid
  6. after each row of squares is a row of dashes
  7. if the battleship has been sunken by the user, then the string '  X  '  (space, X, space) is printed instead of the 3 spaces
  8. hideShip: create 2 random numbers between 1 and MAX, to serve as the coordinates for the battleship
  9. the first 2 random numbers make up the (r, c) location of the battleship
  10. you can choose to print the 2 random numbers to screen to make testing easier
  11. play: play one game until the user has sunken the battleship
  12. call the getNum function to get the size of the board from the user. Pass input arguments to the function so that it can prompt the user appropriately and print the correct range if the input is not valid
  13. call the hideShip function to determine the hidden location of the battleship
  14. call the printBoard function to print the board with no 'X' (since the user hasn't guessed yet)
  15. call the getNum function twice, once to get the row and a second time to get the column from the user. Pass input arguments to the function so that it can prompt the user appropriately and print the correct range if the input is not valid
  16. - if the user hasn't guessed the location: print the same board, and loop back to step d

- if the user successfully guessed the locations: print the board with an 'X' at the correct location, and print the number of trie

  1. main: let the user keep playing the game until the user chooses to end
  1. seed the random generator
  2. call the play function to play the game one time
  3. ask the user whether to continue, and loop back to step b if the answer is 'y' or 'Y'.
    Otherwise the program ends.

Important notes (don't miss them in your code):

  • There should be 5 functions and each function should work as described.
  • The input arguments for the functions are not fully described in this lab document, it's your job to determine what data need to be passed to the functions and what (if any) return value there is
  • Don't use global variables (1pt deduction for each global variable). Instead, pass input arguments to the functions, and catch any return value.
  • Note that there should be only one printBoard function, and it should be able to print the board without the 'X' or with the 'X'. Don't write 2 different printBoard functions.
    Likewise, there is only one getNum function, and it should be able to prompt the user and print the appropriate error message, depending on whether it's the size of the board, the row number, or the column number.
    This is how a function can make your program shorter: you write 1 function and call it 3 times, instead of writing 3 blocks of code to get the 3 values.
  • The board game (the rows and columns and row / column numbers) should line up correctly, no matter the size of the board. This is your practice with using loops.
  • Make sure to document your code:
    -- A comment at the top of the file with your name and lab number

-- A docstring (not a comment) for each function, except for the main function

Solutions

Expert Solution

from random import randint
import os

class Ship:
def __init__(self, size, orientation, location):
self.size = size
  
if orientation == 'horizontal' or orientation == 'vertical':
self.orientation = orientation
else:
raise ValueError("Value must be 'horizontal' or 'vertical'.")
  
if orientation == 'horizontal':
if location['row'] in range(row_size):
self.coordinates = []
for index in range(size):
if location['col'] + index in range(col_size):
self.coordinates.append({'row': location['row'], 'col': location['col'] + index})
else:
raise IndexError("Column is out of range.")
else:
raise IndexError("Row is out of range.")
elif orientation == 'vertical':
if location['col'] in range(col_size):
self.coordinates = []
for index in range(size):
if location['row'] + index in range(row_size):
self.coordinates.append({'row': location['row'] + index, 'col': location['col']})
else:
raise IndexError("Row is out of range.")
else:
raise IndexError("Column is out of range.")

if self.filled():
print_board(board)
print(" ".join(str(coords) for coords in self.coordinates))
raise IndexError("A ship already occupies that space.")
else:
self.fillBoard()
  
def filled(self):
for coords in self.coordinates:
if board[coords['row']][coords['col']] == 1:
return True
return False
  
def fillBoard(self):
for coords in self.coordinates:
board[coords['row']][coords['col']] = 1

def contains(self, location):
for coords in self.coordinates:
if coords == location:
return True
return False
  
def destroyed(self):
for coords in self.coordinates:
if board_display[coords['row']][coords['col']] == 'O':
return False
elif board_display[coords['row']][coords['col']] == '*':
raise RuntimeError("Board display inaccurate")
return True

  
#Settings Variables
row_size = 9 #number of rows
col_size = 9 #number of columns
num_ships = 4
max_ship_size = 5
min_ship_size = 2
num_turns = 40

#Create lists
ship_list = []

board = [[0] * col_size for x in range(row_size)]

board_display = [["O"] * col_size for x in range(row_size)]

#Functions
def print_board(board_array):
print("\n " + " ".join(str(x) for x in range(1, col_size + 1)))
for r in range(row_size):
print(str(r + 1) + " " + " ".join(str(c) for c in board_array[r]))
print()

def search_locations(size, orientation):
locations = []

if orientation != 'horizontal' and orientation != 'vertical':
raise ValueError("Orientation must have a value of either 'horizontal' or 'vertical'.")

if orientation == 'horizontal':
if size <= col_size:
for r in range(row_size):
for c in range(col_size - size + 1):
if 1 not in board[r][c:c+size]:
locations.append({'row': r, 'col': c})
elif orientation == 'vertical':
if size <= row_size:
for c in range(col_size):
for r in range(row_size - size + 1):
if 1 not in [board[i][c] for i in range(r, r+size)]:
locations.append({'row': r, 'col': c})

if not locations:
return 'None'
else:
return locations

def random_location():
size = randint(min_ship_size, max_ship_size)
orientation = 'horizontal' if randint(0, 1) == 0 else 'vertical'

locations = search_locations(size, orientation)
if locations == 'None':
return 'None'
else:
return {'location': locations[randint(0, len(locations) - 1)], 'size': size,\
'orientation': orientation}

def get_row():
while True:
try:
guess = int(input("Row Guess: "))
if guess in range(1, row_size + 1):
return guess - 1
else:
print("\nOops, that's not even in the ocean.")
except ValueError:
print("\nPlease enter a number")

def get_col():
while True:
try:
guess = int(input("Column Guess: "))
if guess in range(1, col_size + 1):
return guess - 1
else:
print("\nOops, that's not even in the ocean.")
except ValueError:
print("\nPlease enter a number")

# Create the ships

temp = 0
while temp < num_ships:
ship_info = random_location()
if ship_info == 'None':
continue
else:
ship_list.append(Ship(ship_info['size'], ship_info['orientation'], ship_info['location']))
temp += 1
del temp

# Play Game
os.system('clear')
print_board(board_display)

for turn in range(num_turns):
print("Turn:", turn + 1, "of", num_turns)
print("Ships left:", len(ship_list))
print()
  
guess_coords = {}
while True:
guess_coords['row'] = get_row()
guess_coords['col'] = get_col()
if board_display[guess_coords['row']][guess_coords['col']] == 'X' or \
board_display[guess_coords['row']][guess_coords['col']] == '*':
print("\nYou guessed that one already.")
else:
break

os.system('clear')

ship_hit = False
for ship in ship_list:
if ship.contains(guess_coords):
print("Hit!")
ship_hit = True
board_display[guess_coords['row']][guess_coords['col']] = 'X'
if ship.destroyed():
print("Ship Destroyed!")
ship_list.remove(ship)
break
if not ship_hit:
board_display[guess_coords['row']][guess_coords['col']] = '*'
print("You missed!")

print_board(board_display)
  
if not ship_list:
break

# End Game
if ship_list:
print("You lose!")
else:
print("All the ships are sunk. You win!")


Related Solutions

Python Language: In the CIS 41A version of Battleship, the user tries to find the computer's...
Python Language: In the CIS 41A version of Battleship, the user tries to find the computer's battleship that has been randomly put on a grid of rows and columns (the game board). Here is how the game is played: The computer asks the user to choose the size of the board, which is a square of 2, 3, or 4 rows and columns. The computer randomly chooses a spot on the board (r, c) where r = row, c =...
Create an application that makes the user guess a number. The user must be allowed tries....
Create an application that makes the user guess a number. The user must be allowed tries. You must have a loop, user input (Scanner), and a constructor. (JAVA)
        Explain how Rawls tries to justify his solution in his own         "unique" version of...
        Explain how Rawls tries to justify his solution in his own         "unique" version of contractarianism.         Explain what the following terms refer to:                (1) Original Position                (2) Veil of Ignorance                (3) Maximin Rule
When a user tries to write a file, the file system needs to detect if that...
When a user tries to write a file, the file system needs to detect if that file is a directory so that it can restrict writes to maintain the directory’s internal consistency. Given a file’s name, how would you design NTFS to keep track of whether each file is a regular file or a directory?
Flowchart + Python. Ask the user for a value. Then, ask the user for the number...
Flowchart + Python. Ask the user for a value. Then, ask the user for the number of expressions of that value. Use While Loops to make a program. So then, it should be so that 5 expressions for the value 9 would be: 9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 Flowcharts and Python Code. Not just Python code. I cannot read handwriting....
In python. Projectile motion: Write a python program that will ask the user for      an...
In python. Projectile motion: Write a python program that will ask the user for      an initial height y0, initial velocity v, launch angle theta, and mass m.      Create two functions, one that will calculate max height      of the projectile, and one that will calculate the range. Ask the     user which one he/she would like to calculate, then present them with the answer. (use kg, m and m/s)
Create a program (Python) YourFirstnameLastnameA06b.py to ask the user to create a password: The user will...
Create a program (Python) YourFirstnameLastnameA06b.py to ask the user to create a password: The user will first enter a password, then enters the same password again; If the second input is the same as first one, the user successfully creates the password. Print “Well done.”; Otherwise, the user will be directed to repeat the whole process (go to step 1.)
Calculating Delivery Cost Program in Python write a program in Python that will ask a user...
Calculating Delivery Cost Program in Python write a program in Python that will ask a user to enter the purchase total, the number of the items that need to be delivered and delivery day. Then the system displays the cost of delivery along with the total cost. Purchase total > $150 Yes Number of the items (N) N<=5 N>=6 Delivery day Same Day Next Day Same Day Next Day Delivery charges ($) 8 N * 1.50 N * 2.50 N...
How to do this in Python (using Lists): Create a python program that allows a user...
How to do this in Python (using Lists): Create a python program that allows a user to display, sort and update as needed a List of U.S States containing the State Capital and State Bird. You will need to embed the State data into your Python code. The user interface will allow the user to perform the following functions: 1. Display all U.S. States in Alphabetical order along with Capital and Bird 2. Search for a specific state and display...
MATLAB Program a Matlab version of Guess the Word. The word should be determined by user...
MATLAB Program a Matlab version of Guess the Word. The word should be determined by user input. Once the word is determined, the game should begin by displaying blanks (-) where all the letters of the word are. The game should then continue to prompt the player to guess a letter in the word. If the player guesses a letter that is in the word and not already displayed, that letter should be displayed everywhere it appears in the word....
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT