ms_learn_csharp/030_project_petting_zoo/030_csharp.md
2024-08-11 21:59:22 -04:00

24 KiB
Raw Blame History

Guided project

Plan a Petting Zoo Visit

Demonstrate your ability to develop a console app that relies on methods with different parameters and return values to coordinate a visit to the petting zoo.

Learning objectives

  • Plan design details with pseudo-code

  • Use methods to perform specific tasks

  • Create methods that accept require and optional parameters

  • Use values returned from methods

Introduction

Methods are a fundamental programming concept. They provide code reusability, improve readability, and reduce the size of your code. Methods help you break down complex problems into modularized tasks, and help organize your code. Now that you've learned about methods, you're ready to start developing more functionality into your programs!

Suppose you're an event coordinator for a petting zoo. You must regularly coordinate visits from different schools and organize animal visits for several groups of students. You decide to write an application that helps you plan school visits. The application divides students into groups and assigns them a set of animals to visit. The students will rotate groups after they visit their assigned animals. You decide to randomize the order animals so that each school's visit is unique.

This module will guide you through the steps required to develop your petting zoo application. Your code will use methods to plan a visit for three schools, randomize the order of animals, assign students to groups, and display the results. You'll use methods that accept parameters and return values, and you'll include some optional parameters as well.

Learning objectives

In this module, youll practice how to:

  • Use methods to perform specific tasks
  • Create methods that accept require and optional parameters
  • Use values returned from methods

Prepare for guided project

You'll be using a code editor to develop an application that relies on different methods to perform a task. Some methods use optional parameters and return values. Here, you'll find the overall goals of the project and how you'll build and test your application. You'll also set up your development environment using some Starter code.

Project overview

You're developing an application for the Contoso Petting Zoo that coordinates school visits. The Contoso Petting Zoo is home to 18 different species of animals. At the zoo, visiting students are assigned to groups, and each group has a set of animals assigned to it. After visiting their set of animals, the students will rotate groups until they've seen all the animals at the petting zoo.

By default, the students are divided into 6 groups. However, there are some classes that have a small or large number of students, so the number of groups must be adjusted accordingly. The animals should also be randomly assigned to each group, so as to keep the experience unique.

The design specification for the Contoso Petting Zoo application is as follows:

  • There are currently three visiting schools:
    • School A has six visiting groups (the default number)
    • School B has three visiting groups
    • School C has two visiting groups
  • For each visiting school, perform the following tasks:
    • Randomize the animals
    • Assign the animals to the correct number of groups
    • Print the school name
    • Print the animal groups

Copy and paste the following code into the code editor. These values represent the different species at the petting zoo.

using System;

string[] pettingZoo = {
    "alpacas", "capybaras", "chickens", "ducks", "emus", "geese", 
    "goats", "iguanas", "kangaroos", "lemurs", "llamas", "macaws", 
    "ostriches", "pigs", "ponies", "rabbits", "sheep", "tortoises",
};

You're now ready to begin the Guided project exercises. Good luck!


Exercise

Plan your code using methods

In this first step of your development process, you'll begin planning your application through pseudo-code. You'll identify the steps and methods that are needed to complete the task. You also need to consider the input and output of these methods as well. Preparing methods via pseudo-code is a helpful step in any coding task, and can help you develop bug-free code quickly.

Important
You need to have completed the Setup instructions in the previous unit, Prepare, before you begin this Exercise.

Convert tasks into pseudo-code

In this task, you'll turn the steps defined in the application specification into pseudo-code. By preparing pseudo-code, developing the full application becomes an easier task. Let's get started!

Take a moment to consider the design specification:

- There will be three visiting schools
    - School A has six visiting groups (the default number)
    - School B has three visiting groups
    - School C has two visiting groups

- For each visiting school, perform the following tasks
    - Randomize the animals
    - Assign the animals to the correct number of groups
    - Print the school name
    - Print the animal groups

To get started, you'll focus on writing the pseudo-code for just one school. When you figure out the code for one school, you can easily apply the same logic to the others.

Enter a new blank code line below the pettingZoo array initialization.

