mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
Port Batnum to Python and VB
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
*/.vs
|
||||
*.suo
|
||||
|
||||
bin/
|
||||
obj/
|
||||
|
||||
159
08 Batnum/python/batnum.py
Normal file
159
08 Batnum/python/batnum.py
Normal 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
199
08 Batnum/vbnet/Program.vb
Normal 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
|
||||
25
08 Batnum/vbnet/batnum.sln
Normal file
25
08 Batnum/vbnet/batnum.sln
Normal 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
|
||||
9
08 Batnum/vbnet/batnum.vbproj
Normal file
9
08 Batnum/vbnet/batnum.vbproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>batnum</RootNamespace>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user