Causing Text to Appear from Underneath a Control

 

Project TicTacToe

image from book
Figure 27-1: TicTacToe window

A complete listing of the Form1.cs source code is shown at the end of this section. For a complete listing of Form1.Designer.cs, see App D --DemoVC#TaggedList.doc in Visual Studio 2005\Tagged KT-Demo Code.

Game Board Layout

The main part of the game board consists of nine panels that overlap by one pixel at their edges.

  1. Create the large 100 x 100 panels first so they can be numbered panel1 through panel9. The panel is one of the controls shown on the IDE Toolbox when the entire form is highlighted.

  2. Place a black edge on each of the panels by highlighting that panel (to place its properties in the Properties window), clicking on Appearance | Border Style , and choosing Fixed Single .

  3. While you are there, you make this panel transparent so window painting will appear on the screen (not behind the panels). If the panel is not transparent, then any painting hides what is underneath the panel. Click on Back Color to reveal a down arrow at the right of the line. Click on the down arrow to reveal a list of colors with tabs across the top of the new window. Click on the Web tab, then select Transparent . By making the panel transparent, anything that is painted onto the window will appear at the forefront to the user .

    These nine large panels have no event handlers associated with them. However, at the middle of each large panel, a tiny 10 x 10 panel is placed to act as the control element for each large panel.

  4. Place the second group of nine 10 x 10 panels numbered panel10 through panel18 to act as the control element for each large panel. These panels force the user to click carefully on the portion of the game board where he wants to place the next X or O.

  5. Create an event handler for each of the nine tiny panels by highlighting the panel, clicking on the Events icon to bring up the event handlers, then double-clicking on Mouse | Mouse Down to place the panel xx _MouseDown event handler in the source code.

Warning  

If you simply double-click on one of the small panels, you will create the default handler for a panel, which is a paint handler. You don t want this! To delete an unwanted default handler from a panel, highlight the tiny panel (to puts its properties in the Properties window), click on the Events icon, and click on the Appearance | Paint item that is already highlighted. Right-click on this item to bring up a pop-up (context) menu with two entries: Reset and Description. Click on Reset to remove the unwanted event handler from the source code.

Each of these nine 10 x 10 panels now has a mouse down event handler affixed to it, and when a player clicks on one of the panels, something happens! If a player is the X player, a large red X appears in the large panel area. If a player is the O player, a large blue O appears in the large panel area.

As soon as a player clicks on a 10 x 10 panel to place his marker there, the small panel is immediately disabled so the panel cannot be used again.

Painting an X or O on the Game Board

