mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-30 06:31:46 -08:00
16
.gitignore
vendored
16
.gitignore
vendored
@@ -1,12 +1,4 @@
|
||||
################################################################################
|
||||
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
|
||||
################################################################################
|
||||
|
||||
/01 Acey Ducey/csharp/obj
|
||||
/47 Hi-Lo/csharp/obj
|
||||
/.vs
|
||||
/33 Dice/csharp/obj
|
||||
/01 Acey Ducey/csharp/.vs/AceyDucey
|
||||
/01 Acey Ducey/csharp/bin/Debug/netcoreapp3.1
|
||||
/33 Dice/csharp/bin/Debug/net5.0
|
||||
/basic-computer-games-dot-net/.vs/basic-computer-games-dot-net/v16
|
||||
/**/obj/
|
||||
/**/.vs/
|
||||
/**/bin/
|
||||
/**/*.user
|
||||
|
||||
121
05 Bagels/csharp/BagelNumber.cs
Normal file
121
05 Bagels/csharp/BagelNumber.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace BasicComputerGames.Bagels
|
||||
{
|
||||
public enum BagelValidation
|
||||
{
|
||||
Valid,
|
||||
WrongLength,
|
||||
NotUnique,
|
||||
NonDigit
|
||||
};
|
||||
public class BagelNumber
|
||||
{
|
||||
private static readonly Random Rnd = new Random();
|
||||
|
||||
private readonly int[] _digits;
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Join('-', _digits);
|
||||
}
|
||||
|
||||
public static BagelNumber CreateSecretNumber(int numDigits)
|
||||
{
|
||||
if (numDigits < 3 || numDigits > 9)
|
||||
throw new ArgumentOutOfRangeException(nameof(numDigits),
|
||||
"Number of digits must be between 3 and 9, inclusive");
|
||||
|
||||
var digits = GetDigits(numDigits);
|
||||
return new BagelNumber(digits);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static BagelValidation IsValid(string number, int length)
|
||||
{
|
||||
if (number.Length != length)
|
||||
return BagelValidation.WrongLength;
|
||||
|
||||
if (!number.All(Char.IsDigit))
|
||||
return BagelValidation.NonDigit;
|
||||
|
||||
if (new HashSet<char>(number).Count != length)
|
||||
return BagelValidation.NotUnique;
|
||||
|
||||
return BagelValidation.Valid;
|
||||
}
|
||||
|
||||
public BagelNumber(string number)
|
||||
{
|
||||
if (number.Any(d => !Char.IsDigit(d)))
|
||||
throw new ArgumentException("Number must be all unique digits", nameof(number));
|
||||
|
||||
_digits = number.Select(d => d - '0').ToArray();
|
||||
}
|
||||
|
||||
//public BagelNumber(long number)
|
||||
//{
|
||||
// var digits = new List<int>();
|
||||
// if (number >= 1E10)
|
||||
// throw new ArgumentOutOfRangeException(nameof(number), "Number can be no more than 9 digits");
|
||||
|
||||
// while (number > 0)
|
||||
// {
|
||||
// long num = number / 10;
|
||||
// int digit = (int)(number - (num * 10));
|
||||
// number = num;
|
||||
// digits.Add(digit);
|
||||
// }
|
||||
|
||||
// _digits = digits.ToArray();
|
||||
//}
|
||||
|
||||
public BagelNumber(int[] digits)
|
||||
{
|
||||
_digits = digits;
|
||||
}
|
||||
|
||||
private static int[] GetDigits(int numDigits)
|
||||
{
|
||||
int[] digits = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
Shuffle(digits);
|
||||
return digits.Take(numDigits).ToArray();
|
||||
|
||||
}
|
||||
|
||||
private static void Shuffle(int[] digits)
|
||||
{
|
||||
for (int i = digits.Length - 1; i > 0; --i)
|
||||
{
|
||||
int pos = Rnd.Next(i);
|
||||
var t = digits[i];
|
||||
digits[i] = digits[pos];
|
||||
digits[pos] = t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public (int pico, int fermi) CompareTo(BagelNumber other)
|
||||
{
|
||||
int pico = 0;
|
||||
int fermi = 0;
|
||||
for (int i = 0; i < _digits.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < other._digits.Length; j++)
|
||||
{
|
||||
if (_digits[i] == other._digits[j])
|
||||
{
|
||||
if (i == j)
|
||||
++fermi;
|
||||
else
|
||||
++pico;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (pico, fermi);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
05 Bagels/csharp/Bagels.csproj
Normal file
13
05 Bagels/csharp/Bagels.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>BasicComputerGames.Bagels</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="TextUtil.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
124
05 Bagels/csharp/Game.cs
Normal file
124
05 Bagels/csharp/Game.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace BasicComputerGames.Bagels
|
||||
{
|
||||
public class Game : GameBase
|
||||
{
|
||||
public void GameLoop()
|
||||
{
|
||||
DisplayIntroText();
|
||||
int points = 0;
|
||||
do
|
||||
{
|
||||
var result =PlayRound();
|
||||
if (result)
|
||||
++points;
|
||||
} while (TryAgain());
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"A {points} point Bagels buff!!");
|
||||
Console.WriteLine("Hope you had fun. Bye.");
|
||||
}
|
||||
|
||||
private const int Length = 3;
|
||||
private const int MaxGuesses = 20;
|
||||
|
||||
private bool PlayRound()
|
||||
{
|
||||
var secret = BagelNumber.CreateSecretNumber(Length);
|
||||
Console.WriteLine("O.K. I have a number in mind.");
|
||||
for (int guessNo = 1; guessNo <= MaxGuesses; ++guessNo)
|
||||
{
|
||||
string strGuess;
|
||||
BagelValidation isValid;
|
||||
do
|
||||
{
|
||||
Console.WriteLine($"Guess #{guessNo}");
|
||||
strGuess = Console.ReadLine();
|
||||
isValid = BagelNumber.IsValid(strGuess, Length);
|
||||
PrintError(isValid);
|
||||
} while (isValid != BagelValidation.Valid);
|
||||
|
||||
var guess = new BagelNumber(strGuess);
|
||||
var fermi = 0;
|
||||
var pico = 0;
|
||||
(pico, fermi) = secret.CompareTo(guess);
|
||||
if(pico + fermi == 0)
|
||||
Console.Write("BAGELS!");
|
||||
else if (fermi == Length)
|
||||
{
|
||||
Console.WriteLine("You got it!");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintList("Pico ", pico);
|
||||
PrintList("Fermi ", fermi);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("Oh, well.");
|
||||
Console.WriteLine($"That's {MaxGuesses} guesses. My Number was {secret}");
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private void PrintError(BagelValidation isValid)
|
||||
{
|
||||
switch (isValid)
|
||||
{
|
||||
case BagelValidation.NonDigit:
|
||||
Console.WriteLine("What?");
|
||||
break;
|
||||
|
||||
case BagelValidation.NotUnique:
|
||||
Console.WriteLine("Oh, I forgot to tell you that the number I have in mind has no two digits the same.");
|
||||
break;
|
||||
|
||||
case BagelValidation.WrongLength:
|
||||
Console.WriteLine($"Try guessing a {Length}-digit number.");
|
||||
break;
|
||||
|
||||
case BagelValidation.Valid:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void PrintList(string msg, int repeat)
|
||||
{
|
||||
for(int i=0; i<repeat; ++i)
|
||||
Console.Write(msg);
|
||||
}
|
||||
|
||||
private void DisplayIntroText()
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine("Bagels");
|
||||
Console.WriteLine("Creating Computing, Morristown, New Jersey.");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine(
|
||||
"Original code author unknow but suspected to be from Lawrence Hall of Science, U.C. Berkley");
|
||||
Console.WriteLine("Originally published in 1978 in the book 'Basic Computer Games' by David Ahl.");
|
||||
Console.WriteLine("Modernized and converted to C# in 2021 by James Curran (noveltheory.com).");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
Console.WriteLine("I am thinking of a three-digit number. Try to guess");
|
||||
Console.WriteLine("my number and I will give you clues as follows:");
|
||||
Console.WriteLine(" pico - One digit correct but in the wrong position");
|
||||
Console.WriteLine(" fermi - One digit correct and in the right position");
|
||||
Console.WriteLine(" bagels - No digits correct");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine("Press any key start the game.");
|
||||
Console.ReadKey(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
05 Bagels/csharp/GameBase.cs
Normal file
39
05 Bagels/csharp/GameBase.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
|
||||
namespace BasicComputerGames.Bagels
|
||||
{
|
||||
public class GameBase
|
||||
{
|
||||
protected Random Rnd { get; } = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// Prompt the player to try again, and wait for them to press Y or N.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the player wants to try again, false if they have finished playing.</returns>
|
||||
protected bool TryAgain()
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("Would you like to try again? (Press 'Y' for yes or 'N' for no)");
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.Write("> ");
|
||||
|
||||
char pressedKey;
|
||||
// Keep looping until we get a recognised input
|
||||
do
|
||||
{
|
||||
// Read a key, don't display it on screen
|
||||
ConsoleKeyInfo key = Console.ReadKey(true);
|
||||
// Convert to upper-case so we don't need to care about capitalisation
|
||||
pressedKey = Char.ToUpper(key.KeyChar);
|
||||
// Is this a key we recognise? If not, keep looping
|
||||
} while (pressedKey != 'Y' && pressedKey != 'N');
|
||||
// Display the result on the screen
|
||||
Console.WriteLine(pressedKey);
|
||||
|
||||
// Return true if the player pressed 'Y', false for anything else.
|
||||
return (pressedKey == 'Y');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
14
05 Bagels/csharp/Program.cs
Normal file
14
05 Bagels/csharp/Program.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace BasicComputerGames.Bagels
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Create an instance of our main Game class
|
||||
var game = new Game();
|
||||
|
||||
// Call its GameLoop function. This will play the game endlessly in a loop until the player chooses to quit.
|
||||
game.GameLoop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{04298E
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "hi-lo", "..\47 Hi-Lo\csharp\hi-lo.csproj", "{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05 Bagels", "05 Bagels", "{946C0E7C-8A83-4C7F-9959-1AF0AEF4A027}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{91DA95EE-DD42-4AEC-A886-07F834061BFC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bagels", "..\05 Bagels\csharp\Bagels.csproj", "{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -39,6 +45,10 @@ Global
|
||||
{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -50,6 +60,8 @@ Global
|
||||
{26D086DE-0BBD-4A18-AC63-2476A7DB52D3} = {AC302ACD-C3B2-460D-BA1A-0A511C36A848}
|
||||
{04298EE8-0EF3-475C-9427-E04C267BBEFB} = {A2BC8E4A-B977-46A6-B897-7E675ACB96F0}
|
||||
{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6} = {04298EE8-0EF3-475C-9427-E04C267BBEFB}
|
||||
{91DA95EE-DD42-4AEC-A886-07F834061BFC} = {946C0E7C-8A83-4C7F-9959-1AF0AEF4A027}
|
||||
{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A} = {91DA95EE-DD42-4AEC-A886-07F834061BFC}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {703D538E-7F20-4DD0-A3DD-7BBE36AC82AF}
|
||||
|
||||
Reference in New Issue
Block a user