The first task is to randomize the animals. Create a pseudo-code method to randomize the petting zoo animals by entering the following code into the editor:

// RandomizeAnimals();

You won't fill in any logic to randomize the animals yet. For now, you'll focus on planning the application as a whole. You can assume that this RandomizeAnimals() method exists and will correctly randomize the pettingZoo array.

Next, create a pseudo-code method to assign the animal groups. Enter the following code into the editor:

// AssignGroup();

Like before, you can assume that this method correctly assigns the animals to a subset group and continue to the next task.

You can easily print the school name using Console.Write. Enter the following code into the editor:

Console.WriteLine("School A");

Lastly, you'll need to print the animal groups. Enter the following code into the editor:

// PrintGroup(group);

Notice that you added a parameter to this method. You know that you need to print different groups of animals several times, so you use a method to perform this task with the group as the input parameter. Take a moment to consider where you can initialize the group argument in your pseudo-code.

Assign the group argument by updating the AssignGroup line of code to the following:

// var group = AssignGroup();

Since you have completed pseudo-code for the general tasks, you can take a moment to consider what data type to assign to the group variable.

You want School A to have animals assigned into six groups. And you know that there are 18 animals. You also know that the animals are represented using string. So you can use a 2D array that contains six groups of three animals each.

Assign the group data type by updating the AssignGroup line of code to the following:

// string[,] group = AssignGroup();

You don't add any arguments to the AssignGroup method the default group value is six.

Check your work

In this task, you'll check that your pseudo-code performs the general tasks listed for each school. You'll also run the code to ensure there are no issues.

Compare your code to the following:

using System;

string[] pettingZoo = {
    "alpacas", "capybaras", "chickens", "ducks", "emus", "geese", 
    "goats", "iguanas", "kangaroos", "lemurs", "llamas", "macaws", 
    "ostriches", "pigs", "ponies", "rabbits", "sheep", "tortoises",
};

// RandomizeAnimals();
// string[,] group = AssignGroup();
Console.WriteLine("School A");
// PrintGroup(group);

At the Terminal command prompt, enter dotnet run

Verify that the "School A" message is displayed.


Exercise

Create a method to shuffle an array

In this step, you'll develop the code to complete your first subtask, which is to randomize the petting zoo animals. Recall that you referenced a method RandomizeAnimals() in your pseudo-code. Let's get started!

Shuffle an array

Randomizing the elements of an array can seem like a daunting task. Before you begin, take a moment to consider how you would swap the values of two variables, a and b.

If you immediately assign a = b, you'll lose the original value of a and end up with two variables equal to b. You need to use a temporary variable to store the value of a before you can overwrite it. Let's use this concept to begin your task.

Enter a new blank code line, then define the RandomizeAnimals method by entering the following code.

void RandomizeAnimals() {

}

For this method, you don't need any input parameters since you'll use the existing global pettingZoo variable. You also don't need any input parameters for this task. To start this method, let's write some code to swap some elements in the array.

Enter the following code in the RandomizeAnimals() method:

int i = 0;
int r = 1;

string temp = pettingZoo[i];
pettingZoo[i] = pettingZoo[r];
pettingZoo[r] = temp;

In this code, you're temporarily using i and r to represent some random indices in the array. Then you swap the values at the two indices with the help of the temp variable. Notice how using temp prevents us from losing the original value of pettingZoo[i] after it's overwritten. Next, let's set r to a random value instead of 1.

Update your code to the following:

Random random = new Random();

int i = 0;
int r = random.Next(pettingZoo.Length);

string temp = pettingZoo[i];
pettingZoo[i] = pettingZoo[r];
pettingZoo[r] = temp;

In this step, you initialized a random object to help us generate a random number. And you initialized r to a random integer between 0 and the length of the pettingZoo array. This will ensure you don't go out of bounds of the array. You can apply this code to the entirety of the array to randomize all of the elements.

Modify the elements using a for-loop by updating your code to the following:

Random random = new Random();

for (int i = 0; i < pettingZoo.Length; i++) {
    int r = random.Next(pettingZoo.Length);

    string temp = pettingZoo[i];
    pettingZoo[i] = pettingZoo[r];
    pettingZoo[r] = temp;
}

