avnc 031
This commit is contained in:
parent
32ed18870c
commit
8d6b17b617
297
031_Challenge_mini_game/031_csharp.md
Normal file
297
031_Challenge_mini_game/031_csharp.md
Normal file
@ -0,0 +1,297 @@
|
||||
# Challenge project
|
||||
|
||||
## Create a mini-game
|
||||
|
||||
Demonstrate your ability to create and use different methods to develop
|
||||
features for a console mini-game.
|
||||
|
||||
### Learning objectives
|
||||
|
||||
- Develop a C# console application that uses methods to implement logical
|
||||
workflows.
|
||||
|
||||
- Understand existing code and make informed changes to design.
|
||||
|
||||
- Create return values as well as required and optional parameters in methods.
|
||||
|
||||
## Introduction
|
||||
|
||||
Creating your own game is an exciting way to practice your programming skills.
|
||||
Games rely heavily on processing user input to make dynamic decisions. Every
|
||||
game must also have a set of defined rules that determine actions and events in
|
||||
the game.
|
||||
|
||||
Suppose you want to create your own game. You might not be ready to develop a
|
||||
fully featured game, so you decide to start as small as possible. You want to
|
||||
move a character across the screen and make it consume an object. The object
|
||||
consume can affect the state of the player. To keep the game going, you wanted
|
||||
to regenerate the object in a new location once it has been consumed. You
|
||||
decide that you'll need to use methods to keep your game code organized.
|
||||
|
||||
In this module, you'll develop the following features of a mini-game
|
||||
application:
|
||||
|
||||
- A feature to determine if the player consumed the food
|
||||
- A feature that updates player status depending on the food consumed
|
||||
- A feature that pauses movement speed depending on the food consumed
|
||||
- A feature to regenerate food in a new location
|
||||
- An option to terminate the game if an unsupported character is pressed
|
||||
- A feature to terminate the game if the Terminal window was resized
|
||||
|
||||
By the end of this module, you'll create a playable mini-game application!
|
||||
|
||||
> Note
|
||||
> This is a challenge project module where you'll complete an end-to-end
|
||||
project from a specification. This module is intended to be a test of your
|
||||
skills; there’s little guidance and no step-by-step instructions.
|
||||
|
||||
#### Learning objectives
|
||||
|
||||
In this module, you'll demonstrate your ability to:
|
||||
|
||||
- Use Visual Studio Code to develop a C# console application that uses methods
|
||||
to implement logical workflows.
|
||||
- Understand existing code and make informed changes to design.
|
||||
- Create return values and methods with required and optional parameters.
|
||||
|
||||
---
|
||||
|
||||
## Prepare for challenge
|
||||
|
||||
You'll be using Visual Studio Code to develop a small mini-game. Your
|
||||
application should establish the basics of the game, including updating player
|
||||
state, manipulating player movement, and consuming and regenerating a food
|
||||
object. You'll develop each of those features and run a simplified game test.
|
||||
|
||||
### Project specification
|
||||
|
||||
The Starter code project for this module includes a Program.cs file with the
|
||||
following code features:
|
||||
|
||||
```txt
|
||||
- The code declares the following variables:
|
||||
- Variables to determine the size of the Terminal window.
|
||||
- Variables to track the locations of the player and food.
|
||||
- Arrays `states` and `foods` to provide available player and food appearances
|
||||
- Variables to track the current player and food appearance
|
||||
|
||||
- The code provides the following methods:
|
||||
- A method to determine if the Terminal window was resized.
|
||||
- A method to display a random food appearance at a random location.
|
||||
- A method that changes the player appearance to match the food consumed.
|
||||
- A method that temporarily freezes the player movement.
|
||||
- A method that moves the player according to directional input.
|
||||
- A method that sets up the initial game state.
|
||||
|
||||
- The code doesn't call the methods correctly to make the game playable. The following features are missing:
|
||||
- Code to determine if the player has consumed the food displayed.
|
||||
- Code to determine if the food consumed should freeze player movement.
|
||||
- Code to determine if the food consumed should increase player movement.
|
||||
- Code to increase movement speed.
|
||||
- Code to redisplay the food after it's consumed by the player.
|
||||
- Code to terminate execution if an unsupported key is entered.
|
||||
- Code to terminate execution if the terminal was resized.
|
||||
```
|
||||
|
||||
Your goal in this challenge is to use the existing features and create the
|
||||
missing features to make the game playable.
|
||||
|
||||
### Setup
|
||||
|
||||
Use the following steps to prepare for the Challenge project exercises:
|
||||
|
||||
To download a zip file containing the Starter project code, select the
|
||||
following link:
|
||||
[Lab Files](https://github.com/MicrosoftLearning/Challenge-project-Create-methods-in-CSharp/archive/refs/heads/main.zip).
|
||||
|
||||
Unzip the download files.
|
||||
|
||||
You're now ready to begin the Challenge project exercises. Good luck!
|
||||
|
||||
---
|
||||
|
||||
## Exercise - Add code to end the game
|
||||
|
||||
Your goal is to develop a mini-game application. You need the game to end if
|
||||
the user resized the Console window the game is running in. You also want to
|
||||
add an option for the game to end if the user enters any nondirectional
|
||||
character.
|
||||
|
||||
### Specification
|
||||
|
||||
In this challenge exercise, you need to update the existing code to support an
|
||||
option to terminate the gameplay if a nondirectional character is entered. You
|
||||
also want to terminate the game if the terminal window was resized. You need to
|
||||
locate the correct methods for your code to use.
|
||||
|
||||
#### Terminate on resize
|
||||
|
||||
This feature must:
|
||||
|
||||
- Determine if the terminal was resized before allowing the game to continue
|
||||
- Clear the Console and end the game if the terminal was resized
|
||||
- Display the following message before ending the program: Console was resized. Program exiting.
|
||||
|
||||
#### Add optional termination
|
||||
|
||||
- Modify the existing `Move` method to support an optional parameter
|
||||
- If enabled, the optional parameter should detect nondirectional key input
|
||||
- If nondirectional input is detected, allow the game to terminate
|
||||
|
||||
### Check your work
|
||||
|
||||
To validate that your code satisfies the specified requirements, complete the
|
||||
following steps:
|
||||
|
||||
At the Terminal command prompt, resize the window.
|
||||
|
||||
Enter a directional key.
|
||||
|
||||
Verify that the program ends after displaying the following message:
|
||||
|
||||
```txt
|
||||
Console was resized. Program exiting.
|
||||
```
|
||||
|
||||
Run the app again.
|
||||
|
||||
At the Terminal command prompt, press directional keys to move the player.
|
||||
|
||||
Press a nondirectional key.
|
||||
|
||||
Verify that the program ends.
|
||||
|
||||
Disable the optional parameter, then build and run the app.
|
||||
|
||||
At the Terminal command prompt, press directional keys to move the player.
|
||||
|
||||
Press a nondirectional key.
|
||||
|
||||
Verify that the program continues.
|
||||
|
||||
Resize the Terminal window.
|
||||
|
||||
Verify that the program ends.
|
||||
|
||||
Once you've validated the results for this exercise, proceed to the next
|
||||
exercise in this challenge.
|
||||
|
||||
---
|
||||
|
||||
## Exercise
|
||||
|
||||
### Make the player consume food
|
||||
|
||||
Your goal is to develop a mini-game application. The mini-game displays food
|
||||
that the player can consume. You need to detect if the player has successfully
|
||||
consumed the food, and if so, redisplay the food. You also want to change the
|
||||
player appearance depending on what food was consumed.
|
||||
|
||||
### Specification
|
||||
|
||||
In this challenge exercise, you need to create a method that determines if the
|
||||
player has consumed the food that was displayed. If the food was consumed, you
|
||||
want to update the player's appearance and redisplay the food.
|
||||
|
||||
#### Check if the player consumed the food
|
||||
|
||||
- Create a method that uses the existing position variables of the player and food
|
||||
- The method should return a value
|
||||
- After the user moves the character, call your method to determine the following:
|
||||
- Whether or not to use the existing method that changes player appearance
|
||||
- Whether or not to use the existing method to redisplay the food
|
||||
|
||||
### Check your work
|
||||
|
||||
To validate that your code satisfies the specified requirements, complete the
|
||||
following steps:
|
||||
|
||||
At the Terminal command prompt, press directional keys to move the player.
|
||||
|
||||
Move the player across the displayed food string.
|
||||
|
||||
Verify that a new food string is displayed.
|
||||
|
||||
Verify that the player appearance changes depending on which food string was
|
||||
consumed.
|
||||
|
||||
Once you've validated the results for this exercise, proceed to the next
|
||||
exercise in this challenge.
|
||||
|
||||
---
|
||||
|
||||
## Exercise
|
||||
|
||||
### Add code to modify movement
|
||||
|
||||
Your goal is to develop a mini-game application. Currently, your mini-game has
|
||||
some basic gameplay capabilities! It terminates correctly, detects when the
|
||||
player consumes food, changes the player appearance, and displays more food.
|
||||
Now you want the food the player consumes to affect the player's ability to
|
||||
move.
|
||||
|
||||
### Specification
|
||||
|
||||
In this challenge exercise, you need to create a method that determines if the
|
||||
player has consumed the food that affects their movement. When the player
|
||||
consumes the food string with value `#####,` the appearance is updated to
|
||||
`(X_X)`. You'll add a feature to detect if the player appearance is `(X_X)`, and
|
||||
if so, temporarily prevent the player from moving.
|
||||
|
||||
You also want to add an optional feature that detects if the player appearance
|
||||
is `(^-^)` and if so, increase or decrease the right and left movement speeds
|
||||
by a value of `3` while that appearance is active. When the player state is
|
||||
`('-')`, you want the speed to return to normal. You want to make this feature
|
||||
optional since consuming food in this state requires more collision detection
|
||||
than you want to develop for now.
|
||||
|
||||
#### Check if the player should freeze
|
||||
|
||||
- Create a method that checks if the current player appearance is `(X_X)`
|
||||
- The method should return a value
|
||||
- Before allowing the user to move the character, call your method to determine the following:
|
||||
- Whether or not to use the existing method that freezes character movement
|
||||
- Make sure the character is only frozen temporarily and the player can still move afterwards
|
||||
|
||||
#### Add an option to increase player speed
|
||||
|
||||
- Modify the existing `Move` method to support an optional movement speed
|
||||
parameter
|
||||
- Use the parameter to increase or decrease right and left movement speed by `3`
|
||||
- Create a method that checks if the current player appearance is `(^-^)`
|
||||
- The method should return a value
|
||||
- Call your method to determine if `Move` should use the movement speed
|
||||
parameter
|
||||
|
||||
### Check your work
|
||||
|
||||
To validate that your code satisfies the specified requirements, complete the
|
||||
following steps:
|
||||
|
||||
Enable the optional parameters.
|
||||
|
||||
At the Terminal command prompt, press directional keys to move the player.
|
||||
|
||||
Move the player across the displayed food string.
|
||||
|
||||
Verify that a new food string is displayed.
|
||||
|
||||
Verify that the player appearance changes depending on which food string was
|
||||
consumed.
|
||||
|
||||
Verify that movement is temporarily stopped when the player appearance is
|
||||
`(X_X)`.
|
||||
|
||||
Verify that left and right movement is faster in the correct directions when
|
||||
the player appearance is `(^-^)`.
|
||||
|
||||
Press a nondirectional key to terminate the program.
|
||||
|
||||
Disable the optional movement speed parameter and rerun the app.
|
||||
|
||||
Verify that movement is normal when the player appearance is `(^-^)`.
|
||||
|
||||
Congratulations if you succeeded in this challenge!
|
||||
|
||||
---
|
||||
|
10
031_Challenge_mini_game/Project_minigame/Final/Final.csproj
Normal file
10
031_Challenge_mini_game/Project_minigame/Final/Final.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
144
031_Challenge_mini_game/Project_minigame/Final/Program.cs
Normal file
144
031_Challenge_mini_game/Project_minigame/Final/Program.cs
Normal file
@ -0,0 +1,144 @@
|
||||
using System;
|
||||
|
||||
Random random = new Random();
|
||||
Console.CursorVisible = false;
|
||||
int height = Console.WindowHeight - 1;
|
||||
int width = Console.WindowWidth - 5;
|
||||
bool should_exit = false;
|
||||
|
||||
// Console position of the player
|
||||
int player_x = 0;
|
||||
int player_y = 0;
|
||||
|
||||
// Console position of the food
|
||||
int food_x = 0;
|
||||
int food_y = 0;
|
||||
|
||||
// Available player and food strings
|
||||
string[] states = { "('-')", "(^-^)", "(X_X)" };
|
||||
string[] foods = { "@@@@@", "$$$$$", "#####" };
|
||||
|
||||
// Current player string displayed in the Console
|
||||
string player = states[0];
|
||||
|
||||
// Index of the current food
|
||||
int food = 0;
|
||||
|
||||
initialize_game();
|
||||
while (!should_exit) {
|
||||
if (terminal_resized()) {
|
||||
Console.Clear();
|
||||
Console.Write("Console was resized. Program exiting.");
|
||||
should_exit = true;
|
||||
} else {
|
||||
if (player_is_faster()) {
|
||||
move(1, false);
|
||||
} else if (player_is_sick()) {
|
||||
freeze_player();
|
||||
} else {
|
||||
move(otherKeysExit: false);
|
||||
}
|
||||
if (got_food()) {
|
||||
change_player();
|
||||
show_food();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the Terminal was resized
|
||||
bool terminal_resized() {
|
||||
return height != Console.WindowHeight - 1 ||
|
||||
width != Console.WindowWidth - 5;
|
||||
}
|
||||
|
||||
// Displays random food at a random location
|
||||
void show_food() {
|
||||
// Update food to a random index
|
||||
food = random.Next(0, foods.Length);
|
||||
|
||||
// Update food position to a random location
|
||||
food_x = random.Next(0, width - player.Length);
|
||||
food_y = random.Next(0, height - 1);
|
||||
|
||||
// Display the food at the location
|
||||
Console.SetCursorPosition(food_x, food_y);
|
||||
Console.Write(foods[food]);
|
||||
}
|
||||
|
||||
// Returns true if the player location matches the food location
|
||||
bool got_food() {
|
||||
return player_y == food_y && player_x == food_x;
|
||||
}
|
||||
|
||||
// Returns true if the player appearance represents a sick state
|
||||
bool player_is_sick() {
|
||||
return player.Equals(states[2]);
|
||||
}
|
||||
|
||||
// Returns true if the player appearance represents a fast state
|
||||
bool player_is_faster() {
|
||||
return player.Equals(states[1]);
|
||||
}
|
||||
|
||||
// Changes the player to match the food consumed
|
||||
void change_player() {
|
||||
player = states[food];
|
||||
Console.SetCursorPosition(player_x, player_y);
|
||||
Console.Write(player);
|
||||
}
|
||||
|
||||
// Temporarily stops the player from moving
|
||||
void freeze_player() {
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
player = states[0];
|
||||
}
|
||||
|
||||
// Reads directional input from the Console and moves the player
|
||||
void move(int speed = 1, bool otherKeysExit = false) {
|
||||
int last_x = player_x;
|
||||
int last_y = player_y;
|
||||
|
||||
switch (Console.ReadKey(true).Key) {
|
||||
case ConsoleKey.UpArrow:
|
||||
player_y--;
|
||||
break;
|
||||
case ConsoleKey.DownArrow:
|
||||
player_y++;
|
||||
break;
|
||||
case ConsoleKey.LeftArrow:
|
||||
player_x -= speed;
|
||||
break;
|
||||
case ConsoleKey.RightArrow:
|
||||
player_x += speed;
|
||||
break;
|
||||
case ConsoleKey.Escape:
|
||||
should_exit = true;
|
||||
break;
|
||||
default:
|
||||
// Exit if any other keys are pressed
|
||||
should_exit = otherKeysExit;
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear the characters at the previous position
|
||||
Console.SetCursorPosition(last_x, last_y);
|
||||
for (int i = 0; i < player.Length; i++) {
|
||||
Console.Write(" ");
|
||||
}
|
||||
|
||||
// Keep player position within the bounds of the Terminal window
|
||||
player_x = (player_x < 0) ? 0 : (player_x >= width ? width : player_x);
|
||||
player_y = (player_y < 0) ? 0 : (player_y >= height ? height : player_y);
|
||||
|
||||
// Draw the player at the new location
|
||||
Console.SetCursorPosition(player_x, player_y);
|
||||
Console.Write(player);
|
||||
}
|
||||
|
||||
// Clears the console, displays the food and player
|
||||
void initialize_game() {
|
||||
Console.Clear();
|
||||
show_food();
|
||||
Console.SetCursorPosition(0, 0);
|
||||
Console.Write(player);
|
||||
}
|
21
031_Challenge_mini_game/Project_minigame/LICENSE
Normal file
21
031_Challenge_mini_game/Project_minigame/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Microsoft Learning
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
109
031_Challenge_mini_game/Project_minigame/Starter/Program.cs
Normal file
109
031_Challenge_mini_game/Project_minigame/Starter/Program.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
|
||||
Random random = new Random();
|
||||
Console.CursorVisible = false;
|
||||
int height = Console.WindowHeight - 1;
|
||||
int width = Console.WindowWidth - 5;
|
||||
bool should_exit = false;
|
||||
|
||||
// Console position of the player
|
||||
int player_x = 0;
|
||||
int player_y = 0;
|
||||
|
||||
// Console position of the food
|
||||
int food_x = 0;
|
||||
int food_y = 0;
|
||||
|
||||
// Available player and food strings
|
||||
string[] states = { "('-')", "(^-^)", "(X_X)" };
|
||||
string[] foods = { "@@@@@", "$$$$$", "#####" };
|
||||
|
||||
// Current player string displayed in the Console
|
||||
string player = states[0];
|
||||
|
||||
// Index of the current food
|
||||
int food = 0;
|
||||
|
||||
initialize_game();
|
||||
while (!should_exit) {
|
||||
move();
|
||||
}
|
||||
|
||||
// Returns true if the Terminal was resized
|
||||
bool terminal_resized() {
|
||||
return height != Console.WindowHeight - 1 ||
|
||||
width != Console.WindowWidth - 5;
|
||||
}
|
||||
|
||||
// Displays random food at a random location
|
||||
void show_food() {
|
||||
// Update food to a random index
|
||||
food = random.Next(0, foods.Length);
|
||||
|
||||
// Update food position to a random location
|
||||
food_x = random.Next(0, width - player.Length);
|
||||
food_y = random.Next(0, height - 1);
|
||||
|
||||
// Display the food at the location
|
||||
Console.SetCursorPosition(food_x, food_y);
|
||||
Console.Write(foods[food]);
|
||||
}
|
||||
|
||||
// Changes the player to match the food consumed
|
||||
void change_player() {
|
||||
player = states[food];
|
||||
Console.SetCursorPosition(player_x, player_y);
|
||||
Console.Write(player);
|
||||
}
|
||||
|
||||
// Temporarily stops the player from moving
|
||||
void freeze_player() {
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
player = states[0];
|
||||
}
|
||||
|
||||
// Reads directional input from the Console and moves the player
|
||||
void move() {
|
||||
int last_x = player_x;
|
||||
int last_y = player_y;
|
||||
|
||||
switch (Console.ReadKey(true).Key) {
|
||||
case ConsoleKey.UpArrow:
|
||||
player_y--;
|
||||
break;
|
||||
case ConsoleKey.DownArrow:
|
||||
player_y++;
|
||||
break;
|
||||
case ConsoleKey.LeftArrow:
|
||||
player_x--;
|
||||
break;
|
||||
case ConsoleKey.RightArrow:
|
||||
player_x++;
|
||||
break;
|
||||
case ConsoleKey.Escape:
|
||||
should_exit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear the characters at the previous position
|
||||
Console.SetCursorPosition(last_x, last_y);
|
||||
for (int i = 0; i < player.Length; i++) {
|
||||
Console.Write(" ");
|
||||
}
|
||||
|
||||
// Keep player position within the bounds of the Terminal window
|
||||
player_x = (player_x < 0) ? 0 : (player_x >= width ? width : player_x);
|
||||
player_y = (player_y < 0) ? 0 : (player_y >= height ? height : player_y);
|
||||
|
||||
// Draw the player at the new location
|
||||
Console.SetCursorPosition(player_x, player_y);
|
||||
Console.Write(player);
|
||||
}
|
||||
|
||||
// Clears the console, displays the food and player
|
||||
void initialize_game() {
|
||||
Console.Clear();
|
||||
show_food();
|
||||
Console.SetCursorPosition(0, 0);
|
||||
Console.Write(player);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
@ -35,3 +35,4 @@ Following
|
||||
28. [Methods with parameters](./028_method_parameters/028_csharp.md)
|
||||
29. [Methods that return values](./029_return_value_method/029_csharp.md)
|
||||
30. [Guided project - Plan a Petting Zoo](./030_project_petting_zoo/030_csharp.md)
|
||||
31. [Challenge project - Create a mini-game](./031_Challenge_mini_game/031_csharp.md)
|
||||
|
Loading…
Reference in New Issue
Block a user