Battleships in C#

My current C# project is to create a Battleships program that would allow easy input of grids and on-screen solving.

An unsolved Battleships puzzle

An unsolved Battleships puzzle

I find myself strongly preferring online solving of this sort of puzzle to doing it on paper. Conceptis has an online solver, but I wanted to also be able to solve the puzzles in Games in the same manner.

Battleships is a grid-based logic puzzle based on the popular (and more familiar) two-person peg game. In the puzzle, the solver is presented with a square grid with numbers on the side and bottom, and some number of spaces already filled in. The goal is to place the “ships” (listed at the bottom of the grid) in such a way that the number on the sides of the grids represents the number of segments in that row or column, each ship is used once, and no two ships touch each other, even diagonally. The puzzle shown is from the July 2010 issue of Games.

Solved Battleships puzzle

Solved Battleships puzzle

I started with the UI, which is written in WPF/XAML. I knew that this would be significantly more work than my Canfield program. Each grid, as well as the row and column numbers, would need to be clickable, there would need to be an easy way to specific “ship” or “water” for spaces, and the ship pieces would need to automatically change shape based on their neighbors. On the other hand, while Canfield uses uploaded PNG files for the graphics, Battleships uses path files drawn by the program itself.

For the ship pieces, I am using GeometryGroups specified in the Window.Resources of the XAML file. For instance, this is the right end of a ship:

    <Window.Resources>
        <GeometryGroup x:Key="RightCap">
            <CombinedGeometry GeometryCombineMode="Union">
                <CombinedGeometry.Geometry1>
                    <RectangleGeometry Rect="0,0 15,30" />
                </CombinedGeometry.Geometry1>
                <CombinedGeometry.Geometry2>
                    <EllipseGeometry Center="15,15"
                    RadiusX="15" RadiusY="15" />
                </CombinedGeometry.Geometry2>
            </CombinedGeometry>
        </GeometryGroup>
    </Window.Resources>

When I want to use that group in a particular cell, I update it via the C# code.

for (x = 0; x < 10; x++)
{
    for (y = 0; y < 10; y++)
    {
        Cells[x, y] = (Path)FindName(string.Format("cell{0}{1}", x, y));
     }
}

To begin with, I’m programming Battleships at a set 10×10 size, which is the standard for Games magazine; once I’m done, I may double back and include other sizes, or I may move on to other grid-based logic puzzles.

Initially, each cell in the main grid contained just the path piece. Unfortunately, though, cells were only clickable on the visible portion of the path, meaning that empty cells (which contain an empty GeometryGroup) were unclickable. Also, I wanted an internal visible grid of blue lines. So now each cell of the grid contains a grid of its own (implicitly 1×1), which contains a rectangle (for the fill and border) and a path piece:

<Grid Name="grid00" Grid.Row="0" Grid.Column="0"
    MouseLeftButtonUp="Cell_LeftClick"
    MouseRightButtonUp="Cell_RightClick">
    <Rectangle Style="{StaticResource BlueBorder}" />
        <Path Name="cell00" Style="{StaticResource Ship}"
            Data="{StaticResource Empty}" />
</Grid>

As the code illustrates, a ship piece is selected (or cleared) by clicking the left mouse button and a water piece by clicking the right mouse button. I thought about doing a rotation (a left click puts a ship in an empty spot, water in a ship spot, or clears a water spot), but I decided I preferred this method.

To create the map of sample ships at the bottom, I initially tried to scale the playing pieces to 50%, but that didn’t work; when WPF set the pieces next to each other, space was reserved for the full 100% width, leaving large white spaces. I’m sure there’s some method I could have used to get the results I wanted, but I eventually gave up playing with it and created a second set of GeometryGroup elements, scaled down.

Battleships midgame

Battleships, while solving

I decided to go old school when indicating a cell’s status as either a clue (solid ship, dark blue water) or a guess (gray ship, light blue water). Rather than creating a class with a status attribute, I’m using 1-7 for clue pieces and 11-17 for guess pieces; hence, my code makes liberal use of the % operator. (I also have room in the code for a “commit” status, so that guesses that are firm [11-17] can be visually differentiated from trial-and-error guesses [21-27].)

I’ve programmed the basic UI, although it still needs a little tweaking. To finish up, I also need to program the module that loads in a puzzle (right now, the puzzle is hard-coded, for testing purposes), as well as creating a help file and other minor enhancements.

Advertisements
This entry was posted in Battleships, C#, Grid-based and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s