Lecture 35 Log into Windows/ACENET. Open the Game of Life project. Go to the course webpage and download the game configuration files, glider.gol, lwss.gol and pulsar.gol, to the project folder. Project 4 is posted, due next Friday. Note: No class next Friday (April 15) due to EECS senior project presentations. Questions? Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 1 Outline DisplayGeneration( ) method Next button Click handler Interesting initial configurations Configuration files Load and Save button Click handlers FileDialogs and FileStreams Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 2 DisplayGeneration( ) DisplayGeneration( ) is a method that transfers the new generation states back to the displayed Label grid using nested for-loops for each row and column index. It also updates the generation count label (lblGenerationCount). Write this method. It does not receive or return anything. Here is its algorithm: 1. Declare and initialize rowMax to grid.GetUpperBound(0) 2. Declare and initialize colMax to grid.GetUpperBound(1) 3. Loop index row from 0 to rowMax by 1 3.1 Loop index col from 0 to colMax by 1 3.1.1 Set grid[i,j].Text to newGrid[i,j] 4. Set lblGenerationCount.Text to generationCount.ToString( ) Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 3 btnNext_Click( ) The last step to a complete application is to finish the Next button Click handler (btnNext_Click). This handler parses the user input in the textboxes to get the number of generations to simulate (n) and the time between updates (t). A generation is simulated by calling the ComputeGeneration( ) method followed by calling the DisplayGeneration( ) method. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 4 btnNext_Click( ) The loop for each generation is provided, along with the code that updates the form to display the new generation state and the code that pauses the application between generation updates. Write the calls to ComputeGeneration( ) and DisplayGeneration( ) as indicated in the comments. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 5 Running the Application To simulate a generation, click the Next button. If you want to see multiple generations for a click, enter a number in the first textbox. If you want the simulation of multiple generations to go faster, enter a lower number in the second textbox. If want it to go slower, enter a larger number. (250 ms is 1/4 of a second.) Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 6 Check These Out! Here are some interesting initial configurations. The left one is called a glider. The right one is called a light-weight spaceship (LWSS). Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 7 Check This Out! This one is called a pulsar. Change the first argument to MakeGrid to 20 to get a big enough grid. Be sure to change it back. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 8 Configuration Files Clicking in an initial configuration each time the program is started is tedious. We would like to be able to read configurations in from a textfile. In order to do so, we first define the file format for the Game of Life application. Each line of the text file will contain "*" (for live cells) or " " (for dead cells). The first line will be row 0, the second line will be row 1, etc. Since the game grid can be of different sizes, the dimensions of the grid also must be stored. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 9 Configuration Files For this project, configuration files will have the following format: The first line will contain the row dimension, e.g., 10 The second line will contain the column dimension, e.g., 20 The rest of the lines will be the rows of the configuration. Each line will have at most column dimension characters. There will be at most row dimension lines of the configuration. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 10 Configuration Files For example, glider.gol is the configuration file for the glider automata example. (This file can be opened in MSVS.) The first two lines indicated the grid should be 10x20. Note that although each line may have up to 20 characters and there may be up to 10 lines, the first line is blank and there are only 4 lines in the file. We will assume that the configuration is not larger than the specified dimensions. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 11 Loading a Configuration Double-click on the Load button to get its Click handler stub. We want this handler to do the following: Ask the user for a filename to open via an OpenFileDialog. If the user clicks "Cancel", go back to waiting Otherwise, open the configuration files, read the dimensions, remove the old grid, and create an appropriate sized grid Then read the rest of lines of the file and set the game grid accordingly. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 12 Reading from a File In computer programs, files are accessed for reading using the following steps: Ask the user for a filename. In the C# GUI, this is done using an OpenFileDialog Using the provided filename, create a StreamReader object and attach the file to it. Once a file is open, reading from a file is like reading from the console, we use the ReadLine( ) method on the StreamReader object. When the program is done using a file, it should close the StreamReader object. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 13 OpenFileDialog The OpenFileDialog GUI element is created by the program. A variable is declare and the dialog is created using the new operator: OpenFileDialog fileChooser = new OpenFileDialog(); Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 14 OpenFileDialog To make the dialog pop up and get the file name from the user, call the ShowDialog( ) method and save the result in a DialogResult variable: DialogResult result = fileChooser.ShowDialog(); Check if the user clicked "Cancel" and if so, go back to waiting // Check if user clicked Cancel if (result == DialogResult.Cancel) return; Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 15 File Streams A file stream is a program object that is opened (i.e., attached to a physical file) when it is created. StreamReader objects are used to read data from a file: // Open the file chosen in the dialog StreamReader fileInput = new StreamReader (fileChooser.FileName); First we need to read and parse the dimensions of the configuration from the first two lines: int newRowSize = int.Parse(fileInput.ReadLine()); int newColSize = int.Parse(fileInput.ReadLine()); Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 16 Making a New Grid To make a new grid, we have to remove the old first, then call the MakeGrid( ) method: int rowMax = grid.GetUpperBound(0); int colMax = grid.GetUpperBound(1); for (int row = 0; row <= rowMax; row++) { for (int col = 0; col <= colMax; col++) { this.Controls.Remove(grid[i,j]); } } MakeGrid (newRowSize, newColSize); Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 17 Reading and Configuring Rows The basic idea is to read the rest of the lines from the file stream one at a time. We keep track of which row is being configured and use a line to set the cells in the current row. We take advantage of two things to determine when to stop reading in lines. The ReadLine( ) method returns null, when it is called after all the lines in a file have been read. The assignment operator (=) returns the value of the assignment. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 18 Reading and Configuring Rows string line; int currentRow = 0; // Read lines one at a time until end of file while ((line = fileInput.ReadLine()) != null) { // For each character in the line for (int col = 0; col < line.Length; col++) { grid[currentRow, col].Text = line[col]; } currentRow++; // go to next row } fileInput.Close(); // done with the file Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 19 Updating the GUI In addition to the grid, we also need to reset the generation count label (should really be done in MakeGrid( )): lblGenerationCount.Text = "0"; And finally, we need to update the form to make it redraw itself: this.Update(); Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 20 Saving a Configuration Double-click on the Save button to get its Click handler stub. This handler is straightforward. We want it to do: Ask the user for a filename to save to via an SaveFileDialog. If the user clicks "Cancel", go back to waiting Otherwise, open the file and write the row dimension of the current grid on a line, then the column dimension on a line Then write a line for each row of the grid. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 21 Writing to a File In computer programs, files are accessed for writing using the following steps: Ask the user for a filename. In the C# GUI, this is done using an SaveFileDialog Using the provided filename, create a StreamWriter object and attach the file to it. Once a file is open, reading from a file is like writing to the console, we use the WriteLine( ) method on the StreamWriter object. It is very important to close a file that is written to so that the (new) contents are saved to the disk. Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 22 Saving a Configuration SaveFileDialog fileChooser = new SaveFileDialog(); DialogResult result = fileChooser.ShowDialog(); // Check if user clicked Cancel if (result == DialogResult.Cancel) return; // Open the file chosen in the dialog StreamWriter fileOutput = new StreamWriter (fileChooser.FileName); // Write dimensions int rowMax = ... int colMax = ... Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 23 Saving a Configuration fileOutput.WriteLine(rowMax+1); fileOutput.WriteLine(colMax+1); // Create a line for each grid row and write it for (int row = 0; row <= rowMax; row++) { string line = ""; // empty string for (int col = 0; col <= colMax; col++) { // append cell state to line line = line + grid[row,col].Text; } fileOutput.WriteLine(line); // write to file } fileOutput.Close(); // done with file Friday, April 8 CS 205 Programming for the Sciences - Lecture 35 24