Introduction
Minesweeper appeared to be an interesting application that can be used to practice WPF skills, so I began to write a game similar to it, although it is not exactly the same as the original Minesweeper. The objective of the game is to click on all safe buttons without clicking on mines or bombs. If you click on a bomb the game will end. It differs from the original game in that there is no way to mark bombs (that seemed redundant) and there is no time tracking or maintaining of statistics. In writing this game I used the following concepts of WPF:
-
Styles
-
Control templates
-
Resources
-
Binding
-
Dialogs in WPF
-
Playing .wav files
Game Field
We need to have a series of buttons placed along a square. In WPF we have layout panels that decide the arrangement of items added to the panel. There are various types of panels; Canvas, StackPanel, DockPanel, WrapPanel and GridPanel. For example, StackPanel allows you to arrange its contents into a horizontal or vertical stack. If panels are not sufficient and you want to, say arrange all added items into a circle then you could write your own custom panel. A grid panel allows you to define a number of rows and columns and also handles reszing and positioning issues automatically (for example: when we change the number of squares in the game), so this layout panel is ideal for this game.
Control templates & changing the appearance of buttons for various states.
Controltemaplates used here are nearly the same as the one used in http://www.c-sharpcorner.com/UploadFile/52f7b2/tilegame-in-wpf/ and we will only go through the details at a high level, for a detailed explanation please refer to the link provided above.
Closed field or button
Initally buttons should represent closed fields, so we need one template for it, for this I have chosen a blue foreground button and all buttons should have the same color, so for this we need to use styles, a style represents a set of properties that can be applied to UI controls. So if we setup a style for a button then all buttons will use that style.
A template occupies a lot of space, so I did not publish it here, please refer to mainwindow.xaml for details.
Number button
When we click on a button, we will check if the id corresponds to any of the mine, if it is not then we calculate the number of mines surrounding the square and show it. A green color foreground button is used for this and is stored as a resource in Windows. Upon the click of a button this template is applied. A resource in WPF is some element/object stored in a dicationary. You provide a key and get some sort of object. Here we associate a resource (control template for the number button) with a window.
The template for this button is shown below.
<ControlTemplate x:Key="mytemplate"
TargetType="local:GameButton">
<Grid>
<Border BorderThickness="0" BorderBrush="White" CornerRadius="5">
<Rectangle x:Name="mainButton" Opacity="1" RadiusX="5" RadiusY="5">
<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop Color="Green" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Border>
<TextBlock x:Name="T1" Text= "{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" HorizontalAlignment="Center"
VerticalAlignment="Center" Grid.IsSharedSizeScope="True" FontSize="40" TextAlignment="Center" Foreground="DarkRed" FontWeight="Bold" FontFamily="Arial" />
</Grid>
</ControlTemplate>
Mine button
Similarly if the button clicked is a mine button then we need to show the template for the button with a bomb; see:
Binding
A number button should show the number of mines surrounding it, so to display that number a TextBlock is used, however to display the content of the button as text we need to use binding. Binding is a way to connect data to the user interface. Binding in general has the following terminology:
-
Source: The authoritative data, the stuff we want to display.
-
Target: The object that will reflect the data in some manner, such as a control that displays values or changes color based on the values and so on.
-
Binding: The rules determining how the data will be reflected
Here "source" is the content of the button and "target" is the TextBlock in the control template. When you want to use the control template in the binding we use TemplataedParent as follows:
Text= "{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"
|
Here we apply this template for the button so the parent for this is the button that is "templatedparent" and we want to bind it to the content property of the button so we specify Path as the content.
Dialogs in WPF
We should use dialogs to show results and settings, in WPF a window can be used for a dialog, you derive a class from a window and can call "ShowDialog" to show the window.
publicpartial class SettingsDlg :Window { public SettingsDlg() { InitializeComponent();
} |
In code we invoke the dialog using the following code:
SettingsDlg dlg = newSettingsDlg(); dlg.Owner = this; dlg.WindowStartupLocation = WindowStartupLocation.CenterOwner; dlg.ShowDialog(); |
Playing .wav files:
We need to play various .wav files in different situations, for example on the click of a button we can play a click sound so we can make this a part of the style because it applies to every button. From XAML we can use <soundplayeraction> as in the following:
<EventTrigger RoutedEvent="Button.PreviewMouseDown">
<SoundPlayerAction Source="..\..\CLICK.WAV"/>
</EventTrigger>
|
But when the bomb explodes we need to play selectively from code as in the following:
if(mineButtons.Contains(btn.Id))
{
btn.Template = (ControlTemplate)FindResource("mytemplate1");
MediaPlayer mplayer = new MediaPlayer();
mplayer.Open(new Uri(@"..\..\EXPLODE.WAV", UriKind.Relative));
mplayer.Play(); |
Game logic
An Id is given for each button and random numbers are generated for mines and maintained in a list. On the click of a button, if the id of a button is in the minelist then the game is over and all mines are shown, if the id of the button is a number then the number is calculated; if the number is 0 then adjacent fields are recursively opened until the number is not 0 and finally when all buttons that are not mines are opened the player is declared the winner. Most of the game code is self-explanatory.
Conclusion
Here we have seen how to use control templates, binding and dialogs to create a WPF game. I will conclude the article by summarizing the rules of the game:
-
You need to click on a button randomly
-
If the button is a mine or a bomb then the game is over
-
If the button is a number button then it will display the number of mines surrounding it
-
If the button is a zero button then it will open adjacent buttons until a number button is found
-
When you click on all buttons that are not mines you will win the game
-
You can right-click to open a new game or to adjust the number of squares.
I hope you will enjoy the game.