public IShape(SheetView sheet, int rowIdx, int colIdx, ShapeDirections direction) : base(sheet, rowIdx, colIdx) { Initialize(); _currentShapeDirection = direction; }
public LShape(SheetView sheet, int rowIdx, int colIdx, ShapeDirections direction, bool isLeft) : base(sheet, rowIdx, colIdx) { _currentShapeDirection = direction; _isLeft = isLeft; Initialize(); }
/// <summary> /// Check if the shape can be rotated to the next direction /// </summary> /// <param name="nextShape">The next shape after the rotation</param> /// <returns>true if can rotate, false otherwise</returns> public override bool CanRotate(ShapeDirections nextShape) { //Consider the default shape // x0 00 //0x0 xxx //0x and 00 //The shape can be rotated if there's no ButtonCellType in its (current top right, current right, current left //and current bottom left cells) or (current top left, current left, current bottom and current bottom right cells) //or 4 locations //The order of 4 locations will be from left to right, top to bottom int loc1ColIdx = 0; int loc1RowIdx = 0; int loc2ColIdx = 0; int loc2RowIdx = 0; int loc3RowIdx = 0; int loc3ColIdx = 0; int loc4ColIdx = 0; int loc4RowIdx = 0; ICellType nextCellType1 = null; ICellType nextCellType2 = null; ICellType nextCellType3 = null; ICellType nextCellType4 = null; //Work around to fix a bug where the shape direction doesn't match the location of the cells if (_currentShapeDirection == ShapeDirections.FaceDown || _currentShapeDirection == ShapeDirections.FaceUp) { if (_left == null || _right == null) { _currentShapeDirection = ShapeDirections.FaceLeft; nextShape = ShapeDirections.FaceDown; } } else { if (_top == null || _bottom == null) { _currentShapeDirection = ShapeDirections.FaceDown; nextShape = ShapeDirections.FaceLeft; } } switch (nextShape) { case ShapeDirections.FaceDown: //Currentis FaceRight loc1ColIdx = _topColIdx + 1; loc1RowIdx = _topRowIdx; loc2ColIdx = _centerColIdx - 1; loc2RowIdx = _centerRowIdx; loc3ColIdx = _centerColIdx + 1; loc3RowIdx = _centerRowIdx; loc4ColIdx = _bottomColIdx - 1; loc4RowIdx = _bottomRowIdx; break; case ShapeDirections.FaceUp: //Current is FaceLeft loc1ColIdx = _topColIdx + 1; loc1RowIdx = _topRowIdx; loc2ColIdx = _centerColIdx - 1; loc2RowIdx = _centerRowIdx; loc3ColIdx = _centerColIdx + 1; loc3RowIdx = _centerRowIdx; loc4ColIdx = _bottomColIdx - 1; loc4RowIdx = _bottomRowIdx; break; case ShapeDirections.FaceLeft: //Current is FaceDown loc1ColIdx = _leftColIdx; loc1RowIdx = _leftRowIdx - 1; loc2ColIdx = _centerColIdx; loc2RowIdx = _centerRowIdx - 1; loc3ColIdx = _centerColIdx; loc3RowIdx = _centerRowIdx + 1; loc4ColIdx = _rightColIdx; loc4RowIdx = _rightRowIdx + 1; break; case ShapeDirections.FaceRight: //Current is FaceUp loc1ColIdx = _leftColIdx; loc1RowIdx = _leftRowIdx - 1; loc2ColIdx = _centerColIdx; loc2RowIdx = _centerRowIdx - 1; loc3ColIdx = _centerColIdx; loc3RowIdx = _centerRowIdx + 1; loc4ColIdx = _rightColIdx; loc4RowIdx = _rightRowIdx + 1; break; } //When the center cell reaches borders, can't rotate if (_centerColIdx == BORDER_LEFT || _centerColIdx == BORDER_RIGHT - 1 || _centerRowIdx == BORDER_BOTTOM - 1) return false; //if (loc1ColIdx < BORDER_LEFT || loc2ColIdx < BORDER_LEFT || loc3ColIdx < BORDER_LEFT // || loc1ColIdx >= BORDER_RIGHT || loc2ColIdx >= BORDER_RIGHT || loc3ColIdx >= BORDER_RIGHT // || loc1RowIdx >= BORDER_BOTTOM || loc2RowIdx >= BORDER_BOTTOM || loc3RowIdx >= BORDER_BOTTOM) // return false; nextCellType1 = _sheet.Cells[loc1RowIdx, loc1ColIdx].CellType; nextCellType2 = _sheet.Cells[loc2RowIdx, loc2ColIdx].CellType; nextCellType3 = _sheet.Cells[loc3RowIdx, loc3ColIdx].CellType; nextCellType4 = _sheet.Cells[loc4RowIdx, loc4ColIdx].CellType; if (nextCellType1 != null || nextCellType2 != null || nextCellType3 != null || nextCellType4 != null) return false; return true; }
/// <summary> /// Generate a new random shape /// </summary> /// <param name="forPreview">Flag to check whether this shape is generated for preview</param> /// <returns>New instance of ITetrisShape class</returns> private ITetrisShape GenerateRandomShape(bool forPreview) { ITetrisShape shape = null; if (forPreview) { //Create a random side _isLeft = _random.Next() % 2 == 1; } if (forPreview) { //Create a random direction _currentDirection = (ShapeDirections)_random.Next(1, 5); } //Init location int colIdx = 17; int rowIdx = 2; if (!forPreview) { colIdx = _random.Next(2, Constants.MAX_WIDTH - 2); rowIdx = 6; } if (forPreview) { //Create a random shape _currentShapeModel = (TetrisShapes)_random.Next(1, 7); } //Check location of new shape before draw it. If it can't be drawn, game over if (!forPreview) { if (!CheckLocationOfNewShape(_currentShapeModel, _currentDirection, colIdx, rowIdx, _isLeft)) GameOver(); } switch (_currentShapeModel) { case TetrisShapes.TShape: shape = new TShape(sheet1, rowIdx, colIdx, _currentDirection); break; case TetrisShapes.SShape: shape = new SShape(sheet1, rowIdx, colIdx); break; case TetrisShapes.DotShape: shape = new DotShape(sheet1, rowIdx, colIdx); break; case TetrisShapes.LShape: shape = new LShape(sheet1, rowIdx, colIdx, _currentDirection, _isLeft); break; case TetrisShapes.IShape: shape = new IShape(sheet1, rowIdx, colIdx, _currentDirection); break; case TetrisShapes.ZShape: shape = new ZShape(sheet1, rowIdx, colIdx, _currentDirection, _isLeft); break; default: shape = new TShape(sheet1, rowIdx, colIdx, _currentDirection); break; } return shape; }
/// <summary> /// Check location of the new shape, if there's any obstacle, game over /// </summary> /// <param name="shape"></param> /// <param name="colIdx"></param> /// <param name="rowIdx"></param> private bool CheckLocationOfNewShape(TetrisShapes shape, ShapeDirections direction, int colIdx, int rowIdx, bool isLeft) { bool canDraw = true; Cell left = sheet1.Cells[rowIdx, colIdx - 1]; Cell center = sheet1.Cells[rowIdx, colIdx]; Cell right = sheet1.Cells[rowIdx, colIdx + 1]; Cell bottom = sheet1.Cells[rowIdx + 1, colIdx]; Cell bottomLeft = sheet1.Cells[rowIdx + 1, colIdx - 1]; Cell bottomRight = sheet1.Cells[rowIdx + 1, colIdx + 1]; if (center.CellType != null) { return false; } switch (shape) { case TetrisShapes.DotShape: //Already checked center break; case TetrisShapes.IShape: switch (direction) { case ShapeDirections.FaceDown: case ShapeDirections.FaceUp: //x //x //x if (left.CellType != null || right.CellType != null) canDraw = false; break; case ShapeDirections.FaceLeft: case ShapeDirections.FaceRight: //xxx if (bottom.CellType != null) canDraw = false; break; } break; case TetrisShapes.LShape: switch (direction) { case ShapeDirections.FaceDown: if (isLeft) { //xxx // x if (left.CellType != null || bottomRight.CellType != null) canDraw = false; } else { ///xxx ///x if (left.CellType != null || bottomLeft.CellType != null) canDraw = false; } break; case ShapeDirections.FaceUp: //x or x //xxx xxx if (left.CellType != null || right.CellType != null) canDraw = false; break; case ShapeDirections.FaceLeft: if (_isLeft) { // x // x //xx if (bottom.CellType != null || bottomLeft.CellType != null) canDraw = false; } else { //x //x //xx if (bottom.CellType != null || bottomRight.CellType != null) canDraw = false; } break; case ShapeDirections.FaceRight: if (_isLeft) { //xx //x //x if (bottom.CellType != null) canDraw = false; } else { //x //x //xx if (bottom.CellType != null || bottomRight.CellType != null) canDraw = false; } break; } break; case TetrisShapes.SShape: //xx //xx if (bottom.CellType != null || bottomRight.CellType != null) canDraw = false; break; case TetrisShapes.TShape: switch (direction) { case ShapeDirections.FaceDown: //xxx // x if (left.CellType != null || right.CellType != null || bottom.CellType != null) canDraw = false; break; case ShapeDirections.FaceUp: // x //xxx if (left.CellType != null || right.CellType != null) canDraw = false; break; case ShapeDirections.FaceLeft: // x //xx // x if (left.CellType != null || bottom.CellType != null) canDraw = false; break; case ShapeDirections.FaceRight: //x //xx //x if (right.CellType != null || bottom.CellType != null) canDraw = false; break; } break; case TetrisShapes.ZShape: switch (direction) { case ShapeDirections.FaceDown: if (_isLeft) { // //xx // xx if (left.CellType != null || bottom.CellType != null || bottomLeft.CellType != null) canDraw = false; } else { // // xx //xx if (bottomLeft.CellType != null || bottom.CellType != null || right.CellType != null) canDraw = false; } break; case ShapeDirections.FaceUp: if (_isLeft) { //xx // xx // if (right.CellType != null) canDraw = false; } else { // xx //xx // if (left.CellType != null) canDraw = false; } break; case ShapeDirections.FaceLeft: if (_isLeft) { // x //xx //x if (bottomLeft.CellType != null || left.CellType != null) canDraw = false; } else { //x //xx // x if (right.CellType != null || bottomRight.CellType != null) canDraw = false; } break; case ShapeDirections.FaceRight: if (_isLeft) { // x //xx //x if (bottom.CellType != null || right.CellType != null) canDraw = false; } else { //x //xx // x if (bottomRight.CellType != null || right.CellType != null) canDraw = false; } break; } break; } return canDraw; }
/// <summary> /// Check if the shape can be rotated to the next direction /// </summary> /// <param name="nextShape">The next shape after the rotation</param> /// <returns>true if can rotate, false otherwise</returns> public override bool CanRotate(ShapeDirections nextShape) { //Consider the default shape // x0 0x0 //0x0 0x0 //0xx (right) and xx (left) //The shape can be rotated if there's no ButtonCellType in its (current top right, current right, current left //and current bottom left cells) or (current top right, current right, current left and current top left cells) //or 4 locations //The order of 4 locations will be from left to right, top to bottom int loc1ColIdx = 0; int loc1RowIdx = 0; int loc2ColIdx = 0; int loc2RowIdx = 0; int loc3RowIdx = 0; int loc3ColIdx = 0; int loc4ColIdx = 0; int loc4RowIdx = 0; ICellType nextCellType1 = null; ICellType nextCellType2 = null; ICellType nextCellType3 = null; ICellType nextCellType4 = null; switch (nextShape) { case ShapeDirections.FaceDown: //Current is FaceRight if (_isLeft) { loc1ColIdx = _centerColIdx - 1; loc1RowIdx = _centerRowIdx; loc2ColIdx = _centerColIdx + 1; loc2RowIdx = _centerRowIdx; loc3ColIdx = _bottomColIdx - 1; loc3RowIdx = _bottomRowIdx; loc4ColIdx = _bottomColIdx + 1; loc4RowIdx = _bottomRowIdx; } else { loc1ColIdx = _topColIdx + 1; loc1RowIdx = _topRowIdx; loc2ColIdx = _centerColIdx - 1; loc2RowIdx = _centerRowIdx; loc3ColIdx = _centerColIdx + 1; loc3RowIdx = _centerRowIdx; loc4ColIdx = _bottomColIdx - 1; loc4RowIdx = _bottomRowIdx; } break; case ShapeDirections.FaceLeft: //Current is FaceDown if (_isLeft) { loc1ColIdx = _leftColIdx; loc1RowIdx = _leftRowIdx - 1; loc2ColIdx = _centerColIdx; loc2RowIdx = _centerRowIdx - 1; loc3ColIdx = _leftColIdx; loc3RowIdx = _leftRowIdx + 1; loc4ColIdx = _centerColIdx; loc4RowIdx = _centerRowIdx + 1; } else { loc1ColIdx = _leftColIdx; loc1RowIdx = _leftRowIdx - 1; loc2ColIdx = _centerColIdx; loc2RowIdx = _centerRowIdx - 1; loc3ColIdx = _centerColIdx; loc3RowIdx = _centerRowIdx + 1; loc4ColIdx = _rightColIdx; loc4RowIdx = _rightRowIdx + 1; } break; case ShapeDirections.FaceUp: //Current is FaceLeft if (_isLeft) { loc1ColIdx = _topColIdx - 1; loc1RowIdx = _topRowIdx; loc2ColIdx = _topColIdx + 1; loc2RowIdx = _topRowIdx; loc3ColIdx = _centerColIdx - 1; loc3RowIdx = _centerRowIdx; loc4ColIdx = _centerColIdx + 1; loc4RowIdx = _centerRowIdx; } else { loc1ColIdx = _topColIdx + 1; loc1RowIdx = _topRowIdx; loc2ColIdx = _centerColIdx - 1; loc2RowIdx = _centerRowIdx; loc3ColIdx = _centerColIdx + 1; loc3RowIdx = _centerRowIdx; loc4ColIdx = _bottomColIdx - 1; loc4RowIdx = _bottomRowIdx; } break; case ShapeDirections.FaceRight: //Current is FaceUp if (_isLeft) { loc1ColIdx = _centerColIdx; loc1RowIdx = _centerRowIdx - 1; loc2ColIdx = _rightColIdx; loc2RowIdx = _rightRowIdx - 1; loc3ColIdx = _centerColIdx; loc3RowIdx = _centerRowIdx + 1; loc4ColIdx = _rightColIdx; loc4RowIdx = _rightRowIdx + 1; } else { loc1ColIdx = _leftColIdx; loc1RowIdx = _leftRowIdx - 1; loc2ColIdx = _centerColIdx; loc2RowIdx = _centerRowIdx - 1; loc3ColIdx = _centerColIdx; loc3RowIdx = _centerRowIdx + 1; loc4ColIdx = _rightColIdx; loc4RowIdx = _rightRowIdx + 1; } break; } //When the center cell reaches borders, can't rotate if (_centerColIdx == BORDER_LEFT || _centerColIdx == BORDER_RIGHT - 1 || _centerRowIdx == BORDER_BOTTOM - 1) return false; nextCellType1 = _sheet.Cells[loc1RowIdx, loc1ColIdx].CellType; nextCellType2 = _sheet.Cells[loc2RowIdx, loc2ColIdx].CellType; nextCellType3 = _sheet.Cells[loc3RowIdx, loc3ColIdx].CellType; nextCellType4 = _sheet.Cells[loc4RowIdx, loc4ColIdx].CellType; if (nextCellType1 != null || nextCellType2 != null || nextCellType3 != null || nextCellType4 != null) return false; return true; }
/// <summary> /// Base function to check whether the shape can be rotated. Default is return true /// </summary> /// <param name="nextDirection"></param> /// <returns></returns> public virtual bool CanRotate(ShapeDirections nextDirection) { return true; }
/// <summary> /// Check if the shape can be rotated to the next direction /// </summary> /// <param name="nextShape">The next shape after the rotation</param> /// <returns>true if can rotate, false otherwise</returns> public override bool CanRotate(ShapeDirections nextShape) { //This shape can't be rotated return false; }
/// <summary> /// Check if the shape can be rotated to the next direction /// </summary> /// <param name="nextShape">The next shape after the rotation</param> /// <returns>true if can rotate, false otherwise</returns> public override bool CanRotate(ShapeDirections nextShape) { //This shape doesn't support rotation return false; }
/// <summary> /// Check if the shape can be rotated to the next direction /// </summary> /// <param name="nextShape">The next shape after the rotation</param> /// <returns>true if can rotate, false otherwise</returns> public override bool CanRotate(ShapeDirections nextShape) { //The shape can be rotated if there's no ButtonCellType in its current left corner, current right corner, //the next right corner and the next right cell int curRightCornerRowIdx = 0; int curRightCornerColIdx = 0; int curLeftCornerRowIdx = 0; int curLeftCornerColIdx = 0; int nextRightCornerRowIdx = 0; int nextRightCornerColIdx = 0; int nextRightRowIdx = 0; int nextRightColIdx = 0; ICellType nextRightCornerCellType = null; ICellType nextRightCellType = null; ICellType curRightCornerCellType = null; ICellType curLeftCornerCellType = null; switch (nextShape) { case ShapeDirections.FaceDown: //Current is FaceRight curRightCornerColIdx = _topColIdx; curRightCornerRowIdx = _rightRowIdx; curLeftCornerColIdx = _topColIdx; curLeftCornerRowIdx = _leftRowIdx; nextRightCornerColIdx = _rightColIdx - 1; nextRightCornerRowIdx = _rightRowIdx; nextRightColIdx = _rightColIdx - 1; nextRightRowIdx = _rightRowIdx - 1; break; case ShapeDirections.FaceLeft: //Current is FaceDown curRightCornerColIdx = _rightColIdx; curRightCornerRowIdx = _topRowIdx; curLeftCornerColIdx = _leftColIdx; curLeftCornerRowIdx = _topRowIdx; nextRightCornerColIdx = _rightColIdx; nextRightCornerRowIdx = _rightRowIdx - 1; nextRightColIdx = _rightColIdx + 1; nextRightRowIdx = _rightRowIdx - 1; break; case ShapeDirections.FaceUp: //Current is FaceLeft curRightCornerColIdx = _topColIdx; curRightCornerRowIdx = _rightRowIdx; curLeftCornerColIdx = _topColIdx; curLeftCornerRowIdx = _leftRowIdx; nextRightCornerColIdx = _rightColIdx + 1; nextRightCornerRowIdx = _rightRowIdx; nextRightColIdx = _rightColIdx + 1; nextRightRowIdx = _rightRowIdx + 1; break; case ShapeDirections.FaceRight: //Current is FaceUp curRightCornerColIdx = _rightColIdx; curRightCornerRowIdx = _topRowIdx; curLeftCornerColIdx = _leftColIdx; curLeftCornerRowIdx = _topRowIdx; nextRightCornerColIdx = _rightColIdx; nextRightCornerRowIdx = _rightRowIdx - 1; nextRightColIdx = _rightColIdx - 1; nextRightRowIdx = _rightRowIdx + 1; break; } //When the center cell reaches borders, can't rotate if (_centerColIdx == BORDER_LEFT || _centerColIdx == BORDER_RIGHT - 1 || _centerRowIdx == BORDER_BOTTOM - 1) return false; //The shape can be rotated if there's no ButtonCellType in its current left corner, current right corner, //the next right corner and the next right cell curRightCornerCellType = _sheet.Cells[curRightCornerRowIdx, curRightCornerColIdx].CellType; curLeftCornerCellType = _sheet.Cells[curLeftCornerRowIdx, curLeftCornerColIdx].CellType; nextRightCornerCellType = _sheet.Cells[nextRightCornerRowIdx, nextRightCornerColIdx].CellType; nextRightCellType = _sheet.Cells[nextRightRowIdx, nextRightColIdx].CellType; if (nextRightCornerCellType != null || nextRightCellType != null || curLeftCornerCellType != null || curRightCornerCellType != null) return false; return true; }