private void NewColumn(object sender, NewColumnEventArgs args) { ProcessJewel(true); int prevColumn = args.PrevCellColumn; bool hadRemoval = false; if (prevColumn >= 0) { // loop over rows to see if squares should be removed: int numSquareRows = Squares[0].Length; var squaresToRemove = new List <Square>(); for (int r = 0; r < numSquareRows; r++) { for (int c = prevColumn; c >= 0; c--) { var s = FindSquare(c, r); if (s?.CanRemove(args.PrevCellColumn, args.CellColumn) == Square.ChainStates.Removeable) { squaresToRemove.Add(s); } } } // execute removal after collecting all squares: hadRemoval = hadRemoval || squaresToRemove.Count > 0; foreach (var s in squaresToRemove) { s.Remove(); } // see if we've reached a column that doesn't have any jeweled cells: if (InProcessOfRemovingJewelCells) { // check if we just wrapped our playfield: int currColumn = Timeline.Column; bool checkWrapped = Timeline.Wrapped(args.PrevCellColumn) && GetCellColumn(NumCellColumns - 1).Any(c => c.RemoveState == Cell.RemoveStates.JewelRemoving); bool checkNoJewelCellsInColumn = Cells[currColumn].All(c => c.RemoveState != Cell.RemoveStates.JewelRemoving && c.RemoveState != Cell.RemoveStates.JewelWillBeRemoved); if (checkNoJewelCellsInColumn || checkWrapped) { for (int c = 0; c <= args.PrevCellColumn; c++) { for (int r = 0; r < Cells[currColumn].Length; r++) { var cell = Cells[c][r]; if (cell.RemoveState == Cell.RemoveStates.JewelRemoving) { cell.Reset(); hadRemoval = true; } } } InProcessOfRemovingJewelCells = false; } } } for (int c = args.CellColumn; c <= args.CellColumn; c++) { for (int r = NumCellRows - 1; r >= 0; r--) { var cell = Cells[c][r]; // advance cell states: if (cell.RemoveState == Cell.RemoveStates.WillBeRemoved) { cell.RemoveState = Cell.RemoveStates.Removing; } } } if (!hadRemoval) { return; } bool emptyField = true; bool hasOneColor = true; Cell.States?oneColor = null; // fall cells based on removed squares: for (int c = 0; c < NumCellColumns; c++) { // collect move counts based on empty cells: var moveCounts = new int[NumCellRows]; int currMoveCount = 0; for (int r = NumCellRows - 1; r >= 0; r--) { var cell = Cells[c][r]; if (cell.IsImmovable) { currMoveCount = 0; } moveCounts[r] = cell.IsOccupied ? currMoveCount : 0; currMoveCount += cell.IsOccupied ? 0 : 1; if (cell.IsOccupied) { emptyField = false; } // check to see if we have only one color: if (oneColor == null) { oneColor = cell.Color; } else if ((cell.IsWhite || cell.IsBlack) && !cell.IsSameColor((Cell.States)oneColor)) { hasOneColor = false; } } // transfer cells: for (int i = NumCellRows - 1; i >= 0; i--) { if (moveCounts[i] > 0) { Cells[c][i].TransferTo(Cells[c][i + moveCounts[i]]); } } } // add status: if (emptyField) { Stats.AddEmptyColorBonus(); } else if (hasOneColor) { Stats.AddSingleColorBonus(); } }
/// <summary> /// Constructor for Playfield. /// Column 0 is the top of the playfield. /// Row 0 is the left of the playfield. /// </summary> /// <param name="numColumns">The number of cell columns.</param> /// <param name="numRows">The number of cell rows.</param> public Playfield(int numColumns, int numRows) { JeweledCells = new List <Cell>(); // score: Stats = new Stats(); const int min = 2; if (numColumns < 0 || numColumns < min || numRows < 0 || numRows < min) { throw new ArgumentOutOfRangeException("Columns and rows (" + numColumns + "x" + numRows + ") must be greater than " + min); } Cells = new Cell[numColumns][]; for (int x = 0; x < NumCellColumns; x++) { Cells[x] = new Cell[numRows]; for (int y = 0; y < NumCellRows; y++) { Cells[x][y] = new Cell(x, y); } } Squares = new Square[numColumns - 1][]; for (int x = 0; x < NumSquareColumns; x++) { Squares[x] = new Square[numRows - 1]; for (int y = 0; y < NumSquareRows; y++) { var s = new Square(x, y, this); s.SquareCompleted += (sender, args) => Stats.AddCompletedSquare(); Squares[x][y] = s; for (int cellX = 0; cellX < Square.NumCellsPerAxis; cellX++) { for (int cellY = 0; cellY < Square.NumCellsPerAxis; cellY++) { var cell = Cells[x + cellX][y + cellY]; int x1 = x; int y1 = y; cell.StateChanged += (sender, args) => { Squares[x1][y1].CellStateChanged(sender, args); if (cell.IsJeweled) { JeweledCells.Add(cell); } else { JeweledCells.Remove(cell); } }; } } } } // timeline: Timeline = new Timeline(numColumns); Timeline.NewColumn += NewColumn; Timeline.WrapColumn += (sender, args) => Stats.IncrementFrame(); }