Legionnaire (C#/XNA)
Spring 2010 | Project Length: 9 weeks (Coursework)
A Metroidvania game programmed from scratch in C# 3.0 using the XNA 3.1 framework
- Worked as a group lead (group of 4 total): scheduling, setting goals and setting up SVN and communication
- Responsibilities: programming basic engine framework (esp. design and code stubbing), custom data structures (esp. hash table), sound, animations, data I/O, merging/cleaning code
Lessons Learned
- Clean up bugs as you see them, rather than hacking in a fix. Our collision detection broke early and often. Once we changed over to our final animations, the player collision for touching the platform was way off with no easy fix.
- Stay organized! We managed to get as much done as we did because we regularly held group meetings and set goals and objectives; however, we would fall behind when we failed to set tasks and deadlines.
- XNA is pretty flexible and powerful!
Downloads
Legionnaire’s Manual (PDF – 678kb)
Source Code (ZIP – 151mb)
Installer (ZIP – 71.6mb)
Screenshots
Code Sample
For part of this project, I coded Tile Sets to allow us to change the appearance of levels on the fly. Here is an example tileset:
. intangible # Content\\Blocks\\wallblock.png solid - Content\\Blocks\\platform.png p
Here is the source code for the Tile Set class, which is utilized like a Dictionary:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework.Graphics;
namespace Metroidvania
{
/// <summary>
/// Implements tile sets for different levels using a dictionary interface.
///
/// Author: Zachary Hoefler
/// </summary>
/// <remarks>
/// This allows for easy re-skinning of levels, and greater
/// variety in tile appearances available. It also enables
/// cusomizable map file formats without having to hard code them.
/// </remarks>
class Tileset : IDictionary
{
public const int DictionarySize = 10007;
private int count;
List<Tile>[] values;
List<char>[] keys;
public Tileset()
{
values = new List[DictionarySize];
keys = new List[DictionarySize];
count = 0;
for (int i = 0; i < DictionarySize; ++i)
{
values[i] = new List(1);
keys[i] = new List(1);
}
}
/// <summary>
/// Test method
/// </summary>
public static void Main(string[] args)
{
Console.WriteLine("Testing Tileset class!");
Console.WriteLine("If it all works, everything should return true!\n");
Tileset tileset = new Tileset();
tileset.Add('x', new Tile());
tileset.Add('_', new Tile());
Console.Write("Testing ContainsKey...");
Console.Write(tileset.ContainsKey('x') + ", ");
Console.WriteLine(tileset.ContainsKey('_'));
tileset.Remove('_');
Console.WriteLine("Testing remove... " + tileset.ContainsKey('x') + ", "
+ !tileset.ContainsKey('_'));
tileset['p'] = new Tile();
Console.WriteLine("Testing indexer set... " + tileset.ContainsKey('p'));
Console.WriteLine("Checking indexer get... " + tileset['p']);
try
{
Console.Write("Checking for nonexistant key...");
Console.WriteLine(tileset['&'] + "SHOULD NOT PRINT");
}
catch (KeyNotFoundException knfe)
{
Console.WriteLine(knfe.Message);
}
Console.WriteLine("Test complete!");
Console.ReadLine();
}
/// <summary>
/// Loads in the key-value pairs for the tileset
/// from a properly formatted file
/// </summary>
/// <remarks>
/// FORMAT:
/// char texture tangibility
/// -or-
/// char tangibility (for textureless tiles)
/// EXAMPLES:
/// x wall.png t
/// _ platform.png p
/// </remarks>
/// <param name="<span class=" />filepath">The path of the file to load
public static Tileset LoadFromFile(string filepath, GraphicsDevice graphicsDevice)
{
List tileData = new List();
Tileset myTileset = new Tileset();
using (TextReader textReader = new StreamReader(filepath))
{
string nextLine = textReader.ReadLine();
while (nextLine != null)
{
tileData.Add(nextLine);
nextLine = textReader.ReadLine();
}
}
foreach (string s in tileData)
{
string[] tokens = s.Split(' ');
if (tokens.Length == 2) // no texture
{
char tileChar = (tokens[0].ToCharArray())[0];
TileTangibility tangibility = GetTangibility(tokens[1]);
myTileset.Add(tileChar, new Tile(null, tangibility));
}
if (tokens.Length == 3) // textured
{
// tokens[0] == tile character
// tokens[1] == filename
// tokens[2] == tangibility
char tileChar = (tokens[0].ToCharArray())[0];
Texture2D texture;
try
{
texture = Texture2D.FromFile(graphicsDevice, tokens[1]);
}
catch (FileNotFoundException fnfe)
{
Console.WriteLine("Couldn't find the texture!");
throw fnfe;
}
TileTangibility tangibility = GetTangibility(tokens[2]);
Tile myTile = new Tile(texture, tangibility);
myTileset.Add(tileChar, myTile);
}
}
return myTileset;
}
/// <summary>
/// Helper method for loading in a Tileset from a file. Converts
/// string to tile tangibility. Returns intangible by default if
/// nothing matches.
/// </summary>
/// <remarks>
/// Provides a lot of redundancy to allow flexibility in
/// file naming conventions.
/// </remarks>
private static TileTangibility GetTangibility(string tangibility)
{
tangibility = tangibility.ToLower();
switch (tangibility)
{
case "s":
return TileTangibility.Solid;
case "t": // t for tangible
return TileTangibility.Solid;
case "solid":
return TileTangibility.Solid;
case "i":
return TileTangibility.Intangible;
case "intangible":
return TileTangibility.Intangible;
case "p":
return TileTangibility.Platform;
case "platform":
return TileTangibility.Platform;
default:
return TileTangibility.Intangible;
}
}
/// <summary>
/// Gets the hash code of a character
/// </summary>
/// <returns>The character's hash code</returns>
public static int GetHash(char key)
{
return (int)key;
}
#region IDictionary<char,Tile> Members
/// <summary>
/// Adds a new key-value pair to the tileset
/// </summary>
/// <param name="key">The char used to represent a tile</param>
/// <param name="value">The Tile associated with the key char</param>
/// An element with the same key already exists in the .
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only.</exception>
public void Add(char key, Tile value)
{
if (ContainsKey(key))
throw new ArgumentException();
if (IsReadOnly)
throw new NotSupportedException();
int hashCode = GetHash(key);
keys[hashCode].Add(key);
values[hashCode].Add(value);
++count;
}
/// <summary>
/// Determines whether the contains an element with the specified key.
/// </summary>
/// <param name="key" />The key to locate in the .
/// <returns>
/// true if the contains an element with the key; otherwise, false.
/// </returns>
public bool ContainsKey(char key)
{
foreach (List charList in keys)
{
foreach (char tileKey in charList)
{
if (tileKey.Equals(key))
return true;
}
}
return false;
}
/// <summary>
/// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
/// </summary>
/// <value></value>
/// <returns>An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>.</returns>
public ICollection<char> Keys
{
get
{
char[] keyArray = new char[count];
int currentIndex = 0;
foreach (List charList in keys)
{
foreach (char c in charList)
{
keyArray[currentIndex] = c;
++currentIndex;
}
}
return keyArray;
}
}
/// <summary>
/// Removes the element with the specified key from the .
/// </summary>
/// <param name="key">The key of the element to remove.</param>
/// <returns>
/// true if the element is successfully removed; otherwise, false. This method also returns false if <paramref name="key"/> was not found in the original .
/// </returns>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only.</exception>
public bool Remove(char key)
{
if (IsReadOnly)
throw new NotSupportedException();
int hashCode = GetHash(key);
List keyList = keys[hashCode];
List valueList = values[hashCode];
// find key location
for (int i = 0; i < keyList.Count; ++i)
{
if (keyList[i].Equals(key))
{ // found; remove key and value
keyList.RemoveAt(i);
valueList.RemoveAt(i);
--count;
return true;
}
}
// key not in tileset
return false;
}
/// <summary>
/// Gets the value associated with the specified key.
/// </summary>
/// <param name="key">The key whose value to get.</param>
/// <param name="value" />When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.
/// <returns>
/// true if the object that implements contains an element with the specified key; otherwise, false.
/// </returns>
public bool TryGetValue(char key, out Tile value)
{
if (ContainsKey(key))
{
value = this[key];
return true;
}
else
{
value = Tile.Empty;
return false;
}
}
/// <summary>
/// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
/// </summary>
/// <value></value>
/// <returns>An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>.</returns>
public ICollection<Tile> Values
{
get
{
Tile[] tileArray = new Tile[count];
int currentIndex = 0;
foreach (List tileList in values)
{
foreach (Tile t in tileList)
{
tileArray[currentIndex] = t;
++currentIndex;
}
}
return tileArray;
}
}
/// <summary>
/// Gets or sets the <see cref="Metroidvania.Tile"/> with the specified key.
/// </summary>
/// <value>The Tile associated with the passed-in key</value>
public Tile this[char key]
{
get
{
return GetTileFromList(key);
}
set
{
Add(key, value);
}
}
/// <summary>
/// Helper method, gets a tile from a list
/// </summary>
/// <exception cref="T:System.Collections.Generic.KeyNotFoundException`1"/>
/// The requested key was not found in the collection.
/// </exception>
private Tile GetTileFromList(char key)
{
int hashCode = GetHash(key);
List keyList = keys[hashCode];
for (int i = 0; i < keyList.Count; ++i)
{
if (keyList[i].Equals(key))
return (values[hashCode])[i];
}
throw new KeyNotFoundException();
}
#endregion
#region ICollection<KeyValuePair<char,Tile>> Members
/// <summary>
/// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public void Add(KeyValuePair<char, Tile> item)
{
if (IsReadOnly)
throw new NotSupportedException();
Add(item.Key, item.Value);
}
/// <summary>
/// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
public void Clear()
{
if (IsReadOnly)
throw new NotSupportedException();
values = new List[DictionarySize];
keys = new List[DictionarySize];
count = 0;
for (int i = 0; i < DictionarySize; ++i)
{
values[i] = new List(1);
keys[i] = new List(1);
}
}
/// <summary>
/// Determines whether the contains a specific value.
/// </summary>
/// <param name="item" />The object to locate in the .
/// <returns>
/// true if <paramref name="item"/> is found in the ; otherwise, false.
/// </returns>
public bool Contains(KeyValuePair item)
{
if (ContainsKey(item.Key) && this[item.Key].Equals(item.Value))
return true;
else
return false;
}
/// <summary>
/// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
/// </summary>
/// <param name="array" />The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing.
/// <param name="<span class=" />arrayIndex">The zero-based index in at which copying begins.
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="array"/> is null.
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="arrayIndex"/> is less than 0.
/// <exception cref="T:System.ArgumentException">
/// <paramref name="array"/> is multidimensional.-or- is equal to or greater than the length of .-or-The number of elements in the source is greater than the available space from to the end of the destination .-or-Type cannot be cast automatically to the type of the destination .
public void CopyTo(KeyValuePair[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException();
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException();
if (arrayIndex > array.GetUpperBound(0) ||
(array.GetUpperBound(0) - arrayIndex) < count)
throw new ArgumentException();
foreach (KeyValuePair keyValPair in this)
{
array[arrayIndex++] = keyValPair;
}
}
/// <summary>
/// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <value></value>
/// <returns>The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</returns>
public int Count
{
get { return count; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
/// </summary>
/// <value></value>
/// <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.</returns>
public bool IsReadOnly
{
get { return false; }
}
/// <summary>
/// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
/// </returns>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public bool Remove(KeyValuePair item)
{
if (IsReadOnly)
throw new NotSupportedException();
if (ContainsKey(item.Key) && this[item.Key].Equals(item.Value))
{
Remove(item.Key);
return true;
}
else
return false;
}
#endregion
#region IEnumerable<KeyValuePair<char,Tile>> Members
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A that can be used to iterate through the collection.
/// </returns>
public IEnumerator> GetEnumerator()
{
for (int i = 0; i < DictionarySize; ++i)
{
for (int j = 0; j < keys[i].Count; ++j)
{
yield return new KeyValuePair(keys[i][j], values[i][j]);
}
}
}
#endregion
#region IEnumerable Members
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
foreach (List tileList in values)
{
foreach (Tile tile in tileList)
{
yield return tile;
}
}
}
#endregion
}
}
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework.Graphics;
namespace Metroidvania
{
/// <summary>
/// Implements tile sets for different levels using a dictionary interface.
///
/// Author: Zachary Hoefler
/// </summary>
/// <remarks>
/// This allows for easy re-skinning of levels, and greater
/// variety in tile appearances available. It also enables
/// cusomizable map file formats without having to hard code them.
/// </remarks>
class Tileset : IDictionary
{
public const int DictionarySize = 10007;
private int count;
List<Tile>[] values;
List<char>[] keys;
public Tileset()
{
values = new List[DictionarySize];
keys = new List[DictionarySize];
count = 0;
for (int i = 0; i < DictionarySize; ++i)
{
values[i] = new List(1);
keys[i] = new List(1);
}
}
/// <summary>
/// Test method
/// </summary>
public static void Main(string[] args)
{
Console.WriteLine(“Testing Tileset class!”);
Console.WriteLine(“If it all works, everything should return true!\n”);
Tileset tileset = new Tileset();
tileset.Add(‘x’, new Tile());
tileset.Add(‘_’, new Tile());
Console.Write(“Testing ContainsKey…”);
Console.Write(tileset.ContainsKey(‘x’) + “, “);
Console.WriteLine(tileset.ContainsKey(‘_’));
tileset.Remove(‘_’);
Console.WriteLine(“Testing remove… ” + tileset.ContainsKey(‘x’) + “, “
+ !tileset.ContainsKey(‘_’));
tileset['p'] = new Tile();
Console.WriteLine(“Testing indexer set… ” + tileset.ContainsKey(‘p’));
Console.WriteLine(“Checking indexer get… ” + tileset['p']);
try
{
Console.Write(“Checking for nonexistant key…”);
Console.WriteLine(tileset['&'] + “SHOULD NOT PRINT”);
}
catch (KeyNotFoundException knfe)
{
Console.WriteLine(knfe.Message);
}
Console.WriteLine(“Test complete!”);
Console.ReadLine();
}
/// <summary>
/// Loads in the key-value pairs for the tileset
/// from a properly formatted file
/// </summary>
/// <remarks>
/// FORMAT:
/// char texture tangibility
/// -or-
/// char tangibility (for textureless tiles)
/// EXAMPLES:
/// x wall.png t
/// _ platform.png p
/// </remarks>
/// <param name=”filepath”>The path of the file to load</param>
public static Tileset LoadFromFile(string filepath, GraphicsDevice graphicsDevice)
{
List<string> tileData = new List<string>();
Tileset myTileset = new Tileset();
using (TextReader textReader = new StreamReader(filepath))
{
string nextLine = textReader.ReadLine();
while (nextLine != null)
{
tileData.Add(nextLine);
nextLine = textReader.ReadLine();
}
}
foreach (string s in tileData)
{
string[] tokens = s.Split(‘ ‘);
if (tokens.Length == 2) // no texture
{
char tileChar = (tokens[0].ToCharArray())[0];
TileTangibility tangibility = GetTangibility(tokens[1]);
myTileset.Add(tileChar, new Tile(null, tangibility));
}
if (tokens.Length == 3) // textured
{
// tokens[0] == tile character
// tokens[1] == filename
// tokens[2] == tangibility
char tileChar = (tokens[0].ToCharArray())[0];
Texture2D texture;
try
{
texture = Texture2D.FromFile(graphicsDevice, tokens[1]);
}
catch (FileNotFoundException fnfe)
{
Console.WriteLine(“Couldn’t find the texture!”);
throw fnfe;
}
TileTangibility tangibility = GetTangibility(tokens[2]);
Tile myTile = new Tile(texture, tangibility);
myTileset.Add(tileChar, myTile);
}
}
return myTileset;
}
/// <summary>
/// Helper method for loading in a Tileset from a file. Converts
/// string to tile tangibility. Returns intangible by default if
/// nothing matches.
/// </summary>
/// <remarks>
/// Provides a lot of redundancy to allow flexibility in
/// file naming conventions.
/// </remarks>
private static TileTangibility GetTangibility(string tangibility)
{
tangibility = tangibility.ToLower();
switch (tangibility)
{
case “s”:
return TileTangibility.Solid;
case “t”: // t for tangible
return TileTangibility.Solid;
case “solid”:
return TileTangibility.Solid;
case “i”:
return TileTangibility.Intangible;
case “intangible”:
return TileTangibility.Intangible;
case “p”:
return TileTangibility.Platform;
case “platform”:
return TileTangibility.Platform;
default:
return TileTangibility.Intangible;
}
}
/// <summary>
/// Gets the hash code of a character
/// </summary>
/// <returns>The character’s hash code</returns>
public static int GetHash(char key)
{
return (int)key;
}
#region IDictionary<char,Tile> Members
/// <summary>
/// Adds a new key-value pair to the tileset
/// </summary>
/// <param name=”key”>The char used to represent a tile</param>
/// <param name=”value”>The Tile associated with the key char</param>
/// An element with the same key already exists in the .
/// <exception cref=”T:System.NotSupportedException”>The <see cref=”T:System.Collections.Generic.IDictionary`2″/> is read-only.</exception>
public void Add(char key, Tile value)
{
if (ContainsKey(key))
throw new ArgumentException();
if (IsReadOnly)
throw new NotSupportedException();
int hashCode = GetHash(key);
keys[hashCode].Add(key);
values[hashCode].Add(value);
++count;
}
/// <summary>
/// Determines whether the contains an element with the specified key.
/// </summary>
/// The key to locate in the .
/// <returns>
/// true if the contains an element with the key; otherwise, false.
/// </returns>
public bool ContainsKey(char key)
{
foreach (List charList in keys)
{
foreach (char tileKey in charList)
{
if (tileKey.Equals(key))
return true;
}
}
return false;
}
/// <summary>
/// Gets an <see cref=”T:System.Collections.Generic.ICollection`1″/> containing the keys of the <see cref=”T:System.Collections.Generic.IDictionary`2″/>.
/// </summary>
/// <value></value>
/// <returns>An <see cref=”T:System.Collections.Generic.ICollection`1″/> containing the keys of the object that implements <see cref=”T:System.Collections.Generic.IDictionary`2″/>.</returns>
public ICollection<char> Keys
{
get
{
char[] keyArray = new char[count];
int currentIndex = 0;
foreach (List charList in keys)
{
foreach (char c in charList)
{
keyArray[currentIndex] = c;
++currentIndex;
}
}
return keyArray;
}
}
/// <summary>
/// Removes the element with the specified key from the .
/// </summary>
/// <param name=”key”>The key of the element to remove.</param>
/// <returns>
/// true if the element is successfully removed; otherwise, false. This method also returns false if <paramref name=”key”/> was not found in the original .
/// </returns>
/// <exception cref=”T:System.NotSupportedException”>The <see cref=”T:System.Collections.Generic.IDictionary`2″/> is read-only.</exception>
public bool Remove(char key)
{
if (IsReadOnly)
throw new NotSupportedException();
int hashCode = GetHash(key);
List keyList = keys[hashCode];
List valueList = values[hashCode];
// find key location
for (int i = 0; i < keyList.Count; ++i)
{
if (keyList[i].Equals(key))
{ // found; remove key and value
keyList.RemoveAt(i);
valueList.RemoveAt(i);
–count;
return true;
}
}
// key not in tileset
return false;
}
/// <summary>
/// Gets the value associated with the specified key.
/// </summary>
/// <param name=”key”>The key whose value to get.</param>
/// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name=”value”/> parameter. This parameter is passed uninitialized.
/// <returns>
/// true if the object that implements contains an element with the specified key; otherwise, false.
/// </returns>
public bool TryGetValue(char key, out Tile value)
{
if (ContainsKey(key))
{
value = this[key];
return true;
}
else
{
value = Tile.Empty;
return false;
}
}
/// <summary>
/// Gets an <see cref=”T:System.Collections.Generic.ICollection`1″/> containing the values in the <see cref=”T:System.Collections.Generic.IDictionary`2″/>.
/// </summary>
/// <value></value>
/// <returns>An <see cref=”T:System.Collections.Generic.ICollection`1″/> containing the values in the object that implements <see cref=”T:System.Collections.Generic.IDictionary`2″/>.</returns>
public ICollection<Tile> Values
{
get
{
Tile[] tileArray = new Tile[count];
int currentIndex = 0;
foreach (List tileList in values)
{
foreach (Tile t in tileList)
{
tileArray[currentIndex] = t;
++currentIndex;
}
}
return tileArray;
}
}
/// <summary>
/// Gets or sets the <see cref=”Metroidvania.Tile”/> with the specified key.
/// </summary>
/// <value>The Tile associated with the passed-in key</value>
public Tile this[char key]
{
get
{
return GetTileFromList(key);
}
set
{
Add(key, value);
}
}
/// <summary>
/// Helper method, gets a tile from a list
/// </summary>
/// <exception cref=”T:System.Collections.Generic.KeyNotFoundException`1″/>
/// The requested key was not found in the collection.
/// </exception>
private Tile GetTileFromList(char key)
{
int hashCode = GetHash(key);
List keyList = keys[hashCode];
for (int i = 0; i < keyList.Count; ++i)
{
if (keyList[i].Equals(key))
return (values[hashCode])[i];
}
throw new KeyNotFoundException();
}
#endregion
#region ICollection<KeyValuePair<char,Tile>> Members
/// <summary>
/// Adds an item to the <see cref=”T:System.Collections.Generic.ICollection`1″/>.
/// </summary>
/// <param name=”item”>The object to add to the <see cref=”T:System.Collections.Generic.ICollection`1″/>.</param>
/// <exception cref=”T:System.NotSupportedException”>The <see cref=”T:System.Collections.Generic.ICollection`1″/> is read-only.</exception>
public void Add(KeyValuePair<char, Tile> item)
{
if (IsReadOnly)
throw new NotSupportedException();
Add(item.Key, item.Value);
}
/// <summary>
/// Removes all items from the <see cref=”T:System.Collections.Generic.ICollection`1″/>.
/// </summary>
/// <exception cref=”T:System.NotSupportedException”>The <see cref=”T:System.Collections.Generic.ICollection`1″/> is read-only. </exception>
public void Clear()
{
if (IsReadOnly)
throw new NotSupportedException();
values = new List[DictionarySize];
keys = new List[DictionarySize];
count = 0;
for (int i = 0; i < DictionarySize; ++i)
{
values[i] = new List<Tile>(1);
keys[i] = new List<char>(1);
}
}
/// <summary>
/// Determines whether the contains a specific value.
/// </summary>
/// The object to locate in the .
/// <returns>
/// true if <paramref name=”item”/> is found in the ; otherwise, false.
/// </returns>
public bool Contains(KeyValuePair item)
{
if (ContainsKey(item.Key) && this[item.Key].Equals(item.Value))
return true;
else
return false;
}
/// <summary>
/// Copies the elements of the <see cref=”T:System.Collections.Generic.ICollection`1″/> to an <see cref=”T:System.Array”/>, starting at a particular <see cref=”T:System.Array”/> index.
/// </summary>
/// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing.
/// The zero-based index in <paramref name=”array”/> at which copying begins.
/// <exception cref=”T:System.ArgumentNullException”>
/// <paramref name=”array”/> is null.
/// <exception cref=”T:System.ArgumentOutOfRangeException”>
/// <paramref name=”arrayIndex”/> is less than 0.
/// <exception cref=”T:System.ArgumentException”>
/// <paramref name=”array”/> is multidimensional.-or- is equal to or greater than the length of .-or-The number of elements in the source is greater than the available space from to the end of the destination .-or-Type cannot be cast automatically to the type of the destination .
public void CopyTo(KeyValuePair[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException();
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException();
if (arrayIndex > array.GetUpperBound(0) ||
(array.GetUpperBound(0) – arrayIndex) < count)
throw new ArgumentException();
foreach (KeyValuePair keyValPair in this)
{
array[arrayIndex++] = keyValPair;
}
}
/// <summary>
/// Gets the number of elements contained in the <see cref=”T:System.Collections.Generic.ICollection`1″/>.
/// </summary>
/// <value></value>
/// <returns>The number of elements contained in the <see cref=”T:System.Collections.Generic.ICollection`1″/>.</returns>
public int Count
{
get { return count; }
}
/// <summary>
/// Gets a value indicating whether the <see cref=”T:System.Collections.Generic.ICollection`1″/> is read-only.
/// </summary>
/// <value></value>
/// <returns>true if the <see cref=”T:System.Collections.Generic.ICollection`1″/> is read-only; otherwise, false.</returns>
public bool IsReadOnly
{
get { return false; }
}
/// <summary>
/// Removes the first occurrence of a specific object from the <see cref=”T:System.Collections.Generic.ICollection`1″/>.
/// </summary>
/// <param name=”item”>The object to remove from the <see cref=”T:System.Collections.Generic.ICollection`1″/>.</param>
/// <returns>
/// true if <paramref name=”item”/> was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
/// </returns>
/// <exception cref=”T:System.NotSupportedException”>The <see cref=”T:System.Collections.Generic.ICollection`1″/> is read-only.</exception>
public bool Remove(KeyValuePair item)
{
if (IsReadOnly)
throw new NotSupportedException();
if (ContainsKey(item.Key) && this[item.Key].Equals(item.Value))
{
Remove(item.Key);
return true;
}
else
return false;
}
#endregion
#region IEnumerable<KeyValuePair<char,Tile>> Members
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A that can be used to iterate through the collection.
/// </returns>
public IEnumerator<KeyValuePair<char, Tile>> GetEnumerator()
{
for (int i = 0; i < DictionarySize; ++i)
{
for (int j = 0; j < keys[i].Count; ++j)
{
yield return new KeyValuePair<char, Tile>(keys[i][j], values[i][j]);
}
}
}
#endregion
#region IEnumerable Members
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
foreach (List tileList in values)
{
foreach (Tile tile in tileList)
{
yield return tile;
}
}
}
#endregion
}
}




