Battleship!

A variation on the classic game. A ship of random length will be placed on a board whose size is determined by you, the player. You may also select the number of turns you would like to use to try to sink it. After each guess, the board will be updated to show your hits and misses. If you hit all of the blocks in the ship before you run out of turns, you win!

To play the game, execute the code in cells 1, 2, and 3. If you do not yet have the ipythonblocks module installed, execute cell 4 first.

The original code from the Codecademy lesson is included at the bottom so you can see how the project evolved from that.



In [ ]:
from random import randint
from ipythonblocks import BlockGrid
from IPython.display import clear_output

In [ ]:
def place_ship(boardsize):
    '''
    Place a ship randomly on the board
    of size boardsize x boardsize.  
    Randomly decide whether it is vertical
    or horizontal, what length ship, the 
    placement of the first block, and check
    that it will fit on the board.  If not,
    adjust the placement.
    '''
    #Select vertical or horizontal ship
    shipdir = randint(0,1)
    #random ship length
    shiplength = randint(1,boardsize-2)
    shipstart = randint(0,boardsize-1)
    shipend = shipstart - 1 + shiplength
    shipdiff = boardsize - 1 - shipend
    if shipdiff < 0:
        shipstart += shipdiff
        shipend += shipdiff
    #print shipdir, shiplength, shipstart, shipend, shipdiff
    shipside = randint(0,boardsize-1)
    ship = []
    if randint(0,1) == 1:
        for i in range(shiplength):
            ship.append((shipstart+i,shipside))
    else:
        for i in range(shiplength):
            ship.append((shipside,shipstart+i))
    return ship

BLACK = (0,0,0)
RED = (255,0,0)
ORANGE = (255,150,0)
OCEAN = (13, 123, 234)

In [ ]:
print "Let's play Battleship!"
boardsize = input("How big should the ocean be? (Enter an integer from 4 to 20)")
nturns = input("How many shots would you like?")

board = BlockGrid(boardsize, boardsize, fill=OCEAN)
board.show()

ship = place_ship(boardsize)
nhits = 0

for turn in range(nturns):
    #print ship
    guess_row = input("Guess Row:")
    guess_col = input("Guess Col:")
    
    if (guess_row < 0 or guess_row >= board.height) or (guess_col < 0 or guess_col >= board.width):
        clear_output()
        board.show()
        print "Oops, that's not even in the ocean."
    else:
        guessblock = board[guess_row,guess_col]
        if (guess_row,guess_col) in ship:
            clear_output()
            board[guess_row,guess_col] = RED
            board.show()
            print "It's a hit!"
            nhits += 1          
        elif (guessblock.red,guessblock.green,guessblock.blue) == BLACK or (guessblock.red,guessblock.green,guessblock.blue) == RED:
            clear_output()
            board.show()
            print "You guessed that one already."
        else:
            clear_output()
            board[guess_row,guess_col] = BLACK
            board.show()
            print "You missed my battleship!"        

    if nhits == len(ship):
        clear_output()
        board[guess_row,guess_col] = RED
        board.show()
        print "Congratulations! You sunk my battleship!"
        break

    if turn+1 == nturns:
        clear_output()
        #Reveal location of ship in yellow
        for block in ship:
            current = board[block[0],block[1]]
            if (current.red,current.green,current.blue) == RED:
                pass
            else:
                board[block[0],block[1]] = ORANGE
        board.show()
        print "Sorry, you are out of turns.  Game Over."
    else:
        print "Remaining turns: ",nturns-1-turn


In [ ]:
#Upgrade the Python package installer, pip, then install ipythonblocks, if not already present.
!pip install --upgrade pip
!pip install ipythonblocks

As an assignment

This project can be assigned after a student completes the Codecademy Python lesson and becomes familiar with the module ipythonblocks .

  1. Open Codecademy and grab your Battleship! code from Lesson 13-18.
  2. Copy it to a new notebook called Battleship and use ipythonblocks to make it more visual.
    • Use a light blue for the background, red for a hit and a different color of your choice for misses.
  3. Once it is working:
    • Expand it to a larger field
    • Make the battleship longer
    • Provide more tries for the player to find it and completely sink it.
    • If the player doesn't sink the ship before the end of the game, reveal the playing board to them so they can see where it was.
  4. Document your code with a markdown cell that explains how to run it and what the options are.
  5. Demonstrate the game in another cell to show that it works as expected. You do not have to provide a demo for each possible outcome. Just one demo will do.
  6. Get creative. You could allow ships to lie diagonally, make the player say how many tries they would like to use to sink it, add more ships, etc.

Codecademy Battleship Program


In [ ]:
from random import randint

board = []

for x in range(5):
    board.append(["O"] * 5)

def print_board(board):
    for row in board:
        print " ".join(row)

print "Let's play Battleship!"
print_board(board)

def random_row(board):
    return randint(0, len(board) - 1)

def random_col(board):
    return randint(0, len(board[0]) - 1)

ship_row = random_row(board)
ship_col = random_col(board)

# Everything from here on should go in your for loop!
# Be sure to indent four spaces!
for turn in range(4):
    guess_row = input("Guess Row:")
    guess_col = input("Guess Col:")

    if guess_row == ship_row and guess_col == ship_col:
        print "Congratulations! You sunk my battleship!"
        break
    else:
        if (guess_row < 0 or guess_row > 4) or (guess_col < 0 or guess_col > 4):
            print "Oops, that's not even in the ocean."
        elif(board[guess_row][guess_col] == "X"):
            print "You guessed that one already."
        else:
            print "You missed my battleship!"
            board[guess_row][guess_col] = "X"
        # Print (turn + 1) here!
    if turn == 3:
        print "Ship was located at row " + str(ship_row) + ", col " + str(ship_col)
        print "Game Over"
    else:
        print turn+1
        print_board(board)