mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
Merge pull request #462 from yuriylsh/main
Implementing 15_Boxing in C#
This commit is contained in:
48
15_Boxing/csharp/AttackStrategy.cs
Normal file
48
15_Boxing/csharp/AttackStrategy.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
namespace Boxing;
|
||||||
|
|
||||||
|
public abstract class AttackStrategy
|
||||||
|
{
|
||||||
|
protected const int KnockoutDamageThreshold = 35;
|
||||||
|
protected readonly Boxer Other;
|
||||||
|
protected readonly Stack<Action> Work;
|
||||||
|
private readonly Action _notifyGameEnded;
|
||||||
|
|
||||||
|
public AttackStrategy(Boxer other, Stack<Action> work, Action notifyGameEnded)
|
||||||
|
{
|
||||||
|
Other = other;
|
||||||
|
Work = work;
|
||||||
|
_notifyGameEnded = notifyGameEnded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Attack()
|
||||||
|
{
|
||||||
|
var punch = GetPunch();
|
||||||
|
if (punch.IsBestPunch)
|
||||||
|
{
|
||||||
|
Other.DamageTaken += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Work.Push(punch.Punch switch
|
||||||
|
{
|
||||||
|
Punch.FullSwing => FullSwing,
|
||||||
|
Punch.Hook => Hook,
|
||||||
|
Punch.Uppercut => Uppercut,
|
||||||
|
_ => Jab
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract AttackPunch GetPunch();
|
||||||
|
protected abstract void FullSwing();
|
||||||
|
protected abstract void Hook();
|
||||||
|
protected abstract void Uppercut();
|
||||||
|
protected abstract void Jab();
|
||||||
|
|
||||||
|
protected void RegisterKnockout(string knockoutMessage)
|
||||||
|
{
|
||||||
|
Work.Clear();
|
||||||
|
_notifyGameEnded();
|
||||||
|
Console.WriteLine(knockoutMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected record AttackPunch(Punch Punch, bool IsBestPunch);
|
||||||
|
}
|
||||||
45
15_Boxing/csharp/Boxer.cs
Normal file
45
15_Boxing/csharp/Boxer.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
namespace Boxing;
|
||||||
|
|
||||||
|
public class Boxer
|
||||||
|
{
|
||||||
|
private int _wins;
|
||||||
|
|
||||||
|
private string Name { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public Punch BestPunch { get; set; }
|
||||||
|
|
||||||
|
public Punch Vulnerability { get; set; }
|
||||||
|
|
||||||
|
public void SetName(string prompt)
|
||||||
|
{
|
||||||
|
Console.WriteLine(prompt);
|
||||||
|
string? name;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
name = Console.ReadLine();
|
||||||
|
} while (string.IsNullOrWhiteSpace(name));
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int DamageTaken { get; set; }
|
||||||
|
|
||||||
|
public void ResetForNewRound() => DamageTaken = 0;
|
||||||
|
|
||||||
|
public void RecordWin() => _wins += 1;
|
||||||
|
|
||||||
|
public bool IsWinner => _wins >= 2;
|
||||||
|
|
||||||
|
public override string ToString() => Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Opponent : Boxer
|
||||||
|
{
|
||||||
|
public void SetRandomPunches()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
BestPunch = (Punch) GameUtils.Roll(4); // B1
|
||||||
|
Vulnerability = (Punch) GameUtils.Roll(4); // D1
|
||||||
|
} while (BestPunch == Vulnerability);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
15_Boxing/csharp/Boxing.csproj
Normal file
10
15_Boxing/csharp/Boxing.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
15_Boxing/csharp/Boxing.sln
Normal file
22
15_Boxing/csharp/Boxing.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}") = "Boxing", "Boxing.csproj", "{52A7BDE5-3085-4F58-AC57-2BA4E65212D8}"
|
||||||
|
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
|
||||||
|
{52A7BDE5-3085-4F58-AC57-2BA4E65212D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{52A7BDE5-3085-4F58-AC57-2BA4E65212D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{52A7BDE5-3085-4F58-AC57-2BA4E65212D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{52A7BDE5-3085-4F58-AC57-2BA4E65212D8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
115
15_Boxing/csharp/OpponentAttackStrategy.cs
Normal file
115
15_Boxing/csharp/OpponentAttackStrategy.cs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
using static Boxing.GameUtils;
|
||||||
|
using static System.Console;
|
||||||
|
|
||||||
|
namespace Boxing;
|
||||||
|
|
||||||
|
public class OpponentAttackStrategy : AttackStrategy
|
||||||
|
{
|
||||||
|
private readonly Opponent _opponent;
|
||||||
|
|
||||||
|
public OpponentAttackStrategy(Opponent opponent, Boxer player, Action notifyGameEnded, Stack<Action> work) : base(player, work, notifyGameEnded)
|
||||||
|
{
|
||||||
|
_opponent = opponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AttackPunch GetPunch()
|
||||||
|
{
|
||||||
|
var punch = (Punch)Roll(4);
|
||||||
|
return new AttackPunch(punch, punch == _opponent.BestPunch);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void FullSwing() // 720
|
||||||
|
{
|
||||||
|
Write($"{_opponent} TAKES A FULL SWING AND");
|
||||||
|
if (Other.Vulnerability == Punch.FullSwing)
|
||||||
|
{
|
||||||
|
ScoreFullSwing();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (RollSatisfies(60, x => x < 30))
|
||||||
|
{
|
||||||
|
WriteLine(" IT'S BLOCKED!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScoreFullSwing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScoreFullSwing()
|
||||||
|
{
|
||||||
|
WriteLine(" POW!!!!! HE HITS HIM RIGHT IN THE FACE!");
|
||||||
|
if (Other.DamageTaken > KnockoutDamageThreshold)
|
||||||
|
{
|
||||||
|
Work.Push(RegisterOtherKnockedOut);
|
||||||
|
}
|
||||||
|
Other.DamageTaken += 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Hook() // 810
|
||||||
|
{
|
||||||
|
Write($"{_opponent} GETS {Other} IN THE JAW (OUCH!)");
|
||||||
|
Other.DamageTaken += 7;
|
||||||
|
WriteLine("....AND AGAIN!");
|
||||||
|
Other.DamageTaken += 5;
|
||||||
|
if (Other.DamageTaken > KnockoutDamageThreshold)
|
||||||
|
{
|
||||||
|
Work.Push(RegisterOtherKnockedOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Uppercut() // 860
|
||||||
|
{
|
||||||
|
Write($"{Other} IS ATTACKED BY AN UPPERCUT (OH,OH)...");
|
||||||
|
if (Other.Vulnerability == Punch.Uppercut)
|
||||||
|
{
|
||||||
|
ScoreUppercut();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (RollSatisfies(200, x => x > 75))
|
||||||
|
{
|
||||||
|
WriteLine($" BLOCKS AND HITS {_opponent} WITH A HOOK.");
|
||||||
|
_opponent.DamageTaken += 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScoreUppercut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScoreUppercut()
|
||||||
|
{
|
||||||
|
WriteLine($"AND {_opponent} CONNECTS...");
|
||||||
|
Other.DamageTaken += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Jab() // 640
|
||||||
|
{
|
||||||
|
Write($"{_opponent} JABS AND ");
|
||||||
|
if (Other.Vulnerability == Punch.Jab)
|
||||||
|
{
|
||||||
|
ScoreJab();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (RollSatisfies(7, x => x > 4))
|
||||||
|
{
|
||||||
|
WriteLine("BLOOD SPILLS !!!");
|
||||||
|
ScoreJab();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteLine("IT'S BLOCKED!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScoreJab() => Other.DamageTaken += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterOtherKnockedOut()
|
||||||
|
=> RegisterKnockout($"{Other} IS KNOCKED COLD AND {_opponent} IS THE WINNER AND CHAMP!");
|
||||||
|
}
|
||||||
121
15_Boxing/csharp/PlayerAttackStrategy.cs
Normal file
121
15_Boxing/csharp/PlayerAttackStrategy.cs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
using static Boxing.GameUtils;
|
||||||
|
using static System.Console;
|
||||||
|
namespace Boxing;
|
||||||
|
|
||||||
|
public class PlayerAttackStrategy : AttackStrategy
|
||||||
|
{
|
||||||
|
private readonly Boxer _player;
|
||||||
|
|
||||||
|
public PlayerAttackStrategy(Boxer player, Opponent opponent, Action notifyGameEnded, Stack<Action> work)
|
||||||
|
: base(opponent, work, notifyGameEnded) => _player = player;
|
||||||
|
|
||||||
|
protected override AttackPunch GetPunch()
|
||||||
|
{
|
||||||
|
var punch = GameUtils.GetPunch($"{_player}'S PUNCH");
|
||||||
|
return new AttackPunch(punch, punch == _player.BestPunch);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void FullSwing() // 340
|
||||||
|
{
|
||||||
|
Write($"{_player} SWINGS AND ");
|
||||||
|
if (Other.Vulnerability == Punch.FullSwing)
|
||||||
|
{
|
||||||
|
ScoreFullSwing();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (RollSatisfies(30, x => x < 10))
|
||||||
|
{
|
||||||
|
ScoreFullSwing();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteLine("HE MISSES");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScoreFullSwing()
|
||||||
|
{
|
||||||
|
WriteLine("HE CONNECTS!");
|
||||||
|
if (Other.DamageTaken > KnockoutDamageThreshold)
|
||||||
|
{
|
||||||
|
Work.Push(() => RegisterKnockout($"{Other} IS KNOCKED COLD AND {_player} IS THE WINNER AND CHAMP!"));
|
||||||
|
}
|
||||||
|
Other.DamageTaken += 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Uppercut() // 520
|
||||||
|
{
|
||||||
|
Write($"{_player} TRIES AN UPPERCUT ");
|
||||||
|
if (Other.Vulnerability == Punch.Uppercut)
|
||||||
|
{
|
||||||
|
ScoreUpperCut();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (RollSatisfies(100, x => x < 51))
|
||||||
|
{
|
||||||
|
ScoreUpperCut();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteLine("AND IT'S BLOCKED (LUCKY BLOCK!)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScoreUpperCut()
|
||||||
|
{
|
||||||
|
WriteLine("AND HE CONNECTS!");
|
||||||
|
Other.DamageTaken += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Hook() // 450
|
||||||
|
{
|
||||||
|
Write($"{_player} GIVES THE HOOK... ");
|
||||||
|
if (Other.Vulnerability == Punch.Hook)
|
||||||
|
{
|
||||||
|
ScoreHookOnOpponent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (RollSatisfies(2, x => x == 1))
|
||||||
|
{
|
||||||
|
WriteLine("BUT IT'S BLOCKED!!!!!!!!!!!!!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScoreHookOnOpponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScoreHookOnOpponent()
|
||||||
|
{
|
||||||
|
WriteLine("CONNECTS...");
|
||||||
|
Other.DamageTaken += 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Jab()
|
||||||
|
{
|
||||||
|
WriteLine($"{_player} JABS AT {Other}'S HEAD");
|
||||||
|
if (Other.Vulnerability == Punch.Jab)
|
||||||
|
{
|
||||||
|
ScoreJabOnOpponent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (RollSatisfies(8, x => x < 4))
|
||||||
|
{
|
||||||
|
WriteLine("IT'S BLOCKED.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScoreJabOnOpponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScoreJabOnOpponent() => Other.DamageTaken += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
15_Boxing/csharp/Program.cs
Normal file
29
15_Boxing/csharp/Program.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using Boxing;
|
||||||
|
using static Boxing.GameUtils;
|
||||||
|
using static System.Console;
|
||||||
|
|
||||||
|
WriteLine(new string('\t', 33) + "BOXING");
|
||||||
|
WriteLine(new string('\t', 15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
|
||||||
|
WriteLine("{0}{0}{0}BOXING OLYMPIC STYLE (3 ROUNDS -- 2 OUT OF 3 WINS){0}", Environment.NewLine);
|
||||||
|
|
||||||
|
var opponent = new Opponent();
|
||||||
|
opponent.SetName("WHAT IS YOUR OPPONENT'S NAME"); // J$
|
||||||
|
var player = new Boxer();
|
||||||
|
player.SetName("INPUT YOUR MAN'S NAME"); // L$
|
||||||
|
|
||||||
|
PrintPunchDescription();
|
||||||
|
player.BestPunch = GetPunch("WHAT IS YOUR MANS BEST"); // B
|
||||||
|
player.Vulnerability = GetPunch("WHAT IS HIS VULNERABILITY"); // D
|
||||||
|
opponent.SetRandomPunches();
|
||||||
|
WriteLine($"{opponent}'S ADVANTAGE IS {opponent.BestPunch.ToFriendlyString()} AND VULNERABILITY IS SECRET.");
|
||||||
|
|
||||||
|
|
||||||
|
for (var i = 1; i <= 3; i ++) // R
|
||||||
|
{
|
||||||
|
var round = new Round(player, opponent, i);
|
||||||
|
round.Start();
|
||||||
|
round.CheckOpponentWin();
|
||||||
|
round.CheckPlayerWin();
|
||||||
|
if (round.GameEnded) break;
|
||||||
|
}
|
||||||
|
WriteLine("{0}{0}AND NOW GOODBYE FROM THE OLYMPIC ARENA.{0}", Environment.NewLine);
|
||||||
9
15_Boxing/csharp/Punch.cs
Normal file
9
15_Boxing/csharp/Punch.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Boxing;
|
||||||
|
|
||||||
|
public enum Punch
|
||||||
|
{
|
||||||
|
FullSwing = 1,
|
||||||
|
Hook = 2,
|
||||||
|
Uppercut = 3,
|
||||||
|
Jab = 4
|
||||||
|
}
|
||||||
96
15_Boxing/csharp/Round.cs
Normal file
96
15_Boxing/csharp/Round.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
namespace Boxing;
|
||||||
|
|
||||||
|
class Round
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly Boxer _player;
|
||||||
|
private readonly Boxer _opponent;
|
||||||
|
private readonly int _round;
|
||||||
|
private Stack<Action> _work = new();
|
||||||
|
private readonly PlayerAttackStrategy _playerAttackStrategy;
|
||||||
|
private readonly OpponentAttackStrategy _opponentAttackStrategy;
|
||||||
|
|
||||||
|
public bool GameEnded { get; private set; }
|
||||||
|
|
||||||
|
public Round(Boxer player, Opponent opponent, int round)
|
||||||
|
{
|
||||||
|
_player = player;
|
||||||
|
_opponent = opponent;
|
||||||
|
_round = round;
|
||||||
|
_work.Push(ResetPlayers);
|
||||||
|
_work.Push(CheckOpponentWin);
|
||||||
|
_work.Push(CheckPlayerWin);
|
||||||
|
|
||||||
|
void NotifyGameEnded() => GameEnded = true;
|
||||||
|
_playerAttackStrategy = new PlayerAttackStrategy(player, opponent, NotifyGameEnded, _work);
|
||||||
|
_opponentAttackStrategy = new OpponentAttackStrategy(opponent, player, NotifyGameEnded, _work);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
while (_work.Count > 0)
|
||||||
|
{
|
||||||
|
var action = _work.Pop();
|
||||||
|
// This delay does not exist in the VB code but it makes a bit easier to follow the game.
|
||||||
|
// I assume the computers at the time were slow enough
|
||||||
|
// so that they did not need this delay...
|
||||||
|
Thread.Sleep(300);
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckOpponentWin()
|
||||||
|
{
|
||||||
|
if (_opponent.IsWinner)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{_opponent} WINS (NICE GOING, {_opponent}).");
|
||||||
|
GameEnded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckPlayerWin()
|
||||||
|
{
|
||||||
|
if (_player.IsWinner)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{_player} AMAZINGLY WINS!!");
|
||||||
|
GameEnded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetPlayers()
|
||||||
|
{
|
||||||
|
_player.ResetForNewRound();
|
||||||
|
_opponent.ResetForNewRound();
|
||||||
|
_work.Push(RoundBegins);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RoundBegins()
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine($"ROUND {_round} BEGINS...");
|
||||||
|
_work.Push(CheckRoundWinner);
|
||||||
|
for (var i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
_work.Push(DecideWhoAttacks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckRoundWinner()
|
||||||
|
{
|
||||||
|
if (_opponent.DamageTaken > _player.DamageTaken)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{_player} WINS ROUND {_round}");
|
||||||
|
_player.RecordWin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{_opponent} WINS ROUND {_round}");
|
||||||
|
_opponent.RecordWin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DecideWhoAttacks()
|
||||||
|
{
|
||||||
|
_work.Push( GameUtils.RollSatisfies(10, x => x > 5) ? _opponentAttackStrategy.Attack : _playerAttackStrategy.Attack );
|
||||||
|
}
|
||||||
|
}
|
||||||
35
15_Boxing/csharp/Utils.cs
Normal file
35
15_Boxing/csharp/Utils.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
namespace Boxing;
|
||||||
|
public static class GameUtils
|
||||||
|
{
|
||||||
|
private static readonly Random Rnd = new((int) DateTime.UtcNow.Ticks);
|
||||||
|
public static void PrintPunchDescription() =>
|
||||||
|
Console.WriteLine($"DIFFERENT PUNCHES ARE: {PunchDesc(Punch.FullSwing)}; {PunchDesc(Punch.Hook)}; {PunchDesc(Punch.Uppercut)}; {PunchDesc(Punch.Jab)}.");
|
||||||
|
|
||||||
|
private static string PunchDesc(Punch punch) => $"({(int)punch}) {punch.ToFriendlyString()}";
|
||||||
|
|
||||||
|
public static Punch GetPunch(string prompt)
|
||||||
|
{
|
||||||
|
Console.WriteLine(prompt);
|
||||||
|
Punch result;
|
||||||
|
while (!Enum.TryParse(Console.ReadLine(), out result) || !Enum.IsDefined(typeof(Punch), result))
|
||||||
|
{
|
||||||
|
PrintPunchDescription();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Func<int, int> Roll { get; } = upperLimit => (int) (upperLimit * Rnd.NextSingle()) + 1;
|
||||||
|
|
||||||
|
public static bool RollSatisfies(int upperLimit, Predicate<int> predicate) => predicate(Roll(upperLimit));
|
||||||
|
|
||||||
|
public static string ToFriendlyString(this Punch punch)
|
||||||
|
=> punch switch
|
||||||
|
{
|
||||||
|
Punch.FullSwing => "FULL SWING",
|
||||||
|
Punch.Hook => "HOOK",
|
||||||
|
Punch.Uppercut => "UPPERCUT",
|
||||||
|
Punch.Jab => "JAB",
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(punch), punch, null)
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user