mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
C# implementation of Bullseye
This commit is contained in:
10
18_Bullseye/csharp/Bullseye.csproj
Normal file
10
18_Bullseye/csharp/Bullseye.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>
|
||||
22
18_Bullseye/csharp/Bullseye.sln
Normal file
22
18_Bullseye/csharp/Bullseye.sln
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30114.105
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bullseye", "Bullseye.csproj", "{04C164DB-594F-41C4-BC0E-0A203A5536C7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{04C164DB-594F-41C4-BC0E-0A203A5536C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{04C164DB-594F-41C4-BC0E-0A203A5536C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{04C164DB-594F-41C4-BC0E-0A203A5536C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{04C164DB-594F-41C4-BC0E-0A203A5536C7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
237
18_Bullseye/csharp/BullseyeGame.cs
Normal file
237
18_Bullseye/csharp/BullseyeGame.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
namespace Bullseye
|
||||
{
|
||||
/// <summary>
|
||||
/// Class encompassing the game
|
||||
/// </summary>
|
||||
public class BullseyeGame
|
||||
{
|
||||
private readonly List<Player> _players;
|
||||
|
||||
// define a constant for the winning score so that it is
|
||||
// easy to change again in the future
|
||||
private const int WinningScore = 200;
|
||||
|
||||
public BullseyeGame()
|
||||
{
|
||||
// create the initial list of players; list is empty, but
|
||||
// the setup of the game will add items to this list
|
||||
_players = new List<Player>();
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
PrintIntroduction();
|
||||
|
||||
SetupGame();
|
||||
|
||||
PlayGame();
|
||||
|
||||
PrintResults();
|
||||
}
|
||||
|
||||
private void SetupGame()
|
||||
{
|
||||
// First, allow the user to enter how many players are going
|
||||
// to play. This could be weird if the user enters negative
|
||||
// numbers, words, or too many players, so there are some
|
||||
// extra checks on the input to make sure the user didn't do
|
||||
// anything too crazy. Loop until the user enters valid input.
|
||||
bool validPlayerCount;
|
||||
int playerCount;
|
||||
do
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.Write("HOW MANY PLAYERS? ");
|
||||
string? input = Console.ReadLine();
|
||||
|
||||
// assume the user has entered something incorrect - the
|
||||
// next steps will validate the input
|
||||
validPlayerCount = false;
|
||||
|
||||
if (Int32.TryParse(input, out playerCount))
|
||||
{
|
||||
if (playerCount > 0 && playerCount <= 20)
|
||||
{
|
||||
validPlayerCount = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("YOU MUST ENTER A NUMBER BETWEEN 1 AND 20!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("YOU MUST ENTER A NUMBER");
|
||||
}
|
||||
|
||||
}
|
||||
while (!validPlayerCount);
|
||||
|
||||
// Next, allow the user to enter names for the players; as each
|
||||
// name is entered, create a Player object to track the name
|
||||
// and their score, and save the object to the list in this class
|
||||
// so the rest of the game has access to the set of players
|
||||
for (int i = 0; i < playerCount; i++)
|
||||
{
|
||||
string? playerName = String.Empty;
|
||||
do
|
||||
{
|
||||
Console.Write($"NAME OF PLAYER #{i+1}? ");
|
||||
playerName = Console.ReadLine();
|
||||
|
||||
// names can be any sort of text, so allow whatever the user
|
||||
// enters as long as it isn't a blank space
|
||||
}
|
||||
while (String.IsNullOrWhiteSpace(playerName));
|
||||
|
||||
_players.Add(new Player(playerName));
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayGame()
|
||||
{
|
||||
Random random = new Random(DateTime.Now.Millisecond);
|
||||
|
||||
int round = 0;
|
||||
bool isOver = false;
|
||||
do
|
||||
{
|
||||
// starting a new round, increment the counter
|
||||
round++;
|
||||
Console.WriteLine($"ROUND {round}");
|
||||
Console.WriteLine("--------------");
|
||||
|
||||
foreach (Player player in _players)
|
||||
{
|
||||
// ask the user how they want to throw
|
||||
Console.Write($"{player.Name.ToUpper()}'S THROW: ");
|
||||
string? input = Console.ReadLine();
|
||||
|
||||
// based on the input, figure out the probabilities
|
||||
int[] probabilities;
|
||||
switch (input)
|
||||
{
|
||||
case "1":
|
||||
{
|
||||
probabilities = new int[] { 65, 55, 50, 50 };
|
||||
break;
|
||||
}
|
||||
case "2":
|
||||
{
|
||||
probabilities = new int[] { 99, 77, 43, 1 };
|
||||
break;
|
||||
}
|
||||
case "3":
|
||||
{
|
||||
probabilities = new int[] { 95, 75, 45, 5 };
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// in case the user types something bad, pretend it's
|
||||
// as if they tripped over themselves while throwing
|
||||
// the dart - they'll either hit a bullseye or completely
|
||||
// miss
|
||||
probabilities = new int[] { 95, 95, 95, 95 };
|
||||
Console.Write("TRIP! ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Next() returns a number in the range: min <= num < max, so specify 101
|
||||
// as the maximum so that 100 is a number that could be returned
|
||||
int chance = random.Next(0, 101);
|
||||
|
||||
if (chance > probabilities[0])
|
||||
{
|
||||
player.Score += 40;
|
||||
Console.WriteLine("BULLSEYE!! 40 POINTS!");
|
||||
}
|
||||
else if (chance > probabilities[1])
|
||||
{
|
||||
player.Score += 30;
|
||||
Console.WriteLine("30-POINT ZONE!");
|
||||
}
|
||||
else if (chance > probabilities[2])
|
||||
{
|
||||
player.Score += 20;
|
||||
Console.WriteLine("20-POINT ZONE");
|
||||
}
|
||||
else if (chance > probabilities[3])
|
||||
{
|
||||
player.Score += 10;
|
||||
Console.WriteLine("WHEW! 10 POINTS.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// missed it
|
||||
Console.WriteLine("MISSED THE TARGET! TOO BAD.");
|
||||
}
|
||||
|
||||
// check to see if the player has won - if they have, then
|
||||
// break out of the loops
|
||||
if (player.Score > WinningScore)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("WE HAVE A WINNER!!");
|
||||
Console.WriteLine($"{player.Name.ToUpper()} SCORED {player.Score} POINTS.");
|
||||
Console.WriteLine();
|
||||
|
||||
isOver = true; // out of the do/while round loop
|
||||
break; // out of the foreach (player) loop
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
while (!isOver);
|
||||
}
|
||||
|
||||
private void PrintResults()
|
||||
{
|
||||
// For bragging rights, print out all the scores, but sort them
|
||||
// by who had the highest score
|
||||
var sorted = _players.OrderByDescending(p => p.Score);
|
||||
|
||||
// padding is used to get things to line up nicely - the results
|
||||
// should look something like:
|
||||
// PLAYER SCORE
|
||||
// Bravo 210
|
||||
// Charlie 15
|
||||
// Alpha 1
|
||||
Console.WriteLine("PLAYER SCORE");
|
||||
foreach (var player in sorted)
|
||||
{
|
||||
Console.WriteLine($"{player.Name.PadRight(12)} {player.Score.ToString().PadLeft(5)}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("THANKS FOR THE GAME.");
|
||||
}
|
||||
|
||||
private void PrintIntroduction()
|
||||
{
|
||||
Console.WriteLine(Title);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(Introduction);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(Operations);
|
||||
}
|
||||
|
||||
private const string Title = @"
|
||||
BULLSEYE
|
||||
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY";
|
||||
|
||||
private const string Introduction = @"
|
||||
IN THIS GAME, UP TO 20 PLAYERS THROW DARTS AT A TARGET
|
||||
WITH 10, 20, 30, AND 40 POINT ZONES. THE OBJECTIVE IS
|
||||
TO GET 200 POINTS.";
|
||||
|
||||
private const string Operations = @"
|
||||
THROW DESCRIPTION PROBABLE SCORE
|
||||
1 FAST OVERARM BULLSEYE OR COMPLETE MISS
|
||||
2 CONTROLLED OVERARM 10, 20, OR 30 POINTS
|
||||
3 UNDERARM ANYTHING";
|
||||
}
|
||||
}
|
||||
28
18_Bullseye/csharp/Player.cs
Normal file
28
18_Bullseye/csharp/Player.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace Bullseye
|
||||
{
|
||||
/// <summary>
|
||||
/// Object to track the name and score of a player
|
||||
/// </summary>
|
||||
public class Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a play with the given name
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the player</param>
|
||||
public Player(string name)
|
||||
{
|
||||
Name = name;
|
||||
Score = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the player
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current score of the player
|
||||
/// </summary>
|
||||
public int Score { get; set; }
|
||||
}
|
||||
}
|
||||
14
18_Bullseye/csharp/Program.cs
Normal file
14
18_Bullseye/csharp/Program.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Bullseye
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
// Entry point to the application; create an instance of the
|
||||
// game class and call Run()
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
new BullseyeGame().Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user