From UBC Wiki


Authors: Regina Adshade Moore & Sam MacKinnon

Haskell Battleship

What is the problem?

We will attempt to implement a version of the classic game Battleship, with a human player against a computer AI. The primary challenge will be representing the changing state of the game in Haskell, as it will need to be updated every move. When it is the player's move, they will input coordinates for firing a torpedo. The game state will then change depending on whether or not the torpedo hits. The computer will then make their move, and this process will repeat until someone has won.

RANDOM and CUSTOM game set ups

Each player gets to choose the positions of 10 ships in Battleship

  • 1 ship of size 4
  • 2 ships of size 3
  • 3 ships of size 2
  • 4 ships of size 1

We will implement the ability to for a player to set the positions of their ships through text input queries, or to choose an "auto" set up option. The computer will default to auto setup, which will randomly select ship positions that do not overlap.


The computer plays with the following strategy:

  • It's first move is always completely random.
  • If it hits a ship, it's next move is a random selection from the 4 squares surrounding the hit square.
  • If two squares of a ship are hit, and are next to each other, the computer's next move is randomly choosen to be one of two squares on either side of the two hit squares (logically following the shape of a ship).
  • Once a ship is sunk, the computer returns to random play
  • The computer never repeats a move

What is the something extra?

Our something extra will be to show the player the game state after every move. This will show the player's grid with their ship locations and the opponent's guesses so far, and the opponents grid with the player's guesses so far and any ships they have already found.

What did we learn from doing this?

We were able to fully complete our task using Haskell, however there were parts of the task for which Haskell was more suitable than others.

One thing that Haskell does well is accessing elements of lists. We used lists to represent the states of our grids, so it was easy with Haskell to access the spaces in the grids. It's also easy to create and append strings in Haskell which made creating the gamespace much easier since we could create different parts of the message shown to the user each move. The simplicity of guard statements in Haskell also helped us to respond to each move more easily than we would have been able to in Prolog.

Weaknesses that we found in Haskell while creating our game were the lack of global and dynamic variables. Since global variables can't be created dynamically, all of the grids that are created after the game begins must be passed as parameters to each function. Also since there are no dynamic variables, new grids must be created each time a move is made. Managing changing state is a bit cumbersome in Haskell for this reason, and explains why Haskell isn't a commonly used language for game programming (OO seems much more suitable for most games).

We did find it quite easy to use user-input strings in Haskell, so we implemented the ability to enter player names and custom ship positions.

Randomness was initially a challenge, but once we figured out how to work with IO types, it wasn't so bad. We learned that the trick is to get values from a generator like such: x <- functionThatGeneratesARandomInt rather than trying to set a variable directly to a random number (ie let x = functionThatGeneratesARandomInt ) which does not work in Haskell.