Removed spaces from top-level directory names.

Spaces tend to cause annoyances in a Unix-style shell environment.
This change fixes that.
This commit is contained in:
Chris Reuter
2021-11-21 18:30:21 -05:00
parent df2e7426eb
commit d26dbf036a
1725 changed files with 0 additions and 0 deletions

7
08_Batnum/README.md Normal file
View File

@@ -0,0 +1,7 @@
### Batnum
As published in Basic Computer Games (1978)
https://www.atariarchives.org/basicgames/showpage.php?page=14
Downloaded from Vintage Basic at
http://www.vintage-basic.net/games.html

90
08_Batnum/batnum.bas Normal file
View File

@@ -0,0 +1,90 @@
10 PRINT TAB(33);"BATNUM"
20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
30 PRINT:PRINT:PRINT
110 PRINT "THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE"
120 PRINT "COMPUTER IS YOUR OPPONENT."
130 PRINT
140 PRINT "THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU"
150 PRINT "AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE."
160 PRINT "WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR"
170 PRINT "NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS."
180 PRINT "DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME."
190 PRINT "ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING."
200 PRINT
210 GOTO 330
220 FOR I=1 TO 10
230 PRINT
240 NEXT I
330 INPUT "ENTER PILE SIZE";N
350 IF N>=1 THEN 370
360 GOTO 330
370 IF N<>INT(N) THEN 220
380 IF N<1 THEN 220
390 INPUT "ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ";M
410 IF M=1 THEN 430
420 IF M<>2 THEN 390
430 INPUT "ENTER MIN AND MAX ";A,B
450 IF A>B THEN 430
460 IF A<1 THEN 430
470 IF A<>INT(A) THEN 430
480 IF B<>INT(B) THEN 430
490 INPUT "ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ";S
500 PRINT:PRINT
510 IF S=1 THEN 530
520 IF S<>2 THEN 490
530 C=A+B
540 IF S=2 THEN 570
550 GOSUB 600
560 IF W=1 THEN 220
570 GOSUB 810
580 IF W=1 THEN 220
590 GOTO 550
600 Q=N
610 IF M=1 THEN 630
620 Q=Q-1
630 IF M=1 THEN 680
640 IF N>A THEN 720
650 W=1
660 PRINT "COMPUTER TAKES";N;"AND LOSES."
670 RETURN
680 IF N>B THEN 720
690 W=1
700 PRINT "COMPUTER TAKES";N;"AND WINS."
710 RETURN
720 P=Q-C*INT(Q/C)
730 IF P>=A THEN 750
740 P=A
750 IF P<=B THEN 770
760 P=B
770 N=N-P
780 PRINT "COMPUTER TAKES";P;"AND LEAVES";N
790 W=0
800 RETURN
810 PRINT:PRINT "YOUR MOVE ";
820 INPUT P
830 IF P<>0 THEN 870
840 PRINT "I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT."
850 W=1
860 RETURN
870 IF P<>INT(P) THEN 920
880 IF P>=A THEN 910
890 IF P=N THEN 960
900 GOTO 920
910 IF P<=B THEN 940
920 PRINT "ILLEGAL MOVE, REENTER IT ";
930 GOTO 820
940 N=N-P
950 IF N<>0 THEN 1030
960 IF M=1 THEN 1000
970 PRINT "TOUGH LUCK, YOU LOSE."
980 W=1
990 RETURN
1000 PRINT "CONGRATULATIONS, YOU WIN."
1010 W=1
1020 RETURN
1030 IF N>=0 THEN 1060
1040 N=N+P
1050 GOTO 920
1060 W=0
1070 RETURN
1080 END

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<NeutralLanguage>en-US</NeutralLanguage>
</PropertyGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31019.35
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Batnum", "Batnum.csproj", "{64F32165-9D67-42B1-B04C-953CC756A170}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{64F32165-9D67-42B1-B04C-953CC756A170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64F32165-9D67-42B1-B04C-953CC756A170}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64F32165-9D67-42B1-B04C-953CC756A170}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64F32165-9D67-42B1-B04C-953CC756A170}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {73E40CC2-0E4E-48CF-8BDD-D6B6E995C14F}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,114 @@
using Batnum.Properties;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Batnum
{
public enum WinOptions
{
/// <summary>
/// Last person to play wins
/// </summary>
WinWithTakeLast = 1,
/// <summary>
/// Last person to play loses
/// </summary>
WinWithAvoidLast = 2
}
public enum Players
{
Computer = 1,
Human = 2
}
public class BatnumGame
{
public BatnumGame(int pileSize, WinOptions winCriteria, int minTake, int maxtake, Players firstPlayer, Func<string, int>askPlayerCallback)
{
this.pileSize = pileSize;
this.winCriteria = winCriteria;
this.minTake = minTake;
this.maxTake = maxtake;
this.currentPlayer = firstPlayer;
this.askPlayerCallback = askPlayerCallback;
}
private int pileSize;
private WinOptions winCriteria;
private int minTake;
private int maxTake;
private Players currentPlayer;
private Func<string, int> askPlayerCallback;
/// <summary>
/// Returns true if the game is running
/// </summary>
public bool IsRunning => pileSize > 0;
/// <summary>
/// Takes the next turn
/// </summary>
/// <returns>A message to be displayed to the player</returns>
public string TakeTurn()
{
//Edge condition - can occur when minTake is more > 1
if (pileSize < minTake)
{
pileSize = 0;
return string.Format(Resources.END_DRAW, minTake);
}
return currentPlayer == Players.Computer ? ComputerTurn() : PlayerTurn();
}
private string PlayerTurn()
{
int draw = askPlayerCallback(Resources.INPUT_TURN);
if (draw == 0)
{
pileSize = 0;
return Resources.INPUT_ZERO;
}
if (draw < minTake || draw > maxTake || draw > pileSize)
{
return Resources.INPUT_ILLEGAL;
}
pileSize = pileSize - draw;
if (pileSize == 0)
{
return winCriteria == WinOptions.WinWithTakeLast ? Resources.END_PLAYERWIN : Resources.END_PLAYERLOSE;
}
currentPlayer = Players.Computer;
return "";
}
private string ComputerTurn()
{
//first calculate the move to play
int sumTake = minTake + maxTake;
int draw = pileSize - sumTake * (int)(pileSize / (float)sumTake);
draw = Math.Clamp(draw, minTake, maxTake);
//detect win/lose conditions
switch (winCriteria)
{
case WinOptions.WinWithAvoidLast when (pileSize == minTake): //lose condition
pileSize = 0;
return string.Format(Resources.END_COMPLOSE, minTake);
case WinOptions.WinWithAvoidLast when (pileSize <= maxTake): //avoid automatic loss on next turn
draw = Math.Clamp(draw, minTake, pileSize - 1);
break;
case WinOptions.WinWithTakeLast when pileSize <= maxTake: // win condition
draw = Math.Min(pileSize, maxTake);
pileSize = 0;
return string.Format(Resources.END_COMPWIN, draw);
}
pileSize -= draw;
currentPlayer = Players.Human;
return string.Format(Resources.COMPTURN, draw, pileSize);
}
}
}

