Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Microsoft CSharp Programming For The Absolute Beginner (2002) [eng].pdf
Скачиваний:
39
Добавлен:
16.08.2013
Размер:
15.71 Mб
Скачать

Figure 8.9: When the user clicks the forEach button, the elements of the array are shown one at a time.

Wanting to step through the elements of an array one at a time is common. Arrays and for loops are a natural combination because doing something to each element of an array one at a time is so common. Although you can use a for loop for this purpose, the foreach loop makes examining an array, element by element, even easier to do.

private void btnForEach_Click(object sender, System.EventArgs e) {

//demonstrates the foreach loop used with arrays foreach (string theLang in languages){

MessageBox.Show(theLang);

} // end foreach

}// end btnFor

The foreach loop is a special variant of the for loop. It requires a local variable of the same type as the array and the array name. In this case, theLang is a string that holds each value in the array. Because it’s a string array, theLang must be a string value. The variable name must be followed by the keyword in, followed by the name of the array. The loop occurs once for each element of the array. Each time through the loop, theLang has a different value picked from the array.

Trick The reason this works in the Pig Latin game is this: When I used the Split() method on a string variable, it converted that variable to an array of strings. I could then use the foreach loop to step easily through that array. Closure at last…

Creating Tables with Two−Dimensional Arrays

The type of array you’ve seen so far in this chapter is used whenever you need to work with a list of data. Sometimes, however, you are more interested in more complex information. When you solve complex problems without a computer, you often find yourself keeping information in two−dimensional tables. C# supports a special two−dimensional array that allows you to work with this kind of information.

Designing the Soccer Game

The Soccer program you saw at the beginning of this chapter relies on a table. If you analyze the Soccer program, you will see that all the action revolves around the user's clicking the various players. Somehow the computer has to know the likelihood that a pass from one player to another will succeed. Figure 8.10 shows a program that illustrates the likelihood of any one player's passing to another.

214

Figure 8.10: The halfback should complete a pass to the wing 80 percent of the time. Hint Usually I use the terms player and user interchangeably, but in this chapter, I

have decided to use these terms more carefully. The soccer game has entities called players, and I have chosen to use that term only when I’m referring to these elements inside the game. I use the term user to describe the person playing the game.

Because this is the most critical part of the Soccer game that concludes this chapter, you should learn the basic concepts in a simpler program first, such as the Shot Demo illustrated in Figure 8.10.

As you can see in the Shot Demo program, the user can select one player to kick the ball and one player (or shot) as the target. Whenever the user makes a selection in one of the list boxes, the percentage likelihood this shot will succeed is displayed. The user can then press the kick button, which will succeed at the indicated percentage, to get a feel for how often the indicated percentage succeeds.

Solving a Subset of the Problem

One way to set this up would be to think about a certain player at first. For example, take the fullback, who generally stays near his own goal in a defensive position. It is very likely that the fullback will complete a pass to the goalie or halfback, because these two players are usually in close proximity. It is less likely that the fullback will complete a pass directly to the wing or center and highly unlikely that an attempt on the opponent’s goal will succeed from the fullback’s position. You could encode this information in a simple chart like Table 8.1.

Table 8.1: The Likelihood of Success from the Fullback Spot

Goalie

Halfback

Wing

Center

Shot

80%

80%

60%

40%

2%

Table 8.1 summarizes the chances of success for a shot or pass from the fullback to other members of the team (or the opposing goal). Although there is absolutely nothing scientific about these values, they are an approximation of the options facing a fullback during a soccer game. Having percentages is nice from a programming point of view because generating a random value that will approximate any percentage is very easy. For example, if you want to set up a condition that will be

215

true 60 percent of the time (to simulate a pass from the fullback to the wing), you could use something like this:

Random roller = new Random(); if (roller.nextDouble() < .6){

MessageBox("Good!");

}else {

MessageBox("No good.");

}// end if

The nextDouble() method produces a random number between 0 and 1. That value will be less than 0.6 about 60 percent of the time. If you have percentages for the likelihood of various situations, writing conditional statements to test whether those situations occur is easy.

Adding Percentages for the Other Players

It would be possible to encapsulate all the information about the fullback’s options in a normal array, but sometimes other players have the ball, too. You can build a more complex table that tries to show all the possible choices in the game. Table 8.2 illustrates one such chart.

