Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python

Adam Cameron
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Adam Cameron
Python Web Development Techdegree Graduate 16,731 Points

Don't know how to start Python Project 2 - Battleship

I thought I was understanding everything in the lessons but clearly I'm not synthesizing usefully because I have no clue how to start this project, and it's only the second one. Maybe I need to consider a different track. Anyway, I asked in Slack and Kenneth suggested implementing a board class first to hold onto rows, columns, and what appears in each cell. Without necessarily writing out code, can anyone give me a clue as to what this might look like?

1 Answer

Travis Bailey
Travis Bailey
13,673 Points

I'm stuck on this project too but got a little further. If it clicks for you, maybe you can help me understand how to place the boats on the board correctly and validate :). Keep in mind there's a bunch of different ways to approach this, below is just the route I'm going.

Anyways, you're going to feel like your brain hurts with this project because it's the first time we're being asked to use object orientated programming (OOP). I'm assuming you've taken the current OOP course, and understand the basics of how to create classes and objects based on those classes. Just keep in mind a class is the blueprint, the object is based on that blueprint, but it's own copy of it. Kind of like a printing press. The class would be the metal plate with ink constantly wiped onto it, the object is the paper after being printed on by the metal plate.

So first part I did was determine how many classes I'd need. I split this up into a ship class, a board class, and a player class. This is because you know you'll have multiple boats, two or more boards, and two players.

The board class in my plan has the most code. I also moved the code provided for the exercise into the board class. Ironically, the board objects (in my program) don't keep track of where the ships are. Instead, that information is held by the boat objects.

You're given the following code by Treehouse to start your project:

SHIP_INFO = [
    ("Aircraft Carrier", 5),
    ("Battleship", 4),
    ("Submarine", 3),
    ("Cruiser", 3),
    ("Patrol Boat", 2)
]

BOARD_SIZE = 10

VERTICAL_SHIP = '|'
HORIZONTAL_SHIP = '-'
EMPTY = 'O'
MISS = '.'
HIT = '*'
SUNK = '#'


def clear_screen():
    print("\033c", end="")


def print_board_heading():
    print("   " + " ".join([chr(c) for c in range(ord('A'), ord('A') + BOARD_SIZE)]))


def print_board(board):
    print_board_heading()

    row_num = 1
    for row in board:
        print(str(row_num).rjust(2) + " " + (" ".join(row)))
        row_num += 1

Daunting right? Still, after a few hours you can crunch through it. The 'print_board_heading()' function was rough for me because it uses comprehensions...which I'm horrible at. However the rest should look a little familiar to you.

'board_size' tells you the size of the grid, 10x10. So you'll want to have a way for someone to reference a move in a 10x10 grid. In battleship fashion, the moves would be like 'A7' or 'J9'. So I created a string that just contained the alphabet. Next, I focused on what my 'board()' objects should do when they are created. So I created an init function. It references the board size (10). However 10 would just give me a single row, so I loop over it twice.

for rows in range(self.board_size):
            row = []
            for spot in range(self.board_size):
                row.append(self.EMPTY)
            self.board.append(row)
        self.print_board()

In the above, I create 10 rows, and each row contains 10 'spots'. All of them are assigned the EMPTY character which is provided. Once ship placement starts it references this list of lists to see if it's actually there (if not it's not in the board space) and if another boat is occupying it. The string in each 'spot' changes based on if a ship is there.

Keep in mind, my plan uses 4 board objects, with each player having two. You'd have one board for when you place your ships, and during the game to see where your ships are placed (and where your opponent has fired, hit, missed, etc. You'll also have another board that tracks your hit/misses. This isn't optimal...and honestly, I should have stuck to two board objects.

Hope the above helped. Like I said, this is just my approach. There are many different ways to approach this.

Adam Cameron
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Adam Cameron
Python Web Development Techdegree Graduate 16,731 Points

Travis, thank you for such a detailed and helpful answer. This project is definitely daunting and has got me doubting everything, which as we know is such a wonderful feeling. I brought this up in the Slack channel and Kenneth suggested I go back to the dungeon-monster game in Python Collections, which I'm planning to do right after responding to you. Hopefully that will give me some ideas re: how to draw a board and then track movement on the board. We covered all that quite some time before starting the Battleship project, and just doing the lesson over the course of a day or two isn't really enough for the concepts to sink in deeply I guess.

The farthest I've gotten was putting all of that provided code into my Board class as you mentioned. I'm going to fiddle around with your approach to drawing the board and see if I can fully grasp what's going on. And I'll surely revisit this thread if I have any eureka moments and blaze ahead in the next few days - but don't hold your breath! Haha.

Adam Cameron
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Adam Cameron
Python Web Development Techdegree Graduate 16,731 Points

Actually Travis, would you mind showing me your second code slice in a little more context? Or at least explaining it a little more? I'm not really understanding how that's working to print your map.

Adam Cameron
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Adam Cameron
Python Web Development Techdegree Graduate 16,731 Points

Oh, and another thing (I promise to stop commenting soon), since I'm about to be stuck where you are: This question mentions using dictionaries, maybe that would work better?

Adam Cameron
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Adam Cameron
Python Web Development Techdegree Graduate 16,731 Points

FYI, here is what I came up with for displaying the board with EMPTY in every space:

board = [[EMPTY] * len(range(BOARD_SIZE)) for number in range(BOARD_SIZE)]

When you pass this to the provided print_board() function you get a nice blank board...and now I'm stumped again! Haha. This is gonna be horrible.