View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Batnum
{
public static class ConsoleUtilities
{
/// <summary>
/// Ask the user a question and expects a comma separated pair of numbers representing a number range in response
/// the range provided must have a maximum which is greater than the minimum
/// </summary>
/// <param name="question">The question to ask</param>
/// <param name="minimum">The minimum value expected</param>
/// <param name="maximum">The maximum value expected</param>
/// <returns>A pair of numbers representing the minimum and maximum of the range</returns>
public static (int min, int max) AskNumberRangeQuestion(string question, Func<int, int, bool> Validate)
{
while (true)
{
Console.Write(question);
Console.Write(" ");
string[] rawInput = Console.ReadLine().Split(',');
if (rawInput.Length == 2)
{
if (int.TryParse(rawInput[0], out int min) && int.TryParse(rawInput[1], out int max))
{
if (Validate(min, max))
{
return (min, max);
}
}
}
Console.WriteLine();
}
}
/// <summary>
/// Ask the user a question and expects a number in response
/// </summary>
/// <param name="question">The question to ask</param>
/// <param name="minimum">A minimum value expected</param>
/// <param name="maximum">A maximum value expected</param>
/// <returns>The number the user entered</returns>
public static int AskNumberQuestion(string question, Func<int, bool> Validate)
{
while (true)
{
Console.Write(question);
Console.Write(" ");
string rawInput = Console.ReadLine();
if (int.TryParse(rawInput, out int number))
{
if (Validate(number))
{
return number;
}
}
Console.WriteLine();
}
}
/// <summary>
/// Align content to center of console.
/// </summary>
/// <param name="content">Content to center</param>
/// <returns>Center aligned text</returns>
public static string CenterText(string content)
{
int windowWidth = Console.WindowWidth;
return String.Format("{0," + ((windowWidth / 2) + (content.Length / 2)) + "}", content);
}
/// <summary>
/// Writes the specified data, followed by the current line terminator, to the standard output stream, while wrapping lines that would otherwise break words.
/// source: https://stackoverflow.com/questions/20534318/make-console-writeline-wrap-words-instead-of-letters
/// </summary>
/// <param name="paragraph">The value to write.</param>
/// <param name="tabSize">The value that indicates the column width of tab characters.</param>
public static void WriteLineWordWrap(string paragraph, int tabSize = 4)
{
string[] lines = paragraph
.Replace("\t", new String(' ', tabSize))
.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
for (int i = 0; i < lines.Length; i++)
{
string process = lines[i];
List<String> wrapped = new List<string>();
while (process.Length > Console.WindowWidth)
{
int wrapAt = process.LastIndexOf(' ', Math.Min(Console.WindowWidth - 1, process.Length));
if (wrapAt <= 0) break;
wrapped.Add(process.Substring(0, wrapAt));
process = process.Remove(0, wrapAt + 1);
}
foreach (string wrap in wrapped)
{
Console.WriteLine(wrap);
}
Console.WriteLine(process);
}
}
}
}

View File

@@ -0,0 +1,30 @@
using Batnum;
using Batnum.Properties;
using System;
Console.WriteLine(ConsoleUtilities.CenterText(Resources.GAME_NAME));
Console.WriteLine(ConsoleUtilities.CenterText(Resources.INTRO_HEADER));
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
ConsoleUtilities.WriteLineWordWrap(Resources.INTRO_PART1);
Console.WriteLine();
ConsoleUtilities.WriteLineWordWrap(Resources.INTRO_PART2);
while (true)
{
Console.WriteLine();
int pileSize = ConsoleUtilities.AskNumberQuestion(Resources.START_QUESTION_PILESIZE, (n) => n > 1);
WinOptions winOption = (WinOptions)ConsoleUtilities.AskNumberQuestion(Resources.START_QUESTION_WINOPTION, (n) => Enum.IsDefined(typeof(WinOptions), n));
(int minTake, int maxTake) = ConsoleUtilities.AskNumberRangeQuestion(Resources.START_QUESTION_DRAWMINMAX, (min,max) => min >= 1 && max < pileSize && max > min);
Players currentPlayer = (Players)ConsoleUtilities.AskNumberQuestion(Resources.START_QUESTION_WHOSTARTS, (n) => Enum.IsDefined(typeof(Players), n));
BatnumGame game = new BatnumGame(pileSize, winOption, minTake, maxTake, currentPlayer, (question) => ConsoleUtilities.AskNumberQuestion(question, (c) => true));
while(game.IsRunning)
{
string message = game.TakeTurn();
Console.WriteLine(message);
}
}

View File

