I'm trying to write a "life" game in WPF C# ( https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life ). I have a problem with creating a loop to write the logic of the game itself. I have a button in the MainWindow class (below): MainWindow.xaml.cs
private void Start_Click(object sender, RoutedEventArgs e)
{
Restart.Visibility = Visibility.Visible;
Stop.Visibility = Visibility.Visible;
Start.Visibility = Visibility.Collapsed;
Continue.Visibility = Visibility.Collapsed;
isEvolving = true;
Game.Evolve(theGrid);
}
and there is a separate class in which the function Game.Evolve is written (below):
public static void Evolve(Grid[] grid)
{
Random random = new Random();
while (MainWindow.isEvolving)
{
Grid square = grid[25];
square.Background = new SolidColorBrush(Color.FromRgb(Convert.ToByte(random.Next(255)),
Convert.ToByte(random.Next(255)), Convert.ToByte(random.Next(255))));
}
}
This is where the infinite loop is created, which causes the program to freeze. If I understand correctly, the implementation of this game requires precisely an infinite loop, so that "Life" can evolve.
I tried creating separate functions that could be stop this one, tried creating coroutines, but if I understand correctly they don't work in WPF, tried creating separate bool variables. None of these options helped. My idea is to have a separate button (below) to stop this loop:
private void Stop_Click(object sender, RoutedEventArgs e)
{
Restart.Visibility = Visibility.Collapsed;
Start.Visibility = Visibility.Collapsed;
Stop.Visibility = Visibility.Collapsed;
Continue.Visibility = Visibility.Visible;
isEvolving = false;
}
but the program just doesn't get to it, because it freezes.
Maybe you can create a task running in another thread.
private async void Start_Click(object sender, RoutedEventArgs e)
{
Restart.Visibility = Visibility.Visible;
Stop.Visibility = Visibility.Visible;
Start.Visibility = Visibility.Collapsed;
Continue.Visibility = Visibility.Collapsed;
isEvolving = true;
//start a new thead
await Task.Run(() =>
{
//code in the new thread
Evolve(theGrid);
});
}
public async Task Evolve(Grid[] grid)
{
Random random = new Random();
while (MainWindow.isEvolving)
{
await Task.Delay(1000); //1sec to slow evolution
//Call the main thread to update UI
App.Current.Dispatcher.Invoke(() =>
{
Grid square = grid[25];
square.Background = new SolidColorBrush(Color.FromRgb(Convert.ToByte(random.Next(255)),
Convert.ToByte(random.Next(255)), Convert.ToByte(random.Next(255))));
});
}
}
Better do not run a Task at all:
private async void Start_Click(object sender, RoutedEventArgs e)
{
Restart.Visibility = Visibility.Visible;
Stop.Visibility = Visibility.Visible;
Start.Visibility = Visibility.Collapsed;
Continue.Visibility = Visibility.Collapsed;
isEvolving = true;
await Evolve(theGrid);
}
public async Task Evolve(Grid[] grid)
{
Random random = new Random();
while (MainWindow.isEvolving)
{
await Task.Delay(1000); //1sec to slow evolution
Grid square = grid[25];
square.Background = new SolidColorBrush(Color.FromRgb(Convert.ToByte(random.Next(255)),
Convert.ToByte(random.Next(255)), Convert.ToByte(random.Next(255))));
}
}