// (c) 2005 kp@kp73.com
using System;
namespace KP.Tetris{
/// <summary>
/// The play area in a tetris game.
/// </summary>
public class Board
{
private static int m_width = Config.UserPreference.BoardWidth;
private static int m_height = Config.UserPreference.BoardHeight;
/// <summary>
/// Get the width (number of cells) of the playable area.
/// </summary>
public static int Width { get { return m_width; } }
/// <summary>
/// Get the height (number of cells) of the playable area.
/// </summary>
public static int Height { get { return m_height; } }
/// <summary>
/// Cell map of the playable area.
/// </summary>
private Cell[,] map;
private GameView view;
private Cell[,] viewMap;
/// <summary>
/// Initialises a new instance of the Board class.
/// </summary>
public Board()
{
map = new Cell[Width, Height];
view = new GameView();
viewMap = new Cell[Width, Height];
view.m_map = viewMap;
view.m_board = this;
}
/// <summary>
/// Indexed access to the map of the play area.
/// </summary>
public Cell this[int x, int y]
{
get { return map[x, y]; }
}
/// <summary>
/// Indicates the number of complete rows.
/// </summary>
private int m_rowsCompleted;
/// <summary>
/// Get the number of complete rows. A complete
/// row is a horizontal area of the play area one cell high
/// with all cells occupied. During a game, completed rows
/// are removed from the play area.
/// </summary>
internal int RowsCompleted
{
get { return m_rowsCompleted; }
}
/// <summary>
/// Merges a teramino into the play area.
/// </summary>
/// <param name="state">State of the tetramino to merge.</param>
internal void MergeTetramino(TetraminoState state)
{
// get a map of the tetramino's view.
TetraminoMap view = state.Tetramino.GetAppearance();
// merge it into the play area map.
for (int y = state.BottomBound; y <= state.TopBound; y++)
{
for (int x = state.LeftBound; x <= state.RightBound; x++)
{
if (x >= 0 && y >= 0)
{
int col = x - state.LeftBound;
int row = y - state.BottomBound;
if (y < Board.Height
&& x < Board.Width
&& view[col, row].IsOccupied)
map[x, y] = view[col, row];
}
}
}
}
/// <summary>
/// Clears any completed rows from the play area. Occupied
/// cells above cleared rows are moved down to fill the vacant
/// cells.
/// </summary>
/// <returns>Number of rows removed.</returns>
internal int RemoveCompletedRows()
{
int numberRemoved = 0;
// for each row
for (int y = 0; y < Board.Height; y++)
{
// determine if row is complete
bool isRowComplete = true;
for (int x = 0; x < Board.Width; x++)
{
isRowComplete &= map[x, y].IsOccupied;
if (!isRowComplete) break;
}
if (isRowComplete)
{
// for each row above this one
for (int row = y; row < Board.Height; row++)
{
for (int col = 0; col < Board.Width; col++)
{
if (row < Board.Height - 1)
// move the cells down one row
map[col, row] = map[col, row + 1];
else
{
// clear row of cells
map[col, row].CellColour = Colour.Black;
map[col, row].IsOccupied = false;
}
}
}
numberRemoved++;
// check this row again
y -= 1;
}
}
this.m_rowsCompleted += numberRemoved;
return numberRemoved;
} // void RemoveCompletedRows
/// <summary>
/// Provides a cell map view of the active play area.
/// </summary>
/// <param name="game">The tetris game to retrieve the view from.</param>
/// <returns>View object includes a view of the board, the active tetramino
/// and a simple merged view</returns>
internal GameView GetGameView(TetrisGame game)
{
TetraminoState state = game.ActiveTetramino.State;
TetraminoMap tetraminoAppearance = game.ActiveTetramino.GetAppearance();
view.a = game.ActiveTetramino;
view.m_board = game.PlayArea;
// merge the board and active piece into one simple view
bool isOccupied = false;
Colour colour = Colour.Black;
for (int y = 0; y < Board.Height; y++)
{
for (int x = 0; x < Board.Width; x++)
{
Cell boardCell = game.PlayArea[x, y];
if (boardCell.IsOccupied)
{
isOccupied = true;
colour = boardCell.CellColour;
}
else if (state != null
&& x >= state.LeftBound
&& x <= state.RightBound
&& y <= state.TopBound
&& y >= state.BottomBound)
{
isOccupied = tetraminoAppearance[x - state.LeftBound, y - state.BottomBound].IsOccupied;
colour = game.ActiveTetramino.Colour;
}
else
{
isOccupied = false;
colour = Colour.Black;
}
viewMap[x, y].IsOccupied = isOccupied;
viewMap[x, y].CellColour = colour;
}
}
return view;
} // GetGameView
} // class Board
} // namespace KP.Tetris
|