@@ -0,0 +1,216 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Batnum.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Batnum.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to COMPUTER TAKES {0} AND LEAVES {1}.
/// </summary>
internal static string COMPTURN {
get {
return ResourceManager.GetString("COMPTURN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to COMPUTER TAKES {0} AND LOSES.
/// </summary>
internal static string END_COMPLOSE {
get {
return ResourceManager.GetString("END_COMPLOSE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to COMPUTER TAKES {0} AND WINS.
/// </summary>
internal static string END_COMPWIN {
get {
return ResourceManager.GetString("END_COMPWIN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ITS A DRAW, THERE ARE ONLY {0} PIECES LEFT.
/// </summary>
internal static string END_DRAW {
get {
return ResourceManager.GetString("END_DRAW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to TOUGH LUCK, YOU LOSE..
/// </summary>
internal static string END_PLAYERLOSE {
get {
return ResourceManager.GetString("END_PLAYERLOSE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONGRATULATIONS, YOU WIN..
/// </summary>
internal static string END_PLAYERWIN {
get {
return ResourceManager.GetString("END_PLAYERWIN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to BATNUM.
/// </summary>
internal static string GAME_NAME {
get {
return ResourceManager.GetString("GAME_NAME", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ILLEGAL MOVE, RENETER IT.
/// </summary>
internal static string INPUT_ILLEGAL {
get {
return ResourceManager.GetString("INPUT_ILLEGAL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to YOUR MOVE ?.
/// </summary>
internal static string INPUT_TURN {
get {
return ResourceManager.GetString("INPUT_TURN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT..
/// </summary>
internal static string INPUT_ZERO {
get {
return ResourceManager.GetString("INPUT_ZERO", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CREATIVE COMPUTING MORRISTOWN, NEW JERSEY.
/// </summary>
internal static string INTRO_HEADER {
get {
return ResourceManager.GetString("INTRO_HEADER", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to THIS PROGRAM IS A &apos;BATTLE&apos; OF NUMBERS GAME, WHERE THE COMPUTER IS YOUR OPPONENT.
/// </summary>
internal static string INTRO_PART1 {
get {
return ResourceManager.GetString("INTRO_PART1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE. WINNNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINING CONDITIONS. DON&apos;T USER ZERO, HOWWEVER, IN PLAYING THE GAME..
/// </summary>
internal static string INTRO_PART2 {
get {
return ResourceManager.GetString("INTRO_PART2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ENTER MIN AND MAX ?.
/// </summary>
internal static string START_QUESTION_DRAWMINMAX {
get {
return ResourceManager.GetString("START_QUESTION_DRAWMINMAX", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ENTER PILE SIZE ?.
/// </summary>
internal static string START_QUESTION_PILESIZE {
get {
return ResourceManager.GetString("START_QUESTION_PILESIZE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ?.
/// </summary>
internal static string START_QUESTION_WHOSTARTS {
get {
return ResourceManager.GetString("START_QUESTION_WHOSTARTS", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ?.
/// </summary>
internal static string START_QUESTION_WINOPTION {
get {
return ResourceManager.GetString("START_QUESTION_WINOPTION", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="COMPTURN" xml:space="preserve">
<value>COMPUTER TAKES {0} AND LEAVES {1}</value>
</data>
<data name="END_COMPLOSE" xml:space="preserve">
<value>COMPUTER TAKES {0} AND LOSES</value>
</data>
<data name="END_COMPWIN" xml:space="preserve">
<value>COMPUTER TAKES {0} AND WINS</value>
</data>
<data name="END_DRAW" xml:space="preserve">
<value>ITS A DRAW, THERE ARE ONLY {0} PIECES LEFT</value>
</data>
<data name="END_PLAYERLOSE" xml:space="preserve">
<value>TOUGH LUCK, YOU LOSE.</value>
</data>
<data name="END_PLAYERWIN" xml:space="preserve">
<value>CONGRATULATIONS, YOU WIN.</value>
</data>
<data name="GAME_NAME" xml:space="preserve">
<value>BATNUM</value>
</data>
<data name="INPUT_ILLEGAL" xml:space="preserve">
<value>ILLEGAL MOVE, RENETER IT</value>
</data>
<data name="INPUT_TURN" xml:space="preserve">
<value>YOUR MOVE ?</value>
</data>
<data name="INPUT_ZERO" xml:space="preserve">
<value>I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.</value>
</data>
<data name="INTRO_HEADER" xml:space="preserve">
<value>CREATIVE COMPUTING MORRISTOWN, NEW JERSEY</value>
</data>
<data name="INTRO_PART1" xml:space="preserve">
<value>THIS PROGRAM IS A 'BATTLE' OF NUMBERS GAME, WHERE THE COMPUTER IS YOUR OPPONENT</value>
</data>
<data name="INTRO_PART2" xml:space="preserve">
<value>THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE. WINNNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINING CONDITIONS. DON'T USER ZERO, HOWWEVER, IN PLAYING THE GAME.</value>
</data>
<data name="START_QUESTION_DRAWMINMAX" xml:space="preserve">
<value>ENTER MIN AND MAX ?</value>
</data>
<data name="START_QUESTION_PILESIZE" xml:space="preserve">
<value>ENTER PILE SIZE ?</value>
</data>
<data name="START_QUESTION_WHOSTARTS" xml:space="preserve">
<value>ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ?</value>
</data>
<data name="START_QUESTION_WINOPTION" xml:space="preserve">
<value>ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ?</value>
</data>
</root>

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="COMPTURN" xml:space="preserve">
<value>L'ORDINATEUR PREND {0} ET LAISSE {1}</value>
</data>
<data name="END_COMPLOSE" xml:space="preserve">
<value>L'ORDINATEUR PREND {0} ET PERD</value>
</data>
<data name="END_COMPWIN" xml:space="preserve">
<value>L'ORDINATEUR PREND {0} ET GAGNE</value>
</data>
<data name="END_DRAW" xml:space="preserve">
<value>MATCH NUL, IL RESTE SEULEMENT {0} PIECES</value>
</data>
<data name="END_PLAYERLOSE" xml:space="preserve">
<value>PAS DE CHANCE. TU AS PERDU.</value>
</data>
<data name="END_PLAYERWIN" xml:space="preserve">
<value>BRAVO! TU AS GAGNE</value>
</data>
<data name="GAME_NAME" xml:space="preserve">
<value>BATNUM</value>
</data>
<data name="INPUT_ILLEGAL" xml:space="preserve">
<value>CE COUP EST INTERDIT. RE-ESSAIE</value>
</data>
<data name="INPUT_TURN" xml:space="preserve">
<value>TON TOUR ?</value>
</data>
<data name="INPUT_ZERO" xml:space="preserve">
<value>JE TE DIS DE NE PAS UTILISER LE ZERO! L'ORDINATEUR GAGNE PAR DEFAUT.</value>
</data>
<data name="INTRO_HEADER" xml:space="preserve">
<value>CREATIVE COMPUTING MORRISTOWN, NEW JERSEY</value>
</data>
<data name="INTRO_PART1" xml:space="preserve">
<value>CE PROGRAMME EST UN JEU 'BATAILLE' DE NOMBRES, OU L'ORDINATEUR EST TON ADVERSAIRE</value>
</data>
<data name="INTRO_PART2" xml:space="preserve">
<value>LE JEU COMMENCE AVEC UNE NOMBRE D'OBJETS DEFINI. TOI ET TON ADVERSAIRE ENLEVEZ EN ALTERNANCE UN NOMBRE D'OBJETS. LES CONDITIONS DE VICTOIRE SON DÉFINIES À L'AVANCE COMME PRENDRE OU NE PAS PRENDRE LE DERNIER OBJET. VOUS POUVEZ ÉGALEMENT PRÉCISER D'AUTRES CONDITIONS DES LE DÉBUT. TOUTEFOIS, N'UTILISEZ PAS LE CHIFFRE ZERO.</value>
</data>
<data name="START_QUESTION_DRAWMINMAX" xml:space="preserve">
<value>ENTRE LE MINIMUM ET MAXIMUM D'OBJETS A RETIRER POUR CHAQUE TOUR ?</value>
</data>
<data name="START_QUESTION_PILESIZE" xml:space="preserve">
<value>ENTRE LE NOMBRE D'OBJETS ?</value>
</data>
<data name="START_QUESTION_WHOSTARTS" xml:space="preserve">
<value>ENTRE QUI COMMENCE - 1 L'ORDINATEUR, 2 TOI ?</value>
</data>
<data name="START_QUESTION_WINOPTION" xml:space="preserve">
<value>ENTRE LA CONDITION DE VICTOIRE - 1 PRENDRE LA DERNIERE PIECE, 2 EVITER LA DERNIERE PIECE ?</value>
</data>
</root>

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="COMPTURN" xml:space="preserve">
<value>COMPUTER TAKES {0} AND LEAVES {1}</value>
</data>
<data name="END_COMPLOSE" xml:space="preserve">
<value>COMPUTER TAKES {0} AND LOSES</value>
</data>
<data name="END_COMPWIN" xml:space="preserve">
<value>COMPUTER TAKES {0} AND WINS</value>
</data>
<data name="END_DRAW" xml:space="preserve">
<value>ITS A DRAW, THERE ARE ONLY {0} PIECES LEFT</value>
</data>
<data name="END_PLAYERLOSE" xml:space="preserve">
<value>TOUGH LUCK, YOU LOSE.</value>
</data>
<data name="END_PLAYERWIN" xml:space="preserve">
<value>CONGRATULATIONS, YOU WIN.</value>
</data>
<data name="GAME_NAME" xml:space="preserve">
<value>BATNUM</value>
</data>
<data name="INPUT_ILLEGAL" xml:space="preserve">
<value>ILLEGAL MOVE, RENETER IT</value>
</data>
<data name="INPUT_TURN" xml:space="preserve">
<value>YOUR MOVE ?</value>
</data>
<data name="INPUT_ZERO" xml:space="preserve">
<value>I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.</value>
</data>
<data name="INTRO_HEADER" xml:space="preserve">
<value>CREATIVE COMPUTING MORRISTOWN, NEW JERSEY</value>
</data>
<data name="INTRO_PART1" xml:space="preserve">
<value>THIS PROGRAM IS A 'BATTLE' OF NUMBERS GAME, WHERE THE COMPUTER IS YOUR OPPONENT</value>
</data>
<data name="INTRO_PART2" xml:space="preserve">
<value>THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE. WINNNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINING CONDITIONS. DON'T USER ZERO, HOWWEVER, IN PLAYING THE GAME.</value>
</data>
<data name="START_QUESTION_DRAWMINMAX" xml:space="preserve">
<value>ENTER MIN AND MAX ?</value>
</data>
<data name="START_QUESTION_PILESIZE" xml:space="preserve">
<value>ENTER PILE SIZE ?</value>
</data>
<data name="START_QUESTION_WHOSTARTS" xml:space="preserve">
<value>ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ?</value>
</data>
<data name="START_QUESTION_WINOPTION" xml:space="preserve">
<value>ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ?</value>
</data>
</root>

View File

@@ -0,0 +1,11 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/)
This conversion uses C#9 and is built for .net 5.0
Functional changes from Original
- handle edge condition for end game where the minimum draw amount is greater than the number of items remaining in the pile
- Takes into account the width of the console
- Mulilingual Support (English/French currently)

3
08_Batnum/java/README.md Normal file
View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Oracle Java](https://openjdk.java.net/)

View File

@@ -0,0 +1,292 @@
import java.util.Arrays;
import java.util.Scanner;
/**
* Game of BatNum
* <p>
* Based on the Basic game of BatNum here
* https://github.com/coding-horror/basic-computer-games/blob/main/08%20Batnum/batnum.bas
* <p>
* Note: The idea was to create a version of the 1970's Basic game in Java, without introducing
* new features - no additional text, error checking, etc has been added.
*/
public class BatNum {
private enum GAME_STATE {
STARTING,
START_GAME,
CHOOSE_PILE_SIZE,
SELECT_WIN_OPTION,
CHOOSE_MIN_AND_MAX,
SELECT_WHO_STARTS_FIRST,
PLAYERS_TURN,
COMPUTERS_TURN,
ANNOUNCE_WINNER,
GAME_OVER
}
// Used for keyboard input
private final Scanner kbScanner;
// Current game state
private GAME_STATE gameState;
private int pileSize;
// How to win the game options
enum WIN_OPTION {
TAKE_LAST,
AVOID_LAST
}
// Tracking the winner
enum WINNER {
COMPUTER,
PLAYER
}
private WINNER winner;
private WIN_OPTION winOption;
private int minSelection;
private int maxSelection;
// Used by computer for optimal move
private int rangeOfRemovals;
public BatNum() {
gameState = GAME_STATE.STARTING;
// Initialise kb scanner
kbScanner = new Scanner(System.in);
}
/**
* Main game loop
*/
public void play() {
do {
switch (gameState) {
// Show an introduction and optional instructions the first time the game is played.
case STARTING:
intro();
gameState = GAME_STATE.START_GAME;
break;
// Start new game
case START_GAME:
gameState = GAME_STATE.CHOOSE_PILE_SIZE;
break;
case CHOOSE_PILE_SIZE:
System.out.println();
System.out.println();
pileSize = displayTextAndGetNumber("ENTER PILE SIZE ");
if (pileSize >= 1) {
gameState = GAME_STATE.SELECT_WIN_OPTION;
}
break;
case SELECT_WIN_OPTION:
int winChoice = displayTextAndGetNumber("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ");
if (winChoice == 1) {
winOption = WIN_OPTION.TAKE_LAST;
gameState = GAME_STATE.CHOOSE_MIN_AND_MAX;
} else if (winChoice == 2) {
winOption = WIN_OPTION.AVOID_LAST;
gameState = GAME_STATE.CHOOSE_MIN_AND_MAX;
}
break;
case CHOOSE_MIN_AND_MAX:
String range = displayTextAndGetInput("ENTER MIN AND MAX ");
minSelection = getDelimitedValue(range, 0);
maxSelection = getDelimitedValue(range, 1);
if (maxSelection > minSelection && minSelection >= 1) {
gameState = GAME_STATE.SELECT_WHO_STARTS_FIRST;
}
// Used by computer in its turn
rangeOfRemovals = minSelection + maxSelection;
break;
case SELECT_WHO_STARTS_FIRST:
int playFirstChoice = displayTextAndGetNumber("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ");
if (playFirstChoice == 1) {
gameState = GAME_STATE.COMPUTERS_TURN;
} else if (playFirstChoice == 2) {
gameState = GAME_STATE.PLAYERS_TURN;
}
break;
case PLAYERS_TURN:
int playersMove = displayTextAndGetNumber("YOUR MOVE ");
if (playersMove == 0) {
System.out.println("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.");
winner = WINNER.COMPUTER;
gameState = GAME_STATE.ANNOUNCE_WINNER;
break;
}
if (playersMove == pileSize && winOption == WIN_OPTION.AVOID_LAST) {
winner = WINNER.COMPUTER;
gameState = GAME_STATE.ANNOUNCE_WINNER;
break;
}
// Check if players move is with the min and max possible
if (playersMove >= minSelection && playersMove <= maxSelection) {
// Valid so reduce pileSize by amount player entered
pileSize -= playersMove;
// Did this move result in there being no more objects on pile?
if (pileSize == 0) {
// Was the game setup so the winner was whoever took the last object
if (winOption == WIN_OPTION.TAKE_LAST) {
// Player won
winner = WINNER.PLAYER;
} else {
// Computer one
winner = WINNER.COMPUTER;
}
gameState = GAME_STATE.ANNOUNCE_WINNER;
} else {
// There are still items left.
gameState = GAME_STATE.COMPUTERS_TURN;
}
} else {
// Invalid move
System.out.println("ILLEGAL MOVE, REENTER IT ");
}
break;
case COMPUTERS_TURN:
int pileSizeLeft = pileSize;
if (winOption == WIN_OPTION.TAKE_LAST) {
if (pileSize > maxSelection) {
int objectsToRemove = calculateComputersTurn(pileSizeLeft);
pileSize -= objectsToRemove;
System.out.println("COMPUTER TAKES " + objectsToRemove + " AND LEAVES " + pileSize);
gameState = GAME_STATE.PLAYERS_TURN;
} else {
System.out.println("COMPUTER TAKES " + pileSize + " AND WINS.");
winner = WINNER.COMPUTER;
gameState = GAME_STATE.ANNOUNCE_WINNER;
}
} else {
pileSizeLeft--;
if (pileSize > minSelection) {
int objectsToRemove = calculateComputersTurn(pileSizeLeft);
pileSize -= objectsToRemove;
System.out.println("COMPUTER TAKES " + objectsToRemove + " AND LEAVES " + pileSize);
gameState = GAME_STATE.PLAYERS_TURN;
} else {
System.out.println("COMPUTER TAKES " + pileSize + " AND LOSES.");
winner = WINNER.PLAYER;
gameState = GAME_STATE.ANNOUNCE_WINNER;
}
}
break;
case ANNOUNCE_WINNER:
switch (winner) {
case PLAYER:
System.out.println("CONGRATULATIONS, YOU WIN.");
break;
case COMPUTER:
System.out.println("TOUGH LUCK, YOU LOSE.");
break;
}
gameState = GAME_STATE.START_GAME;
break;
}
} while (gameState != GAME_STATE.GAME_OVER);
}
/**
* Figure out the computers turn - i.e. how many objects to remove
*
* @param pileSizeLeft current size
* @return the number of objects to remove.
*/
private int calculateComputersTurn(int pileSizeLeft) {
int computersNumberToRemove = pileSizeLeft - rangeOfRemovals * (pileSizeLeft / rangeOfRemovals);
if (computersNumberToRemove < minSelection) {
computersNumberToRemove = minSelection;
}
if (computersNumberToRemove > maxSelection) {
computersNumberToRemove = maxSelection;
}
return computersNumberToRemove;
}
private void intro() {
System.out.println(simulateTabs(33) + "BATNUM");
System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
System.out.println();
System.out.println("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE");
System.out.println("COMPUTER IS YOUR OPPONENT.");
System.out.println();
System.out.println("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU");
System.out.println("AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.");
System.out.println("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR");
System.out.println("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.");
System.out.println("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.");
System.out.println("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.");
}
/*
* Print a message on the screen, then accept input from Keyboard.
* Converts input to Integer
*
* @param text message to be displayed on screen.
* @return what was typed by the player.
*/
private int displayTextAndGetNumber(String text) {
return Integer.parseInt(displayTextAndGetInput(text));
}
/*
* Print a message on the screen, then accept input from Keyboard.
*
* @param text message to be displayed on screen.
* @return what was typed by the player.
*/
private String displayTextAndGetInput(String text) {
System.out.print(text);
return kbScanner.next();
}
/**
* Simulate the old basic tab(xx) command which indented text by xx spaces.
*
* @param spaces number of spaces required
* @return String with number of spaces
*/
private String simulateTabs(int spaces) {
char[] spacesTemp = new char[spaces];
Arrays.fill(spacesTemp, ' ');
return new String(spacesTemp);
}
/**
* Accepts a string delimited by comma's and returns the nth delimited
* value (starting at count 0).
*
* @param text - text with values separated by comma's
* @param pos - which position to return a value for
* @return the int representation of the value
*/
private int getDelimitedValue(String text, int pos) {
String[] tokens = text.split(",");
return Integer.parseInt(tokens[pos]);
}
}

View File

@@ -0,0 +1,8 @@
public class BatNumGame {
public static void main(String[] args) {
BatNum batNum = new BatNum();
batNum.play();
}
}

View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Shells)

View File

@@ -0,0 +1,9 @@
<html>
<head>
<title>BATNUM</title>
</head>
<body>
<pre id="output" style="font-size: 12pt;"></pre>
<script src="batnum.js"></script>
</body>
</html>

View File

@@ -0,0 +1,161 @@
// BATNUM
//
// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
//
function print(str)
{
document.getElementById("output").appendChild(document.createTextNode(str));
}
function input()
{
var input_element;
var input_str;
return new Promise(function (resolve) {
input_element = document.createElement("INPUT");
print("? ");
input_element.setAttribute("type", "text");
input_element.setAttribute("length", "50");
document.getElementById("output").appendChild(input_element);
input_element.focus();
input_str = undefined;
input_element.addEventListener("keydown", function (event) {
if (event.keyCode == 13) {
input_str = input_element.value;
document.getElementById("output").removeChild(input_element);
print(input_str);
print("\n");
resolve(input_str);
}
});
});
}
function tab(space)
{
var str = "";
while (space-- > 0)
str += " ";
return str;
}
// Main program
async function main()
{
print(tab(33) + "BATNUM\n");
print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
print("\n");
print("\n");
print("\n");
print("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE\n");
print("COMPUTER IS YOUR OPPONENT.\n");
print("\n");
print("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU\n");
print("AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.\n");
print("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR\n");
print("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.\n");
print("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.\n");
print("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.\n");
print("\n");
first_time = 1;
while (1) {
while (1) {
if (first_time == 1) {
first_time = 0;
} else {
for (i = 1; i <= 10; i++)
print("\n");
}
print("ENTER PILE SIZE");
n = parseInt(await input());
if (n >= 1)
break;
}
while (1) {
print("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ");
m = parseInt(await input());
if (m == 1 || m == 2)
break;
}
while (1) {
print("ENTER MIN AND MAX ");
str = await input();
a = parseInt(str);
b = parseInt(str.substr(str.indexOf(",") + 1));
if (a <= b && a >= 1)
break;
}
while (1) {
print("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ");
s = parseInt(await input());
print("\n");
print("\n");
if (s == 1 || s == 2)
break;
}
w = 0;
c = a + b;
while (1) {
if (s == 1) {
// Computer's turn
q = n;
if (m != 1)
q--;
if (m != 1 && n <= a) {
w = 1;
print("COMPUTER TAKES " + n + " AND LOSES.\n");
} else if (m == 1 && n <= b) {
w = 1;
print("COMPUTER TAKES " + n + " AND WINS.\n");
} else {
p = q - c * Math.floor(q / c);
if (p < a)
p = a;
if (p > b)
p = b;
n -= p;
print("COMPUTER TAKES " + p + " AND LEAVES " + n + "\n");
w = 0;
}
s = 2;
}
if (w)
break;
if (s == 2) {
while (1) {
print("\n");
print("YOUR MOVE ");
p = parseInt(await input());
if (p == 0) {
print("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.\n");
w = 1;
break;
} else if (p >= a && p <= b && n - p >= 0) {
break;
}
}
if (p != 0) {
n -= p;
if (n == 0) {
if (m != 1) {
print("TOUGH LUCK, YOU LOSE.\n");
} else {
print("CONGRATULATIONS, YOU WIN.\n");
}
w = 1;
} else {
w = 0;
}
}
s = 1;
}
if (w)
break;
}
}
}
main();

View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))

3
08_Batnum/perl/README.md Normal file
View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Perl](https://www.perl.org/)

View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Python](https://www.python.org/about/)

159
08_Batnum/python/batnum.py Normal file
View File

@@ -0,0 +1,159 @@
from enum import Enum
class WinOptions(Enum):
Undefined = 0
TakeLast = 1
AvoidLast = 2
class StartOptions(Enum):
Undefined = 0
ComputerFirst = 1
PlayerFirst = 2
def PrintIntro():
'''Prints out the introduction and rules for the game.'''
print("BATNUM".rjust(33, ' '))
print("CREATIVE COMPUTING MORRISSTOWN, NEW JERSEY".rjust(15, ' '))
print()
print()
print()
print("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE")
print("COMPUTER IS YOUR OPPONENT.")
print()
print("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU")
print( "AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.")
print("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR")
print("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.")
print("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.")
print("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.")
print()
return
def GetParams():
'''This requests the necessary parameters to play the game.
Returns a set with the five game parameters:
pileSize - the starting size of the object pile
minSelect - minimum selection that can be made on each turn
maxSelect - maximum selection that can be made on each turn
startOption - 1 if the computer is first
or 2 if the player is first
winOption - 1 if the goal is to take the last object
or 2 if the goal is to not take the last object
'''
pileSize = 0
winOption = WinOptions.Undefined
minSelect = 0
maxSelect = 0
startOption = StartOptions.Undefined
while pileSize < 1:
pileSize = int(input("ENTER PILE SIZE "))
while winOption == WinOptions.Undefined:
winOption = int(input("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: "))
while minSelect < 1 or maxSelect < 1 or minSelect > maxSelect:
(minSelect, maxSelect) = [int(x) for x in input("ENTER MIN AND MAX ").split(' ')]
while startOption == StartOptions.Undefined:
startOption = int(input("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST "))
return (pileSize, minSelect, maxSelect, startOption, winOption)
def PlayerMove(pileSize, minSelect, maxSelect, startOption, winOption):
'''This handles the player's turn - asking the player how many objects
to take and doing some basic validation around that input. Then it
checks for any win conditions.
Returns a boolean indicating whether the game is over and the new pileSize.'''
playerDone = False
while not playerDone:
playerMove = int(input("YOUR MOVE "))
if playerMove == 0:
print ("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.")
return (True, pileSize)
if playerMove > maxSelect or playerMove < minSelect:
print("ILLEGAL MOVE, REENTER IT")
continue
pileSize = pileSize - playerMove
playerDone = True
if pileSize <= 0:
if winOption == WinOptions.AvoidLast:
print("TOUGH LUCK, YOU LOSE.")
else:
print("CONGRATULATIONS, YOU WIN.")
return (True, pileSize)
return (False, pileSize)
def ComputerPick(pileSize, minSelect, maxSelect, startOption, winOption):
'''This handles the logic to determine how many objects the computer
will select on its turn.
'''
q = pileSize - 1 if winOption == WinOptions.AvoidLast else pileSize
c = minSelect + maxSelect
computerPick = q - (c * int(q / c))
if computerPick < minSelect:
computerPick = minSelect
if computerPick > maxSelect:
computerPick = maxSelect
return computerPick
def ComputerMove(pileSize, minSelect, maxSelect, startOption, winOption):
'''This handles the computer's turn - first checking for the various
win/lose conditions and then calculating how many objects
the computer will take.
Returns a boolean indicating whether the game is over and the new pileSize.'''
# First, check for win conditions on this move
# In this case, we win by taking the last object and
# the remaining pile is less than max select
# so the computer can grab them all and win
if winOption == WinOptions.TakeLast and pileSize <= maxSelect:
print (f"COMPUTER TAKES {pileSize} AND WINS.")
return (True, pileSize)
# In this case, we lose by taking the last object and
# the remaining pile is less than minsize and the computer
# has to take all of them.
if winOption == WinOptions.AvoidLast and pileSize <= minSelect:
print (f"COMPUTER TAKES {minSelect} AND LOSES.")
return (True, pileSize)
# Otherwise, we determine how many the computer selects
currSel = ComputerPick(pileSize, minSelect, maxSelect, startOption, winOption)
pileSize = pileSize - currSel
print(f"COMPUTER TAKES {currSel} AND LEAVES {pileSize}")
return (False, pileSize)
def PlayGame(pileSize, minSelect, maxSelect, startOption, winOption):
'''This is the main game loop - repeating each turn until one
of the win/lose conditions is met.
'''
gameOver = False
# playersTurn is a boolean keeping track of whether it's the
# player's or computer's turn
playersTurn = startOption == StartOptions.PlayerFirst
while not gameOver:
if playersTurn:
(gameOver, pileSize) = PlayerMove(pileSize, minSelect, maxSelect, startOption, winOption)
playersTurn = False
if gameOver:
return
if not playersTurn:
(gameOver, pileSize) = ComputerMove(pileSize, minSelect, maxSelect, startOption, winOption)
playersTurn = True
return
if __name__ == "__main__":
pileSize = 0
minSelect = 0
maxSelect = 0
# 1 = to take last, 2 = to avoid last
winOption = 0
# 1 = computer first, 2 = user first
startOption = 0
while True:
PrintIntro()
(pileSize, minSelect, maxSelect, startOption, winOption) = GetParams()
# Just keep playing the game until the user kills it with ctrl-C
PlayGame(pileSize, minSelect, maxSelect, startOption, winOption)

3
08_Batnum/ruby/README.md Normal file
View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Ruby](https://www.ruby-lang.org/en/)

199
08_Batnum/vbnet/Program.vb Normal file
View File

@@ -0,0 +1,199 @@
Imports System
Module BatNum
Enum WinOptions
Undefined = 0
TakeLast = 1
AvoidLast = 2
End Enum
Enum StartOptions
Undefined = 0
ComputerFirst = 1
PlayerFirst = 2
End Enum
Dim pileSize As Integer = 0
Dim minSelect As Integer = 0
Dim maxSelect As Integer = 0
Dim startOption As StartOptions = StartOptions.Undefined
Dim winOption As WinOptions = WinOptions.Undefined
' <summary>
' Prints the intro and rules of the game.
' </summary>
Private Sub PrintIntro()
Console.WriteLine("BATNUM".PadLeft(33, " "))
Console.WriteLine("CREATIVE COMPUTING MORRISSTOWN, NEW JERSEY".PadLeft(15, " "))
Console.WriteLine()
Console.WriteLine()
Console.WriteLine()
Console.WriteLine("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE")
Console.WriteLine("COMPUTER IS YOUR OPPONENT.")
Console.WriteLine()
Console.WriteLine("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU")
Console.WriteLine("AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.")
Console.WriteLine("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR")
Console.WriteLine("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.")
Console.WriteLine("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.")
Console.WriteLine("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.")
Console.WriteLine()
End Sub
' <summary>
' Asks the user for the various parameters necessary
' to play the game.
' </summary>
Private Sub GetParams()
' Reset the game parameters
pileSize = 0
minSelect = 0
maxSelect = 0
startOption = StartOptions.Undefined
winOption = WinOptions.Undefined
While pileSize < 1
Console.Write("ENTER PILE SIZE ")
pileSize = Convert.ToInt32(Console.ReadLine())
End While
While winOption = WinOptions.Undefined
Console.Write("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ")
winOption = Convert.ToInt32(Console.ReadLine())
End While
While minSelect < 1 Or maxSelect < 1 Or minSelect > maxSelect
Console.Write("ENTER MIN AND MAX ")
Dim vals = Console.ReadLine().ToString().Split(" ").[Select](Function(n) Integer.Parse(n)).ToList()
If vals.Count() <> 2 Then
Continue While
End If
minSelect = vals(0)
maxSelect = vals(1)
End While
While startOption = StartOptions.Undefined
Console.Write("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ")
startOption = Convert.ToInt32(Console.ReadLine())
End While
End Sub
'<summary>
'This handles the player's turn - asking the player how many objects
'to take And doing some basic validation around that input. Then it
'checks for any win conditions.
'</summary>
'<returns>Returns a Boolean indicating whether the game Is over And the New pileSize.</returns>'
Private Function PlayerMove() As Boolean
Dim playerDone As Boolean = False
While Not playerDone
Console.WriteLine("YOUR MOVE ")
Dim playerNum As Integer = Convert.ToInt32(Console.ReadLine())
If playerNum = 0 Then
Console.WriteLine("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.")
Return True
End If
If playerNum > maxSelect Or playerNum < minSelect Then
Console.WriteLine("ILLEGAL MOVE, REENTER IT")
Continue While
End If
pileSize = pileSize - playerNum
playerDone = True
If pileSize <= 0 Then
If winOption = WinOptions.AvoidLast Then
Console.WriteLine("TOUGH LUCK, YOU LOSE.")
Else
Console.WriteLine("CONGRATULATIONS, YOU WIN.")
End If
Return True
End If
End While
Return False
End Function
'<summary>
'This handles the logic to determine how many objects the computer
'will select on its turn.
'</summary>
Private Function ComputerPick() As Integer
Dim q As Integer = IIf(winOption = WinOptions.AvoidLast, pileSize - 1, pileSize)
Dim c As Integer = minSelect + maxSelect
Dim computerNum As Integer = q - (c * Int(q / c))
If computerNum < minSelect Then
computerNum = minSelect
End If
If computerNum > maxSelect Then
ComputerPick = maxSelect
End If
Return computerNum
End Function
'<summary>
'This handles the computer's turn - first checking for the various
'win/lose conditions And then calculating how many objects
'the computer will take.
'</summary>
'<returns>Returns a boolean indicating whether the game is over.</returns>'
Private Function ComputerMove() As Boolean
' First, check For win conditions On this move
' In this Case, we win by taking the last Object And
' the remaining pile Is less than max Select
' so the computer can grab them all And win
If winOption = WinOptions.TakeLast And pileSize <= maxSelect Then
Console.WriteLine($"COMPUTER TAKES {pileSize} AND WINS.")
Return True
End If
' In this Case, we lose by taking the last Object And
' the remaining pile Is less than minsize And the computer
' has To take all Of them.
If winOption = WinOptions.AvoidLast And pileSize <= minSelect Then
Console.WriteLine($"COMPUTER TAKES {minSelect} AND LOSES.")
Return True
End If
' Otherwise, we determine how many the computer selects
Dim currSel As Integer = ComputerPick()
pileSize = pileSize - currSel
Console.WriteLine($"COMPUTER TAKES {currSel} AND LEAVES {pileSize}")
Return False
End Function
'<summary>
'This is the main game loop - repeating each turn until one
'of the win/lose conditions Is met.
'</summary>
Private Sub PlayGame()
Dim gameOver As Boolean = False
' playersTurn Is a Boolean keeping track Of whether it's the
' player's or computer's turn
Dim playersTurn As Boolean = (startOption = StartOptions.PlayerFirst)
While Not gameOver
If playersTurn Then
gameOver = PlayerMove()
playersTurn = False
If gameOver Then Return
End If
If Not playersTurn Then
gameOver = ComputerMove()
playersTurn = True
End If
End While
End Sub
Public Sub Play()
While True
PrintIntro()
GetParams()
PlayGame()
End While
End Sub
End Module
Module Program
Sub Main(args As String())
BatNum.Play()
End Sub
End Module

View File

@@ -0,0 +1,3 @@
Original BASIC source [downloaded from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Visual Basic .NET](https://en.wikipedia.org/wiki/Visual_Basic_.NET)

View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31321.278
MinimumVisualStudioVersion = 10.0.40219.1
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "batnum", "batnum.vbproj", "{D577E429-F84D-4E84-86E7-E6526CFD5FD9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D577E429-F84D-4E84-86E7-E6526CFD5FD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D577E429-F84D-4E84-86E7-E6526CFD5FD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D577E429-F84D-4E84-86E7-E6526CFD5FD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D577E429-F84D-4E84-86E7-E6526CFD5FD9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {426DF7FE-66E7-4319-9AD8-7A2DD3964A2F}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>batnum</RootNamespace>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>