- •Microsoft C# Programming for the Absolute Beginner
- •Table of Contents
- •Microsoft C# Programming for the Absolute Beginner
- •Introduction
- •Overview
- •Chapter 1: Basic Input and Output: A Mini Adventure
- •Project: The Mini Adventure
- •Reviewing Basic C# Concepts
- •Namespaces
- •Classes
- •Methods
- •Statements
- •The Console Object
- •.NET Documentation
- •Getting into the Visual Studio .Net Environment
- •Examining the Default Code
- •Creating a Custom Namespace
- •Adding Summary Comments
- •Creating the Class
- •Moving from Code to a Program
- •Compiling Your Program
- •Looking for Bugs
- •Getting Input from the User
- •Creating a String Variable
- •Getting a Value with the Console.ReadLine() Method
- •Incorporating a Variable in Output
- •Combining String Values
- •Combining Strings with Concatenation
- •Adding a Tab Character
- •Using the Newline Sequence
- •Displaying a Backslash
- •Displaying Quotation Marks
- •Launching the Mini Adventure
- •Planning the Story
- •Creating the Variables
- •Getting Values from the User
- •Writing the Output
- •Finishing the Program
- •Summary
- •Chapter 2: Branching and Operators: The Math Game
- •The Math Game
- •Using Numeric Variables
- •The Simple Math Game
- •Numeric Variable Types
- •Integer Variables
- •Long Integers
- •Data Type Problems
- •Math Operators
- •Converting Variables
- •Explicit Casting
- •The Convert Object
- •Creating a Branch in Program Logic
- •The Hi Bill Game
- •Condition Testing
- •The If Statement
- •The Else Clause
- •Multiple Conditions
- •Working with The Switch Statement
- •The Switch Demo Program
- •Examining How Switch Statements Work
- •Creating a Random Number
- •Introducing the Die Roller
- •Exploring the Random Object
- •Creating a Random Double with the .NextDouble() Method
- •Getting the Values of Dice
- •Creating the Math Game
- •Designing the Game
- •Creating the Variables
- •Managing Addition
- •Managing Subtraction
- •Managing Multiplication and Division
- •Checking the Answers
- •Waiting for the Carriage Return
- •Summary
- •Chapter 3: Loops and Strings: The Pig Latin Program
- •Project: The Pig Latin Program
- •Investigating The String Object
- •The String Mangler Program
- •A Closer Look at Strings
- •Using the Object Browser
- •Experimenting with String Methods
- •Performing Common String Manipulations
- •Using a For Loop
- •Examining The Bean Counter Program
- •Creating a Sentry Variable
- •Checking for an Upper Limit
- •Incrementing the Variable
- •Examining the Behavior of the For Loop
- •The Fancy Beans Program
- •Skipping Numbers
- •Counting Backwards
- •Using a Foreach Loop to Break Up a Sentence
- •Using a While Loop
- •The Magic Word Program
- •Writing an Effective While Loop
- •Planning Your Program with the STAIR Process
- •S: State the Problem
- •T: Tool Identification
- •A: Algorithm
- •I: Implementation
- •R: Refinement
- •Applying STAIR to the Pig Latin Program
- •Stating the Problem
- •Identifying the Tools
- •Creating the Algorithm
- •Implementing and Refining
- •Writing the Pig Latin Program
- •Setting Up the Variables
- •Creating the Outside Loop
- •Dividing the Phrase into Words
- •Extracting the First Character
- •Checking for a Vowel
- •Adding Debugging Code
- •Closing Up the code
- •Summary
- •Introducing the Critter Program
- •Creating Methods to Reuse Code
- •The Song Program
- •Building the Main() Method
- •Creating a Simple Method
- •Adding a Parameter
- •Returning a Value
- •Creating a Menu
- •Creating a Main Loop
- •Creating the Sentry Variable
- •Calling a Method
- •Working with the Results
- •Writing the showMenu() Method
- •Getting Input from the User
- •Handling Exceptions
- •Returning a Value
- •Creating a New Object with the CritterName Program
- •Creating the Basic Critter
- •Using Scope Modifiers
- •Using a Public Instance Variable
- •Creating an Instance of the Critter
- •Adding a Method
- •Creating the talk() Method for the CritterTalk Program
- •Changing the Menu to Use the talk() Method
- •Creating a Property in the CritterProp Program
- •Examining the Critter Prop Program
- •Creating the Critter with a Name Property
- •Using Properties as Filters
- •Making the Critter More Lifelike
- •Adding More Private Variables
- •Adding the Age() Method
- •Adding the Eat() Method
- •Adding the Play() Method
- •Modifying the Talk() Method
- •Making Changes in the Main Class
- •Summary
- •Introducing the Snowball Fight
- •Inheritance and Encapsulation
- •Creating a Constructor
- •Adding a Constructor to the Critter Class
- •Creating the CritViewer Class
- •Reviewing the Static Keyword
- •Calling a Constructor from the Main() Method
- •Working with Multiple Files
- •Overloading Constructors
- •Viewing the Improved Critter Class
- •Adding Polymorphism to Your Objects
- •Modifying the Critter Viewer in CritOver to Demonstrate Overloaded Constructors
- •Using Inheritance to Make New Classes
- •Creating a Class to View the Clone
- •Creating the Critter Class
- •Improving an Existing Class
- •Introducing the Glitter Critter
- •Adding Methods to a New Class
- •Changing the Critter Viewer Again
- •Creating the Snowball Fight
- •Building the Fighter
- •Building the Robot Fighter
- •Creating the Main Menu Class
- •Summary
- •Overview
- •Introducing the Visual Critter
- •Thinking Like a GUI Programmer
- •Creating a Graphical User Interface (GUI)
- •Examining the Code of a Windows Program
- •Adding New Namespaces
- •Creating the Form Object
- •Creating a Destructor
- •Creating the Components
- •Setting Component Properties
- •Setting Up the Form
- •Writing the Main() Method
- •Creating an Interactive Program
- •Responding to a Simple Event
- •Creating and Adding the Components
- •Adding an Event to the Program
- •Creating an Event Handler
- •Allowing for Multiple Selections
- •Choosing a Font with Selection Controls
- •Creating the User Interface
- •Examining Selection Tools
- •Creating Instance Variables in the Font Chooser
- •Writing the AssignFont() Method
- •Writing the Event Handlers
- •Working with Images and Scroll Bars
- •Setting Up the Picture Box
- •Adding a Scroll Bar
- •Revisiting the Visual Critter
- •Designing the Program
- •Determining the Necessary Tools
- •Designing the Form
- •Writing the Code
- •Summary
- •Chapter 7: Timers and Animation: The Lunar Lander
- •Introducing the Lunar Lander
- •Reading Values from the Keyboard
- •Introducing the Key Reader Program
- •Setting Up the Key Reader Program
- •Coding the KeyPress Event
- •Coding the KeyDown Event
- •Determining Which Key Was Pressed
- •Animating Images
- •Introducing the ImageList Control
- •Setting Up an Image List
- •Looking at the Image Collection
- •Displaying an Image from the Image List
- •Using a Timer to Automate Animation
- •Introducing the Timer Control
- •Configuring the Timer
- •Adding Motion
- •Checking for Keyboard Input
- •Working with the Location Property
- •Detecting Collisions between Objects
- •Coding the Crasher Program
- •Getting Values for newX and newY
- •Bouncing the Ball off the Sides
- •Checking for Collisions
- •Extracting a Rectangle from a Component
- •Getting More from the MessageBox Object
- •Introducing the MsgDemo Program
- •Retrieving Values from the MessageBox
- •Coding the Lunar Lander
- •The Visual Design
- •The Constructor
- •The timer1_Tick() Method
- •The moveShip() Method
- •The checkLanding() Method
- •The theForm_KeyDown() Method
- •The showStats() Method
- •The killShip() Method
- •The initGame() Method
- •Summary
- •Chapter 8: Arrays: The Soccer Game
- •The Soccer Game
- •Introducing Arrays
- •Exploring the Counter Program
- •Creating an Array of Strings
- •Referring to Elements in an Array
- •Working with Arrays
- •Using the Array Demo Program to Explore Arrays
- •Building the Languages Array
- •Sorting the Array
- •Designing the Soccer Game
- •Solving a Subset of the Problem
- •Adding Percentages for the Other Players
- •Setting Up the Shot Demo Program
- •Setting Up the List Boxes
- •Using a Custom Event Handler
- •Writing the changeStatus() Method
- •Kicking the Ball
- •Designing Programs by Hand
- •Examining the Form by Hand Program
- •Adding Components in the Constructor
- •Responding to the Button Event
- •Building the Soccer Program
- •Setting Up the Variables
- •Examining the Constructor
- •Setting Up the Players
- •Setting Up the Opponents
- •Setting Up the Goalies
- •Responding to Player Clicks
- •Handling Good Shots
- •Handling Bad Shots
- •Setting a New Current Player
- •Handling the Passage of Time
- •Updating the Score
- •Summary
- •Chapter 9: File Handling: The Adventure Kit
- •Introducing the Adventure Kit
- •Viewing the Main Screen
- •Loading an Adventure
- •Playing an Adventure
- •Creating an Adventure
- •Reading and Writing Text Files
- •Exploring the File IO Program
- •Importing the IO Namespace
- •Writing to a Stream
- •Reading from a Stream
- •Creating Menus
- •Exploring the Menu Demo Program
- •Adding a MainMenu Object
- •Adding a Submenu
- •Setting Up the Properties of Menu Items
- •Writing Event Code for Menus
- •Using Dialog Boxes to Enhance Your Programs
- •Exploring the Dialog Demo Program
- •Adding Standard Dialogs to Your Form
- •Using the File Dialog Controls
- •Responding to File Dialog Events
- •Using the Font Dialog Control
- •Using the Color Dialog Control
- •Storing Entire Objects with Serialization
- •Exploring the Serialization Demo Program
- •Creating the Contact Class
- •Referencing the Serializable Namespace
- •Storing a Class
- •Retrieving a Class
- •Returning to the Adventure Kit Program
- •Examining the Room Class
- •Creating the Dungeon Class
- •Writing the Game Class
- •Writing the Editor Class
- •Writing the MainForm Class
- •Summary
- •Chapter 10: Chapter Basic XML: The Quiz Maker
- •Introducing the Quiz Maker Game
- •Taking a Quiz
- •Creating and Editing Quizzes
- •Investigating XML
- •Defining XML
- •Creating an XML Document in .NET
- •Creating an XML Schema for Your Language
- •Investigating the .NET View of XML
- •Exploring the XmlNode Class
- •Exploring the XmlDocument Class
- •Reading an Existing XML Document
- •Creating the XML Viewer Program
- •Writing New Values to an XML Document
- •Building the Document Structure
- •Adding an Element to the Document
- •Displaying the XML Code
- •Examining the Quizzer Program
- •Building the Main Form
- •Writing the Quiz Form
- •Writing the Editor Form
- •Summary
- •Overview
- •Introducing the SpyMaster Program
- •Creating a Simple Database
- •Accessing the Data Server
- •Accessing the Data in a Program
- •Using Queries to Modify Data Results
- •Limiting Data with the SELECT Statement
- •Using an Existing Database
- •Adding the Capability to Display Queries
- •Creating a Visual Query Builder
- •Working with Relational Databases
- •Improving Your Data with Normalization
- •Using a Join to Connect Two Tables
- •Creating a View
- •Referring to a View in a Program
- •Incorporating the Agent Specialty Attribute
- •Working with Other Databases
- •Creating a New Connection
- •Converting a Data Set to XML
- •Reading from XML to a Data Source
- •Creating the SpyMaster Database
- •Building the Main Form
- •Editing the Assignments
- •Editing the Specialties
- •Viewing the Agents
- •Editing the Agent Data
- •Summary
- •List of Figures
- •List of Tables
- •List of Sidebars
Figure 5.3: With a good strategy, you can beat the computer much of the time, but not always.
The design of the snowball fight is simple. Both the player and the opponent are custom classes that have a lot in common. They have three properties: name, snowballs, and strength. Each player starts with three snowballs and, to win, has to make more during the fight. Each player also begins with three lives. When a player has been hit three times, that player loses the fight. The computer opponent is like the human player but has features that enable it to automatically play against the user.
Inheritance and Encapsulation
To make the snowball fight and other programs in the book, you must learn a few tricks about building classes. To illustrate these new concepts, I’ll build a few more critters like the ones in Chapter 4, “Objects and Encapsulation: The Critter Program.” The basic critter is interesting, but what if you want to make new kinds of critters that share the same behavior but exhibit different characteristics? For example, you might want to make a new kind of critter that is grumpy.
When programmers began using objects, they quickly realized the importance of being able to make changes to objects. Computer scientists (who love to obfuscate simple ideas by using techie terms) think that objects should support inheritance and polymorphism. These fancy words describe some simple but important ideas. Inheritance works much like genetics. Objects can have children and grandchildren, and an object’s descendants will inherit traits from the parents and grandparents. Polymorphism means that an object can have the same kind of behavior as its relatives but can implement that behavior differently. Don’t worry if these explanations leave you cold for now. I just want you to have a bird’s−eye view of these concepts before digging into specific examples later in this chapter.
Creating a Constructor
Imagine that you want to write a program using several critters. Each critter could have a different name and different characteristics (perhaps different starting values for hunger and happiness). Using the Critter class from Chapter 4, you could do it, but you’d have to create each critter in several steps. First, you’d have to create the critter, and then you’d need another statement of code to modify each characteristic. It would look something like this:
Critter myCritter = new Critter();
102
myCritter.name = "alpha"; myCritter.age = 10;
Although this is not difficult, a more convenient way to create a critter would enable you to initialize all its values at the same time. You could set up a critter with a line like this:
Critter myCritter = new Critter("alpha", 10, 9, 0);
The critter automatically assumes the name alpha, a happiness level of 10, a hunger level of 9, and an age of 0. (The age of 0 means that it will age after the first turn) You can apply a set of parameters whenever you create an instance of the critter class. Classes (such as the Critter) can have a special method called a constructor. A class’s constructor is a special method that is used to help create the critter. The constructor is automatically called whenever you create an instance of the class when using the new keyword.
Adding a Constructor to the Critter Class
I took the Critter class from Chapter 4 and added a constructor to it:
using System;
namespace CritterConstructor
{
///<summary>
///Critter with a constructor
///</summary>
public class Critter { // your basic critter
//instance variables private string pName; private int pFull = 10; private int pHappy = 10; private int pAge = 0;
//constructor
public Critter(string theName, int fullness, int happiness, int theAge){
name = theName; pFull = fullness; pHappy = happiness; pAge = theAge;
} // end constructor
public string name
public string talk() ...
public void age() ...
public void play() ...
public void eat() ...
}// end class
}// end namespace
I minimized all the properties and methods so that you can focus on the new part of the critter. Constructors are special methods that have the same name as the class. A constructor is usually public, and you do not have to specify a return value because the constructor will return an instance of the class as its value. Whenever you make an instance of a class (remember, the class is a
103
recipe, and instances are the cookies), the computer looks for a constructor. The constructor usually has special instructions for getting the class started. In this case, I added a constructor for the Critter class that accepts four parameters. Each parameter is mapped to a specific instance variable. Constructors are typically used to initialize instance variables, even in more complex classes. The other nice thing about a constructor is that you know that any code inside a constructor will happen as soon as the object is created. Therefore, any code you want to run at the beginning of the class’s life span should be written in the constructor. Constructors can have parameters just like any other method.
The Critter class does not have a Main() method. In any given namespace, it generally makes sense for only one class to have a Main() method. However, your project can (and usually will) have many classes and several instances of each class. The Critter class is not intended to be an executable program, so I will use it inside other classes that do have a Main() method. When you look at the files created by the .NET compiler, the programs that have a Main() method usually have an associated .exe (executable) file. Those that do not have a Main() method are compiled into dynamic linked libraries (.dll files). You might have heard that the only difference between an .exe file and a .dll file is that an executable (.exe) file has a Main() method and a dynamically linked library (dll) doesn’t. This is a generalization (and not completely true). Important internal differences exist between these files, but for the purposes of this book, this is a reasonable simplification.
Creating the CritViewer Class
If you type in the Critter class from the preceding section and attempt to run it, it will compile, but it won’t run. Often, you make classes that are meant to be used as parts inside other classes. A gas tank, for example, is an important part, or class, of the automobile. Gas tanks have parts and require assembly. When a gas tank is finished, it is sent to the auto assembly plant and installed. The gas tank is a class, but you can’t drive it because it’s designed to be part of a larger assembly. The program itself is one object (like the car), but it usually comprises constituent objects. Only the primary object needs a Main() method.
The Critter class will not stand on its own, so you need a container class to demonstrate the critter’s capabilities. In Chapter 4, you use a menu class to do this. Here, you use a much simpler program to contain the critter so that you can concentrate on new ways of building objects. The Critter Constructor program featured in Figure 5.4 demonstrates a version of the Critter program, with one class for a viewer and the modified Critter class with a constructor.
Figure 5.4: The critter viewer demonstrates the basic functionality of the critter.
Hint
104
Building a simple container to demonstrate and test a new class is a common strategy of object−oriented programmers. Because an object is encapsulated, it should work as well in one program as in another. You can create very straightforward programs to test your objects before you use the objects in a more complex program. With this technique, you are more likely to isolate errors in your custom classes before you add them to complex assemblies, where more can go wrong.
To demonstrate my new critter, I’ll build a CritterViewer class, which is reasonably simple:
using System;
namespace CritterConstructor
{
///<summary>
///CritViewer is a simple class designed simply to hold a critter
///Demonstrates self−instantiation
///Andy Harris, 12/21/01
///</summary>
class CritViewer
{
static void Main(string[] args)
{
// the main method simply creates an instance of the
/// critviewer object
CritViewer cv = new CritViewer(); } // end main
//This next method is the constructor for CritViewer public CritViewer(){
Critter myCritter = new Critter("alpha", 10, 10, 0); Console.WriteLine("I'm in critViewer"); Console.WriteLine(myCritter.talk());
Console.WriteLine();
Console.WriteLine("Please press Enter key to continue");
Console.ReadLine();
} // end constructor
} // end CritViewer Class
}// end namespace
Note the simplicity of the Main() method in this code:
static void Main(string[] args)
{
// the main method simply creates an instance of the
/// critviewer object
CritViewer cv = new CritViewer(); } // end main
Reviewing the Static Keyword
So far in this book, most of the code appears in the Main() method of the program. Although this approach is fine for these simple programs, it has limitations because the Main() method must be declared a static method. The keyword static in the preceding code means that the Main() method can be called before the class exists. A static method can be called without requiring an instance of the class. For example, most of the methods in the Convert class in Chapter 2, "Branching and Operators: The Math Game," are static methods. You don’t have to create an instance of the Convert class to use its methods. Likewise, the WriteLine() method of the Console class is static.
105