public Spreadsheet(int Rows, int Columns) { SpreadS = new SCell[Rows, Columns]; nRows = Rows; nColumns = Columns; xs = new XmlSerializer(typeof(List <CellProps>)); ChangedCells = new List <int[]>(); //initialize and populate cells for (int i = 0; i < Rows; i++) { for (int j = 0; j < Columns; j++) { SpreadS[i, j] = new SCell(i, j) { Text = i.ToString() + " " + j.ToString() }; //if PropertyChanged event is fired for this cell, call OnCellPropertyChanged is called //"Subscribing" to this cell's PropertyChanged and AlertValChange events SpreadS[i, j].PropertyChanged += this.OnCellPropertyChanged; SpreadS[i, j].AlertValChange += this.OnCellPropertyChanged; } } }
//Defines response behavior of listening cells to when a referenced cell's value changes. //Checks to see if referenced cell is valid. public void OnAlertCellValueChange(object sender, PropertyChangedEventArgs e) { SCell target = (SCell)sender; //If it is, then test to see if the value is a double. If so, then update the eqn variables if (Double.TryParse(target.Value, out double num)) { Eqn.SetVar(((char)(target.ColumnIndex + 65)).ToString() + (target.RowIndex + 1).ToString(), num); this.Value = Eqn.Evald().ToString(); } else //otherwise, it is invalid { this.Value = "#REFF!"; } }
//******************************************************************************************** //Method: public static void NewGame() //Purpose: Creates a new game when the New Game button is clicked //Parameters: N/A //Returns: nothing //********************************************************************************************* public static void NewGame() { //Clears the gamefield GameField.Clear(); int count = 0; //Sets a counting variable to track mine creation Random random = new Random(); //Creates a random number object int x = 0; //Initializes a varaible to track the X value int y = 0; //Initializes a variable to track the Y value //Loop to create the array of game cells for (int count1 = 0; count1 < 10; count1++) { for (int count2 = 0; count2 < 10; count2++) { //Creates a new Game Cell for each location in the array CellArray[count1, count2] = new SCell(EState.Invisible, ""); } } //Loops while fewer than 10 mines have been created do { //Loops while the cell contains a mine do { x = random.Next(0,10); //Generates a random number for the X location y = random.Next(0,10); //Generates a random number for the Y location } while(CellArray[x,y]._State == "Mine"); //Sets cell to a mine if it does not contain one CellArray[x,y]._State = "Mine"; //adds one to mine total count++; } while (count < 10); //Loop to check all cells in array for mines, and place numbers in //surrounding cells for number of mines touching them for (int Row = 0; Row < 10; Row++) { for(int Column = 0; Column < 10; Column++) { //tracks number of mines surrounding each cell int MineCount = 0; if (CellArray[Row, Column]._State == "Mine") { } //error checking for top left corner else if (Row == 0 && Column == 0) { if(CellArray[Row+1,Column]._State == "Mine") MineCount++; if(CellArray[Row+1,Column+1]._State == "Mine") MineCount++; if (CellArray[Row, Column + 1]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } //error checking for bottom left corner else if (Row == 0 && Column == 9) { if (CellArray[Row + 1, Column-1]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column]._State == "Mine") MineCount++; if (CellArray[Row, Column - 1]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } //error checking for top right corner else if (Row == 9 && Column == 0) { if (CellArray[Row - 1, Column]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row, Column + 1]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } //Error checking for bottom right corner else if (Row == 9 && Column == 9) { if (CellArray[Row - 1, Column]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column - 1]._State == "Mine") MineCount++; if (CellArray[Row, Column - 1]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } //error checking for right wall else if (Row == 0) { if (CellArray[Row + 1, Column-1]._State == "Mine") MineCount++; if (CellArray[Row, Column - 1]._State == "Mine") MineCount++; if (CellArray[Row, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } //Error checking for top wall else if (Column == 0) { if (CellArray[Row, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } //Error checking for bottom wall else if (Column == 9) { if (CellArray[Row + 1, Column]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column - 1]._State == "Mine") MineCount++; if (CellArray[Row, Column - 1]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column - 1]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } //Error checking for right wall else if (Row == 9) { if (CellArray[Row, Column - 1]._State == "Mine") MineCount++; if (CellArray[Row, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column - 1]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } //Runs if cell is not on a wall or corner else { if (CellArray[Row - 1, Column - 1]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column]._State == "Mine") MineCount++; if (CellArray[Row - 1, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row, Column - 1]._State == "Mine") MineCount++; if (CellArray[Row, Column + 1]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column - 1]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column]._State == "Mine") MineCount++; if (CellArray[Row + 1, Column + 1]._State == "Mine") MineCount++; CellArray[Row, Column]._State = MineCount.ToString(); } } } }
//************************************************************************************************** //Method: private void ClearGame() //Purpose: Clears the game //Parameters: None //Returns: None //************************************************************************************************** private void ClearGame() { for (int j = 0; j < 10; j++) // Iterates through each cell in the array for (int k = 0; k < 10; k++) // Iterates through each cell in the array gameArray[j, k] = new SCell(" ", Estate.Invisible); // Sets cell location to a blank and invisible }
//Defining Response behaviour to CellPropertyChanged event. //If the cell Text changes, then the cell is recalculated. private void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e) { SCell target = (SCell)sender; int[] newcell = { target.RowIndex, target.ColumnIndex }; bool flag = false; foreach (int[] location in ChangedCells) { flag = location.SequenceEqual(newcell); if (flag == true) { break; } } if (flag == false) { ChangedCells.Add(newcell); } string temp = ""; //if the target text has been set before and starts with '='... if (e.PropertyName == "Text" && target.Text != null && target.Text != "" && target.Text[0] == '=') { //just grab the rest of the string... for (int i = 1; i < target.Text.Length; i++) { temp += target.Text[i].ToString(); } //... and set the target cell's value to it string[] parts = target.Eqn.Shunt(temp).Split(' '); bool equation = true; //Checking to see if it is a valid equation. looks for non-value, non-variable, and non-operator parts foreach (string part in parts) { if (equation == true && (Regex.Match(part, @"(^[+,\-,/,*]$)").Success || Regex.Match(part, @"(^\d+\.?\d*$)").Success || (Regex.Match(part, @"(^[A-Z{1}][\d+])").Success) && !Regex.Match(part, @"(\W)").Success)) { equation = true; } else { equation = false; } } if (equation == true) { //prepare target: //Removing all subscriptions. Subscriptions to referenced cells are (re)added later. foreach (ExpTree.ExpTree.Var variable in target.Eqn.GetRegi()) { int row = Int32.Parse(variable.Name[1].ToString()) - 1; int col = variable.Name[0] - 65; //unsubscribing to referenced cell's event: SpreadS[row, col].AlertValChange -= target.OnAlertCellValueChange; } //rebuilding target cell's equation target.Eqn.Rebuild(temp); //~*~* MaTh *~*~ //target.Eqn.Expression = temp; target.Value = target.Eqn.Evald().ToString(); //setting variables in target cell to values in respective cells, if there are any foreach (ExpTree.ExpTree.Var variable in target.Eqn.GetRegi()) { int row = Int32.Parse(variable.Name.Substring(1)) - 1; int col = variable.Name[0] - 65; //subscribing to referenced cell's event for when just the value changes SpreadS[row, col].AlertValChange += target.OnAlertCellValueChange; //Checking to see if referenced cell is valid for an equation input if (SpreadS[row, col].Value == null || !IsEqn(SpreadS[row, col].Eqn.Expression) || !Double.TryParse(SpreadS[row, col].Value, out double num)) { target.Value = "#REFF!"; } else { target.Eqn.SetVar(variable.Name, Double.Parse(SpreadS[row, col].Value)); target.Value = target.Eqn.Evald().ToString(); } } } else { target.Value = target.Text; } } //...otherwise just set the target cell's value to it else if (e.PropertyName == "Text") { if (Double.TryParse(target.Text, out double num)) { target.Eqn.Expression = num.ToString(); } target.Value = target.Text; } // finally, fire off CellPropertyChanged event CellPropertyChanged?.Invoke(target, e); }