⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 board.cs

📁 C#开发的运行于windows mobile PDA上的游戏
💻 CS
字号:
////////////////////////////////////////////////
// 
// Project: Lines.NET
// Version: 1.1
// Author:  Vladimir L.
// 
// homepage: http://www.boomsoft.org
// e-mail:   support@boomsoft.org
// 
// Copyright (c) 2003-2004, Boomsoft.org
// 

using System;
using System.Drawing;

namespace Lines.Core
{
	/// <summary>
	/// Represents game board the field where differently colored balls are placed and moved.
	/// </summary>
	/// <remarks>
	/// A single instance of this class is incapsulated and used by <see cref="Game"/> class. There is no need 
	/// to create other instances of this class. Each time the new game is started a new instance of this class
	/// is created.
	/// </remarks>
	public class Board
	{
		/// <summary>
		/// Refers to the owner, an instance of <see cref="Game"/> class.
		/// </summary>
		private Game game;
		
		/// <summary>
		/// Defines the field size of game board (width, height).
		/// </summary>
		private Size size;
		/// <summary>
		/// Defines the maximum index of color that might be generated during game.
		/// </summary>
		private int colors;

		/// <summary>
		/// A 2-D array of balls, which is the game field itself.
		/// </summary>
		private Ball[,] board;
		/// <summary>
		/// Reference to pseudo-random number generator that is used to allocate new balls.
		/// </summary>
		private Random random;
		
		/// <summary>
		/// Gets the game board field size (width, height).
		/// </summary>
		public Size BoardSize
		{
			get {return size;}
		}

		/// <summary>
		/// Gets the maximum index of color that might be generated during game.
		/// </summary>
		/// <remarks>
		/// The colors of balls will vary between 1 and value of this property inclusively.
		/// </remarks>
		public int Colors
		{
			get {return colors;}
		}

		#region Constructors
		/// <summary>
		/// Creates an instance of Board class.
		/// <seealso cref="AppSettings.BoardWidth"/>
		/// <seealso cref="AppSettings.BoardHeight"/>
		/// <seealso cref="AppSettings.Colors"/>
		/// </summary>
		/// <param name="game">The reference to board owner, an instance of <see cref="Game"/> class.</param>
		/// <remarks>
		/// Creates an instance of Board class with default size and number of colors defined by 
		/// <see cref="AppSettings"/> class.
		/// </remarks>
		public Board(Game game) 
			: this(game, new Size(AppSettings.Instance.BoardWidth, AppSettings.Instance.BoardHeight))
		{
		}

		/// <summary>
		/// Creates an instance of Board class.
		/// <seealso cref="AppSettings.Colors"/>
		/// </summary>
		/// <param name="game">The reference to board owner, an instance of <see cref="Game"/> class.</param>
		/// <param name="size">The game board field size (width, height).</param>
		/// <remarks>
		/// Creates an instance of Board class with default number of colors defined by 
		/// <see cref="AppSettings"/> class.
		/// </remarks>
		public Board(Game game, Size size)
			: this(game, size, AppSettings.Instance.Colors)
		{
		}

		/// <summary>
		/// Creates an instance of Board class.
		/// </summary>
		/// <param name="game">The reference to board owner, an instance of <see cref="Game"/> class.</param>
		/// <param name="size">The game board field size (width, height).</param>
		/// <param name="colors">The number ball colors that are used during the game.</param>
		public Board(Game game, Size size, int colors)
		{
			this.game = game;
			this.size = size;
			this.board = new Ball[size.Width, size.Height];
			this.colors = colors;
			this.random = new Random((int)DateTime.Now.Ticks);
		}
		#endregion

		/// <summary>
		/// Gets ball at a certain location on the board.
		/// </summary>
		/// <param name="x">The x-coordinate of location.</param>
		/// <param name="y">The y-coordinate of location.</param>
		/// <returns>A reference to a <see cref="Ball"/> object that is located on specified position,
		/// or <c>null</c> if this position is empty.</returns>
		public Ball GetBallAt(int x, int y)
		{
			return board[x, y];
		}

