I'm working on a Minesweeper game for my girlfriend as a surprise. In this stage of the process, I set the width and the height of the grid in the code-behind of the user control that declares the board (I was thinking of making a litte extra configuration window in the menu where she would be able to select different sizes for the board later).
The code for this is really straight forward and based on the JavaScript tutorial given here by Ania Kubow: https://www.youtube.com/watch?v=W0No1JDc6vE
namespace Minesweeper.Views;
public partial class BoardView : UserControl {
public int BoardWidth { get; set; } = 10;
public int BoardHeight { get; set; } = 10;
public int BombCount { get; set; } = 20;
public List<BoardTileView> Tiles { get; set; } = new();
public BoardView() => InitializeComponent();
private void BoardView_Loaded(object sender, RoutedEventArgs e) {
List<string> bombs = Enumerable.Repeat(Constants.Bomb, BombCount).ToList();
List<string> valid = Enumerable.Repeat(
Constants.Valid, BoardWidth * BoardHeight - BombCount).ToList();
List<string> tiles = bombs.Concat(valid).ToList();
tiles.FisherYatesShuffle();
AddRowDefinitions();
AddColumnDefinitions();
// Add tiles to board grid
for (int row = 0; row < BoardWidth; row++) {
var isLeftEdge = row == 0;
var isRightEdge = row == BoardWidth - 1;
for (int col = 0; col < BoardHeight; col++) {
int index = row * (col + 1);
BoardTileView boardTile = new() {
Name = $"Tile{index}",
};
if (tiles[index].Equals(
Constants.Bomb,
StringComparison.InvariantCultureIgnoreCase)) {
boardTile.testName.Background = Brushes.HotPink;
boardTile.IsBomb = true;
}
Grid.SetRow(boardTile, row);
Grid.SetColumn(boardTile, col);
boardGrid.Children.Add(boardTile);
Tiles.Add(boardTile);
// Check for adjacent bomb count
}
}
}
private void AddRowDefinitions() {
for (int i = 0; i < BoardWidth; i++) {
boardGrid.RowDefinitions.Add(new RowDefinition());
}
}
private void AddColumnDefinitions() {
for (int i = 0; i < BoardHeight; i++) {
boardGrid.ColumnDefinitions.Add(new ColumnDefinition());
}
}
private bool IsBomb(string tile) =>
tile.Equals(Constants.Bomb, StringComparison.InvariantCultureIgnoreCase);
}
The XAML is just a UserControl with a Grid named boardGrid
.
The BoardTileView is just a UserControl with a Canvas with a PeachPuff Background and a public property IsBomb
. In its XAML it has a x:Name="testName"
, so I can change its Background color to HotPink when it is a bomb for testing purposes.
The Fisher-Yates shuffle extension method is the following replacing the RNGCryptoServiceProvider with RandomNumberGenerator: Randomize a List<T>
The actual problem
Whenever I change the BoardWidth
and BoardHeight
property to something that is greater than 15, the application crashes without throwing an exception in Debug mode, which made me think, is there a limit to the amount of children a WPF Grid
can have that I'm not aware of, or is something else going on here?
The code above works fine up until a 15 by 15 grid. I was expecting I could make this grid even larger without consequences. I tried increasing the MainWindow in size to no avail.
The solution can be found on my Github here, because there is a lot of moving parts to a WPF application of course: https://github.com/binarybotany/Minesweeper