Battleship Game

Battleship is one of the best-known board games and has long been adapted into numerous digital versions that let players compete against a computer-controlled opponent. This article presents a Python implementation of the game with a graphical user interface built using tkinter.

In addition to creating a functional game, the goal was to develop an object-oriented application that could serve an illustrative example of how to use Python’s many language features, as well as to demonstrate object-oriented design, in which the game logic and the user interface are clearly separated.

The complete source code is included at the end of this article and is also available on GitHub: https://github.com/pythonknowledgebuilding/battleship

The first part of this article explains how to play the game. The second part explores the application’s architecture and the principles behind its design and implementation, with a particular focus on the design decisions behind the project. This section is intended primarily for readers interested in the program’s structure, as it provides the background needed to better understand the source code.

How to Play

This application is a computer implementation of the classic Battleship game, in which you compete against the computer. The game follows the traditional rules: both players place their fleets on separate 10×10 boards and then take turns trying to sink each other’s ships.

Getting Started

When the program starts, two game boards are displayed. The board on the left represents your fleet, while the board on the right represents the computer’s hidden fleet. At the beginning of the game, the program displays the size of the ship you need to place next.

Placing Your Ships

Ships are placed by clicking cells on your own board. The program always indicates the size of the next ship to be placed. You build a ship by selecting its cells one by one.

After each click, the program checks whether the currently selected cells can still form a valid ship. As a result, it is impossible to select a cell that would make the ship placement invalid.

The program enforces the standard Battleship placement rules:

  • Ships may be placed only horizontally or vertically.
  • A ship must occupy consecutive cells with no gaps.
  • Ships may not touch each other, not even at the corners.

When a ship has been completed, an audible notification is played and the program automatically prompts you to place the next ship.

Once all ships have been placed, the game automatically enters the battle phase.

Battle Phase

During the battle phase, fire at the opponent by left-clicking a cell on the board on the right.

The result of each shot is displayed immediately:

  • Small black dot: the shot missed.
  • Red X on a gray background: the shot hit a ship, but it has not yet sunk.
  • Black cell: the entire ship has been sunk.

Each shot fired by the human player is automatically followed by the computer’s move, which is displayed on your own board using the same visual indicators.

End of the Game

The game continues until all ships belonging to one player have been sunk. The program then displays a message announcing the winner.

Revealing the Opponent’s Undamaged Ships

Once the battle phase has begun, you can right-click the opponent’s board to reveal the locations of the computer player’s ship cells that have not yet been hit.

This feature is useful after losing a game, as it lets you see where the remaining enemy ships were located and which cells you would still have needed to find in order to win.

Screenshots

The following screenshots illustrate several key stages of the game, including ship placement, the battle phase, and the end of the game.

Application Architecture and Design

The program’s structure takes into account the principles of object-oriented design. Accordingly, the game logic, the user interface, and the event handling that controls the game are implemented as separate components.

Application Structure

The application consists of two modules.

The model module contains the complete game logic, including the game boards, ships, shot processing, the computer player’s behavior, and overall game state management. Since this module is entirely independent of the graphical interface, it can be reused with a different user interface, whether graphical or console-based.

The main module implements the tkinter-based graphical user interface. Its sole responsibility is to display the game boards, handle mouse input, and present the results provided by the model. All knowledge of the game rules resides exclusively in the model.

The overall design can be regarded as a simplified implementation of the Model–View–Controller (MVC) architecture. The responsibilities of the model and the view are clearly separated, while the controller role is performed by the BattleshipGame application object instead of a dedicated controller class. This object handles user events, forwards requests to the model, and updates the user interface based on the model’s responses.

The Game Model

The central component of the model is the Board class, which represents an individual player’s game board. It stores the ships placed on the board, keeps track of all shots fired at it, and provides the operations required for ship placement and shot evaluation.

Ships are represented as independent objects. A Ship instance stores only the cells it occupies, yet this is sufficient to derive all of its important properties, including its length, orientation, damage state, and whether it has been sunk. A ship is responsible for evaluating shots fired at it and for validating its own geometric properties. It also collaborates with the Board object when determining whether it can be placed legally.

Cell coordinates are represented by a dedicated Cell data class. Using a separate class provides a consistent representation of board positions, replacing simple coordinate pairs with well-defined objects. Since Cell is immutable (frozen=True), its instances can be used as elements of sets and as dictionary keys, which significantly simplifies several algorithms throughout the program.

Ship Placement

The computer player’s fleet is generated by the ComputerFleetFactory class. The algorithm repeatedly generates random horizontal or vertical ships and keeps trying new positions until a valid placement is found. Ships are not allowed to overlap or touch each other, even at the corners.

The human player’s ship placement follows a different approach. After each mouse click, the program generates every possible ship that:

  • has the required length,
  • contains all previously selected cells, and
  • can be placed legally on the board.

If at least one valid ship can be constructed from the selected cells, the selection is accepted; otherwise, the click is ignored. This approach provides a simple and intuitive user experience while continuously enforcing the placement rules.

Shot Processing

Shot evaluation is performed in two stages. The Board object first determines whether a ship occupies the targeted cell. If so, the corresponding Ship object evaluates whether the shot is a hit or sinks the ship.

The result is represented by a member of the ShotResult enumeration, which clearly distinguishes the three possible outcomes: miss, hit, or sunk.

Computer Player Strategy

The computer player’s shooting algorithm employs two consecutive strategies.

As long as no ship has been hit, it selects target cells at random from those that have not yet been fired upon and that are guaranteed not to belong to an already sunk ship.

Once a ship has been hit, the strategy changes. With only a single damaged ship cell, the algorithm targets one of the four neighboring cells. As soon as two adjacent hits reveal the ship’s orientation, the search continues only toward the two ends of the ship until it has been completely sunk.

Design Summary

The objective of this project was not only to implement a playable game but also to develop a clean, maintainable object-oriented application. To achieve this, individual responsibilities are assigned to dedicated classes, cell coordinates are encapsulated in a dedicated data class, and many of the algorithms make extensive use of Python’s built-in data structures, particularly set operations. This design not only improves code readability but also makes the components easier to extend, modify, and maintain independently.

Everything you need to develop this application is covered in the e-book Python Knowledge Building Step by Step From the Basics to Your First Desktop Application.

Source Code

The complete source code of the program is shown below. The full project is also available on GitHub, where the source files can be downloaded.

GitHub: https://github.com/pythonknowledgebuilding/battleship

Interested in the e-book Python Knowledge Building Step by Step: From the Basics to Your First Desktop Application?