		/// <summary>
		/// Creates an instance of <see cref="Ball"/> class with predefined color and places it 
		/// on a certain posion on the board.
		/// </summary>
		/// <param name="x">The x-coordinate of location the ball to be placed on.</param>
		/// <param name="y">The y-coordinate of location the ball to be placed on.</param>
		/// <param name="color">The color index of ball.</param>
		/// <returns>The reference to a newly created ball.</returns>
		public Ball CreateBallAt(int x, int y, int color)
		{
			Ball ball = new Ball(this, color, x, y);
			SetBallAt(ball, x, y);

			return ball;
		}

		/// <summary>
		/// Sets ball at a certain position on the board.
		/// </summary>
		/// <param name="ball">The ball to be set.</param>
		/// <param name="x">The x-coordinate of ball's new location.</param>
		/// <param name="y">The y-coordinate of ball's new location.</param>
		/// <exception cref="ModelException">If the position the ball should be set to is already occupied.</exception>
		public void SetBallAt(Ball ball, int x, int y)
		{
			if (GetBallAt(x, y) != null)
			{
				throw new ModelException("The position [" + x + ", " + y + "] is already occupied!");
			}
			
			board[x, y] = ball;
			ball.MoveTo(x, y);
		}
		
		/// <summary>
		/// Removes ball from a certain position on the board.
		/// </summary>
		/// <param name="x">The x-coordinate of ball's location.</param>
		/// <param name="y">The y-coordinate of ball's location.</param>
		public void DeleteBallAt(int x, int y)
		{
			board[x, y] = null;
		}

		/// <summary>
		/// Computes the amount of empty squares on the board.
		/// </summary>
		/// <returns>The amount of empty locations.</returns>
		public int GetEmptySquaresCount()
		{
			int result = 0;
			for (int i = 0; i < size.Width; i++)
			{
				for (int j = 0; j < size.Height; j++)
				{
					if (GetBallAt(i, j) == null)
					{
						result++;
					}
				}
			}
			return result;
		}

		/// <summary>
		/// Randomly selects a one of the empty squares on the board.
		/// </summary>
		/// <returns>The randomly selected empty location.</returns>
		public Point GetRandomEmptySquare()
		{
			int pos = random.Next(1, GetEmptySquaresCount() + 1);
			int curPos = 0;
			for (int i = 0; i < size.Width; i++)
			{
				for (int j = 0; j < size.Height; j++)
				{
					if (GetBallAt(i, j) == null)
					{
						curPos++;
						if (curPos == pos)
						{
							return new Point(i, j);
						}
					}
				}
			}
			throw new ModelException("Enable to allocate a new empty position!");
		}

		/// <summary>
		/// Generates random balls for the next step.
		/// </summary>
		/// <param name="amount">The amount of balls to be created.</param>
		/// <returns>An array of generated balls, or <c>null</c> if there is no free place to allocate 
		/// such amount of balls.</returns>
		/// <remarks>
		/// The locations and colors of balls are randomly selected with a help of 
		/// <see cref="GetRandomEmptySquare()"/> and <see cref="GetRandomColor()"/> methods.
		/// </remarks>
		public Ball[] GenerateVirtualBalls(int amount)
		{
			if (GetEmptySquaresCount() < amount)
			{
				//throw new ModelException("Unable to allocate " + amount + " empty positions!");
				return null;
			}
			
			Ball[] result = new Ball[amount];
			for (int i = 0; i < amount; i++)
			{
				Point pos = GetRandomEmptySquare();
				result[i] = CreateBallAt(pos.X, pos.Y, GetRandomColor());
			}
			for (int i = 0; i < amount; i++)
			{
				DeleteBallAt(result[i].X, result[i].Y);
			}

			return result;
		}

		/// <summary>
		/// Generates random color index.
		/// </summary>
		/// <returns>The random index color.</returns>
		/// <remarks>
		/// Tha range of colors lies between 1 and <see cref="Colors"/> inclusively.
		/// </remarks>
		public int GetRandomColor()
		{
			return random.Next(1, colors + 1);
		}

		/// <summary>
		/// Gets the ball that is currently selected on the board.
		/// </summary>
		/// <returns>The reference to a ball that is currently selected, or <c>null</c> in 
		/// case there is no selected ball on the board.</returns>
		public Ball GetSelectedBall()
		{
			for (int i = 0; i < size.Width; i++)
			{
				for (int j = 0; j < size.Height; j++)
				{
					Ball ball = GetBallAt(i, j);
					if ((ball != null) &&
						(ball.Selected))
					{
						return ball;
					}
				}
			}
			return null;
		}

