| VB.NET | C#.NET | Managed C++.NET etc... |
| Web Services | Web Forms | Windows Forms |
| Data and XML Classes (ADO.NET, SQL, XML, XSLT, XPath, etc...) |
||
| Framework Base Classes (IO, string, net, security, threading, text, reflection, collections, etc... |
||
| Common Language Runtime (debug, exception, type checking, JIT) |
||
| Windows Platform | ||
class HelloWorld
{
static void Main()
{
System.Console.WriteLine("Hello, world!");
}
}
|
The command line compilation program for C# is called csc.exe. It is located in C:\Windows\Microsoft.NET\Framework\vx.x e.g. C:\Windows\Microsoft.NET\Framework\v1.1.4322
Exercise: Modify the simple HelloWorld program to print a name passed in as a parameter on the command line, e.g. "Hello, John!"
Exercise: Use the online debugger to inspect variables and step through code in the HelloWorld program.
IStorable storableDocument = (IStorable) new Document("Test Document");
IStorable storableDocument = doc as IStorable;instead of
if (doc is IStorable) {
IStorable storableDocument = (IStorable) doc;
}
void ITalk.Read()Such methods are automatically public (not access modifier is allowed), and the method can only be accessed via a cast to the interface, since the object reference will always point to the method that implicitely implements the (other) interface.
foreach (Employee e in employeeArray) {
Console.WriteLine(e.Name);
}
int[,] rectArray = new int[3,5]; nit[,,] cubeArray = new int[3,3,3];
int[,] rectArray = new int[,] {{2,3,3}, {5,6,7}} or
int[,] rectArray = new {{2,3,3}, {5,6,7}} or
int[][] jaggedArray = new int[2][]; jaggedArray[0] = new int[5]; jaggedArray[1] = new int[6];
public string this[int index]
{
get
{
return strings[index];
}
set
{
strings[index] = value;
}
}
// bookstore.cs
using System;
// A set of classes for handling a bookstore:
namespace Bookstore
{
using System.Collections;
// Describes a book in the book list:
public struct Book
{
public string Title; // Title of the book.
public string Author; // Author of the book.
public decimal Price; // Price of the book.
public bool Paperback; // Is it paperback?
public Book(string title, string author, decimal price, bool paperBack)
{
Title = title;
Author = author;
Price = price;
Paperback = paperBack;
}
}
// Declare a delegate type for processing a book:
public delegate void ProcessBookDelegate(Book book);
// Maintains a book database.
public class BookDB
{
// List of all books in the database:
ArrayList list = new ArrayList();
// Add a book to the database:
public void AddBook(string title, string author, decimal price, bool paperBack)
{
list.Add(new Book(title, author, price, paperBack));
}
// Call a passed-in delegate on each paperback book to process it:
public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
{
foreach (Book b in list)
{
if (b.Paperback)
// Calling the delegate:
processBook(b);
}
}
}
}
// Using the Bookstore classes:
namespace BookTestClient
{
using Bookstore;
// Class to total and average prices of books:
class PriceTotaller
{
int countBooks = 0;
decimal priceBooks = 0.0m;
internal void AddBookToTotal(Book book)
{
countBooks += 1;
priceBooks += book.Price;
}
internal decimal AveragePrice()
{
return priceBooks / countBooks;
}
}
// Class to test the book database:
class Test
{
// Print the title of the book.
static void PrintTitle(Book b)
{
Console.WriteLine(" {0}", b.Title);
}
// Execution starts here.
static void Main()
{
BookDB bookDB = new BookDB();
// Initialize the database with some books:
AddBooks(bookDB);
// Print all the titles of paperbacks:
Console.WriteLine("Paperback Book Titles:");
// Create a new delegate object associated with the static
// method Test.PrintTitle:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
// Get the average price of a paperback by using
// a PriceTotaller object:
PriceTotaller totaller = new PriceTotaller();
// Create a new delegate object associated with the nonstatic
// method AddBookToTotal on the object totaller:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
totaller.AveragePrice());
}
// Initialize the book database with some test books:
static void AddBooks(BookDB bookDB)
{
bookDB.AddBook("The C Programming Language",
"Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
bookDB.AddBook("The Unicode Standard 2.0",
"The Unicode Consortium", 39.95m, true);
bookDB.AddBook("The MS-DOS Encyclopedia",
"Ray Duncan", 129.95m, false);
bookDB.AddBook("Dogbert's Clues for the Clueless",
"Scott Adams", 12.00m, true);
}
}
}
|
Events are managed using delegates. Screen controls, such as buttons produce events. When an event occurs, the control uses a delegate to process that event.
First one creates a delegate for change notifications:
// A delegate type for hooking up change notifications. public delegate void ChangedEventHandler(object sender, EventArgs e);Next, one defines an event associated with this delegate.
class ListWithNotification
{
//...other stuff
public event ChangedEventHandler Changed;
Next, one raises the even when appropriate, e.g.
//... ListWithNotification continued
public override int Add(object value)
{
int i = base.Add(value);
Changed(this, EventArgs.Empty);
return i;
}
Next, one adds a specific handler matching the delegate signature to the
event:
class EventListener
{
private void ListChangedHandler(object sender, EventArgs e)
{
Console.WriteLine("This is called when the event fires.");
}
Finally, one adds this handler to the list of handlers the event will notify when it
fires:
//...EventListener continued
this.list = list;
// Add "ListChanged" to the Changed event on "List".
list.Changed += new ChangedEventHandler(ListChangedHandler);
In the main program, one creates an instance of the list, then creates the handler
for that list, and finally uses the list.
The complete listing is below:
using System;
namespace MyCollections
{
using System.Collections;
// A delegate type for hooking up change notifications.
public delegate void ChangedEventHandler(object sender, EventArgs e);
// A class that works just like ArrayList, but sends event
// notifications whenever the list changes.
public class ListWithNotification: ArrayList
{
// An event that clients can use to be notified whenever the
// elements of the list change.
public event ChangedEventHandler Changed;
// Override some of the methods that can change the list;
// invoke event after each
public override int Add(object value)
{
int i = base.Add(value);
Changed(this, EventArgs.Empty);
return i;
}
public override void Clear()
{
base.Clear();
Changed(this, EventArgs.Empty);
}
public override object this[int index]
{
set
{
base[index] = value;
Changed(this, EventArgs.Empty);
}
}
}
}
namespace TestEvents
{
using MyCollections;
class EventListener
{
private ListWithNotification list;
public EventListener(ListWithNotification list)
{
this.list = list;
// Add "ListChanged" to the Changed event on "List".
list.Changed += new ChangedEventHandler(ListChangedHandler);
}
// This will be called whenever the list changes.
private void ListChangedHandler(object sender, EventArgs e)
{
Console.WriteLine("This is called when the event fires.");
}
public void Detach()
{
// Detach the event and delete the list
list.Changed -= new ChangedEventHandler(ListChangedHandler);
list = null;
}
}
class Test
{
// Test the ListWithNotification class.
public static void Main()
{
// Create a new list.
ListWithNotification list = new ListWithNotification();
// Create a class that listens to the list's change event.
EventListener listener = new EventListener(list);
// Add and remove items from the list.
list.Add("item 1");
list.Clear();
listener.Detach();
}
}
}
|
namespace MyApplicationNamespace {
using System;
using NUnit.Framework;
[TestFixture]
public class TestHellowWorld
{
[Test] public void DefaultHelloWorldMessage()
{
HelloWorld hello = new HelloWorld();
Assert.AreEqual("Hello, World!", hello.GetMessage());
}
[Test] public void ParameterizedHelloWorldMessage()
{
HelloWorld hello = new HelloWorld("John");
Assert.AreEqual("Hello, John!", hello.GetMessage());
}
}
}//end namespace
Exercise: Develop a hangman game using TDD and NUnit.
using System;
using System.Windows.Forms;
namespace HelloWorld
{
public class HelloWorld : Form
{
private System.Windows.Forms.Label helloWorldMessage;
private System.Windows.Forms.Button cancelButton;
public HelloWorld()
{
helloWorldMessage = new Label();
cancelButton = new Button();
this.Text = "Hello World";
helloWorldMessage.Location = new System.Drawing.Point(16,24);
helloWorldMessage.Text = "Hello, World!";
helloWorldMessage.Size = new System.Drawing.Size(216,24);
cancelButton.Location = new System.Drawing.Point(150, 200);
cancelButton.Size = new System.Drawing.Size(112,32);
cancelButton.Text = "&Cancel";
cancelButton.Click += new System.EventHandler(this.CancelButtonHandler);
AutoScaleBaseSize = new System.Drawing.Size(5, 13);
ClientSize = new System.Drawing.Size(300, 300);
Controls.Add(helloWorldMessage);
Controls.Add(cancelButton);
}
protected void CancelButtonHandler (object Sender, System.EventArgs e)
{
Application.Exit();
}
public static void Main()
{
Application.Run(new HelloWorld());
}
}
}//end namespace
|
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace GraphicalCS
{
///
|
using System;
using System.Drawing;
using System.Collections;
public abstract class DShape {
public abstract void Draw(Graphics g);
protected Rectangle bounding;
protected Color penColor; // should have property, too
// should also have methods to move, resize, etc.
}
public interface IFillable {
void Fill(Graphics g);
Color FillBrushColor { get; set; }
}
public class DPoint : DShape {
public DPoint(Point p, Color penColor) {
bounding = new Rectangle(p, new Size(1, 1));
this.penColor = penColor;
}
public override void Draw(Graphics g) {
using (Pen p = new Pen(penColor)) {
g.DrawRectangle(p, bounding);
}
}
}
public class DHollowCircle : DShape
{
public DHollowCircle(Point p, int radius, Color penColor) {
p.Offset(-radius, -radius); // need to convert to upper left
int diameter = radius * 2;
bounding = new Rectangle(p, new Size(diameter, diameter));
this.penColor = penColor;
}
public override void Draw(Graphics g) {
using (Pen p = new Pen(penColor)) {
g.DrawEllipse(p, bounding);
}
}
}
public class DFilledCircle : DHollowCircle, IFillable
{
public DFilledCircle(Point center, int radius, Color penColor, Color brushColor)
: base(center, radius, penColor) {
this.brushColor = brushColor;
}
public void Fill(Graphics g) {
using (Brush b = new SolidBrush(brushColor)) {
g.FillEllipse(b, bounding);
}
}
protected Color brushColor;
public Color FillBrushColor {
get {
return brushColor;
}
set {
brushColor = value;
}
}
public override void Draw(Graphics g) {
Fill(g);
base.Draw(g);
}
}
public class DHollowRectangle : DShape {
public DHollowRectangle(Rectangle rect, Color penColor) {
bounding = rect;
this.penColor = penColor;
}
public override void Draw(Graphics g) {
using (Pen p = new Pen(penColor)) {
g.DrawRectangle(p, bounding);
}
}
}
public class DFilledRectangle : DHollowRectangle, IFillable {
public DFilledRectangle(Rectangle rect, Color penColor,
Color brushColor) : base(rect, penColor) {
this.brushColor = brushColor;
}
public void Fill(Graphics g) {
using (Brush b = new SolidBrush(brushColor)) {
g.FillRectangle(b, bounding);
}
}
protected Color brushColor;
public Color FillBrushColor {
get {
return brushColor;
}
set {
brushColor = value;
}
}
public override void Draw(Graphics g) {
Fill(g);
base.Draw(g);
}
}
public class DShapeList {
ArrayList wholeList = new ArrayList();
ArrayList filledList = new ArrayList();
public void Add(DShape d) {
wholeList.Add(d);
if (d is IFillable)
filledList.Add(d);
}
public void DrawList(Graphics g) {
if (wholeList.Count == 0)
{
Font f = new Font("Arial", 10);
g.DrawString("Nothing to draw; list is empty...",
f, Brushes.Gray, 50, 50);
}
else
{
foreach (DShape d in wholeList)
d.Draw(g);
}
}
public IFillable[] GetFilledList() {
return (IFillable[])filledList.ToArray(typeof(IFillable));
}
}
|
Exercise: Develop a game of Hangman using Windows Forms.
You can use ILDASM.EXE to view assembly metadata.
Exercise: Create a multi-module assembly as per p.482 of Programming C#, 3rd Edition.
Here is the makefile for this project (use nmake /fmakefile.mk /A to compile):
ASSEMBLY=MultiModuleAssembly.dll BIN=.\bin SRC=. DEST=.\bin CSC=csc /nologo /debug+ /d:DEBUG /d:TRACE MODULETARGET=/t:module LIBTARGET=/t:library EXETARGET=/t:exe REFERENCES=System.dll MODULES=$(DEST)\Fraction.dll $(DEST)\Calc.dll METADATA=$(SRC)\AssemblyInfo.cs all:$(DEST)\MultiModuleAssembly.dll $(DEST)\$(ASSEMBLY): $(METADATA) $(MODULES) $(DEST) $(CSC) $(LIBTARGET) /addmodule:$(MODULES: =;) /out:$@ %s $(DEST)\Calc.dll: Calc.cs $(DEST) $(CSC) $(MODULETARGET) /r:$(REFERENCES: =;) /out:$@ %s $(DEST)\Fraction.dll: Fraction.cs $(BIN) $(CSC) $(MODULETARGET) /r:$(REFERENCES: =;) /out:$@ %s $(DEST):: !if !EXISTS($(BIN)) mkdir $(BIN) !endif |
Once this is done, you can return to Customize Toolbox, select .NET Framework Components, and import the AxCalcControl.dll file. You can now drag this control onto your form and use it just as you would a normal ActiveX control.
ComCalculator calc = new ComCalculator(); calc.Add(x, y);
If the type library is not available, you must use late binding with reflection, e.g.
Type calcType = Type.GetTypeFromProgId(ComCalculator");
object calcObject = Activator.CreateInstance(calcType);
Double result = (Double) calcType.InvokeMember("Add", BindingFlags.InvokeMethod,
null, calcObject, new object[] {(Double)2.2, (Double)3.3});
dim calc
dim msg
dim result
set calc = CreateObject("MyAssemblyNamespace.Calculator");
result = calc.Multiply(7, 3);
msg = "7 * 3 = : & result & ".";
Call MsgBox(msg);
[DllImport("kernel32.dll", EntryPoint="MoveFile", ExactSpelling=false, CharSet=Charset.Unicode,
SetLastError=true)]
public static extern bool MoveFile(string sourceFile, string destinationFile);
See page 660 of Programming C#, 3rd Edition for more details.
parentColumn = dataSet.Tables["Customer"].Columns["CustomerId"];
childColumn = dataSet.Tables["Order"].Columns["CustomerId"];
DataRelation dataRelation = new System.Data.DataRelation("CustomersToOrders",
parentColumn, childColumn);
grid1.DataSource = dataSet.DefaultViewManager;
grid1.DataMember = "Customer";
Exercise: Review example on page 383 of Programming C#, 3rd Edition. Also, create a form using
the DataForm Wizard. Explore the code in both cases.
http://localhost/WSCalc/Service1.asmx/Add?x=32&y=22
Each Web Form consists of two files, the GUI and the back-end code: The gui which contains all of the controls is stored in a .aspx file. The code-behind file, which handles all of the events is in a normal C# file (using the same name as the form is a reasonable convention).
ASP.NET is event-driven. In other words, when a form is submitted, the server issues events based on the state of the form. For example, if you've selected a particular radio button on the form, the CheckedChanged event will fire for that radio button. Postback events cause the form to actually submit, so asp:Button is an obvious example. asp:RadioButton is not a PostBack object, so the event for button selection will only be fired once the submit button is clicked. One can generally cause a non-postback control to become a postback control by setting AutoPostback=True, e.g.
<asp:RadioButton runat="server" id="button1" Text="One" GroupName="radioGroup" AutoPostBack="true" />
namespace HangmanServer {
using System;
using NUnit.Framework;
using System.Collections;
[TestFixture]
public class TestHangman
{
[Test] public void CreateGame()
{
Hangman hangman = new Hangman("happy");
Assert.AreEqual(GameState.IN_PROGRESS, hangman.GetGameState());
Assert.AreEqual("happy", hangman.GetSecretWord());
Assert.AreEqual(0, hangman.GetErrorCount());
char[] letters = hangman.GetLetters();
for (int i=0; i<5; i++) {
Assert.AreEqual('\0', letters.GetValue(i));
}
}
[Test] public void SecretWordAlwaysLowerCase()
{
Hangman hangman = new Hangman("HaPPy");
Assert.AreEqual("happy", hangman.GetSecretWord());
}
[Test] public void CorrectGuess()
{
Hangman hangman = new Hangman("happy");
hangman.Guess('a');
Assert.AreEqual(GameState.IN_PROGRESS, hangman.GetGameState());
Assert.AreEqual(0, hangman.GetErrorCount());
char[] letters = hangman.GetLetters();
Assert.AreEqual('\0', letters.GetValue(0));
Assert.AreEqual('a', letters.GetValue(1));
Assert.AreEqual('\0', letters.GetValue(2));
Assert.AreEqual('\0', letters.GetValue(3));
Assert.AreEqual('\0', letters.GetValue(4));
}
[Test] public void CorrectGuessUppercase()
{
Hangman hangman = new Hangman("happy");
hangman.Guess('P');
Assert.AreEqual(GameState.IN_PROGRESS, hangman.GetGameState());
Assert.AreEqual(0, hangman.GetErrorCount());
char[] letters = hangman.GetLetters();
Assert.AreEqual('\0', letters.GetValue(0));
Assert.AreEqual('\0', letters.GetValue(1));
Assert.AreEqual('p', letters.GetValue(2));
Assert.AreEqual('p', letters.GetValue(3));
Assert.AreEqual('\0', letters.GetValue(4));
}
[Test] public void WrongGuess()
{
Hangman hangman = new Hangman("happy");
hangman.Guess('x');
Assert.AreEqual(GameState.IN_PROGRESS, hangman.GetGameState());
Assert.AreEqual(1, hangman.GetErrorCount());
char[] letters = hangman.GetLetters();
for (int i=0; i<5; i++) {
Assert.AreEqual('\0', letters.GetValue(i));
}
}
[Test] public void GameLost()
{
Hangman hangman = new Hangman("sad");
hangman.Guess('b');
Assert.AreEqual(1, hangman.GetErrorCount());
hangman.Guess('c');
Assert.AreEqual(2, hangman.GetErrorCount());
hangman.Guess('d');
Assert.AreEqual(2, hangman.GetErrorCount());
hangman.Guess('e');
Assert.AreEqual(3, hangman.GetErrorCount());
hangman.Guess('f');
Assert.AreEqual(4, hangman.GetErrorCount());
hangman.Guess('g');
Assert.AreEqual(5, hangman.GetErrorCount());
hangman.Guess('h');
Assert.AreEqual(6, hangman.GetErrorCount());
hangman.Guess('i');
Assert.AreEqual(7, hangman.GetErrorCount());
Assert.AreEqual(GameState.LOST, hangman.GetGameState());
char[] letters = hangman.GetLetters();
Assert.AreEqual('\0', letters.GetValue(0));
Assert.AreEqual('\0', letters.GetValue(1));
Assert.AreEqual('d', letters.GetValue(2));
}
[Test] public void GameWon()
{
Hangman hangman = new Hangman("happy");
hangman.Guess('h');
hangman.Guess('a');
hangman.Guess('p');
hangman.Guess('y');
Assert.AreEqual(0, hangman.GetErrorCount());
Assert.AreEqual(GameState.WON, hangman.GetGameState());
char[] letters = hangman.GetLetters();
Assert.AreEqual('h', letters.GetValue(0));
Assert.AreEqual('a', letters.GetValue(1));
Assert.AreEqual('p', letters.GetValue(2));
Assert.AreEqual('p', letters.GetValue(3));
Assert.AreEqual('y', letters.GetValue(4));
}
[Test] public void RepeatedWrongGuessIsFree()
{
Hangman hangman = new Hangman("repeat");
hangman.Guess('x');
hangman.Guess('x');
Assert.AreEqual(1, hangman.GetErrorCount());
}
[Test] public void RepeatedCorrectGuessIsFree()
{
Hangman hangman = new Hangman("repeat");
hangman.Guess('e');
hangman.Guess('e');
Assert.AreEqual(0, hangman.GetErrorCount());
}
[Test] public void SecretWordCannotBeNull()
{
try
{
Hangman hangman = new Hangman(null);
Assert.Fail("secret word cannot be null");
}
catch (InvalidSecretWordException e)
{
Assert.AreEqual("secret word cannot be null", e.Message);
}
}
[Test] public void SecretWordMinimumTwoCharacters()
{
try
{
Hangman hangman = new Hangman("x");
Assert.Fail(
"secret word must be at least two characters long");
}
catch (InvalidSecretWordException e)
{
Assert.AreEqual(
"secret word must be at least two characters long",
e.Message);
}
}
[Test] public void LostGameCannotBeContinued()
{
Hangman hangman = new Hangman("sad");
hangman.Guess('b');
hangman.Guess('c');
hangman.Guess('e');
hangman.Guess('f');
hangman.Guess('g');
hangman.Guess('h');
hangman.Guess('i');
try
{
hangman.Guess('x');
Assert.Fail("game is over");
}
catch (GameOverException)
{
}
}
[Test] public void WonGameCannotBeContinued()
{
Hangman hangman = new Hangman("happy");
hangman.Guess('h');
hangman.Guess('a');
hangman.Guess('p');
hangman.Guess('y');
try
{
hangman.Guess('x');
Assert.Fail("game is over");
}
catch (GameOverException)
{
}
}
[Test] public void GuessHistoryIsTracked()
{
Hangman hangman = new Hangman("repeat");
hangman.Guess('r');
hangman.Guess('x');
hangman.Guess('r');
hangman.Guess('t');
IEnumerator guessHistory = hangman.GetGuessHistory();
guessHistory.MoveNext();
GameGuess gameGuess = (GameGuess) guessHistory.Current;
Assert.AreEqual('r', gameGuess.Letter);
Assert.AreEqual(GameGuess.CORRECT, gameGuess.Status);
guessHistory.MoveNext();
gameGuess = (GameGuess) guessHistory.Current;
Assert.AreEqual('x', gameGuess.Letter);
Assert.AreEqual(GameGuess.WRONG, gameGuess.Status);
guessHistory.MoveNext();
gameGuess = (GameGuess) guessHistory.Current;
Assert.AreEqual('r', gameGuess.Letter);
Assert.AreEqual(GameGuess.REPEAT, gameGuess.Status);
guessHistory.MoveNext();
gameGuess = (GameGuess) guessHistory.Current;
Assert.AreEqual('t', gameGuess.Letter);
Assert.AreEqual(GameGuess.CORRECT, gameGuess.Status);
}
/* note: should make a test to make sure secret
* word is a dictionary word */
}
} //end namespace
|
namespace HangmanServer
{
using System;
using System.Collections;
public class Hangman
{
private int errorCount;
private string secretWord;
private char[] letters;
private ArrayList previousGuesses = new ArrayList();
private GameState gameState = GameState.IN_PROGRESS;
public static void Main(string[] args)
{
}
public Hangman(string secretWord)
{
ValidateSecretWord(secretWord);
this.secretWord = secretWord.ToLower();
letters = new char[secretWord.Length];
}
public GameState GetGameState()
{
return gameState;
}
public int GetErrorCount()
{
return errorCount;
}
public char[] GetLetterMask()
{
return letters;
}
public void Guess(char guess)
{
CheckGameOver();
GameGuess guessHistoryItem;
if (IsRepeatGuess(guess))
{
guessHistoryItem = new GameGuess(guess, GameGuess.REPEAT);
previousGuesses.Add(guessHistoryItem);
return;
}
bool correctGuess = false;
for (int i=0; i<secretWord.Length; i++)
{
char letter = secretWord[i];
if (guess == letter ||
char.ToLower(guess) == letter)
{
letters[i] = letter;
correctGuess = true;
}
}
if (correctGuess == false)
{
guessHistoryItem = new GameGuess(guess, GameGuess.WRONG);
errorCount++;
} else
{
guessHistoryItem = new GameGuess(guess, GameGuess.CORRECT);
}
previousGuesses.Add(guessHistoryItem);
CheckGameOver();
}
public IEnumerator GetGuessHistory()
{
IEnumerable a;
return previousGuesses.GetEnumerator();
}
internal string GetSecretWord()
{
return secretWord;
}
private bool IsSecretSolved()
{
for (int i=0; i<letters.Length; i++)
{
if (letters[i] != secretWord[i])
{
return false;
}
}
return true;
}
private void CheckGameOver()
{
if (gameState == GameState.WON
|| gameState == GameState.LOST)
{
throw new GameOverException();
}
if (errorCount == 7)
{
gameState = GameState.LOST;
}
bool solved = IsSecretSolved();
if (solved)
{
gameState = GameState.WON;
}
}
private bool IsRepeatGuess(char guess)
{
foreach (GameGuess previouslyGuessedLetter
in previousGuesses)
{
if (previouslyGuessedLetter.Letter == guess)
{
return true;
}
}
return false;
}
private void ValidateSecretWord(String secretWord)
{
if (secretWord == null)
{
throw new InvalidSecretWordException(
"secret word cannot be null");
}
if (secretWord.Length < 2)
{
throw new InvalidSecretWordException(
"secret word must be at least two characters long");
}
}
}
} //end namespace
|
namespace HangmanServer {
public struct GameGuess
{
public const string CORRECT = "CORRECT";
public const string WRONG = "WRONG";
public const string REPEAT = "REPEAT";
private char letter;
private string status;
public GameGuess(char letter, string status)
{
this.letter = letter;
this.status = status;
}
public char Letter
{
get
{
return letter;
}
}
public string Status
{
get
{
return status;
}
}
}
} //end namespace
|
namespace HangmanServer
{
public enum GameState
{
IN_PROGRESS,
WON,
LOST
}
} //end namespace
|
namespace HangmanServer
{
public class GameOverException : System.ApplicationException
{
public GameOverException ()
{
}
}
} //end namespace
|
namespace HangmanServer
{
public class InvalidSecretWordException : System.ApplicationException
{
public InvalidSecretWordException (string message) : base(message)
{
}
}
} //end namespace
|