Now you cycle through each element in the array, select a random index, and swap it with the current element. However, if you run this code and observe the changes on pettingZoo, you might notice an issue. Some elements don't get swapped at all, and some elements are swapped multiple times.

You can improve the distribution of randomly selected elements by updating the range as you move through the array.

Update your code to the following:

int r = random.Next(i, pettingZoo.Length);

Now, as you iterate through the for loop, you update the range of the randomly selected index to exclude values less than i. This is because indices at values less than i have already been swapped in previous iterations of the loop.

Uncomment the call to RandomizeAnimals() by removing the starting // characters.

Check your work

In this task, you'll run your application from the terminal and verify your code is working correctly. Let's get started.

Compare your code with the following to ensure it's correct:

using System;

string[] pettingZoo = {
    "alpacas", "capybaras", "chickens", "ducks", "emus", "geese", 
    "goats", "iguanas", "kangaroos", "lemurs", "llamas", "macaws", 
    "ostriches", "pigs", "ponies", "rabbits", "sheep", "tortoises",
};

RandomizeAnimals();
// string[,] group = AssignGroup();
Console.WriteLine("School A");
// PrintGroup(group);

void RandomizeAnimals() {
    Random random = new Random();
    for (int i = 0; i < pettingZoo.Length; i++) {
        int r = random.Next(i, pettingZoo.Length);
        string temp = pettingZoo[r];
        pettingZoo[r] = pettingZoo[i];
        pettingZoo[i] = temp;
    }
}

To test the RandomizeAnimals method, copy and paste the following code into the editor at the end of the code:

foreach(string animal in pettingZoo) {
    Console.WriteLine(animal);
}

At the Terminal command prompt, enter dotnet run

Verify that your code produces the following output:

Verify that the expected "School A" message is displayed, followed by a randomized list of the animals. The animals shouldn't appear in alphabetical order. For example:

School A
ponies
iguanas
goats
tortoises
ducks
rabbits
lemurs
alpacas
capybaras
emus
sheep
llamas
pigs
macaws
kangaroos
geese
chickens
ostriches

Remove the foreach loop you added to test your method.


Exercise

Create a method with an optional parameter

In this step, you'll develop the code to complete another subtask, which is to assign the petting zoo animals to groups. Recall that you referenced a method AssignGroup() in your pseudo-code. Let's get started!

Develop your method

In this task, you'll complete a method that assigns the petting zoo animals to groups. You'll use what you learned about method return types and parameters to create your method. Let's get started!

Enter a new blank code line, then define the assignGroups method by entering the following code.

string[,] AssignGroup(int groups) {

}

Remember that you decided this method would return a 2D array. The number of groups can also change depending on the size of the visiting school. However, there's a default group size of 6, so you should make this parameter optional.

Change groups to an optional parameter by updating the method to the following code:

string[,] AssignGroup(int groups = 6) {

}

Recall that an optional parameter is defined by assigning it a default value. Required parameters should be declared first before any optional ones. Next you'll begin adding logic to your code.

Update your method with the following code:

string[,] AssignGroup(int groups = 6) {
    string[,] result = new string[groups, pettingZoo.Length/groups];

    return result;
}

Since your method specifies a return value, you start your method definition by creating a value to return. This allows you to continue adding logic without compile-time errors.

Notice that you used [groups, pettingZoo.Length/groups] to define the array size. groups represents the number of animal groups you want to create. pettingZoo.Length/groups reflects how many animals are assigned to each group. For example, since pettingZoo is a fixed array of 18 elements, the 2D array size for School A is [6,3].

Next, you'll assign the animals to each group.

Update your code with the following nested for loop:

string[,] AssignGroup(int groups = 6) {
    string[,] result = new string[groups, pettingZoo.Length/groups];
    for (int i = 0; i < groups; i++) {
        for (int j = 0; j < result.GetLength(1); j++) {

        }
    }
    return result;
}

In this code, the outer for loop cycles through each group. The inner for loop cycles for the number of animals the group should contain. Next, you need to assign the animals.