		/// <summary>
		/// Sets selected status to a certain ball.
		/// <seealso cref="DeselectBall()"/>
		/// </summary>
		/// <param name="ball">The ball to be selected.</param>
		/// <remarks>
		/// Previously selected ball will be automatically diselected.
		/// </remarks>
		public void SelectBall(Ball ball)
		{
			SelectBall(ball.X, ball.Y);
		}

		/// <summary>
		/// Sets selected status to a ball on a certain location.
		/// <seealso cref="DeselectBall()"/>
		/// </summary>
		/// <param name="x">The x-coordinate of location.</param>
		/// <param name="y">The y-coordinate of location.</param>
		/// <remarks>
		/// Previously selected ball will be automatically diselected. If there is no ball
		/// under specified location there will not be any selected ball by the end of this
		/// operation.
		/// </remarks>
		public void SelectBall(int x, int y)
		{
			// Deselect a ball if one is already selected
			DeselectBall();

			// Select a new ball
			Ball ball = GetBallAt(x, y);
			if (ball != null)
			{
				ball.Select(true);
			}
		}

		/// <summary>
		/// Diselects the currently selected ball if any.
		/// </summary>
		public void DeselectBall()
		{
			Ball ball = GetSelectedBall();
			if (ball != null)
			{
				ball.Select(false);
			}
		}

		/// <summary>
		/// Creates route between two points with a help of <see cref="PathFinder"/> class.
		/// </summary>
		/// <param name="from">The point to build the route from.</param>
		/// <param name="to">The destination point of route.</param>
		/// <returns>An array of points to move between defined locations if the <see cref="PathFinder"/>
		/// was able to find a route, <c>null</c> otherwise.</returns>
		public Point[] CreateRoute(Point from, Point to)
		{
			int[,] matrix = new int[BoardSize.Width, BoardSize.Height];

			for (int i = 0; i < BoardSize.Width; i++)
			{
				for (int j = 0; j < BoardSize.Height; j++)
				{
					Ball ball = GetBallAt(i, j);
					if (ball != null)
					{
						matrix[i, j] = PathFinder.POS_OCCUPIED;
					}
				}
			}

			PathFinder pathFinder = new PathFinder(matrix);
			return pathFinder.FindPath(from, to);
		}

		/// <summary>
		/// Moves a ball from one position to another.
		/// </summary>
		/// <param name="from">The location where to move the ball from.</param>
		/// <param name="to">The destination location of the ball.</param>
		/// <exception cref="ModelException">If there is no ball under the <c>from</c> location or 
		/// the <c>to</c> location is currently occupied.</exception>
		public void MoveBall(Point from, Point to)
		{
			Ball ball = GetBallAt(from.X, from.Y);
			if (ball == null)
			{
				throw new ModelException("There is no ball under position [" + from.X + ", " + from.Y + "]");
			}
			Ball posTo = GetBallAt(to.X, to.Y);
			if (posTo != null)
			{
				throw new ModelException("The position [" + to.X + ", " + to.Y + "] is already occupied!");
			}
			
			board[from.X, from.Y] = null;
			board[to.X, to.Y] = ball;
			ball.MoveTo(to.X, to.Y);
		}

		/// <summary>
		/// Finds balls that compose lines to remove them from the board.
		/// </summary>
		/// <param name="ballsInLine">Defines the minimum length of line (See <see cref="Game.BallsInLine"/>).</param>
		/// <returns>An array of balls that should be removed from the board at the current step, or
		/// <c>null</c> if there is no such.</returns>
		public Ball[] FindBallsToDestroy(int ballsInLine)
		{
			int[,] matrix = new int[BoardSize.Width, BoardSize.Height];

			for (int x = 0; x < BoardSize.Width; x++)
			{
				for (int y = 0; y < BoardSize.Height; y++)
				{
					Ball ball = GetBallAt(x, y);
					matrix[x, y] = ball != null ? ball.Color : -1;
				}
			}

			DestroyFinder finder = new DestroyFinder(matrix, ballsInLine);
			Point[] locations = finder.FindLocations();
			
			Ball[] result = new Ball[locations.Length];
			int i = 0;
			foreach (Point location in locations)
			{
				result[i++] = GetBallAt(location.X, location.Y);
			}

			return result;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -