diff --git a/.gitignore b/.gitignore
index a186b7a3..78bed0e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*/.vs
+*.suo
bin/
obj/
diff --git a/08 Batnum/python/batnum.py b/08 Batnum/python/batnum.py
new file mode 100644
index 00000000..0f3473ed
--- /dev/null
+++ b/08 Batnum/python/batnum.py
@@ -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)
diff --git a/08 Batnum/vbnet/Program.vb b/08 Batnum/vbnet/Program.vb
new file mode 100644
index 00000000..4ba9ad9d
--- /dev/null
+++ b/08 Batnum/vbnet/Program.vb
@@ -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
+
+ '
+ ' Prints the intro and rules of the game.
+ '
+ 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
+
+ '
+ ' Asks the user for the various parameters necessary
+ ' to play the game.
+ '
+ 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
+
+ '
+ '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.'
+ 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
+
+ '
+ 'This handles the logic to determine how many objects the computer
+ 'will select on its turn.
+ '
+ 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
+
+ '
+ '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.'
+ 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
+
+ '
+ 'This is the main game loop - repeating each turn until one
+ 'of the win/lose conditions Is met.
+ '
+ 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
diff --git a/08 Batnum/vbnet/batnum.sln b/08 Batnum/vbnet/batnum.sln
new file mode 100644
index 00000000..b3f63f59
--- /dev/null
+++ b/08 Batnum/vbnet/batnum.sln
@@ -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
diff --git a/08 Batnum/vbnet/batnum.vbproj b/08 Batnum/vbnet/batnum.vbproj
new file mode 100644
index 00000000..3c21499c
--- /dev/null
+++ b/08 Batnum/vbnet/batnum.vbproj
@@ -0,0 +1,9 @@
+
+
+
+ Exe
+ batnum
+ netcoreapp3.1
+
+
+