Update your for loop with the following code:

int start = 0;

for (int i = 0; i < groups; i++) {
    for (int j = 0; j < result.GetLength(1); j++) {
        result[i,j] = pettingZoo[start++];
    }
}

In this code, you define start to represent the starting position of pettingZoo. Using this marker allows you to navigate through the pettingZoo array one element at a time even though the for-loops have different iterations.

Now your method assigns the petting zoo animals to the designated number of groups. Now you can uncomment your call to AssignGroup.

Locate the AssignGroup() method call and remove the starting // characters.

Remember that since you're omitting the optional parameter, the group variable will be a 2D array of [6,3].

Check your work

In this task, you'll run your application from the terminal and verify your code is working correctly. Let's get started.

Compare your code to the following to ensure it's correct:

using System;

string[] pettingZoo = {
    "alpacas", "capybaras", "chickens", "ducks", "emus", "geese", 
    "goats", "iguanas", "kangaroos", "lemurs", "llamas", "macaws", 
    "ostriches", "pigs", "ponies", "rabbits", "sheep", "tortoises",
};

RandomizeAnimals();
string[,] group = AssignGroup();
Console.WriteLine("School A");
// PrintGroup(group);

void RandomizeAnimals() {
    Random random = new Random();

    for (int i = 0; i < pettingZoo.Length; i++) {
        int r = random.Next(i, pettingZoo.Length);

        string temp = pettingZoo[r];
        pettingZoo[r] = pettingZoo[i];
        pettingZoo[i] = temp;
    }
}

string[,] AssignGroup(int groups = 6) {
    string[,] result = new string[groups, pettingZoo.Length/groups];
    int start = 0;

    for (int i = 0; i < groups; i++) {
        for (int j = 0; j < result.GetLength(1); j++) {
            result[i,j] = pettingZoo[start++];
        }
    }

    return result;
}

At the Terminal command prompt, enter dotnet run

Verify that the expected "School A" message is displayed and that there are no error messages.

If your code produces unexpected errors, you'll need to review your code to find your error and make updates. Run the code again to see if you've fixed the problem. Continue updating and running your code until your code produces the expected results.


Exercise

Create a method to display the results

In this step, you'll define the method to display the results of the animal groups. You'll also complete the animal group assignments for the other visiting schools. Let's get started!

Develop your method

Enter a new blank code line. Then define the PrintGroup method by entering the following code.

void PrintGroup(string[,] group) {

}

Remember that you decided this method would take a 2D array as input. Now you just need your method to print the contents of the 2D array.

Add the following code to the PrintGroup method:

void PrintGroup(string[,] group) {
    for (int i = 0; i < group.GetLength(0); i++) {
        for (int j = 0; j < group.GetLength(1); j++) {
            Console.Write($"{group[i,j]}  ");
        }
    }
}

Here, you use GetLength(0) to get the number of rows in the array, and GetLength(1) for the number of columns. Then you use Console.Write to print the element with some extra spaces between the animals. Next, let's add some helper text and a new line to separate the groups.

Update your method with the following code:

void PrintGroup(string[,] group) {
    for (int i = 0; i < group.GetLength(0); i++) {
        Console.Write($"Group {i + 1}: ");
        for (int j = 0; j < group.GetLength(1); j++) {
            Console.Write($"{group[i,j]}  ");
        }
        Console.WriteLine();
    }
}

Now you have all the code in place to complete the task to prepare for the school visit.

Locate the PrintGroup method call and remove the starting // characters.

Next, you'll run your code and observe the results.

Save then run your code by entering dotnet run at the terminal command prompt.

To verify that your code is working as expected, check that the output of your application is similar the following output, taking into account the random order of the animals:

School A
Group 1: ducks  emus  rabbits  
Group 2: lemurs  chickens  geese  
Group 3: iguanas  macaws  alpacas  
Group 4: goats  kangaroos  pigs  
Group 5: capybaras  llamas  tortoises
Group 6: sheep  ostriches  ponies

Consider that you need to perform the same tasks for each school. The differences would be the name of the school and the number of groups. This is a perfect opportunity to use a method with those parameters.