Table 8.2: Percentages For All Plays

Kicker

Goalie

Fullback

Halfback

Wing

Center

Goal

Goalie

–1

.8

.6

.4

.1

.01

Fullback

.8

–1

.8

.6

.4

.02

Halfback

.8

.8

–1

.8

.6

.03

Wing

.8

.8

.8

–1

.8

.04

Center

.8

.8

.8

.8

–1

.2

Table 8.2 extends Table 8.1 to consider the likelihood of every opportunity offered to the player during the Soccer game. In this table, the percentages are written as double values (so 80% is written as .8, for example). Also, I used a –1 to indicate an impossible shot. I wanted to require the user to keep moving the ball around the field so that if he attempts to pass from a player to that same player, it will always fail (and in the final game, the opposing team will get a chance to score).

There is absolutely nothing scientific about the percentages I chose. I pulled them completely out of the air as a starting point. When the mechanics of the game are working, it will probably be necessary to tweak the values in this table.

Setting Up the Shot Demo Program

The Shot Demo program uses a special form of array to duplicate the information from Table 8.2 in the computer’s memory. The class−level code includes a new type of array to hold the data:

double chance = 0d;

private double[,] shotChance = { {−1, .8, .6, .4, .1, .01}, {.8, −1, .8, .6, .4, .02}, {.8, .8, −1, .8, .6, .03}, {.8, .8, .8, −1, .8, .04}, {.8, .8, .8, .8, −1, .2},

};

216

Because the program uses percentages extensively, the double type is used to handle all percentage values. The player’s likelihood of succeeding at a shot is stored in the chance variable. The shotChance is an array of doubles. However, you can see that its structure is fundamentally different from the other arrays you’ve seen so far. The data I’m trying to encapsulate in shotDemo comes from a two−dimensional table, so I store it in a two−dimensional array. You set up an array to have two (or more) dimensions by adding a comma (or more) to the brackets that follow the array type. You can predefine the values of the array if you know what the array will contain when you are initializing it. Each row is enclosed in braces, and the entire structure is enclosed in another set of braces. The rows, just like the data inside the rows, are separated by commas.

You can also set up the array without initializing it. If you wanted to make a 3−by−4 double array, for example, you could use a line such as

private double[,] myArray = new double[3,4];

When you have a two−dimensional array, you refer to it using two indices. For example, shotChance[3,2] refers to the third column, second row of the shotChance array, which is the value

.8. (Don’t forget that the computer starts counting with 0, so the third column is what people would consider the fourth column.)

In the Real World

Beginning programmers almost never use an array in this situation. Instead, they shy away from data structures and look at a solution that uses control structures. This is usually a mistake. It would be possible to use a series of if−elseif−endif statements or a nested switch structure to get the same behavior as the array technique I’ll show you here, but that technique would require between 75 and 100 lines of code. A lot of repeated code means many places where things can go wrong and a major headache if you find that you need to tweak your logic. By taking the time to think carefully about a data structure, the 75 lines of code can be shrunk to 4. It’s an amazing improvement in efficiency, and those four lines of code are easier to fix and modify. Experienced programmers often look for control structures that are more complex in the short run but pay off in code complexity for the long run.

Hint There’s no reason to stop at two dimensions. It’s possible to build arrays with four, five, or as many dimensions as you like. Usually, programmers don’t need to make arrays much larger than three dimensions because they can store objects in the arrays, which allow for even more complex and flexible data.

Setting Up the List Boxes

The user will use the list boxes to control the program, so setting them up properly is very important. In particular, the elements in the lists must go in the correct order. The lstKicker list box represents all the various kickers. Each player can be a kicker, but not the opponent’s goal (it is strictly a target), so the list box is filled with the names of the positions. I took special care to associate the names with the rows of the original table (Goalie, Fullback, Halfback, Wing, and Center). The lstTarget list box contains all the various targets. Each player position is a potential target, as is the opposing goal, so this list box has six elements, corresponding to the columns in the original table.

To ensure that the list boxes would begin with legal values, I added code to the constructor to initialize the list boxes:

lstKicker.SelectedIndex = 0;

217

Соседние файлы в предмете Программирование на C++