using System;
using System.Drawing;
namespace AnotherBlock
{
/// <summary>
/// Represents a Tetris block.
/// </summary>
public class Block
{
/// <summary>
/// Private attribute that holds the current width of the block (in block units).
/// </summary>
private short width;
/// <summary>
/// Private attribute that holds the current height of the block (in block units).
/// </summary>
private short height;
/// <summary>
/// Private attribute that holds the shape of the block.
/// </summary>
private Brick[,] shape;
/// <summary>
/// Private attribute that holds the top position of the block in the play field (in block units).
/// </summary>
private short top;
/// <summary>
/// Private attribute that holds the left position of the block in the play field (in block units).
/// </summary>
private short left;
/// <summary>
/// Private attribute that holds the block type of the block.
/// </summary>
private BlockType blockType = BlockType.Undefined;
/// <summary>
/// Private attribute that holds the image #1 of the block unit.
/// </summary>
private Image blockImage01 = Image.FromFile("images/block01.gif");
/// <summary>
/// Private attribute that holds the image #2 of the block unit.
/// </summary>
private Image blockImage02 = Image.FromFile("images/block02.gif");
/// <summary>
/// Private attribute that holds the image #3 of the block unit.
/// </summary>
private Image blockImage03 = Image.FromFile("images/block03.gif");
/// <summary>
/// Private attribute that holds the image #4 of the block unit.
/// </summary>
private Image blockImage04 = Image.FromFile("images/block04.gif");
/// <summary>
/// Private attribute that holds the image #5 of the block unit.
/// </summary>
private Image blockImage05 = Image.FromFile("images/block05.gif");
/// <summary>
/// Private attribute that holds the image #6 of the block unit.
/// </summary>
private Image blockImage06 = Image.FromFile("images/block06.gif");
/// <summary>
/// Private attribute that holds the image #7 of the block unit.
/// </summary>
private Image blockImage07 = Image.FromFile("images/block07.gif");
/// <summary>
/// Private attribute that holds the image #8 of the block unit.
/// </summary>
private Image blockImage08 = Image.FromFile("images/block08.gif");
/// <summary>
/// Private attribute that holds the image #9 of the block unit.
/// </summary>
private Image blockImage09 = Image.FromFile("images/block09.gif");
/// <summary>
/// Private attribute that holds the image #10 of the block unit.
/// </summary>
private Image blockImage10 = Image.FromFile("images/block10.gif");
/// <summary>
/// Private attribute that holds the image #11 of the block unit.
/// </summary>
private Image blockImage11 = Image.FromFile("images/block11.gif");
/// <summary>
/// Private attribute that holds the image #12 of the block unit.
/// </summary>
private Image blockImage12 = Image.FromFile("images/block12.gif");
/// <summary>
/// Private attribute that holds the image #13 of the block unit.
/// </summary>
private Image blockImage13 = Image.FromFile("images/block13.gif");
/// <summary>
/// Private attribute that holds the image #14 of the block unit.
/// </summary>
private Image blockImage14 = Image.FromFile("images/block14.gif");
/// <summary>
/// Class constructor that creates a block with a random block type.
/// </summary>
public Block()
{
// Creates a random number generator.
Random randomGenerator = new Random();
// Randomizes the block type.
BlockType randomBlockType = (BlockType)(randomGenerator.Next(1, 8));
// Sets the block type.
this.BlockType = randomBlockType;
}
/// <summary>
/// Class constructor that creates a block with a given block type.
/// </summary>
/// <param name="blockType">Block type of the new block being created.</param>
public Block(BlockType blockType)
{
// Sets the block type.
this.BlockType = blockType;
}
/// <summary>
/// Property that holds and sets the top position of the block in the play field (in block units).
/// </summary>
/// <remarks>
/// Value must be between 0 and the playing field height.
/// </remarks>
public short Top
{
get
{
// Returns the value in the top attribute.
return top;
}
set
{
// Checks if the value is within the allowed range.
if ((value > -1) && (value < (Game.PlayingFieldHeight + 1)))
{
// The value is within the allowed range.
// Sets the top attribute to the value.
top = value;
}
else
{
// The value is not within the allowed range.
// Throws an argument exception with the error.
throw new ArgumentException("Property Top must be between 0 and " + Game.PlayingFieldHeight.ToString() + ".");
}
}
}
/// <summary>
/// Property that holds and sets the left position of the block in the play field (in block units).
/// </summary>
/// <remarks>
/// Value must be between 0 and the playing field width, taking into consideration the block width.
/// </remarks>
public short Left
{
get
{
// Returns the value in the left attribute.
return left;
}
set
{
// Checks if the value is within the allowed range.
if ((value > -1) && ((value + this.Width) <= Game.PlayingFieldWidth))
{
// The value is within the allowed range.
// Sets the left attribute to the value.
left = value;
}
else
{
// The value is not within the allowed range.
// Throws an argument exception with the error.
throw new ArgumentException("Property Left must be between 0 and " + ((int)(Game.PlayingFieldWidth - this.Width)).ToString() + ".");
}
}
}
/// <summary>
/// Property that holds and sets the current width of the block (in block units).
/// </summary>
/// <remarks>
/// Value must be between 1 and 4.
/// </remarks>
public short Width
{
get
{
// Returns the value in the width attribute.
return width;
}
set
{
// Checks if the value is within the allowed range.
if ((value > 0) && (value < 5))
{
// The value is within the allowed range.
// Sets the width attribute to the value.
width = value;
}
else
{
// The value is not within the allowed range.
// Throws an argument exception with the error.
throw new ArgumentException("Property Width must be between 1 and 4.");
}
}
}
/// <summary>
/// Property that holds and sets the current height of the block (in block units).
/// </summary>
/// <remarks>
/// Value must be between 1 and 4.
/// </remarks>
public short Height
{
get
{
// Returns the value in the height attribute.
return height;
}
set
{
// Checks if the value is within the allowed range.
if ((value > 0) && (value < 5))
{
// The value is within the allowed range.
// Sets the width attribute to the value.
height = value;
}
else
{
// The value is not within the allowed range.
// Throws an argument exception with the error.
throw new ArgumentException("Property Height must be between 1 and 4.");
}
}
}
/// <summary>
/// Property that holds and sets the shape of the block.
/// </summary>
public Brick[,] Shape
{
get
{
// Returns the value in the shape attribute.
return shape;
}
set
{
// Checks if the length of the value to be set is right, according the the width and height of the block.
if (value.Length == width * height)
{
// The value is right.
// Sets the shape attribute to the value.
shape = value;
}
else
{
// The value is not right.
// Throws an argument exception with the error.
throw new ArgumentException("Specified index length does not match block dimensions.");
}
}
}
/// <summary>
/// Property that holds and sets the block type.
/// </summary>
/// <remarks>
/// The block type can be set only one time.
/// </remarks>
public BlockType BlockType
{
get
{
// Returns the value in the blockType attribute.
return blockType;
}
set
{
// Creates a new shape.
Brick[,] shape;
// Tests if the current block type is "Undefined".
if (blockType == BlockType.Undefined)
{
// Current block type is "Undefined".
// Sets the
blockType = value;
// Checks for the new block type.
switch(blockType)
{
case BlockType.Straight:
// Block type is "Straight".
// Sets the Width, Height, Top and Left properties.
this.Width = 4;
this.Height = 1;
this.Top = 0;
this.Left = 3;
// Creates the new shape for this block.
shape = new Brick[this.Width, this.Height];
shape[0, 0].Filled = true;
shape[1, 0].Filled = true;
shape[2, 0].Filled = true;
shape[3, 0].Filled = true;
// Creates the images for this block.
shape[0, 0].BrickImage = blockImage13;
shape[1, 0].BrickImage = blockImage14;
shape[2, 0].BrickImage = blockImage13;
shape[3, 0].BrickImage = blockImage14;
// Sets the Shape property to the new shape created.
this.Shape = shape;
break;
case BlockType.Rectangle:
// Block type is "Rectangle".
// Sets the Width, Height, Top and Left properties.
this.Width = 2;
this.Height = 2;
this.Top = 0;
this.Left = 4;
// Creates the new shape for this block.
shape = new Brick[this.Width, this.Height];
shape[0, 0].Filled = true;
shape[0, 1].Filled = true;
shape[1, 0].Filled = true;
shape[1, 1].Filled = true;
// Creates the images for this block.
shape[0, 0].BrickImage = blockImage05;
shape[0, 1].BrickImage = blockImage06;
shape[1, 0].BrickImage = blockImage06;
shape[1, 1].BrickImage = blockImage05;
// Sets the Shape property to the new shape created.
this.Shape = shape;
break;
case BlockType.CornerLeft:
// Block type is "CornerLeft".
// Sets the Width, Height, Top and Left properties.
this.Width = 3;
this.Height = 2;
this.Top = 0;
this.Left = 4;
// Creates the new shape for this block.
shape = new Brick[this.Width, this.Height];
shape[0, 0].Filled = true;
shape[1, 0].Filled = true;
shape[2, 0].Filled = true;
shape[0, 1].Filled = true;
shape[1, 1].Filled = false;
shape[2, 1].Filled = false;
// Creates the images for this block.
shape[0, 0].BrickImage = blockImage08;
shape[1, 0].BrickImage = blockImage07;
shape[2, 0].BrickImage = blockImage08;
shape[0, 1].BrickImage = blockImage07;
// Sets the Shape property to the new shape created.
this.Shape = shape;
break;
case BlockType.CornerRight:
// Block type is "CornerRight".
// Sets the Width, Height, Top and Left properties.
this.Width = 3;
this.Height = 2;
this.Top = 0;
this.Left = 4;
// Creates the new shape for this block.
shape = new Brick[this.Width, this.Height];
shape[0, 0].Filled = true;
shape[1, 0].Filled = true;
shape[2, 0].Filled = true;
shape[0, 1].Filled = false;
shape[1, 1].Filled = false;
shape[2, 1].Filled = true;
// Creates the images for this block.
shape[0, 0].BrickImage = blockImage11;
shape[1, 0].BrickImage = blockImage12;
shape[2, 0].BrickImage = blockImage11;
shape[2, 1].BrickImage = blockImage12;
// Sets the Shape property to the new shape created.
this.Shape = shape;
break;
case BlockType.Cross:
// Block type is "Cross".
// Sets the Width, Height, Top and Left properties.
this.Width = 3;
this.Height = 2;
this.Top = 0;
this.Left = 4;
// Creates the new shape for this block.
shape = new Brick[this.Width, this.Height];
shape[0, 0].Filled = true;
shape[1, 0].Filled = true;
shape[2, 0].Filled = true;
shape[0, 1].Filled = false;
shape[1, 1].Filled = true;
shape[2, 1].Filled = false;
// Creates the images for this block.
shape[0, 0].BrickImage = blockImage04;
shape[1, 0].BrickImage = blockImage03;
shape[2, 0].BrickImage = blockImage04;
shape[1, 1].BrickImage = blockImage03;
// Sets the Shape property to the new shape created.
this.Shape = shape;
break;
case BlockType.Zigzag1:
// Block type is "Zigzag1".
// Sets the Width, Height, Top and Left properties.
this.Width = 2;
this.Height = 3;
this.Top = 0;
this.Left = 4;
// Creates the new shape for this block.
shape = new Brick[this.Width, this.Height];
shape[0, 0].Filled = false;
shape[1, 0].Filled = true;
shape[0, 1].Filled = true;
shape[1, 1].Filled = true;
shape[0, 2].Filled = true;
shape[1, 2].Filled = false;
// Creates the images for this block.
shape[1, 0].BrickImage = blockImage10;
shape[0, 1].BrickImage = blockImage10;
shape[1, 1].BrickImage = blockImage09;
shape[0, 2].BrickImage = blockImage09;
// Sets the Shape property to the new shape created.
this.Shape = shape;
break;
case BlockType.Zigzag2:
// Block type is "Zigzag2".
// Sets the Width, Height, Top and Left properties.
this.Width = 2;
this.Height = 3;
this.Top = 0;
this.Left = 4;
// Creates the new shape for this block.
shape = new Brick[this.Width, this.Height];
shape[0, 0].Filled = true;
shape[1, 0].Filled = false;
shape[0, 1].Filled = true;
shape[1, 1].Filled = true;
shape[0, 2].Filled = false;
shape[1, 2].Filled = true;
// Creates the images for this block.
shape[0, 0].BrickImage = blockImage02;
shape[0, 1].BrickImage = blockImage01;
shape[1, 1].BrickImage = blockImage02;
shape[1, 2].BrickImage = blockImage01;
// Sets the Shape property to the new shape created.
this.Shape = shape;
break;
}
}
else
{
// Current block type is not Undefined.
// Throws an argument exception with the error.
throw new ArgumentException("The property BlockType can't be changed once defined for the first time.");
}
}
}
/// <summary>
/// Method that draws the block in a surface.
/// </summary>
/// <param name="drawingSurface">The graphics surface where the block will be drawn.</param>
public void Draw(Graphics drawingSurface)
{
// Runs through the block Width.
for(int i = 0; i < this.Width; i++)
{
// Runs through the block Height.
for(int j = 0; j < this.Height; j++)
{
// Checks if the current brick of the block is set to be solid.
if (this.Shape[i, j].Filled == true)
{
// Current brick of the block is set to be solid.
// Creates a rectangle in the right position of this brick.
Rectangle rect = new Rectangle((this.Left + i) * Game.BlockImageWidth, (this.Top + j) * Game.BlockImageHeight, Game.BlockImageWidth, Game.BlockImageHeight);
// Draws the block image in the just created rectangle.
drawingSurface.DrawImage(this.Shape[i, j].BrickImage, rect);
}
}
}
}
/// <summary>
/// Method that rotates the block.
/// </summary>
/// <param name="clockwise">True if the block will be rotated clockwise, false if counterclockwise.</param>
public void Rotate(bool clockwise)
{
short newWidth = 0;
short newHeight = 0;
Brick[,] newShape;
// Inverts the width with the height.
newWidth = this.Height;
newHeight = this.Width;
// Creates a new shape with the new width and height.
newShape = new Brick[newWidth, newHeight];
// Checks if the block must be rotated clockwise or counterclockwise.
if(clockwise)
{
// The block must be rotated clockwise.
// Tests if the block can be rotated clockwise, according to its position in the play field.
if (((this.Left + newWidth) <= Game.PlayingFieldWidth) && ((this.Top + newHeight) < Game.PlayingFieldHeight))
{
// The block can be rotated.
// Populates the new shape by rotating the old shape.
for(int i = 0; i < this.Width; i++)
{
for(int j = 0; j < this.Height; j++)
{
newShape[((this.Height - 1) - j), i] = this.Shape[i, j];
}
}
// Puts the new values in the current block.
this.Width = newWidth;
this.Height = newHeight;
this.Shape = newShape;
}
}
else
{
// The block must be rotated counterclockwise.
// Tests if the block can be rotated counterclockwise, according to its position in the play field.
if (((this.Left + newWidth) <= Game.PlayingFieldWidth) && ((this.Top + newHeight) < Game.PlayingFieldHeight))
{
// The block can be rotated.
// Populates the new shape by rotating the old shape.
for(int i = 0; i < this.Width; i++)
{
for(int j = 0; j < this.Height; j++)
{
newShape[j, ((this.Width - 1) - i)] = this.Shape[i, j];
}
}
// Puts the new values in the current block.
this.Width = newWidth;
this.Height = newHeight;
this.Shape = newShape;843