Create a new blank code line above the RandomizeAnimals() method call. Then create a new method by entering the following code:

void PlanSchoolVisit(string schoolName, int groups = 6) {
    RandomizeAnimals();
    string[,] group = AssignGroup();
    Console.WriteLine("School A");
    PrintGroup(group);
}

With this code, you're able to perform the same tasks for each school. You also set groups to the default value of 6. Next, you'll update your method to use the input values.

Update your method with the following code:

void PlanSchoolVisit(string schoolName, int groups = 6) {
    RandomizeAnimals();
    string[,] group = AssignGroup(groups);
    Console.WriteLine(schoolName);
    PrintGroup(group);
}

Now you're ready to call this method for each of the schools.

Create a new blank code line above the PlanSchoolVisit method. Then enter the following code:

PlanSchoolVisit("School A");
PlanSchoolVisit("School B", 3);
PlanSchoolVisit("School C", 2);

Check your work

In this task, you'll run your application from terminal and verify your code is working correctly. Let's get started.

Compare your code to the following to ensure it's correct:

using System;

string[] pettingZoo = {
    "alpacas", "capybaras", "chickens", "ducks", "emus", "geese", 
    "goats", "iguanas", "kangaroos", "lemurs", "llamas", "macaws", 
    "ostriches", "pigs", "ponies", "rabbits", "sheep", "tortoises",
};

PlanSchoolVisit("School A");
PlanSchoolVisit("School B", 3);
PlanSchoolVisit("School C", 2);

void PlanSchoolVisit(string schoolName, int groups = 6) {
    RandomizeAnimals(); 
    string[,] group1 = AssignGroup(groups);
    Console.WriteLine(schoolName);
    PrintGroup(group1);
}

void RandomizeAnimals() {
    Random random = new Random();
    for (int i = 0; i < pettingZoo.Length; i++) {
        int r = random.Next(i, pettingZoo.Length);
        string temp = pettingZoo[r];
        pettingZoo[r] = pettingZoo[i];
        pettingZoo[i] = temp;
    }
}

string[,] AssignGroup(int groups = 6) {
    string[,] result = new string[groups, pettingZoo.Length/groups];
    int start = 0;
    for (int i = 0; i < groups; i++) {
        for (int j = 0; j < result.GetLength(1); j++) {
            result[i,j] = pettingZoo[start++];
        }
    }
    return result;
}

void PrintGroup(string[,] groups) {
    for (int i = 0; i < groups.GetLength(0); i++) {
        Console.Write($"Group {i + 1}: ");
        for (int j = 0; j < groups.GetLength(1); j++) {
            Console.Write($"{groups[i,j]}  ");
        }
        Console.WriteLine();
    }
}

At the Terminal command prompt, enter dotnet run

Check that the output of your application is similar to the following, taking into account the randomized order of animals:

School A
Group 1: kangaroos  lemurs  pigs  
Group 2: alpacas  sheep  chickens  
Group 3: ducks  geese  capybaras  
Group 4: ponies  iguanas  tortoises  
Group 5: ostriches  llamas  rabbits  
Group 6: macaws  goats  emus  
School B
Group 1: llamas  ducks  ponies  geese  chickens  goats
Group 2: iguanas  capybaras  macaws  kangaroos  rabbits  sheep
Group 3: lemurs  tortoises  alpacas  pigs  emus  ostriches
School C
Group 1: sheep  ducks  pigs  macaws  kangaroos  ostriches  rabbits  goats  lemurs
Group 2: iguanas  capybaras  chickens  emus  tortoises  geese  ponies  alpacas  llamas

You should check that School A has six groups, School B has three groups, and School C has two groups. The order of the animals should be randomized for each school.

If your code produces unexpected errors, you'll need to review your code to find your error and make updates. Run the code again to see if you've fixed the problem. Continue updating and running your code until your code produces the expected results.


Summary

Your goal was to build an application that uses methods to achieve a complex task. You broke down the problem into modularized methods to create an organized, readable solution. You also used parameters and return types to complete your code.