// Return true if the game is still going // Return false if the game ends public bool AdvanceTime() { if (game_end) { return(false); } Tetromino f = this.minos.First(); f.AdvanceTime(this.fast ? this.level * 2 : this.level); bool going = true; // check bottom of f bool touch = false; foreach (int i in f.GetColumns()) { int b = f.GetBottom(i); int bott = b / this.scale; if (bott == 20 || this.grid[i, bott].Color != System.Drawing.Color.FromArgb(128, 255, 255, 255)) { touch = true; break; } } if (touch) { // fill squares if the bottom of the piece now touches another piece/the bottom List <int> rows = new List <int>(); foreach (System.Drawing.Rectangle r in f.GetRectangles(0, 0)) { int x = r.X / this.scale; int y = r.Y / this.scale; if (x >= 0 && x < 10 && y >= 0 && y < 20) { this.grid[x, y].Color = f.Color; rows.Add(y); } if (y < 0) { // game ends if y < 0 going = false; GridBlock tmp = new GridBlock(r.X, r.Y - (r.Y % this.scale)); tmp.Color = f.Color; this.overflow.Add(tmp); } } this.ClearLines(rows); if (going) { this.minos.RemoveFirst(); this.minos.AddLast(new Tetromino(scale)); this.minos.First().SetStart(this.scale * 4, -3 * this.scale); // validate that the new piece doesn't cause a game over foreach (System.Drawing.Rectangle r in this.minos.First().GetRectangles(0, 0)) { int x = r.X / this.scale; int y = r.Y / this.scale; if (x >= 0 && x < 10 && y >= 0 && y < 20) { // if a piece already occupies where the new block ends up, the game is over going &= (this.grid[x, y].Color == System.Drawing.Color.FromArgb(128, 255, 255, 255)); } } if (!going) { f = this.minos.First(); foreach (System.Drawing.Rectangle r in this.minos.First().GetRectangles(0, 0)) { int x = r.X / this.scale; int y = r.Y / this.scale; if (x >= 0 && x < 10 && y >= 0 && y < 20) { // if a piece already occupies where the new block ends up, the game is over this.grid[x, y].Color = f.Color; } else { GridBlock tmp = new GridBlock(r.X, r.Y - (r.Y % this.scale)); tmp.Color = f.Color; this.overflow.Add(tmp); } } } } } this.game_end = !going; return(going); }
// instant drop // Returns true if the game continues, false if the game ends public bool DeadDrop() { if (this.game_end) { return(false); } Tetromino f = this.minos.First(); bool no_touch = true; // the bottom does not touch any blocks while (no_touch) { // keep going until the block hits the floor f.AdvanceTime(this.scale); foreach (int i in f.GetColumns()) { int b = f.GetBottom(i); int bott = b / this.scale; no_touch &= bott != 20 && this.grid[i, bott].Color == System.Drawing.Color.FromArgb(128, 255, 255, 255); } } bool going = true; List <int> rows = new List <int>(); foreach (System.Drawing.Rectangle r in f.GetRectangles(0, 0)) { // fill in the grid int x = r.X / this.scale; int y = r.Y / this.scale; if (x >= 0 && x < 10 && y >= 0 && y < 20) { this.grid[x, y].Color = f.Color; rows.Add(y); } if (y < 0) { going = false; GridBlock tmp = new GridBlock(r.X, r.Y - (r.Y % this.scale)); tmp.Color = f.Color; this.overflow.Add(tmp); } } this.ClearLines(rows); if (going) { this.minos.RemoveFirst(); this.minos.AddLast(new Tetromino(scale)); this.minos.First().SetStart(this.scale * 4, -3 * this.scale); // validate that the new piece doesn't cause a game over foreach (System.Drawing.Rectangle r in this.minos.First().GetRectangles(0, 0)) { int x = r.X / this.scale; int y = r.Y / this.scale; if (x >= 0 && x < 10 && y >= 0 && y < 20) { // if a piece already occupies where the new block ends up, the game is over going &= (this.grid[x, y].Color == System.Drawing.Color.FromArgb(128, 255, 255, 255)); } } if (!going) { f = this.minos.First(); foreach (System.Drawing.Rectangle r in this.minos.First().GetRectangles(0, 0)) { int x = r.X / this.scale; int y = r.Y / this.scale; if (x >= 0 && x < 10 && y >= 0 && y < 20) { // if a piece already occupies where the new block ends up, the game is over this.grid[x, y].Color = f.Color; } else { GridBlock tmp = new GridBlock(r.X, r.Y - (r.Y % this.scale)); tmp.Color = f.Color; this.overflow.Add(tmp); } } } } this.game_end = !going; return(going); }