Each of the nine panels performs the same sequence of events when a player clicks on a 10 x 10 panel in the middle of a large panel. Here is the code for the top-left panel, which is numbered as 0:

 TT0180:        private void panel10_MouseDown(object sender,                                               System.Windows.Forms.MouseEventArgs e) TT0181:        { // Top-left panel, position '0'. TT0182:          panel10.Enabled = false; TT0183:          if (XTurn) TT0184:          { TT0185:            SX[0] = 1; TT0186:            XTurn = false; TT0187:            label1.Text = "'O' Plays"; TT0188:          } TT0189:          else TT0190:          { TT0191:            SO[0] = 1; TT0192:            XTurn = true; TT0193:            label1.Text = "'X' Plays"; TT0194:          } TT0195:          WinnerW(); TT0196:          Invalidate(); TT0197:        } 

Line TT0182 disables the panel so it cannot be selected again.

XTurn is the master counter. It is set to true when it is player X s turn and false when it is player O s turn .

Integer arrays SO[] and SX[] are all set to 0 when the game starts. If player X picks this panel, then SX[0] is set to 1 (the SX[0] position is the top-left panel). The integer 1 in this array means that it belongs either to the X player or the O player. As soon as the SO[] or SX[] array is posted, XTurn is flipped from true to false, or vice versa (lines TT0186 or TT0192). Line TT0195 immediately calls the method WinnerW() to check for a possible winner (and end the game).

Line TT0196 calls for a repainting of the screen with the command Invalidate().

Winner or No Winner?

As soon as the WinnerW() method is called, control moves to lines TT0030-TT0108. Note that this method is listed immediately after line TT0026, InitializeComponent(). This is the only place the programmer can place a global subroutine that services all other procedures in the form. The method is void because it returns nothing when it is called. All of its outputs are placed in public variables listed at the top of the public class Form1.

The WinnerW() method performs a myriad of tasks . The nine positions where a player can place an X or O are designated as positions 0 through 8:

  • Position 0: Top-left box

  • Position 1: Top-center box

  • Position 2: Top-right box

  • Position 3: Center-left box

  • Position 4: Center box

  • Position 5: Center-right box

  • Position 6: Bottom-left box

  • Position 7: Bottom-center box

  • Position 8: Bottom-right box

Therefore, the winning combinations of boxes that a player must fill to win are:

  • 0 plus 1 plus 2

  • 0 plus 4 plus 8

  • 0 plus 3 plus 6

  • 1 plus 4 plus 7

  • 2 plus 4 plus 6

  • 2 plus 5 plus 8

  • 3 plus 4 plus 5

  • 6 plus 7 plus 8

Neither player can possibly win until a total of five X s and O s have been placed on the screen, so line TT0035 doesn t bother to check for a winner until that time. Lines TT0036-TT0084 perform all the checks to declare a winner, and when this occurs, either XWinner or OWinner is set to true. For scorekeeping purposes, the appropriate intXWins or intOWins number is incremented. If all nine plays have been made and there is no winner, line TT0080 detects the tie and increments the variable intTies in TT0083. Lines TT0087-TT0089 post the scores on the scoreboard.

Lines TT0093-TT0097 ask the players if they want to play the game again. If the answer is no, the button at the top of the screen is disabled in line TT0104. If the answer is yes, the button remains enabled, ready for the next game.

To recycle to play the next game, it is necessary to clear the red X s and blue O s from the screen. This is accomplished by setting bool Start to false, which stops the entering of X s and O s onto the screen (line TT0100).

Painting the X s and O s on the Screen

All screen painting occurs in lines TT0370-TT0394. Line TT0373 sets the font at 92-point Arial (1 inch equals 72 points). Since only one of the two drawn characters (X or O) can appear over any one panel (or no character appears there), the Form1_Paint() method uses a series of if else statements like this:

 TT0376:        if (SX[0] == 1) grfx.DrawString("X", font1, Brushes.Red, 39, 34); TT0377:        else if (SO[0] == 1) grfx.DrawString("O", font1, Brushes.Blue, 34, 34); 

The starting coordinates for each painted character were set to make an X or O appear in the middle of the panel. Note that the X coordinates are (39, 34) and the O coordinates are (34, 34).

Recycling for the Next Game

The players choose to play another game in line TT0097 in the WinnerW() method. The screen is cleared of any X or O characters since the boolean variable Start in line TT0374 has been set to false. As soon as the Start Game button is picked again, the button1_Click() method in lines TT0132-TT0157 is set into motion again.

Lines TT0132-TT0133 reset integer arrays SO[] and SX[] to all 0 s so the WinnerW() method will work correctly in the game being started. intNoOfClicks is reset to 0 in line TT0134.

 TT0134:        intNoOfClicks = 0; 

Lines TT0135-TT0143 reset the nine 10 x 10 panels to an enabled mode (each one was disabled in the earlier game when a player selected that panel to place her X or O in that position).

Setting Start = true in line TT0144 enables screen painting in line TT0374.

Line TT0145 increments intGameNumber so lines TT0146-TT0155 can prepare for the next game (deciding if X plays first or O plays first).

Line TT0156 prepares the screen for the next game.

TicTacToe (TT) Listing

 Form1.cs: TT0001:       #region Using directives TT0002:       using System; TT0003:       using System.Collections.Generic; TT0004:       using System.ComponentModel; TT0005:       using System.Data; TT0006:       using System.Drawing; TT0007:       using System.Windows.Forms; TT0008:       #endregion TT0009:       namespace TicTacToe TT0010:       { TT0011:         partial class Form1 : Form TT0012:         {                   // Programmer added variables. TT0013:           public bool Start = false; TT0014:           public bool XTurn = true; TT0015:           public bool OWinner = false; TT0016:           public bool XWinner = false; TT0017:           public int intXWins = 0; TT0018:           public int intOWins = 0; TT0019:           public int intTies = 0; TT0020:           public int intNumberOfGames = 0; TT0021:           public int intNoOfClicks = 0; TT0022:           public int intGameNumber = 0; TT0023:           public int[] SO = new int[9]; TT0024:           public int[] SX = new int[9]; TT0025:           public Form1() TT0026:           {InitializeComponent(); } //-----------------------------------------------------------------------------------------// TT0030:           public void WinnerW() TT0031:           { // Has a person won the game? TT0032:             intNoOfClicks++; TT0033:             OWinner = false; TT0034:             XWinner = false; TT0035:             if (intNoOfClicks > 4) TT0036:             { // Check for an 'O' Winner: TT0037:               if ((SO[0] == 1) && (SO[1] == 1) && (SO[2] == 1)) TT0038:               { OWinner = true; goto JUMP; } TT0039:               else if ((SO[0] == 1) && (SO[4] == 1) && (SO[8] == 1)) TT0040:               { OWinner = true; goto JUMP; } TT0041:               else if ((SO[0] == 1) && (SO[3] == 1) && (SO[6] == 1)) TT0042:               { OWinner = true; goto JUMP; } TT0043:               else if ((SO[1] == 1) && (SO[4] == 1) && (SO[7] == 1)) TT0044:               { OWinner = true; goto JUMP; } TT0045:               else if ((SO[2] == 1) && (SO[4] == 1) && (SO[6] == 1)) TT0046:               { OWinner = true; goto JUMP; } TT0047:               else if ((SO[2] == 1) && (SO[5] == 1) && (SO[8] == 1)) TT0048:               { OWinner = true; goto JUMP; } TT0049:               else if ((SO[3] == 1) && (SO[4] == 1) && (SO[5] == 1)) TT0050:               { OWinner = true; goto JUMP; } TT0051:               else if ((SO[6] == 1) && (SO[7] == 1) && (SO[8] == 1)) TT0052:               { OWinner = true; goto JUMP; }                       // Check for an 'X' winner: TT0053:               if ((SX[0] == 1) && (SX[1] == 1) && (SX[2] == 1)) TT0054:               { XWinner = true; goto JUMP; } TT0055:               else if ((SX[0] == 1) && (SX[4] == 1) && (SX[8] == 1)) TT0056:               { XWinner = true; goto JUMP; } TT0057:               else if ((SX[0] == 1) && (SX[3] == 1) && (SX[6] == 1)) TT0058:               { XWinner = true; goto JUMP; } TT0059:               else if ((SX[1] == 1) && (SX[4] == 1) && (SX[7] == 1)) TT0060:               { XWinner = true; goto JUMP; } TT0061:               else if ((SX[2] == 1) && (SX[4] == 1) && (SX[6] == 1)) TT0062:               { XWinner = true; goto JUMP; } TT0063:               else if ((SX[2] == 1) && (SX[5] == 1) && (SX[8] == 1)) TT0064:               { XWinner = true; goto JUMP; } TT0065:               else if ((SX[3] == 1) && (SX[4] == 1) && (SX[5] == 1)) TT0066:               { XWinner = true; goto JUMP; } TT0067:               else if ((SX[6] == 1) && (SX[7] == 1) && (SX[8] == 1)) TT0068:               { XWinner = true; goto JUMP; } TT0069:               JUMP:                       // Has a winner been found? TT0070:               if (OWinner) TT0071:               { TT0072:                 label8.Text = "'O' Wins! Game Over."; TT0073:                 intOWins++; TT0074:               } TT0075:               else if (XWinner) TT0076:               { TT0077:                 label8.Text = "'X' Wins! Game Over."; TT0078:                 intXWins++; TT0079:               } TT0080:               else if (intNoOfClicks == 9) TT0081:               { TT0082:                 label8.Text = "Tie Game. No Winner."; TT0083:                 intTies++; TT0084:               }                       // Play another game? TT0085:               if ((OWinner) || (XWinner) || (intNoOfClicks == 9)) TT0086:               {                         // Post the scoreboard. TT0087:                 label5.Text = intXWins.ToString(); TT0088:                 label6.Text = intOWins.ToString(); TT0089:                 label7.Text = intTies.ToString(); TT0090:                 intNumberOfGames++;                         // Post number of games played to main window. TT0091:                 label10.Text = intNumberOfGames.ToString(); TT0092:                 Invalidate(); TT0093:                 string strMessage; TT0094:                 if (OWinner) strMessage = "'O' Wins! Play Another Game?"; TT0095:                 else if (XWinner) strMessage = "'X' Wins! Play Another Game?"; TT0096:                 else strMessage = " Tie Game. Play Another Game?"; TT0097:                 DialogResult dr = MessageBox.Show(strMessage, "Question:",                         MessageBoxButtons.YesNo, MessageBoxIcon.Question); TT0098:                 if (dr == DialogResult.Yes) TT0099:                 { TT0100:                   Start = false; // Turn off the 'X's and 'O's. TT0101:                   Invalidate(); TT0102:                 } TT0103:                 else TT0104:                 button1.Enabled = false; TT0105:               } TT0106:               Invalidate(); TT0107:             } TT0108:           } //-----------------------------------------------------------------------------------------// TT0120:           private void Form1_Load(object sender, EventArgs e) TT0121:           { // Game Initialization. TT0122:             label5.Text = intXWins.ToString(); TT0123:             label6.Text = intOWins.ToString(); TT0124:             label7.Text = intTies.ToString(); TT0125:           } //-----------------------------------------------------------------------------------------// TT0130:           private void button1_Click(object sender, EventArgs e) TT0131:           { // Start game. TT0132:             for (int jj = 0; jj < 9; jj++) SO[jj] = 0; TT0133:             for (int kk = 0; kk < 9; kk++) SX[kk] = 0; TT0134:             intNoOfClicks = 0; TT0135:             panel10.Enabled = true; TT0136:             panel11.Enabled = true; TT0137:             panel12.Enabled = true; TT0138:             panel13.Enabled = true; TT0139:             panel14.Enabled = true; TT0140:             panel15.Enabled = true; TT0141:             panel16.Enabled = true; TT0142:             panel17.Enabled = true; TT0143:             panel18.Enabled = true; TT0144:             Start = true; TT0145:             intGameNumber++;                     // If this next statement is 'true' then this next game will be                     // an 'ODD' numbered game. If 'ODD', then 'X' leads. TT0146:             if ((intNumberOfGames / 2) == ((intNumberOfGames + 1) / 2)) TT0147:             { TT0148:               label1.Text = "'X' Plays"; // ODD game coming up. TT0149:               XTurn = true; TT0150:             } TT0151:             else TT0152:             { TT0153:               label1.Text = "'O' Plays"; // EVEN game coming up. TT0154:               XTurn = false; TT0155:             } TT0156:             Invalidate(); TT0157:           } //-----------------------------------------------------------------------------------------// TT0170:           private void button2_Click(object sender, EventArgs e) TT0171:           { // Quit. TT0172:             Close(); TT0173:           } //-----------------------------------------------------------------------------------------// TT0180:           private void panel10_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0181:           { // Top-left panel, position '0'. TT0182:             panel10.Enabled = false; TT0183:             if (XTurn) TT0184:             { TT0185:               SX[0] = 1; TT0186:               XTurn = false; TT0187:               label1.Text = "'O' Plays"; TT0188:             } TT0189:             else TT0190:             { TT0191:               SO[0] = 1; TT0192:               XTurn = true; TT0193:               label1.Text = "'X' Plays"; TT0194:             } TT0195:             WinnerW(); TT0196:             Invalidate(); TT0197:           } //-----------------------------------------------------------------------------------------// TT0200:           private void panel11_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0201:           { // Top-center panel, position '1'. TT0202:             panel11.Enabled = false; TT0203:             if (XTurn) TT0204:             { TT0205:               SX[1] = 1; TT0206:               XTurn = false; TT0207:               label1.Text = "'O' Plays"; TT0208:             } TT0209:             else TT0210:             { TT0211:               SO[1] = 1; TT0212:               XTurn = true; TT0213:               label1.Text = "'X' Plays"; TT0214:             } TT0215:             WinnerW(); TT0216:             Invalidate(); TT0217:           } //-----------------------------------------------------------------------------------------// TT0220:           private void panel12_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0221:           { // Top-right panel, position '2'. TT0222:             panel12.Enabled = false; TT0223:             if (XTurn) TT0224:             { TT0225:               SX[2] = 1; TT0226:               XTurn = false; TT0227:               label1.Text = "'O' Plays"; TT0228:             } TT0229:             else TT0230:             { TT0231:               SO[2] = 1; TT0232:               XTurn = true; TT0233:               label1.Text = "'X' Plays"; TT0234:             } TT0235:             WinnerW(); TT0236:             Invalidate(); TT0237:           } //-----------------------------------------------------------------------------------------// TT0240:           private void panel13_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0241:           { // Center-left panel, position '3'. TT0242:             panel13.Enabled = false; TT0243:             if (XTurn) TT0244:             { TT0245:               SX[3] = 1; TT0246:               XTurn = false; TT0247:               label1.Text = "'O' Plays"; TT0248:             } TT0249:             else TT0250:             { TT0251:               SO[3] = 1; TT0252:               XTurn = true; TT0253:               label1.Text = "'X' Plays"; TT0254:             } TT0255:             WinnerW(); TT0256:             Invalidate(); TT0257:           } //-----------------------------------------------------------------------------------------// TT0260:           private void panel14_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0261:           { // Center-center panel, position '4'. TT0262:             panel14.Enabled = false; TT0263:             if (XTurn) TT0264:             { TT0265:               SX[4] = 1; TT0266:               XTurn = false; TT0267:               label1.Text = "'O' Plays"; TT0268:             } TT0269:             else TT0270:             { TT0271:               SO[4] = 1; TT0272:               XTurn = true; TT0273:               label1.Text = "'X' Plays"; TT0274:             } TT0275:             WinnerW(); TT0276:             Invalidate(); TT0277:           } //-----------------------------------------------------------------------------------------// TT0280:           private void panel15_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0281:           { // Center-right panel, position '5'. TT0282:             panel15.Enabled = false; TT0283:             if (XTurn) TT0284:             { TT0285:               SX[5] = 1; TT0286:               XTurn = false; TT0287:               label1.Text = "'O' Plays"; TT0288:             } TT0289:             else TT0290:             { TT0291:               SO[5] = 1; TT0292:               XTurn = true; TT0293:               label1.Text = "'X' Plays"; TT0294:             } TT0295:             WinnerW(); TT0296:             Invalidate(); TT0297:           } //-----------------------------------------------------------------------------------------// TT0300:           private void panel16_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0301:           { // Bottom-left panel, position '6'. TT0302:             panel16.Enabled = false; TT0303:             if (XTurn) TT0304:             { TT0305:               SX[6] = 1; TT0306:               XTurn = false; TT0307:               label1.Text = "'O' Plays"; TT0308:             } TT0309:             else TT0310:             { TT0311:               SO[6] = 1; TT0312:               XTurn = true; TT0313:               label1.Text = "'X' Plays"; TT0314:             } TT0315:             WinnerW(); TT0316:             Invalidate(); TT0317:           } //-----------------------------------------------------------------------------------------// TT0320:           private void panel17_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0321:           { // Bottom-center panel, position '7'. TT0322:             panel17.Enabled = false; TT0323:             if (XTurn) TT0324:             { TT0325:               SX[7] = 1; TT0326:               XTurn = false; TT0327:               label1.Text = "'O' Plays"; TT0328:             } TT0329:             else TT0330:             { TT0331:               SO[7] = 1; TT0332:               XTurn = true; TT0333:               label1.Text = "'X' Plays"; TT0334:             } TT0335:             WinnerW(); TT0336:             Invalidate(); TT0337:           } //-----------------------------------------------------------------------------------------// TT0340:           private void panel18_MouseDown(object sender,                     System.Windows.Forms.MouseEventArgs e) TT0341:           { // Bottom-right panel, position '8'. TT0342:             panel18.Enabled = false; TT0343:             if (XTurn' TT0344:             { TT0345:               SX[8] = 1; TT0346:               XTurn = false; TT0347:               label1.Text = "'O' Plays"; TT0348:             } TT0349:             else TT0350:             { TT0351:               SO[8] = 1; TT0352:               XTurn = true; TT0353:               label1.Text = "'X' Plays"; TT0354:             } TT0355:             WinnerW(); TT0356:             Invalidate(); TT0367:           } //-----------------------------------------------------------------------------------------// TT0370:           private void Form1_Paint(object sender, PaintEventArgs e) TT0371:           { // Paint the window. TT0372:             Graphics grfx = e.Graphics; TT0373:             Font font1 = new Font("Arial", 92); TT0374:             if (Start) TT0375:             { TT0376:               if (SX[0] == 1) grfx.DrawString("X", font1, Brushes.Red, 39, 34); TT0377:               else if (SO[0] == 1) grfx.DrawString("O", font1, Brushes.Blue, 34, 34); TT0378:               if (SX[1] == 1) grfx.DrawString("X", font1, Brushes.Red, 138, 34); TT0379:               else if (SO[1] == 1) grfx.DrawString("O", font1, Brushes.Blue, 133, 34); TT0380:               if (SX[2] == 1) grfx.DrawString("X", font1, Brushes.Red, 237, 34); TT0381:               else if (SO[2] == 1) grfx.DrawString("O", font1, Brushes.Blue, 232, 34); TT0382:               if (SX[3] == 1) grfx.DrawString("X", font1, Brushes.Red, 39, 133); TT0383:               else if (SO[3] == 1) grfx.DrawString("O", font1, Brushes.Blue, 34, 133); TT0384:               if (SX[4] == 1) grfx.DrawString("X", font1, Brushes.Red, 138, 133); TT0385:               else if (SO[4] == 1) grfx.DrawString("O", font1, Brushes.Blue, 133,                                133); TT0386:               if (SX[5] == 1) grfx.DrawString("X", font1, Brushes.Red, 237, 133); TT0387:               else if (SO[5] == 1) grfx.DrawString("O", font1, Brushes.Blue, 232,                                133); TT0388:               if (SX[6] == 1) grfx.DrawString("X", font1, Brushes.Red, 39, 232); TT0389:               else if (SO[6] == 1) grfx.DrawString("O", font1, Brushes.Blue, 34, 233); TT0390:               if (SX[7] == 1) grfx.DrawString("X", font1, Brushes.Red, 138, 232); TT0391:               else if (SO[7] == 1) grfx.DrawString("O", font1, Brushes.Blue, 133,                                233); TT0392:               if (SX[8] == 1) grfx.DrawString("X", font1, Brushes.Red, 237, 232); TT0393:               else if (SO[8] == 1) grfx.DrawString("O", font1, Brushes.Blue, 232,                                233); TT0394:             } TT0395:           } TT0396:         } TT0397:       } Form1.Designer.cs: [See 'TicTacToe' listing in 'App D -- DemoVC#TaggedList.doc'.] 
 


Unlocking Microsoft C# V 2.0 Programming Secrets
Unlocking Microsoft C# V 2.0 Programming Secrets (Wordware Applications Library)
ISBN: 1556220979
EAN: 2147483647
Year: 2005
Pages: 129

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net