Port Batnum to Python and VB

This commit is contained in:
Joe Walter
2021-05-30 10:51:29 -04:00
parent eb082f10fb
commit ec2d063fb9
5 changed files with 393 additions and 0 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
*/.vs */.vs
*.suo
bin/ bin/
obj/ obj/

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)

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,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>