Merge branch 'coding-horror:main' into rust-port-amazing

This commit is contained in:
Anthony Rubick
2022-03-07 09:17:35 +00:00
committed by GitHub
567 changed files with 9657 additions and 5558 deletions

2
.gitignore vendored
View File

@@ -26,7 +26,7 @@ obj/
out/
*.py[co]
.python-version
Pipfile
.DS_Store

33
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,33 @@
# pre-commit run --all-files
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:
- id: check-ast
- id: check-case-conflict
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-json
- id: check-yaml
- id: debug-statements
- id: end-of-file-fixer
- id: trailing-whitespace
- id: mixed-line-ending
- repo: https://github.com/pre-commit/mirrors-isort
rev: v5.10.1
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 22.1.0
hooks:
- id: black
- repo: https://github.com/asottile/pyupgrade
rev: v2.31.0
hooks:
- id: pyupgrade
args: [--py37-plus]
- repo: https://github.com/asottile/blacken-docs
rev: v1.12.1
hooks:
- id: blacken-docs
additional_dependencies: [black==20.8b1]

View File

@@ -65,11 +65,11 @@ dotnet_naming_rule.private_members_should_be_pascal_case.style = camel_case
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum, delegate
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_private_members.applicable_kinds = property, method, field, event
dotnet_naming_symbols.non_private_members.applicable_accessibilities = public, internal, protected, protected_internal, private_protected
@@ -80,19 +80,19 @@ dotnet_naming_symbols.private_members.applicable_accessibilities = private
# Naming styles
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.camel_case.required_prefix =
dotnet_naming_style.camel_case.required_suffix =
dotnet_naming_style.camel_case.word_separator =
dotnet_naming_style.camel_case.required_prefix =
dotnet_naming_style.camel_case.required_suffix =
dotnet_naming_style.camel_case.word_separator =
dotnet_naming_style.camel_case.capitalization = camel_case

View File

@@ -9,7 +9,7 @@ public record PortInfo(
string LangPath, string Lang, string Ext, string ProjExt,
string[] CodeFiles, string[] Slns, string[] Projs
) {
private static readonly EnumerationOptions enumerationOptions = new() {
RecurseSubdirectories = true,
MatchType = MatchType.Simple,
@@ -34,7 +34,7 @@ public record PortInfo(
int.TryParse(parts[0], out var n) && n > 0 ? // ignore utilities folder
n :
(int?)null,
specialGameNames.TryGetValue(parts[1], out var specialName) ?
specialGameNames.TryGetValue(parts[1], out var specialName) ?
specialName :
parts[1].Replace("_", "").Replace("-", "")
);

View File

@@ -180,7 +180,7 @@ void generateMissingSlns() {
void generateMissingProjs() {
foreach (var item in infos.Where(x => x.Projs.None())) {
// We can't use the dotnet command to create a new project using the built-in console template, because part of that template
// is a Program.cs / Program.vb file. If there already are code files, there's no need to add a new empty one; and
// is a Program.cs / Program.vb file. If there already are code files, there's no need to add a new empty one; and
// if there's already such a file, it might try to overwrite it.
var projText = item.Lang switch {

View File

@@ -8,7 +8,7 @@ my $LN= "Line";
my $Pedantic= 0;
my $Indent= 0;
my %Vars; # num | str | anm | ast
my %Vars; # num | str | anm | ast
my @Data;
my %Code;
open(FH, $File);
@@ -278,7 +278,7 @@ sub PRINT {
push @Out, $Par;
}
my $Out= join(". ", @Out);
my $Out= join(". ", @Out);
if ($Enter) { $Out.= qq|. "\\n"|; }
return "print ".$Out;
}
@@ -347,7 +347,7 @@ sub FORMULA {
if ($Vars{$Key}!~ /^a/) { next; }
$Str=~ s/\$$Key\((.*?)\)/\$$Key\[$1\]/g;
}
if ($Cond==1) {
$Str=~ s/<>/ ne /g;
$Str=~ s/=/ eq /g;
@@ -357,7 +357,7 @@ sub FORMULA {
sub SMARPLIT {
my ($Str, $Sep, $Nin)= @_;
my ($Str, $Sep, $Nin)= @_;
my @Parts;
my $Text= "";
my $Flag= 0;
@@ -373,8 +373,5 @@ sub SMARPLIT {
$Text.= $Char;
}
if ($Text) { push @Parts, &TRIM($Text); }
return @Parts;
return @Parts;
}

View File

@@ -1,9 +1,9 @@
/**
* Program to show unimplemented games by language, optionally filtered by
* Program to show unimplemented games by language, optionally filtered by
* language
*
*
* Usage: node find-unimplemented.js [[[lang1] lang2] ...]
*
*
* Adapted from find-missing-implementtion.js
*/

View File

@@ -34,4 +34,4 @@ abstract class ConsoleTest {
private fun String.trimWhiteSpace() =
replace("[\\s]+".toRegex(), " ")
}
}

View File

@@ -1,26 +1,40 @@
import os
lang_pos = {
"csharp": 1, "java": 2, "javascript": 3,
"pascal": 4, "perl": 5, "python": 6, "ruby": 7, "vbnet": 8
"csharp": 1,
"java": 2,
"javascript": 3,
"pascal": 4,
"perl": 5,
"python": 6,
"ruby": 7,
"vbnet": 8,
}
write_string = "# TODO list \n game | csharp | java | javascript | pascal | perl | python | ruby | vbnet \n --- | --- | --- | --- | --- | --- | --- | --- | --- \n"
# Set the directory you want to start from
rootDir = '..'
rootDir = ".."
strings_done = []
checklist = ["game", "csharp", "java", "javascript",
"pascal", "perl", "python", "ruby", "vbnet"]
checklist = [
"game",
"csharp",
"java",
"javascript",
"pascal",
"perl",
"python",
"ruby",
"vbnet",
]
prev_game = ""
for dirName, subdirList, fileList in os.walk(rootDir):
split_dir = dirName.split(os.path.sep)
if len(split_dir) == 2 and not split_dir[1] in ['.git', '00_Utilities']:
if len(split_dir) == 2 and not split_dir[1] in [".git", "00_Utilities"]:
if prev_game == "":
prev_game = split_dir[1]
checklist[0] = split_dir[1]
@@ -28,11 +42,20 @@ for dirName, subdirList, fileList in os.walk(rootDir):
if prev_game != split_dir[1]:
# it's a new dir
strings_done.append(checklist)
checklist = [split_dir[1], "csharp", "java", "javascript",
"pascal", "perl", "python", "ruby", "vbnet"]
checklist = [
split_dir[1],
"csharp",
"java",
"javascript",
"pascal",
"perl",
"python",
"ruby",
"vbnet",
]
prev_game = split_dir[1]
elif len(split_dir) == 3 and split_dir[1] != '.git':
elif len(split_dir) == 3 and split_dir[1] != ".git":
if split_dir[2] in lang_pos.keys():
if len(fileList) > 1 or len(subdirList) > 0:
# there is more files than the readme
@@ -41,10 +64,11 @@ for dirName, subdirList, fileList in os.walk(rootDir):
checklist[lang_pos[split_dir[2]]] = "⬜️"
sorted_strings = list(map(lambda l: " | ".join(l) + "\n",
sorted(strings_done, key=lambda x: x[0])))
write_string += ''.join(sorted_strings)
sorted_strings = list(
map(lambda l: " | ".join(l) + "\n", sorted(strings_done, key=lambda x: x[0]))
)
write_string += "".join(sorted_strings)
with open("README.md", "w", encoding='utf-8') as f:
with open("README.md", "w", encoding="utf-8") as f:
f.write(write_string)

View File

@@ -19,7 +19,7 @@ printf("%$Tab\s", "BAS");
foreach my $Dir (@Langs) {
printf("%$Tab\s", $Dir);
}
}
print "\n";
my $Count;
@@ -39,7 +39,7 @@ foreach my $Lin (@Ret) {
if ($Ret>1) { printf("%$Tab\s", "YES"); $Sum{$Dir}++; }
else { printf("%$Tab\s", " ");}
}
print "\n";
print "\n";
}
@@ -57,4 +57,3 @@ foreach my $Dir (@Dirs) {
printf("%$Tab\s", "$Per");
}
print "\n";

View File

@@ -9,7 +9,7 @@ namespace AceyDucey
/// </summary>
internal class GameState
{
/// <summary>
/// How much money does the player have at the moment?
/// </summary>

View File

@@ -55,7 +55,7 @@ void main()
{
writeln("YOU WIN!!!");
cash += bet;
}
}
else
{
writeln("Sorry, you lose.");

View File

@@ -169,4 +169,4 @@ public class AceyDucey {
System.out.println("A VALUE BETWEEN THE FIRST TWO.");
System.out.println("IF YOU DO NOT WANT TO BET, INPUT: 0");
}
}
}

View File

@@ -15,8 +15,8 @@ public class AceyDucey17 {
System.out.println("""
ACEY DUCEY CARD GAME
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER
THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP
YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING

View File

@@ -18,4 +18,4 @@ public class AceyDuceyGame {
keepPlaying = game.playAgain();
} while (keepPlaying);
}
}
}

View File

@@ -99,7 +99,7 @@ async function main() {
}
}
}
if (bet == 0)
if (bet == 0)
{
// User chose not to bet.
print('CHICKEN!!');

View File

@@ -16,4 +16,3 @@ begin
Acey_Ducey:= TGame.Create;
Acey_Ducey.Run;
end.

View File

@@ -108,4 +108,3 @@ begin
end;
end.

View File

@@ -133,4 +133,3 @@ begin
end;
end.

View File

@@ -149,4 +149,3 @@ begin
until not TryAgain;
WriteLN('O.K., HOPE YOU HAD FUN!');
end.

View File

@@ -11,6 +11,7 @@
#
######################################################
class Card:
def __init__(self, suit, rank):
self.suit = suit
@@ -19,14 +20,14 @@ class Card:
def __str__(self):
r = self.rank
if r == 11:
r = 'J'
r = "J"
elif r == 12:
r = 'Q'
r = "Q"
elif r == 13:
r = 'K'
r = "K"
elif r == 14:
r = 'A'
return f'{r}{self.suit}'
r = "A"
return f"{r}{self.suit}"
class Deck:
@@ -35,12 +36,13 @@ class Deck:
self.build()
def build(self):
for suit in ['\u2665', '\u2666', '\u2663', '\u2660']:
for suit in ["\u2665", "\u2666", "\u2663", "\u2660"]:
for rank in range(2, 15):
self.cards.append(Card(suit, rank))
def shuffle(self):
import random
random.shuffle(self.cards)
def deal(self):
@@ -69,34 +71,34 @@ class Game:
self.card_b = self.deck.deal()
card_b = self.card_b
print(f'You have:\t ${self.money} ')
print(f'Your cards:\t {card_a} {card_b}')
print(f"You have:\t ${self.money} ")
print(f"Your cards:\t {card_a} {card_b}")
bet = int(input('What is your bet? '))
bet = int(input("What is your bet? "))
player_card = self.deck.deal()
if 0 < bet <= self.money:
print(f'Your deal:\t {player_card}')
print(f"Your deal:\t {player_card}")
if card_a.rank < player_card.rank < card_b.rank:
print('You Win!')
print("You Win!")
self.money += bet
else:
print('You Lose!')
print("You Lose!")
self.money -= bet
self.not_done = False
else:
print('Chicken!')
print(f'Your deal should have been: {player_card}')
print("Chicken!")
print(f"Your deal should have been: {player_card}")
if card_a.rank < player_card.rank < card_b.rank:
print(f'You could have won!')
print(f"You could have won!")
else:
print(f'You would lose, so it was wise of you to chicken out!')
print(f"You would lose, so it was wise of you to chicken out!")
self.not_done = False
break
if len(self.deck.cards) <= 3:
print('You ran out of cards. Game over.')
print("You ran out of cards. Game over.")
self.not_done = False
break
@@ -107,22 +109,24 @@ class Game:
self.not_done = False
if __name__ == '__main__':
print('''
if __name__ == "__main__":
print(
"""
Acey Ducey is a card game where you play against the computer.
The Dealer(computer) will deal two cards facing up.
You have an option to bet or not bet depending on whether or not you
You have an option to bet or not bet depending on whether or not you
feel the card will have a value between the first two.
If you do not want to bet input a 0
''')
"""
)
GAME_OVER = False
while not GAME_OVER:
game = Game()
game.play()
print(f'You have ${game.money} left')
print('Would you like to play again? (y/n)')
if input() == 'n':
print(f"You have ${game.money} left")
print("Would you like to play again? (y/n)")
if input() == "n":
GAME_OVER = True
print('\nThanks for playing!')
print("\nThanks for playing!")

View File

@@ -1,7 +1,7 @@
Public Class AceyDucey
''' <summary>
''' Create a single instance of the Random class to be used
''' throughout the program.
''' Create a single instance of the Random class to be used
''' throughout the program.
''' </summary>
Private ReadOnly Property Rnd As New Random()
@@ -10,7 +10,7 @@
''' Defaults to 0
''' </summary>
''' <remarks>
''' Since <see cref="Integer"/> is a value type, and no value
''' Since <see cref="Integer"/> is a value type, and no value
''' has been explicitly set, the default value of the type is used.
''' </remarks>
Private _balance As Integer
@@ -51,7 +51,7 @@
''' Play one turn of Acey Ducey
''' </summary>
''' <remarks>
''' A turn consists of displaying to cards, making a wager
''' A turn consists of displaying to cards, making a wager
''' and determining the result (win/lose)
''' </remarks>
Private Sub PlayTurn()
@@ -80,11 +80,11 @@
'''
'''The use of AndAlso is used to short-circuit the evaluation of the IF condition.
'''Short-circuiting means that both sides of the condition do not need to be
'''evaluated. In this case, if the left criteria returns FALSE, the right criteria
'''evaluated. In this case, if the left criteria returns FALSE, the right criteria
'''is ignored and the evaluation result is returned as FALSE.
'''
'''This works because AndAlso requires both condition to return TRUE in order to be
'''evaluated as TRUE. If the first condition is FALSE we already know the evaluation result.
'''This works because AndAlso requires both condition to return TRUE in order to be
'''evaluated as TRUE. If the first condition is FALSE we already know the evaluation result.
If finalCard >= cards.First() AndAlso finalCard <= cards.Last() Then
Console.WriteLine("YOU WIN!!!")
_balance += wager 'Condensed version of _balance = _balance + wager
@@ -99,14 +99,14 @@
''' </summary>
''' <remarks>
''' The original version generates two cards (A and B)
''' If A is greater than or equal to B, both cards are regenerated.
''' <br/><br/>
''' This version generates the two cards, but only regenerates A
''' If A is greater than or equal to B, both cards are regenerated.
''' <br/><br/>
''' This version generates the two cards, but only regenerates A
''' if A is equal to B. The cards are then returned is ascending order,
''' ensuring that A is less than B (maintaining the original end result)
''' </remarks>
Private Function GetOrderedCards() As Integer()
'''When declaring fixed size arrays in VB.NET you declare the MAX INDEX of the array
'''When declaring fixed size arrays in VB.NET you declare the MAX INDEX of the array
'''and NOT the SIZE (number of elements) of the array.
'''As such, card(1) gives you and array with index 0 and index 1, which means
'''the array stores two elements and not one
@@ -133,7 +133,7 @@
End Function
''' <summary>
''' Display the face value of the card
''' Display the face value of the card
''' </summary>
Private Sub DisplayCard(card As Integer)
Dim output As String
@@ -221,7 +221,7 @@
''' Display the opening title and instructions
''' </summary>
''' <remarks>
''' Refer to
''' Refer to
''' <see href="https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/strings/interpolated-strings">
''' Interpolated Strings
''' </see> documentation for the use of $ and { } with strings

View File

@@ -2,16 +2,16 @@ Imports System
''' <summary>
''' This is a modern adapation of Acey Ducey from BASIC Computer Games.
'''
'''
''' The structural changes primarily consist of replacing the many GOTOs with
''' Do/Loop constructs to force the continual execution of the program.
'''
''' Some modern improvements were added, primarily the inclusion of a multiple
''' subroutines and functions, which eliminates repeated logic and reduces
''' then need for nested loops.
'''
'''
''' Some modern improvements were added, primarily the inclusion of a multiple
''' subroutines and functions, which eliminates repeated logic and reduces
''' then need for nested loops.
'''
''' The archaic RND function is greatly simplified with the .NET Framework's Random class.
'''
'''
''' Elementary comments are provided for non-programmers or novices.
''' </summary>
Module Program

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
namespace Amazing
{
using System;
using System.Collections.Generic;
namespace Amazing
{
class AmazingGame
{
private const int FIRST_COL = 0;
@@ -35,9 +35,9 @@ namespace Amazing
}
public void Play()
{
Console.WriteLine(Tab(28) + "AMAZING PROGRAM");
Console.WriteLine(Tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
{
Console.WriteLine(Tab(28) + "AMAZING PROGRAM");
Console.WriteLine(Tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
Console.WriteLine();
int width = 0;
@@ -113,25 +113,25 @@ namespace Amazing
{
if (i == enterCol) Console.Write(". ");
else Console.Write(".--");
}
Console.WriteLine(".");
}
Console.WriteLine(".");
for (int i = 0; i < grid.Length; i++)
{
{
Console.Write("I");
for (int j = 0; j < grid.Width; j++)
{
if (grid.Cells[i,j].ExitType == EXIT_UNSET || grid.Cells[i, j].ExitType == EXIT_DOWN)
Console.Write(" I");
else Console.Write(" ");
}
Console.WriteLine();
}
Console.WriteLine();
for (int j = 0; j < grid.Width; j++)
{
if (grid.Cells[i,j].ExitType == EXIT_UNSET || grid.Cells[i, j].ExitType == EXIT_RIGHT)
Console.Write(":--");
else Console.Write(": ");
}
}
Console.WriteLine(".");
}
}
@@ -164,7 +164,7 @@ namespace Amazing
}
private String DisplayTextAndGetInput(String text)
{
{
Console.WriteLine(text);
return Console.ReadLine();
}
@@ -308,13 +308,13 @@ namespace Amazing
return newCell;
}
}
}
class Program
{
static void Main(string[] args)
}
class Program
{
static void Main(string[] args)
{
new AmazingGame().Play();
}
}
}
new AmazingGame().Play();
}
}
}

View File

@@ -259,4 +259,4 @@ public class Amazing {
return newCell;
}
}
}
}

View File

@@ -12,10 +12,10 @@ 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");

View File

@@ -14,4 +14,3 @@ begin
AmazingApp:= TAmazingApplication.Create;
AmazingApp.Run;
end.

View File

@@ -101,4 +101,3 @@ begin
end;
end.

View File

@@ -277,4 +277,3 @@ begin
end;
end.

View File

@@ -68,4 +68,3 @@ begin
end;
end.

View File

@@ -281,4 +281,3 @@ begin
//DebugWalls;
PrintMaze;
end.

View File

@@ -79,7 +79,7 @@ sub input_dimensions {
print 'WHAT ARE YOUR WIDTH AND LENGTH? ';
($w, $h) = <STDIN> =~ / \d+ /xg;
if ($w < 1 || $h < 1) {
say "MEANINGLESS DIMENSIONS. TRY AGAIN."
}

View File

@@ -1,20 +1,20 @@
import random
# Python translation by Frank Palazzolo - 2/2021
print(' '*28+'AMAZING PROGRAM')
print(' '*15+'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY')
print(" " * 28 + "AMAZING PROGRAM")
print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
while True:
width, length = input('What are your width and length?').split(',')
width, length = input("What are your width and length?").split(",")
width = int(width)
length = int(length)
if width != 1 and length != 1:
break
print('Meaningless dimensions. Try again.')
print("Meaningless dimensions. Try again.")
# Build two 2D arrays
#
@@ -32,90 +32,87 @@ while True:
used = []
walls = []
for i in range(length):
used.append([0]*width)
walls.append([0]*width)
used.append([0] * width)
walls.append([0] * width)
# Use direction variables with nice names
GO_LEFT,GO_UP,GO_RIGHT,GO_DOWN=[0,1,2,3]
GO_LEFT, GO_UP, GO_RIGHT, GO_DOWN = [0, 1, 2, 3]
# Give Exit directions nice names
EXIT_DOWN = 1
EXIT_RIGHT = 2
# Pick a random entrance, mark as used
enter_col=random.randint(0,width-1)
row,col=0,enter_col
count=1
used[row][col]=count
count=count+1
enter_col = random.randint(0, width - 1)
row, col = 0, enter_col
count = 1
used[row][col] = count
count = count + 1
while count!=width*length+1:
while count != width * length + 1:
# remove possible directions that are blocked or
# hit cells that we have already processed
possible_dirs = [GO_LEFT,GO_UP,GO_RIGHT,GO_DOWN]
if col==0 or used[row][col-1]!=0:
possible_dirs = [GO_LEFT, GO_UP, GO_RIGHT, GO_DOWN]
if col == 0 or used[row][col - 1] != 0:
possible_dirs.remove(GO_LEFT)
if row==0 or used[row-1][col]!=0:
if row == 0 or used[row - 1][col] != 0:
possible_dirs.remove(GO_UP)
if col==width-1 or used[row][col+1]!=0:
if col == width - 1 or used[row][col + 1] != 0:
possible_dirs.remove(GO_RIGHT)
if row==length-1 or used[row+1][col]!=0:
possible_dirs.remove(GO_DOWN)
if row == length - 1 or used[row + 1][col] != 0:
possible_dirs.remove(GO_DOWN)
# If we can move in a direction, move and make opening
if len(possible_dirs)!=0:
direction=random.choice(possible_dirs)
if direction==GO_LEFT:
col=col-1
walls[row][col]=EXIT_RIGHT
elif direction==GO_UP:
row=row-1
walls[row][col]=EXIT_DOWN
elif direction==GO_RIGHT:
walls[row][col]=walls[row][col]+EXIT_RIGHT
col=col+1
elif direction==GO_DOWN:
walls[row][col]=walls[row][col]+EXIT_DOWN
row=row+1
used[row][col]=count
count=count+1
if len(possible_dirs) != 0:
direction = random.choice(possible_dirs)
if direction == GO_LEFT:
col = col - 1
walls[row][col] = EXIT_RIGHT
elif direction == GO_UP:
row = row - 1
walls[row][col] = EXIT_DOWN
elif direction == GO_RIGHT:
walls[row][col] = walls[row][col] + EXIT_RIGHT
col = col + 1
elif direction == GO_DOWN:
walls[row][col] = walls[row][col] + EXIT_DOWN
row = row + 1
used[row][col] = count
count = count + 1
# otherwise, move to the next used cell, and try again
else:
while True:
if col!=width-1:
col=col+1
elif row!=length-1:
row,col=row+1,0
if col != width - 1:
col = col + 1
elif row != length - 1:
row, col = row + 1, 0
else:
row,col=0,0
if used[row][col]!=0:
row, col = 0, 0
if used[row][col] != 0:
break
# Add a random exit
col=random.randint(0,width-1)
row=length-1
walls[row][col]=walls[row][col]+1
col = random.randint(0, width - 1)
row = length - 1
walls[row][col] = walls[row][col] + 1
# Print the maze
for col in range(width):
if col==enter_col:
print('. ',end='')
if col == enter_col:
print(". ", end="")
else:
print('.--',end='')
print('.')
print(".--", end="")
print(".")
for row in range(length):
print('I',end='')
print("I", end="")
for col in range(width):
if walls[row][col]<2:
print(' I',end='')
if walls[row][col] < 2:
print(" I", end="")
else:
print(' ',end='')
print(" ", end="")
print()
for col in range(width):
if walls[row][col]==0 or walls[row][col]==2:
print(':--',end='')
if walls[row][col] == 0 or walls[row][col] == 2:
print(":--", end="")
else:
print(': ',end='')
print('.')
print(": ", end="")
print(".")

View File

@@ -213,4 +213,4 @@ class Amazing
end
end
Amazing.new.run
Amazing.new.run

View File

@@ -145,7 +145,7 @@ Module Program
Return SelectRandomDirection(Directions.Up, Directions.Down)
ElseIf SolutionCompleted Then 'We're on the bottom row, can only go up
Return GoUp()
Else 'We're on the bottom row, can only go up, but there's no solution
Else 'We're on the bottom row, can only go up, but there's no solution
Return SelectRandomDirection(Directions.Up, Directions.SolveAndReset)
End If
'== Definitely can go Up and Right ==

View File

@@ -15,4 +15,4 @@
return $"{Text} : IsEnd {IsEnd}";
}
}
}
}

View File

@@ -244,4 +244,3 @@ public class Animal {
}
}

View File

@@ -28,16 +28,16 @@ class AnimalJavaTest : ConsoleTest() {
DOES IT SWIM ? {NO}
IS IT A BIRD ? {NO}
THE ANIMAL YOU WERE THINKING OF WAS A ? {COW}
PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A
PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A
COW FROM A BIRD
? {DOES IT EAT GRASS}
FOR A COW THE ANSWER WOULD BE ? {YES}
ARE YOU THINKING OF AN ANIMAL ? {YES}
DOES IT SWIM ? {NO}
DOES IT EAT GRASS ? {YES}
DOES IT EAT GRASS ? {YES}
IS IT A COW ? {YES}
WHY NOT TRY ANOTHER ANIMAL?
ARE YOU THINKING OF AN ANIMAL ? {QUIT}
ARE YOU THINKING OF AN ANIMAL ? {QUIT}
"""
) {
Animal.main(emptyArray())
@@ -47,9 +47,8 @@ class AnimalJavaTest : ConsoleTest() {
private val title = """
ANIMAL
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
PLAY 'GUESS THE ANIMAL'
THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.
"""
}

View File

@@ -12,10 +12,10 @@ 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");
@@ -70,7 +70,7 @@ n = animals.length;
function show_animals() {
var x;
print("\n");
print("ANIMALS I ALREADY KNOW ARE:\n");
str = "";
@@ -108,7 +108,7 @@ async function main()
if (str[0] == "Y")
break;
}
k = 0;
do {
// Subroutine to print questions
@@ -119,7 +119,7 @@ async function main()
if (q[z] == "\\")
break;
str += q[z];
}
}
print(str);
c = await input();
if (c[0] == "Y" || c[0] == "N")
@@ -127,9 +127,9 @@ async function main()
}
t = "\\" + c[0];
x = q.indexOf(t);
k = parseInt(q.substr(x + 2));
k = parseInt(q.substr(x + 2));
} while (animals[k].substr(0,2) == "\\Q") ;
print("IS IT A " + animals[k].substr(2));
a = await input();
if (a[0] == "Y") {

View File

@@ -28,16 +28,16 @@ class AnimalKtTest : ConsoleTest() {
DOES IT SWIM? {NO}
IS IT A BIRD? {NO}
THE ANIMAL YOU WERE THINKING OF WAS A? {COW}
PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A
PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A
COW FROM A BIRD
? {DOES IT EAT GRASS}
FOR A COW THE ANSWER WOULD BE? {YES}
ARE YOU THINKING OF AN ANIMAL? {YES}
DOES IT SWIM? {NO}
DOES IT EAT GRASS? {YES}
DOES IT EAT GRASS? {YES}
IS IT A COW? {YES}
WHY NOT TRY ANOTHER ANIMAL?
ARE YOU THINKING OF AN ANIMAL? {QUIT}
ARE YOU THINKING OF AN ANIMAL? {QUIT}
"""
) {
main()
@@ -47,9 +47,8 @@ class AnimalKtTest : ConsoleTest() {
private val title = """
ANIMAL
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
PLAY 'GUESS THE ANIMAL'
THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.
"""
}

View File

@@ -61,7 +61,7 @@ class Node:
# we replace the animal with a new question
self.text = new_question
if answer_new_ques == 'y':
if answer_new_ques == "y":
self.yes_node = Node(new_animal, None, None)
self.no_node = Node(old_animal, None, None)
else:
@@ -79,7 +79,7 @@ def list_known_animals(root_node):
return
if root_node.is_leaf():
print(root_node.text, end=' '*11)
print(root_node.text, end=" " * 11)
return
if root_node.yes_node:
@@ -96,13 +96,13 @@ def parse_input(message, check_list, root_node):
try:
inp = input(message)
if check_list and inp.lower() == 'list':
print('Animals I already know are:')
if check_list and inp.lower() == "list":
print("Animals I already know are:")
list_known_animals(root_node)
print('\n')
print("\n")
token = inp[0].lower()
if token == 'y' or token == 'n':
if token == "y" or token == "n":
correct_input = True
except IndexError:
pass
@@ -111,28 +111,27 @@ def parse_input(message, check_list, root_node):
def avoid_void_input(message):
answer = ''
while answer == '':
answer = ""
while answer == "":
answer = input(message)
return answer
def initial_message():
print(' '*32 + 'Animal')
print(' '*15 + 'Creative Computing Morristown, New Jersey\n')
print('Play ´Guess the Animal´')
print('Think of an animal and the computer will try to guess it.\n')
print(" " * 32 + "Animal")
print(" " * 15 + "Creative Computing Morristown, New Jersey\n")
print("Play ´Guess the Animal´")
print("Think of an animal and the computer will try to guess it.\n")
# Initial tree
yes_child = Node('Fish', None, None)
no_child = Node('Bird', None, None)
root = Node('Does it swim?', yes_child, no_child)
yes_child = Node("Fish", None, None)
no_child = Node("Bird", None, None)
root = Node("Does it swim?", yes_child, no_child)
# Main loop of game
initial_message()
keep_playing = parse_input(
'Are you thinking of an animal? ', True, root) == 'y'
keep_playing = parse_input("Are you thinking of an animal? ", True, root) == "y"
while keep_playing:
keep_asking = True
# Start traversing the tree by the root
@@ -144,33 +143,37 @@ while keep_playing:
# we have to keep asking i.e. traversing nodes
answer = parse_input(actual_node.text, False, None)
if answer == 'y':
if answer == "y":
actual_node = actual_node.yes_node
else:
actual_node = actual_node.no_node
else:
# we have reached a possible answer
answer = parse_input('Is it a {}? '.format(
actual_node.text), False, None)
if answer == 'n':
answer = parse_input(f"Is it a {actual_node.text}? ", False, None)
if answer == "n":
# add the new animal to the tree
new_animal = avoid_void_input(
'The animal you were thinking of was a ? ')
"The animal you were thinking of was a ? "
)
new_question = avoid_void_input(
'Please type in a question that would distinguish a {} from a {}: '.format(new_animal, actual_node.text))
"Please type in a question that would distinguish a {} from a {}: ".format(
new_animal, actual_node.text
)
)
answer_new_question = parse_input(
'for a {} the answer would be: '.format(new_animal), False, None)
f"for a {new_animal} the answer would be: ", False, None
)
actual_node.update_node(
new_question+'?', answer_new_question, new_animal)
new_question + "?", answer_new_question, new_animal
)
else:
print("Why not try another animal?")
keep_asking = False
keep_playing = parse_input(
'Are you thinking of an animal? ', True, root) == 'y'
keep_playing = parse_input("Are you thinking of an animal? ", True, root) == "y"
########################################################

View File

@@ -92,4 +92,4 @@ end
trap "SIGINT" do puts; exit 130 end
main
main

View File

@@ -4,6 +4,6 @@ Conversion to [Visual Basic .NET](https://en.wikipedia.org/wiki/Visual_Basic_.NE
This takes some inspiration from the [C# port of Animal](https://github.com/zspitz/basic-computer-games/tree/main/03_Animal/csharp).
The `Game` class takes a console abstraction (`ConsoleAdapterBase`), which could also be used for different UIs, such as WinForms or a web page.
This solution also has an xUnit tests project.
The `Game` class takes a console abstraction (`ConsoleAdapterBase`), which could also be used for different UIs, such as WinForms or a web page.
This solution also has an xUnit tests project.
Responses can be entered in any capitalization, but animals and the distinguishing question will be converted to uppercase.

View File

@@ -261,4 +261,4 @@ public enum GameWinner
Draw,
}
public record struct GameOutcome(GameWinner Winner, int Difference);
public record struct GameOutcome(GameWinner Winner, int Difference);

View File

@@ -95,4 +95,4 @@ void ComputerTurn()
Console.WriteLine($"MY MOVE IS {movesString}");
}
string Tab(int n) => new(' ', n);
string Tab(int n) => new(' ', n);

View File

@@ -12,10 +12,10 @@ 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");
@@ -65,7 +65,7 @@ function show_number(number)
function show_board()
{
var i;
print("\n");
print(" ");
for (i = 12; i >= 7; i--)
@@ -184,12 +184,12 @@ async function main()
e = 0;
for (i = 0; i <= 12; i++)
b[i] = 3;
c = 0;
f[n] = 0;
b[13] = 0;
b[6] = 0;
while (1) {
show_board();
print("YOUR MOVE");

View File

@@ -54,7 +54,7 @@ namespace BasicComputerGames.Bagels
_digits = number.Select(d => d - '0').ToArray();
}
//public BagelNumber(long number)
//{
// var digits = new List<int>();
@@ -118,4 +118,4 @@ namespace BasicComputerGames.Bagels
return (pico, fermi);
}
}
}
}

View File

@@ -121,4 +121,4 @@ namespace BasicComputerGames.Bagels
Console.ReadKey(true);
}
}
}
}

View File

@@ -36,4 +36,4 @@ namespace BasicComputerGames.Bagels
}
}
}
}

View File

@@ -16,34 +16,34 @@ import java.util.Random;
import java.util.Set;
public class BagelGame {
public static final String CORRECT = "FERMI FERMI FERMI";
public static final int MAX_GUESSES = 20;
enum GameState {
RUNNING,
WON,
LOST
}
private GameState state = GameState.RUNNING;
private List<Integer> secretNum;
private int guessNum = 1;
public BagelGame() {
// No-arg constructor for when you don't need to set the seed
this(new Random());
}
public BagelGame(long seed) {
// Setting the seed as a long value
this(new Random(seed));
}
public BagelGame(Random rand) {
// This is the "real" constructor, which expects an instance of
// Random to use for shuffling the digits of the secret number.
// Since the digits cannot repeat in our "number", we can't just
// pick three random 0-9 integers. Instead, we'll treat it like
// a deck of ten cards, numbered 0-9.
@@ -57,23 +57,23 @@ public class BagelGame {
// uses a fresh Random class PRNG, but we're supplying our own
// to give us controll over whether or not we set the seed
Collections.shuffle(digits, rand);
// Just take the first three digits
secretNum = digits.subList(0, 3);
}
public boolean isOver() {
return state != GameState.RUNNING;
}
public boolean isWon() {
return state == GameState.WON;
}
public int getGuessNum() {
return guessNum;
}
public String getSecretAsString() {
// Convert the secret number to a three-character string
String secretString = "";
@@ -82,7 +82,7 @@ public class BagelGame {
}
return secretString;
}
@Override
public String toString() {
// Quick report of game state for debugging purposes
@@ -91,13 +91,13 @@ public class BagelGame {
s += "Secret Number: " + secretNum;
return s;
}
public String validateGuess(String guess) {
// Checks the passed string and returns null if it's a valid guess
// (i.e., exactly three numeric characters)
// If not valid, returns an "error" string to display to user.
String error = "";
if (guess.length() == 3) {
// Correct length. Are all the characters numbers?
try {
@@ -122,20 +122,20 @@ public class BagelGame {
return error;
}
public String makeGuess(String s) throws IllegalArgumentException {
// Processes the passed guess string (which, ideally, should be
// validated by previously calling validateGuess)
// Return a response string (PICO, FERMI, etc.) if valid
// Also sets game state accordingly (sets win state or increments
// number of guesses)
// Convert string to integer list, just to keep things civil
List<Integer> guess = new ArrayList<Integer>(3);
for (int i = 0; i < 3; i++) {
guess.add((int)s.charAt(i) - 48);
}
// Build response string...
String response = "";
// Correct digit, but in wrong place?
@@ -177,5 +177,5 @@ public class BagelGame {
}
return response;
}
}
}

View File

@@ -35,7 +35,7 @@ import java.util.Scanner;
public class Bagels {
public static void main(String[] args) {
int gamesWon = 0;
// Intro text
@@ -43,7 +43,7 @@ public class Bagels {
System.out.println("Creative Computing Morristown, New Jersey");
System.out.println("\n\n");
System.out.print("Would you like the rules (Yes or No)? ");
// Need instructions?
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
@@ -55,15 +55,15 @@ public class Bagels {
System.out.println(" FERMI - One digit correct and in the right position");
System.out.println(" BAGELS - No digits correct");
}
// Loop for playing multiple games
boolean stillPlaying = true;
while(stillPlaying) {
// Set up a new game
BagelGame game = new BagelGame();
System.out.println("\nO.K. I have a number in mind.");
// Loop guess and responsses until game is over
while (!game.isOver()) {
String guess = getValidGuess(game);
@@ -73,7 +73,7 @@ public class Bagels {
System.out.println(response);
}
}
// Game is over. But did we win or lose?
if (game.isWon()) {
System.out.println("You got it!!!\n");
@@ -83,24 +83,24 @@ public class Bagels {
System.out.print("That's " + BagelGame.MAX_GUESSES + " guesses. ");
System.out.println("My number was " + game.getSecretAsString());
}
stillPlaying = getReplayResponse();
}
// Print goodbye message
if (gamesWon > 0) {
System.out.println("\nA " + gamesWon + " point Bagels buff!!");
}
System.out.println("Hope you had fun. Bye.\n");
}
private static String getValidGuess(BagelGame game) {
// Keep asking for a guess until valid
Scanner scan = new Scanner(System.in);
boolean valid = false;
String guess = "";
String error;
while (!valid) {
System.out.print("Guess # " + game.getGuessNum() + " ? ");
guess = scan.nextLine().trim();
@@ -113,7 +113,7 @@ public class Bagels {
}
return guess;
}
private static boolean getReplayResponse() {
// keep asking for response until valid
Scanner scan = new Scanner(System.in);
@@ -126,8 +126,5 @@ public class Bagels {
}
}
}
}

View File

@@ -12,10 +12,10 @@ 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");
@@ -154,7 +154,7 @@ async function main()
print("HOPE YOU HAD FUN. BYE.\n");
else
print("\nA " + y + " POINT BAGELS BUFF!!\n");
}
main();

View File

@@ -20,7 +20,7 @@ sub yes_input {
print ' 'x32; print "Bagels\n";
print ' 'x14; print "Creative Computing Morristown, New Jersey\n\n";
# Provide instructions if requested
# Provide instructions if requested
print "Would you like the rules (yes or no)? ";
if (yes_input()) {
@@ -39,7 +39,7 @@ HERE
# There are three code loops here. The outermost one, labeled 'PLAY',
# performs one game start to finish every time it runs.
# The next loop is a for loop that implements the required 20 guesses.
# And the innermost loop, labeled 'CHECK', does the game logic of
# And the innermost loop, labeled 'CHECK', does the game logic of
# checking the user's guess to make sure it's valid, figuring out
# the response, and rewarding the user if they won.
@@ -59,7 +59,7 @@ PLAY: while (1) {
# Note that the CHECK loop will automatically loop to ask
# for the user's input, and it's only with the 'next' and
# 'last' statements that this loop is exited. So if the
# 'last' statements that this loop is exited. So if the
# user's input is somehow invalid, we just print out an
# appropriate message. Execution will by default return
# to the start of the loop, and only leaves the loop if
@@ -75,15 +75,15 @@ PLAY: while (1) {
if ($A !~ m{^(\d)(\d)(\d)$}) {
print "What?\n";
# Program execution will now pass through the rest
# of the logic below and loop back to the start
# of the logic below and loop back to the start
# of the CHECK loop.
} else {
# As a side effect of the regex match above, the
# As a side effect of the regex match above, the
# $1, $2, and $3 variables are each of the digits
# of the user's guess. Perl treats numbers and
# strings interchangably, so we will not have to
# use the ASC() conversion functions required
# use the ASC() conversion functions required
# by the BASIC program.
my @B = ($1,$2,$3);
@@ -134,11 +134,11 @@ PLAY: while (1) {
# Print out the clues. The 'x' operator
# prints out the string the indicated number
# of times. The "BAGELS" line uses Perl's
# ternary operator to print the word if
# of times. The "BAGELS" line uses Perl's
# ternary operator to print the word if
# the expression ($C + $D) is equal to 0.
printf("%s%s%s\n",
printf("%s%s%s\n",
"PICO " x$C,
"FERMI "x$D,
($C+$D==0 ? "BAGELS" : '')
@@ -152,11 +152,11 @@ PLAY: while (1) {
} # end of regex match else block
# If program execution reaches this particular point,
# then the user's input has not been accepted (the
# then the user's input has not been accepted (the
# only ways out of this loop are the "next PLAY" statement
# when the user wins, and the "last CHECK" statement
# when the user's input is successfully parsed).
# So the program execution goes back to the top of the
# So the program execution goes back to the top of the
# CHECK loop, printing the request for user input
# again.
@@ -183,7 +183,7 @@ continue {
# This 'continue' loop is reached either when the PLAY loop has completed
# or via the 'next PLAY' statement when the user wins a game. In either
# case we ask if the player wants to go again, and use the 'last'
# case we ask if the player wants to go again, and use the 'last'
# statement to exit the loop if the response is not yes.
print "Play again (yes or no) ? ";
last unless yes_input();

View File

@@ -37,7 +37,6 @@ import random
MAX_GUESSES = 20
def print_rules():
print("\nI am thinking of a three-digit number. Try to guess")
print("my number and I will give you clues as follows:")
@@ -46,18 +45,16 @@ def print_rules():
print(" BAGELS - No digits correct")
def pick_number():
# Note that this returns a list of individual digits
# as separate strings, not a single integer or string
numbers = [i for i in range(10)]
random.shuffle(numbers)
num = numbers[0:3]
num = [str(i) for i in num]
num = [str(i) for i in num]
return num
def get_valid_guess():
valid = False
while not valid:
@@ -71,8 +68,9 @@ def get_valid_guess():
if len(set(guess)) == 3:
valid = True
else:
print("Oh, I forgot to tell you that " +
"the number I have in mind")
print(
"Oh, I forgot to tell you that " + "the number I have in mind"
)
print("has no two digits the same.")
else:
print("What?")
@@ -82,16 +80,15 @@ def get_valid_guess():
return guess
def build_result_string(num, guess):
result = ""
# Correct digits in wrong place
for i in range(2):
if num[i] == guess[i+1]:
if num[i] == guess[i + 1]:
result += "PICO "
if num[i+1] == guess[i]:
if num[i + 1] == guess[i]:
result += "PICO "
if num[0] == guess[2]:
result += "PICO "
@@ -110,8 +107,6 @@ def build_result_string(num, guess):
return result
######################################################################
@@ -123,7 +118,7 @@ print("\n\n")
# Anything other than N* will show the rules
response = input("Would you like the rules (Yes or No)? ")
if len(response) > 0:
if response.upper()[0] != 'N':
if response.upper()[0] != "N":
print_rules()
else:
print_rules()
@@ -134,7 +129,7 @@ while still_running:
# New round
num = pick_number()
num_str = ''.join(num)
num_str = "".join(num)
guesses = 1
print("\nO.K. I have a number in mind.")
@@ -147,15 +142,13 @@ while still_running:
print("You got it!!!\n")
games_won += 1
guessing = False
else:
else:
print(build_result_string(num, guess))
guesses += 1
if guesses > MAX_GUESSES:
print("Oh well")
print(f"That's {MAX_GUESSES} guesses. " +
"My number was " + num_str)
guessing = False
print(f"That's {MAX_GUESSES} guesses. " + "My number was " + num_str)
guessing = False
valid_response = False
while not valid_response:
@@ -172,7 +165,6 @@ if games_won > 0:
print("Hope you had fun. Bye.\n")
######################################################################
#
# Porting Notes
@@ -180,7 +172,7 @@ print("Hope you had fun. Bye.\n")
# The original program did an unusually good job of validating the
# player's input (compared to many of the other programs in the
# book). Those checks and responses have been exactly reproduced.
#
#
#
# Ideas for Modifications
#
@@ -192,10 +184,3 @@ print("Hope you had fun. Bye.\n")
# that creates the "result" string?
#
######################################################################

View File

@@ -162,7 +162,7 @@ namespace banner
// numSections decides how many 'sections' need to be printed
// for a given line of each character
int[] numSections = new int[7];
// fillInSection decides whether each 'section' of the
// fillInSection decides whether each 'section' of the
// character gets filled in with the character or with blanks
int[] fillInSection = new int[9];

View File

@@ -11,21 +11,21 @@ import java.lang.Math;
* <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.
*
*
* Converted from BASIC to Java by Darren Cardenas.
*/
public class Banner {
public class Banner {
private final Scanner scan; // For user input
public Banner() {
scan = new Scanner(System.in);
} // End of constructor Banner
public void play() {
public Banner() {
scan = new Scanner(System.in);
} // End of constructor Banner
public void play() {
int bitIndex = 0;
int centerFlag = 0;
@@ -38,19 +38,19 @@ public class Banner {
int vertical = 0;
int vIndex = 0;
int writeIndex = 0;
int[] writerMap = new int[10];
int[] writeLimit = new int[10];
int[] writeLimit = new int[10];
String centerResponse = "";
String characters = "";
String letter = "";
String lineContent = "";
String lineContent = "";
String setPage = "";
String statement = "";
String token = ""; // Print token
Map<String, int[]> symbolData = new HashMap<String, int[]>();
Map<String, int[]> symbolData = new HashMap<String, int[]>();
symbolData.put(" ", new int[]{0,0,0,0,0,0,0,0 });
symbolData.put("A", new int[]{0,505,37,35,34,35,37,505 });
symbolData.put("G", new int[]{0,125,131,258,258,290,163,101});
@@ -92,133 +92,133 @@ public class Banner {
symbolData.put("=", new int[]{0,41,41,41,41,41,41,41 });
symbolData.put("!", new int[]{0,1,1,1,384,1,1,1 });
symbolData.put("0", new int[]{0,57,69,131,258,131,69,57 });
symbolData.put(".", new int[]{0,1,1,129,449,129,1,1 });
symbolData.put(".", new int[]{0,1,1,129,449,129,1,1 });
System.out.print("HORIZONTAL? ");
System.out.print("HORIZONTAL? ");
horizontal = Integer.parseInt(scan.nextLine());
System.out.print("VERTICAL? ");
vertical = Integer.parseInt(scan.nextLine());
System.out.print("CENTERED? ");
System.out.print("VERTICAL? ");
vertical = Integer.parseInt(scan.nextLine());
System.out.print("CENTERED? ");
centerResponse = scan.nextLine().toUpperCase();
centerFlag = 0;
// Lexicographical comparison
if (centerResponse.compareTo("P") > 0) {
centerFlag = 1;
centerFlag = 1;
}
System.out.print("CHARACTER (TYPE 'ALL' IF YOU WANT CHARACTER BEING PRINTED)? ");
System.out.print("CHARACTER (TYPE 'ALL' IF YOU WANT CHARACTER BEING PRINTED)? ");
characters = scan.nextLine().toUpperCase();
System.out.print("STATEMENT? ");
statement = scan.nextLine().toUpperCase();
// Initiates the print
System.out.print("SET PAGE? ");
setPage = scan.nextLine();
setPage = scan.nextLine();
// Begin loop through statement letters
for (letterIndex = 1; letterIndex <= statement.length(); letterIndex++) {
for (letterIndex = 1; letterIndex <= statement.length(); letterIndex++) {
// Extract a letter
letter = String.valueOf(statement.charAt(letterIndex - 1));
// Begin loop through all symbol data
for (String symbolString: symbolData.keySet()) {
// Begin loop through all symbol data
for (String symbolString: symbolData.keySet()) {
// Begin letter handling
if (letter.equals(" ")) {
for (index = 1; index <= (7 * horizontal); index++) {
if (letter.equals(" ")) {
for (index = 1; index <= (7 * horizontal); index++) {
System.out.println("");
}
}
break;
} else if (letter.equals(symbolString)) {
} else if (letter.equals(symbolString)) {
token = characters;
if (characters.equals("ALL")) {
if (characters.equals("ALL")) {
token = symbolString;
}
}
for (dataIndex = 1; dataIndex <= 7; dataIndex++) {
// Avoid overwriting symbol data
tempVal = symbolData.get(symbolString)[dataIndex];
for (bitIndex = 8; bitIndex >= 0; bitIndex--) {
if (Math.pow(2, bitIndex) < tempVal) {
writerMap[9 - bitIndex] = 1;
tempVal -= Math.pow(2, bitIndex);
if (tempVal == 1) {
writeLimit[dataIndex] = 9 - bitIndex;
if (tempVal == 1) {
writeLimit[dataIndex] = 9 - bitIndex;
break;
}
} else {
writerMap[9 - bitIndex] = 0;
writerMap[9 - bitIndex] = 0;
}
} // End of bitIndex loop
for (hIndex = 1; hIndex <= horizontal; hIndex++) {
// Add whitespace for centering
// Add whitespace for centering
lineContent = " ".repeat((int)((63 - 4.5 * vertical) * centerFlag / token.length()));
for (writeIndex = 1; writeIndex <= writeLimit[dataIndex]; writeIndex++) {
if (writerMap[writeIndex] == 0) {
for (vIndex = 1; vIndex <= vertical; vIndex++) {
for (index = 1; index <= token.length(); index++) {
lineContent += " ";
}
}
if (writerMap[writeIndex] == 0) {
for (vIndex = 1; vIndex <= vertical; vIndex++) {
for (index = 1; index <= token.length(); index++) {
lineContent += " ";
}
}
} else {
for (vIndex = 1; vIndex <= vertical; vIndex++) {
for (vIndex = 1; vIndex <= vertical; vIndex++) {
lineContent += token;
}
}
}
} // End of writeIndex loop
System.out.println(lineContent);
} // End of hIndex loop
} // End of hIndex loop
} // End of dataIndex loop
// Add padding between letters
for (index = 1; index <= 2 * horizontal; index++) {
for (index = 1; index <= 2 * horizontal; index++) {
System.out.println("");
}
} // End letter handling
} // End loop through all symbol data
} // End loop through statement letters
// Add extra length to the banner
for (index = 1; index <= 75; index++) {
for (index = 1; index <= 75; index++) {
System.out.println("");
}
}
} // End of method play
} // End of method play
public static void main(String[] args) {
Banner game = new Banner();
game.play();
} // End of method main
} // End of class Banner

View File

@@ -12,10 +12,10 @@ 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");
@@ -107,7 +107,7 @@ async function main()
as = await input();
print("SET PAGE"); // This means to prepare printer, just press Enter
os = await input();
for (t = 0; t < as.length; t++) {
ps = as.substr(t, 1);
for (o = 0; o < 50 * 8; o += 8) {
@@ -156,13 +156,13 @@ async function main()
str += xs;
}
}
print(str + "\n");
print(str + "\n");
}
}
for (h = 1; h <= 2 * x; h++)
for (h = 1; h <= 2 * x; h++)
print("\n");
}
}
}
}
main();

View File

@@ -77,8 +77,7 @@ def print_banner():
g1 = 0
if input("Centered ").lower().startswith("y"):
g1 = 1
mStr = input(
"Character (type 'ALL' if you want character being printed) ").upper()
mStr = input("Character (type 'ALL' if you want character being printed) ").upper()
aStr = input("Statement ")
# This means to prepare printer, just press Enter
oStr = input("Set page ")
@@ -92,11 +91,11 @@ def print_banner():
else:
for u in range(0, 7):
for k in range(8, -1, -1):
if 2 ** k >= s[u]:
if 2**k >= s[u]:
j[8 - k] = 0
else:
j[8 - k] = 1
s[u] = s[u] - 2 ** k
s[u] = s[u] - 2**k
if s[u] == 1:
f[u] = 8 - k
break

View File

@@ -146,7 +146,7 @@ Module Banner
' numSections decides how many 'sections' need to be printed
' for a given line of each character
Dim numSections(7) As Integer
' fillInSection decides whether each 'section' of the
' fillInSection decides whether each 'section' of the
' character gets filled in with the character Or with blanks
Dim fillInSection(9) As Integer

View File

@@ -1,5 +1,5 @@
import java.lang.Math;
import java.util.*;
import java.util.*;
import java.util.Scanner;
/* The basketball class is a computer game that allows you to play as
@@ -15,7 +15,7 @@ public class Basketball {
int shot = -1;
List<Integer> shot_choices = Arrays.asList(0, 1, 2, 3, 4);
double opponent_chance = 0;
String opponent = null;
String opponent = null;
public Basketball() {
@@ -41,7 +41,7 @@ public class Basketball {
else {
scanner.next();
}
// makes sure that input is legal
while (!defense_choices.contains(defense)) {
System.out.print("Your new defensive allignment is? ");
@@ -57,7 +57,7 @@ public class Basketball {
// takes input for opponent's name
System.out.print("\nChoose your opponent? ");
opponent = scanner.next();
opponent = scanner.next();
start_of_period();
}
@@ -67,13 +67,13 @@ public class Basketball {
score[team] += points;
print_score();
}
private void ball_passed_back() {
System.out.print("Ball passed back to you. ");
dartmouth_ball();
}
// change defense, called when the user enters 0 for their shot
private void change_defense() {
defense = -1;
@@ -82,13 +82,13 @@ public class Basketball {
while (!defense_choices.contains(defense)) {
System.out.println("Your new defensive allignment is? ");
if (scanner.hasNextDouble()) {
defense = (double)(scanner.nextDouble());
defense = (double)(scanner.nextDouble());
}
else {
continue;
continue;
}
}
dartmouth_ball();
}
@@ -102,15 +102,15 @@ public class Basketball {
}
else {
System.out.println("Shooter makes one shot and misses one.");
score[team] += 1;
}
score[team] += 1;
}
}
else {
System.out.println("Shooter makes both shots.");
score[team] += 2;
}
print_score();
print_score();
}
// called when time = 50, starts a new period
@@ -127,13 +127,13 @@ public class Basketball {
// simulates a center jump for posession at the beginning of a period
private void start_of_period() {
System.out.println("Center jump");
System.out.println("Center jump");
if (Math.random() > .6) {
System.out.println("Dartmouth controls the tap.\n");
System.out.println("Dartmouth controls the tap.\n");
dartmouth_ball();
}
else {
System.out.println(opponent + " controls the tap.\n");
System.out.println(opponent + " controls the tap.\n");
opponent_ball();
}
}
@@ -142,10 +142,10 @@ public class Basketball {
private void two_minute_warning() {
System.out.println(" *** Two minutes left in the game ***");
}
// called when the user enters 1 or 2 for their shot
private void dartmouth_jump_shot() {
time ++;
time ++;
if (time == 50) {
halftime();
}
@@ -171,135 +171,135 @@ public class Basketball {
else {
if (Math.random() > .5) {
System.out.println("Shot is blocked. Ball controlled by " +
opponent + ".\n");
opponent_ball();
}
opponent + ".\n");
opponent_ball();
}
else {
System.out.println("Shot is blocked. Ball controlled by Dartmouth.");
dartmouth_ball();
}
System.out.println("Shot is blocked. Ball controlled by Dartmouth.");
dartmouth_ball();
}
}
}
else {
System.out.println("Shot is off target.");
System.out.println("Shot is off target.");
if (defense / 6 * Math.random() > .45) {
System.out.println("Rebound to " + opponent + "\n");
opponent_ball();
}
System.out.println("Rebound to " + opponent + "\n");
opponent_ball();
}
else {
System.out.println("Dartmouth controls the rebound.");
System.out.println("Dartmouth controls the rebound.");
if (Math.random() > .4) {
if (defense == 6 && Math.random() > .6) {
System.out.println("Pass stolen by " + opponent
+ ", easy lay up");
add_points(0, 2);
dartmouth_ball();
}
+ ", easy lay up");
add_points(0, 2);
dartmouth_ball();
}
else {
// ball is passed back to you
ball_passed_back();
}
ball_passed_back();
}
}
else {
System.out.println("");
dartmouth_non_jump_shot();
System.out.println("");
dartmouth_non_jump_shot();
}
}
}
}
}
else {
System.out.println("Shot is good.");
add_points(1, 2);
opponent_ball();
System.out.println("Shot is good.");
add_points(1, 2);
opponent_ball();
}
}
// called when the user enters 0, 3, or 4
// lay up, set shot, or defense change
private void dartmouth_non_jump_shot() {
time ++;
time ++;
if (time == 50) {
halftime();
}
else if (time == 92) {
two_minute_warning();
}
if (shot == 4) {
System.out.println("Set shot.");
}
else if (shot == 3) {
System.out.println("Lay up.");
System.out.println("Lay up.");
}
else if (shot == 0) {
change_defense();
change_defense();
}
// simulates different outcomes after a lay up or set shot
if (7/defense*Math.random() > .4) {
if (7/defense*Math.random() > .7) {
if (7/defense*Math.random() > .875) {
if (7/defense*Math.random() > .925) {
System.out.println("Charging foul. Dartmouth loses the ball.\n");
opponent_ball();
System.out.println("Charging foul. Dartmouth loses the ball.\n");
opponent_ball();
}
else {
System.out.println("Shot blocked. " + opponent + "'s ball.\n");
opponent_ball();
System.out.println("Shot blocked. " + opponent + "'s ball.\n");
opponent_ball();
}
}
else {
foul_shots(1);
opponent_ball();
foul_shots(1);
opponent_ball();
}
}
else {
System.out.println("Shot is off the rim.");
System.out.println("Shot is off the rim.");
if (Math.random() > 2/3) {
System.out.println("Dartmouth controls the rebound.");
System.out.println("Dartmouth controls the rebound.");
if (Math.random() > .4) {
System.out.println("Ball passed back to you.\n");
dartmouth_ball();
System.out.println("Ball passed back to you.\n");
dartmouth_ball();
}
else {
dartmouth_non_jump_shot();
dartmouth_non_jump_shot();
}
}
else {
System.out.println(opponent + " controls the rebound.\n");
opponent_ball();
System.out.println(opponent + " controls the rebound.\n");
opponent_ball();
}
}
}
else {
System.out.println("Shot is good. Two points.");
add_points(1, 2);
opponent_ball();
System.out.println("Shot is good. Two points.");
add_points(1, 2);
opponent_ball();
}
}
// plays out a Dartmouth posession, starting with your choice of shot
private void dartmouth_ball() {
Scanner scanner = new Scanner(System.in); // creates a scanner
System.out.print("Your shot? ");
shot = -1;
System.out.print("Your shot? ");
shot = -1;
if (scanner.hasNextInt()) {
shot = scanner.nextInt();
shot = scanner.nextInt();
}
else {
System.out.println("");
scanner.next();
scanner.next();
}
while (!shot_choices.contains(shot)) {
System.out.print("Incorrect answer. Retype it. Your shot?");
if (scanner.hasNextInt()) {
shot = scanner.nextInt();
shot = scanner.nextInt();
}
else {
System.out.println("");
scanner.next();
scanner.next();
}
}
@@ -308,154 +308,154 @@ public class Basketball {
dartmouth_jump_shot();
}
else {
dartmouth_non_jump_shot();
dartmouth_non_jump_shot();
}
}
else {
if (score[0] != score[1]) {
System.out.println("\n ***** End Of Game *****");
System.out.println("\n ***** End Of Game *****");
System.out.println("Final Score: Dartmouth: " + score[1] + " "
+ opponent + ": " + score[0]);
+ opponent + ": " + score[0]);
System.exit(0);
}
else {
System.out.println("\n ***** End Of Second Half *****");
System.out.println("Score at end of regulation time:");
System.out.println("\n ***** End Of Second Half *****");
System.out.println("Score at end of regulation time:");
System.out.println(" Dartmouth: " + score[1] + " " +
opponent + ": " + score[0]);
System.out.println("Begin two minute overtime period");
time = 93;
start_of_period();
opponent + ": " + score[0]);
System.out.println("Begin two minute overtime period");
time = 93;
start_of_period();
}
}
}
// simulates the opponents jumpshot
private void opponent_jumpshot() {
System.out.println("Jump Shot.");
System.out.println("Jump Shot.");
if (8/defense*Math.random() > .35) {
if (8/defense*Math.random() > .75) {
if (8/defense*Math.random() > .9) {
System.out.println("Offensive foul. Dartmouth's ball.\n");
dartmouth_ball();
System.out.println("Offensive foul. Dartmouth's ball.\n");
dartmouth_ball();
}
else {
foul_shots(0);
dartmouth_ball();
foul_shots(0);
dartmouth_ball();
}
}
else {
System.out.println("Shot is off the rim.");
System.out.println("Shot is off the rim.");
if (defense/6*Math.random() > .5) {
System.out.println(opponent + " controls the rebound.");
if (defense == 6) {
if (Math.random() > .75) {
System.out.println("Ball stolen. Easy lay up for Dartmouth.");
add_points(1, 2);
opponent_ball();
System.out.println("Ball stolen. Easy lay up for Dartmouth.");
add_points(1, 2);
opponent_ball();
}
else {
if (Math.random() > .5) {
System.out.println("");
opponent_non_jumpshot();
System.out.println("");
opponent_non_jumpshot();
}
else {
System.out.println("Pass back to " + opponent +
" guard.\n");
opponent_ball();
" guard.\n");
opponent_ball();
}
}
}
else {
if (Math.random() > .5) {
opponent_non_jumpshot();
opponent_non_jumpshot();
}
else {
System.out.println("Pass back to " + opponent +
" guard.\n");
opponent_ball();
" guard.\n");
opponent_ball();
}
}
}
else {
System.out.println("Dartmouth controls the rebound.\n");
dartmouth_ball();
System.out.println("Dartmouth controls the rebound.\n");
dartmouth_ball();
}
}
}
}
else {
System.out.println("Shot is good.");
add_points(0, 2);
dartmouth_ball();
System.out.println("Shot is good.");
add_points(0, 2);
dartmouth_ball();
}
}
// simulates opponents lay up or set shot
private void opponent_non_jumpshot() {
if (opponent_chance > 3) {
System.out.println("Set shot.");
System.out.println("Set shot.");
}
else {
System.out.println("Lay up");
System.out.println("Lay up");
}
if (7/defense*Math.random() > .413) {
System.out.println("Shot is missed.");
System.out.println("Shot is missed.");
if (defense/6*Math.random() > .5) {
System.out.println(opponent + " controls the rebound.");
System.out.println(opponent + " controls the rebound.");
if (defense == 6) {
if (Math.random() > .75) {
System.out.println("Ball stolen. Easy lay up for Dartmouth.");
add_points(1, 2);
opponent_ball();
System.out.println("Ball stolen. Easy lay up for Dartmouth.");
add_points(1, 2);
opponent_ball();
}
else {
if (Math.random() > .5) {
System.out.println("");
opponent_non_jumpshot();
System.out.println("");
opponent_non_jumpshot();
}
else {
System.out.println("Pass back to " + opponent +
" guard.\n");
opponent_ball();
" guard.\n");
opponent_ball();
}
}
}
else {
if (Math.random() > .5) {
System.out.println("");
opponent_non_jumpshot();
System.out.println("");
opponent_non_jumpshot();
}
else {
System.out.println("Pass back to " + opponent + " guard\n");
opponent_ball();
System.out.println("Pass back to " + opponent + " guard\n");
opponent_ball();
}
}
}
else {
System.out.println("Dartmouth controls the rebound.\n");
dartmouth_ball();
System.out.println("Dartmouth controls the rebound.\n");
dartmouth_ball();
}
}
else {
System.out.println("Shot is good.");
add_points(0, 2);
dartmouth_ball();
System.out.println("Shot is good.");
add_points(0, 2);
dartmouth_ball();
}
}
// simulates an opponents possesion
// #randomly picks jump shot or lay up / set shot.
private void opponent_ball() {
time ++;
time ++;
if (time == 50) {
halftime();
}
opponent_chance = 10/4*Math.random()+1;
opponent_chance = 10/4*Math.random()+1;
if (opponent_chance > 2) {
opponent_non_jumpshot();
opponent_non_jumpshot();
}
else {
opponent_jumpshot();
opponent_jumpshot();
}
}
@@ -463,7 +463,3 @@ public class Basketball {
Basketball new_game = new Basketball();
}
}

View File

@@ -12,10 +12,10 @@ 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");

View File

@@ -6,7 +6,7 @@ import random
# You are able to choose your shot types as well as defensive formations
class Basketball():
class Basketball:
def __init__(self):
self.time = 0
self.score = [0, 0] # first value is opponents score, second is home
@@ -22,12 +22,14 @@ class Basketball():
print("This is Dartmouth College basketball. ")
print("Υou will be Dartmouth captain and playmaker.")
print("Call shots as follows:")
print("1. Long (30ft.) Jump Shot; 2. Short (15 ft.) Jump Shot; "
+ "3. Lay up; 4. Set Shot")
print(
"1. Long (30ft.) Jump Shot; 2. Short (15 ft.) Jump Shot; "
+ "3. Lay up; 4. Set Shot"
)
print("Both teams will use the same defense. Call Defense as follows:")
print("6. Press; 6.5 Man-to-Man; 7. Zone; 7.5 None.")
print("To change defense, just type 0 as your next shot.")
print("Your starting defense will be? ", end='')
print("Your starting defense will be? ", end="")
# takes input for a defense
try:
@@ -38,7 +40,7 @@ class Basketball():
# if the input wasn't a valid defense, takes input again
while self.defense not in self.defense_choices:
print("Your new defensive allignment is? ", end='')
print("Your new defensive allignment is? ", end="")
try:
self.defense = float(input())
@@ -46,7 +48,7 @@ class Basketball():
continue
# takes input for opponent's name
print("\nChoose your opponent? ", end='')
print("\nChoose your opponent? ", end="")
self.opponent = input()
self.start_of_period()
@@ -58,7 +60,7 @@ class Basketball():
self.print_score()
def ball_passed_back(self):
print("Ball passed back to you. ", end='')
print("Ball passed back to you. ", end="")
self.dartmouth_ball()
# change defense, called when the user enters 0 for their shot
@@ -77,8 +79,8 @@ class Basketball():
# simulates two foul shots for a player and adds the points
def foul_shots(self, team):
print("Shooter fouled. Two shots.")
if random.random() > .49:
if random.random() > .75:
if random.random() > 0.49:
if random.random() > 0.75:
print("Both shots missed.")
else:
print("Shooter makes one shot and misses one.")
@@ -97,13 +99,12 @@ class Basketball():
# prints the current score
def print_score(self):
print("Score: " + str(self.score[1])
+ " to " + str(self.score[0]) + "\n")
print("Score: " + str(self.score[1]) + " to " + str(self.score[0]) + "\n")
# simulates a center jump for posession at the beginning of a period
def start_of_period(self):
print("Center jump")
if random.random() > .6:
if random.random() > 0.6:
print("Dartmouth controls the tap.\n")
self.dartmouth_ball()
else:
@@ -123,10 +124,10 @@ class Basketball():
self.two_minute_warning()
print("Jump Shot.")
# simulates chances of different possible outcomes
if random.random() > .341 * self.defense / 8:
if random.random() > .682 * self.defense / 8:
if random.random() > .782 * self.defense / 8:
if random.random() > .843 * self.defense / 8:
if random.random() > 0.341 * self.defense / 8:
if random.random() > 0.682 * self.defense / 8:
if random.random() > 0.782 * self.defense / 8:
if random.random() > 0.843 * self.defense / 8:
print("Charging foul. Dartmouth loses ball.\n")
self.opponent_ball()
else:
@@ -134,24 +135,26 @@ class Basketball():
self.foul_shots(1)
self.opponent_ball()
else:
if random.random() > .5:
print("Shot is blocked. Ball controlled by " +
self.opponent + ".\n")
if random.random() > 0.5:
print(
"Shot is blocked. Ball controlled by "
+ self.opponent
+ ".\n"
)
self.opponent_ball()
else:
print("Shot is blocked. Ball controlled by Dartmouth.")
self.dartmouth_ball()
else:
print("Shot is off target.")
if self.defense / 6 * random.random() > .45:
if self.defense / 6 * random.random() > 0.45:
print("Rebound to " + self.opponent + "\n")
self.opponent_ball()
else:
print("Dartmouth controls the rebound.")
if random.random() > .4:
if self.defense == 6 and random.random() > .6:
print("Pass stolen by " + self.opponent
+ ", easy lay up")
if random.random() > 0.4:
if self.defense == 6 and random.random() > 0.6:
print("Pass stolen by " + self.opponent + ", easy lay up")
self.add_points(0, 2)
self.dartmouth_ball()
else:
@@ -182,10 +185,10 @@ class Basketball():
self.change_defense()
# simulates different outcomes after a lay up or set shot
if 7/self.defense*random.random() > .4:
if 7/self.defense*random.random() > .7:
if 7/self.defense*random.random() > .875:
if 7/self.defense*random.random() > .925:
if 7 / self.defense * random.random() > 0.4:
if 7 / self.defense * random.random() > 0.7:
if 7 / self.defense * random.random() > 0.875:
if 7 / self.defense * random.random() > 0.925:
print("Charging foul. Dartmouth loses the ball.\n")
self.opponent_ball()
else:
@@ -196,9 +199,9 @@ class Basketball():
self.opponent_ball()
else:
print("Shot is off the rim.")
if random.random() > 2/3:
if random.random() > 2 / 3:
print("Dartmouth controls the rebound.")
if random.random() > .4:
if random.random() > 0.4:
print("Ball passed back to you.\n")
self.dartmouth_ball()
else:
@@ -213,7 +216,7 @@ class Basketball():
# plays out a Dartmouth posession, starting with your choice of shot
def dartmouth_ball(self):
print("Your shot? ", end='')
print("Your shot? ", end="")
self.shot = None
try:
self.shot = int(input())
@@ -221,13 +224,13 @@ class Basketball():
self.shot = None
while self.shot not in self.shot_choices:
print("Incorrect answer. Retype it. Your shot? ", end='')
print("Incorrect answer. Retype it. Your shot? ", end="")
try:
self.shot = int(input())
except:
continue
if self.time < 100 or random.random() < .5:
if self.time < 100 or random.random() < 0.5:
if self.shot == 1 or self.shot == 2:
self.dartmouth_jump_shot()
else:
@@ -235,13 +238,25 @@ class Basketball():
else:
if self.score[0] != self.score[1]:
print("\n ***** End Of Game *****")
print("Final Score: Dartmouth: " + str(self.score[1]) + " "
+ self.opponent + ": " + str(self.score[0]))
print(
"Final Score: Dartmouth: "
+ str(self.score[1])
+ " "
+ self.opponent
+ ": "
+ str(self.score[0])
)
else:
print("\n ***** End Of Second Half *****")
print("Score at end of regulation time:")
print(" Dartmouth: " + str(self.score[1]) + " " +
self.opponent + ": " + str(self.score[0]))
print(
" Dartmouth: "
+ str(self.score[1])
+ " "
+ self.opponent
+ ": "
+ str(self.score[0])
)
print("Begin two minute overtime period")
self.time = 93
self.start_of_period()
@@ -249,9 +264,9 @@ class Basketball():
# simulates the opponents jumpshot
def opponent_jumpshot(self):
print("Jump Shot.")
if 8/self.defense*random.random() > .35:
if 8/self.defense*random.random() > .75:
if 8/self.defense*random.random() > .9:
if 8 / self.defense * random.random() > 0.35:
if 8 / self.defense * random.random() > 0.75:
if 8 / self.defense * random.random() > 0.9:
print("Offensive foul. Dartmouth's ball.\n")
self.dartmouth_ball()
else:
@@ -259,27 +274,25 @@ class Basketball():
self.dartmouth_ball()
else:
print("Shot is off the rim.")
if self.defense/6*random.random() > .5:
if self.defense / 6 * random.random() > 0.5:
print(self.opponent + " controls the rebound.")
if self.defense == 6:
if random.random() > .75:
if random.random() > 0.75:
print("Ball stolen. Easy lay up for Dartmouth.")
self.add_points(1, 2)
self.opponent_ball()
else:
if random.random() > .5:
if random.random() > 0.5:
print("")
self.opponent_non_jumpshot()
else:
print("Pass back to " + self.opponent +
" guard.\n")
print("Pass back to " + self.opponent + " guard.\n")
self.opponent_ball()
else:
if random.random() > .5:
if random.random() > 0.5:
self.opponent_non_jumpshot()
else:
print("Pass back to " + self.opponent +
" guard.\n")
print("Pass back to " + self.opponent + " guard.\n")
self.opponent_ball()
else:
print("Dartmouth controls the rebound.\n")
@@ -295,25 +308,24 @@ class Basketball():
print("Set shot.")
else:
print("Lay up")
if 7/self.defense*random.random() > .413:
if 7 / self.defense * random.random() > 0.413:
print("Shot is missed.")
if self.defense/6*random.random() > .5:
if self.defense / 6 * random.random() > 0.5:
print(self.opponent + " controls the rebound.")
if self.defense == 6:
if random.random() > .75:
if random.random() > 0.75:
print("Ball stolen. Easy lay up for Dartmouth.")
self.add_points(1, 2)
self.opponent_ball()
else:
if random.random() > .5:
if random.random() > 0.5:
print("")
self.opponent_non_jumpshot()
else:
print("Pass back to " + self.opponent +
" guard.\n")
print("Pass back to " + self.opponent + " guard.\n")
self.opponent_ball()
else:
if random.random() > .5:
if random.random() > 0.5:
print("")
self.opponent_non_jumpshot()
else:
@@ -333,7 +345,7 @@ class Basketball():
self.time += 1
if self.time == 50:
self.halftime()
self.z1 = 10/4*random.random()+1
self.z1 = 10 / 4 * random.random() + 1
if self.z1 > 2:
self.opponent_non_jumpshot()
else:

View File

@@ -3,7 +3,7 @@
30 PRINT:PRINT:PRINT
110 PRINT "THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE"
120 PRINT "COMPUTER IS YOUR OPPONENT."
130 PRINT
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"

View File

@@ -55,7 +55,7 @@ namespace Batnum
/// <returns>A message to be displayed to the player</returns>
public string TakeTurn()
{
//Edge condition - can occur when minTake is more > 1
//Edge condition - can occur when minTake is more > 1
if (pileSize < minTake)
{
pileSize = 0;

View File

@@ -10,7 +10,7 @@ namespace Batnum
{
/// <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
/// 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>

View File

@@ -27,4 +27,3 @@ while (true)
}
}

View File

@@ -10,8 +10,8 @@
namespace Batnum.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
@@ -23,15 +23,15 @@ namespace Batnum.Properties {
[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>
@@ -45,7 +45,7 @@ namespace Batnum.Properties {
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
@@ -59,7 +59,7 @@ namespace Batnum.Properties {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to COMPUTER TAKES {0} AND LEAVES {1}.
/// </summary>
@@ -68,7 +68,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("COMPTURN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to COMPUTER TAKES {0} AND LOSES.
/// </summary>
@@ -77,7 +77,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("END_COMPLOSE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to COMPUTER TAKES {0} AND WINS.
/// </summary>
@@ -86,7 +86,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("END_COMPWIN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ITS A DRAW, THERE ARE ONLY {0} PIECES LEFT.
/// </summary>
@@ -95,7 +95,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("END_DRAW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to TOUGH LUCK, YOU LOSE..
/// </summary>
@@ -104,7 +104,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("END_PLAYERLOSE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONGRATULATIONS, YOU WIN..
/// </summary>
@@ -113,7 +113,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("END_PLAYERWIN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to BATNUM.
/// </summary>
@@ -122,7 +122,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("GAME_NAME", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ILLEGAL MOVE, RENETER IT.
/// </summary>
@@ -131,7 +131,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("INPUT_ILLEGAL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to YOUR MOVE ?.
/// </summary>
@@ -140,7 +140,7 @@ namespace Batnum.Properties {
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>
@@ -149,7 +149,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("INPUT_ZERO", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CREATIVE COMPUTING MORRISTOWN, NEW JERSEY.
/// </summary>
@@ -158,7 +158,7 @@ namespace Batnum.Properties {
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>
@@ -167,7 +167,7 @@ namespace Batnum.Properties {
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>
@@ -176,7 +176,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("INTRO_PART2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ENTER MIN AND MAX ?.
/// </summary>
@@ -185,7 +185,7 @@ namespace Batnum.Properties {
return ResourceManager.GetString("START_QUESTION_DRAWMINMAX", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ENTER PILE SIZE ?.
/// </summary>
@@ -194,7 +194,7 @@ namespace Batnum.Properties {
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>
@@ -203,7 +203,7 @@ namespace Batnum.Properties {
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>

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
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
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>
@@ -26,36 +26,36 @@
<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
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
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
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
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
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
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
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -168,4 +168,4 @@
<data name="START_QUESTION_WINOPTION" xml:space="preserve">
<value>ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ?</value>
</data>
</root>
</root>

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
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
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>
@@ -26,36 +26,36 @@
<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
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
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
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
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
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
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
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -168,4 +168,4 @@
<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>
</root>

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
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
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>
@@ -26,36 +26,36 @@
<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
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
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
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
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
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
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
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -168,4 +168,4 @@
<data name="START_QUESTION_WINOPTION" xml:space="preserve">
<value>ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ?</value>
</data>
</root>
</root>

View File

@@ -8,4 +8,3 @@ 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)

View File

@@ -289,4 +289,4 @@ public class BatNum {
String[] tokens = text.split(",");
return Integer.parseInt(tokens[pos]);
}
}
}

View File

@@ -12,10 +12,10 @@ 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");

View File

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

268
08_Batnum/perl/batnum.pl Normal file
View File

@@ -0,0 +1,268 @@
use strict;
use warnings;
my %WIN_OPTIONS = (
"UNDEFINED" => 0,
"TAKE_LAST" => 1,
"AVOID_LAST" => 2,
);
my %START_OPTIONS = (
"UNDEFINED" => 0,
"COMPUTER_FIRST" => 1,
"PLAYER_FIRST" => 2,
);
sub run {
# input: no input perameters
#
# output: nothing returned
#
# description: This is the primary game loop. Once a game is concluded
# another will begin right away until the exeecution
# is terminated.
my $pile_size = undef;
my $min_select = undef;
my $max_select = undef;
my $win_option = undef;
my $start_option = undef;
while (1) {
write_intro();
($pile_size, $min_select, $max_select, $win_option, $start_option)
= &get_user_input();
play($pile_size, $min_select, $max_select, $win_option, $start_option);
printf "\n";
}
}
sub write_intro {
# input: no input perameters
#
# output: nothing returned
#
# description: This subroutine prints the intro and rules.
printf "%33s", "BATNUM\n";
printf "%15s", "CREATIVE COMPUTING MORRISSTOWN, NEW JERSEY\n";
printf "%s", "\n";
printf "%s", "\n";
printf "%s", "\n";
printf "%s", "THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE\n";
printf "%s", "COMPUTER IS YOUR OPPONENT.\n";
printf "%s", "\n";
printf "%s", "THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU\n";
printf "%s", "AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.\n";
printf "%s", "WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR\n";
printf "%s", "NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.\n";
printf "%s", "DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.\n";
printf "%s", "ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.\n";
printf "%s", "\n";
}
sub get_user_input {
# input: no input perameters
#
# output: (int) pile_size
# (int) min_select
# (int) max_select
# (int) win_option
# (int) start_option
#
# description: This subroutine gets the necessary perametes from the player.
#
# pile_size (int > 0)
# min_select (int > 0) max_select (int > 0)
# -> min/max, space delimated
# win_option (int 1|2)
# start_option (int 1|2)
my $pile_size = 0;
my $min_select = 0;
my $max_select = 0;
my $win_option = $WIN_OPTIONS{ "UNDEFINED" };
my $start_option = $START_OPTIONS{ "UNDEFINED" };
while ($pile_size < 1) {
printf "%s", "ENTER PILE SIZE: ";
$pile_size = <STDIN>;
}
while ($min_select < 1 || $max_select < 1 || $min_select > $max_select) {
printf "%s", "ENTER MIN AND MAX: ";
my $raw_input = <STDIN>;
($min_select, $max_select) = split(' ', $raw_input);
}
while ($win_option eq $WIN_OPTIONS{ "UNDEFINED" }) {
printf "%s", "ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ";
$win_option = <STDIN>;
}
while ($start_option eq $START_OPTIONS{ "UNDEFINED" }) {
printf "%s", "ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST: ";
$start_option = <STDIN>;
}
return ($pile_size, $min_select, $max_select, $win_option, $start_option);
}
sub play {
# input: (int) pile_size
# (int) min_select
# (int) max_select
# (int) win_option
# (int) start_option
#
# output: nothing returned
#
# description: This is where the game logic lives. The player and computer
# both take turns until the current game is over.
my $pile_size = shift;
my $min_select = shift;
my $max_select = shift;
my $win_option = shift;
my $start_option = shift;
my $game_over = 0;
my $players_turn = $start_option eq $START_OPTIONS{ "PLAYER_FIRST" } ? 1 : 0;
while (!$game_over) {
if ($players_turn) {
($game_over, $pile_size) = players_move(
$pile_size, $min_select, $max_select, $win_option);
$players_turn = 0;
if ($game_over) {
return;
}
} else {
($game_over, $pile_size) = computers_move(
$pile_size, $min_select, $max_select, $win_option);
$players_turn = 1;
}
}
return;
}
sub players_move {
# input: (int) pile_size
# (int) min_select
# (int) max_select
# (int) win_option
#
# output: (boolean) game is over
# (int) new pile_size
#
# description: This subroutine handles the players move.
my $pile_size = shift;
my $min_select = shift;
my $max_select = shift;
my $win_option = shift;
my $finished = 0;
while (!$finished) {
my $remove_amount = undef;
printf "%s", "YOUR MOVE: ";
$remove_amount = <>;
if ($remove_amount eq 0) {
printf "%s", "I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.";
return (1, $pile_size);
} elsif ($remove_amount > $max_select || $remove_amount < $min_select) {
printf "%s", "ILLEGAL MOVE, TRY AGAIN.\n";
next;
} else {
$pile_size -= $remove_amount;
$finished = 1;
}
if ($pile_size <= 0) {
if ($win_option eq $WIN_OPTIONS{ "AVOID_LAST" }) {
printf "%s", "TOUGH LUCK, YOU LOSE.\n";
} else {
printf "%s", "CONGRATULATIONS, YOU WIN.\n";
}
return (1, $pile_size);
}
}
return (0, $pile_size);
}
sub computers_move {
# input: (int) pile_size
# (int) min_select
# (int) max_select
# (int) win_option
#
# output: (boolean) game is over
# (int) new pile_size
#
# description: This subroutine handles the computers move.
my $pile_size = shift;
my $min_select = shift;
my $max_select = shift;
my $win_option = shift;
if ($win_option eq $WIN_OPTIONS{ "TAKE_LAST" } && $pile_size <= $max_select) {
printf "COMPUTER TAKES %d AND WINS.\n", $pile_size;
return (1, $pile_size);
}
if ($win_option eq $WIN_OPTIONS{ "AVOID_LAST" } && $pile_size <= $min_select) {
printf "COMPUTER TAKES %d AND LOSES.\n", $pile_size;
return (1, $pile_size);
}
my $remove_amount = get_computer_remove_amount($min_select, $max_select);
$pile_size -= $remove_amount;
if ($pile_size <= 0) {
printf "COMPUTER TAKES %d AND WINS.\n", $remove_amount;
return (1, $pile_size);
} else {
printf "COMPUTER TAKES %d AND LEAVES %d.\n", $remove_amount, $pile_size;
}
return (0, $pile_size);
}
sub get_computer_remove_amount {
# input: (int) min_select
# (int) max_select
#
# output: (int) random number (x) where,
# min_select <= x <= max_select
#
# description: This subroutine generates the amount of items the computer
# will remove.
my $min_select = shift;
my $max_select = shift;
return (int(rand($max_select - $min_select)) + $min_select);
}
# start the game
run();

View File

@@ -1,19 +1,22 @@
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, ' '))
"""Prints out the introduction and rules for the game."""
print("BATNUM".rjust(33, " "))
print("CREATIVE COMPUTING MORRISSTOWN, NEW JERSEY".rjust(15, " "))
print()
print()
print()
@@ -21,7 +24,7 @@ def PrintIntro():
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("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.")
@@ -29,8 +32,9 @@ def PrintIntro():
print()
return
def GetParams():
'''This requests the necessary parameters to play the game.
"""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
@@ -38,9 +42,9 @@ def GetParams():
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
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
@@ -52,22 +56,25 @@ def GetParams():
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(' ')]
(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
"""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.'''
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.")
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")
@@ -82,10 +89,11 @@ def PlayerMove(pileSize, minSelect, maxSelect, startOption, winOption):
return (True, pileSize)
return (False, pileSize)
def ComputerPick(pileSize, minSelect, maxSelect, startOption, winOption):
'''This handles the logic to determine how many objects the computer
"""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))
@@ -95,24 +103,25 @@ def ComputerPick(pileSize, minSelect, maxSelect, startOption, winOption):
computerPick = maxSelect
return computerPick
def ComputerMove(pileSize, minSelect, maxSelect, startOption, winOption):
'''This handles the computer's turn - first checking for the various
"""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.'''
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.")
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.")
print(f"COMPUTER TAKES {minSelect} AND LOSES.")
return (True, pileSize)
# Otherwise, we determine how many the computer selects
@@ -121,10 +130,11 @@ def ComputerMove(pileSize, minSelect, maxSelect, startOption, winOption):
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
"""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
@@ -132,18 +142,23 @@ def PlayGame(pileSize, minSelect, maxSelect, startOption, winOption):
while not gameOver:
if playersTurn:
(gameOver, pileSize) = PlayerMove(pileSize, minSelect, maxSelect, startOption, winOption)
(gameOver, pileSize) = PlayerMove(
pileSize, minSelect, maxSelect, startOption, winOption
)
playersTurn = False
if gameOver:
return
if not playersTurn:
(gameOver, pileSize) = ComputerMove(pileSize, minSelect, maxSelect, startOption, winOption)
(gameOver, pileSize) = ComputerMove(
pileSize, minSelect, maxSelect, startOption, winOption
)
playersTurn = True
return
if __name__ == "__main__":
pileSize = 0
minSelect = 0
maxSelect = 0

View File

@@ -305,7 +305,7 @@ namespace Battle
var shipType = (shipNum - 1) / 2 + 1;
lost[shipType] = lost[shipType] + 1;
Print("AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS.");
Print("SO FAR, THE BAD GUYS HAVE LOST");
Write($"{lost[1]} DESTROYER(S), {lost[2]} CRUISER(S), AND ");

View File

@@ -155,7 +155,7 @@ public class Battle {
System.out.println("\n****************************\n");
}
}
}
}
}
}

View File

@@ -38,10 +38,10 @@ public class Input {
System.out.println("Need two coordinates separated by ','");
continue;
}
coords = new int[2];
boolean error = false;
// each field should contain an integer from 1 to the size of the sea
// each field should contain an integer from 1 to the size of the sea
try {
for (int c = 0 ; c < 2; ++c ) {
int val = Integer.parseInt(fields[c].strip());

View File

@@ -1,4 +1,4 @@
// Track the content of the sea
// Track the content of the sea
class Sea {
// the sea is a square grid of tiles. It is a one-dimensional array, and this
// class maps x and y coordinates to an array index
@@ -20,11 +20,11 @@ class Sea {
public String encodedDump() {
StringBuilder out = new StringBuilder();
for (int x = 0; x < size; ++x) {
for (int y = 0; y < size; ++y)
for (int y = 0; y < size; ++y)
out.append(Integer.toString(get(x, y)));
out.append('\n');
}
return out.toString();
return out.toString();
}
/* return true if x,y is in the sea and empty

View File

@@ -17,7 +17,7 @@ class Ship {
private boolean placed; // whether this ship is in the sea yet
private boolean sunk; // whether this ship has been sunk
private ArrayList<Boolean> hits; // which tiles of the ship have been hit
private int startX; // starting position coordinates
private int startY;
private int orientX; // x and y deltas from each tile occupied to the next

View File

@@ -12,10 +12,10 @@ 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");

View File

@@ -40,8 +40,9 @@ def place_ship(sea: SeaType, size: int, code: int) -> None:
point = add_vector(point, vector)
points.append(point)
if (not all([is_within_sea(point, sea) for point in points]) or
any([value_at(point, sea) for point in points])):
if not all([is_within_sea(point, sea) for point in points]) or any(
[value_at(point, sea) for point in points]
):
# ship out of bounds or crosses other ship, trying again
continue
@@ -54,7 +55,7 @@ def place_ship(sea: SeaType, size: int, code: int) -> None:
def print_encoded_sea(sea: SeaType) -> None:
for x in range(len(sea)):
print(' '.join([str(sea[y][x]) for y in range(len(sea) - 1, -1, -1)]))
print(" ".join([str(sea[y][x]) for y in range(len(sea) - 1, -1, -1)]))
def is_within_sea(point: PointType, sea: SeaType) -> bool:
@@ -70,18 +71,18 @@ def count_sunk(sea: SeaType, *codes: int) -> int:
def value_at(point: PointType, sea: SeaType) -> int:
return sea[point[1] - 1][point[0] -1]
return sea[point[1] - 1][point[0] - 1]
def set_value_at(value: int, point: PointType, sea: SeaType) -> None:
sea[point[1] - 1][point[0] -1] = value
sea[point[1] - 1][point[0] - 1] = value
def get_next_target(sea: SeaType) -> PointType:
while True:
try:
guess = input('? ')
point = guess.split(',')
guess = input("? ")
point = guess.split(",")
if len(point) != 2:
raise ValueError()
@@ -93,7 +94,9 @@ def get_next_target(sea: SeaType) -> PointType:
return point
except ValueError:
print(f'INVALID. SPECIFY TWO NUMBERS FROM 1 TO {len(sea)}, SEPARATED BY A COMMA.')
print(
f"INVALID. SPECIFY TWO NUMBERS FROM 1 TO {len(sea)}, SEPARATED BY A COMMA."
)
def setup_ships(sea: SeaType):
@@ -106,23 +109,27 @@ def setup_ships(sea: SeaType):
def main() -> None:
sea = tuple(([0 for _ in range(SEA_WIDTH)] for _ in range(SEA_WIDTH)))
sea = tuple([0 for _ in range(SEA_WIDTH)] for _ in range(SEA_WIDTH))
setup_ships(sea)
print(f'''
print(
f"""
BATTLE
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
THE FOLLOWING CODE OF THE BAD GUYS' FLEET DISPOSITION
HAS BEEN CAPTURED BUT NOT DECODED:
''')
"""
)
print_encoded_sea(sea)
print('''
print(
"""
DE-CODE IT AND USE IT IF YOU CAN
BUT KEEP THE DE-CODING METHOD A SECRET.
START GAME''')
START GAME"""
)
splashes = 0
hits = 0
@@ -131,33 +138,39 @@ START GAME''')
target_value = value_at(target, sea)
if target_value < 0:
print(f'YOU ALREADY PUT A HOLE IN SHIP NUMBER {abs(target_value)} AT THAT POINT.')
print(
f"YOU ALREADY PUT A HOLE IN SHIP NUMBER {abs(target_value)} AT THAT POINT."
)
if target_value <= 0:
print('SPLASH! TRY AGAIN.')
print("SPLASH! TRY AGAIN.")
splashes += 1
continue
print(f'A DIRECT HIT ON SHIP NUMBER {target_value}')
print(f"A DIRECT HIT ON SHIP NUMBER {target_value}")
hits += 1
set_value_at(-target_value, target, sea)
if not has_ship(sea, target_value):
print('AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS.')
print('SO FAR, THE BAD GUYS HAVE LOST')
print(f'{count_sunk(sea, 1, 2)} DESTROYER(S),',
f'{count_sunk(sea, 3, 4)} CRUISER(S),',
f'AND {count_sunk(sea, 5, 6)} AIRCRAFT CARRIER(S).')
print("AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS.")
print("SO FAR, THE BAD GUYS HAVE LOST")
print(
f"{count_sunk(sea, 1, 2)} DESTROYER(S),",
f"{count_sunk(sea, 3, 4)} CRUISER(S),",
f"AND {count_sunk(sea, 5, 6)} AIRCRAFT CARRIER(S).",
)
if any(has_ship(sea, code) for code in range(1, 7)):
print(f'YOUR CURRENT SPLASH/HIT RATIO IS {splashes}/{hits}')
print(f"YOUR CURRENT SPLASH/HIT RATIO IS {splashes}/{hits}")
continue
print('YOU HAVE TOTALLY WIPED OUT THE BAD GUYS\' FLEET '
f'WITH A FINAL SPLASH/HIT RATIO OF {splashes}/{hits}')
print(
"YOU HAVE TOTALLY WIPED OUT THE BAD GUYS' FLEET "
f"WITH A FINAL SPLASH/HIT RATIO OF {splashes}/{hits}"
)
if not splashes:
print('CONGRATULATIONS -- A DIRECT HIT EVERY TIME.')
print("CONGRATULATIONS -- A DIRECT HIT EVERY TIME.")
print("\n****************************")
break

View File

@@ -2,7 +2,6 @@
from dataclasses import dataclass
from random import randrange
DESTROYER_LENGTH = 2
CRUISER_LENGTH = 3
AIRCRAFT_CARRIER_LENGTH = 4
@@ -14,10 +13,10 @@ class Point:
y: int
@classmethod
def random(cls, start: int, stop: int) -> 'Point':
def random(cls, start: int, stop: int) -> "Point":
return Point(randrange(start, stop), randrange(start, stop))
def __add__(self, vector: 'Vector') -> 'Point':
def __add__(self, vector: "Vector") -> "Point":
return Point(self.x + vector.x, self.y + vector.y)
@@ -27,10 +26,10 @@ class Vector:
y: int
@staticmethod
def random() -> 'Vector':
def random() -> "Vector":
return Vector(randrange(-1, 2, 2), randrange(-1, 2, 2))
def __mul__(self, factor: int) -> 'Vector':
def __mul__(self, factor: int) -> "Vector":
return Vector(self.x * factor, self.y * factor)
@@ -38,25 +37,25 @@ class Sea:
WIDTH = 6
def __init__(self):
self._graph = tuple(([0 for _ in range(self.WIDTH)] for _ in range(self.WIDTH)))
self._graph = tuple([0 for _ in range(self.WIDTH)] for _ in range(self.WIDTH))
def _validate_item_indices(self, point: Point) -> None:
if not isinstance(point, Point):
raise ValueError(f'Sea indices must be Points, not {type(point).__name__}')
raise ValueError(f"Sea indices must be Points, not {type(point).__name__}")
if not((1 <= point.x <= self.WIDTH) and (1 <= point.y <= self.WIDTH)):
raise IndexError('Sea index out of range')
if not ((1 <= point.x <= self.WIDTH) and (1 <= point.y <= self.WIDTH)):
raise IndexError("Sea index out of range")
# Allows us to get the value using a point as a key, for example, `sea[Point(3,2)]`
def __getitem__(self, point: Point) -> int:
self._validate_item_indices(point)
return self._graph[point.y - 1][point.x -1]
return self._graph[point.y - 1][point.x - 1]
# Allows us to get the value using a point as a key, for example, `sea[Point(3,2)] = 3`
def __setitem__(self, point: Point, value: int) -> None:
self._validate_item_indices(point)
self._graph[point.y - 1][point.x -1] = value
self._graph[point.y - 1][point.x - 1] = value
# Allows us to check if a point exists in the sea for example, `if Point(3,2) in sea:`
def __contains__(self, point: Point) -> bool:
@@ -70,9 +69,14 @@ class Sea:
# Redefines how python will render this object when asked as a str
def __str__(self):
# Display it encoded
return "\n".join([' '.join([str(self._graph[y][x])
for y in range(self.WIDTH - 1, -1, -1)])
for x in range(self.WIDTH)])
return "\n".join(
[
" ".join(
[str(self._graph[y][x]) for y in range(self.WIDTH - 1, -1, -1)]
)
for x in range(self.WIDTH)
]
)
def has_ship(self, ship_code: int) -> bool:
return any(ship_code in row for row in self._graph)
@@ -96,8 +100,8 @@ class Battle:
def _next_target(self) -> Point:
while True:
try:
guess = input('? ')
coordinates = guess.split(',')
guess = input("? ")
coordinates = guess.split(",")
if len(coordinates) != 2:
raise ValueError()
@@ -109,11 +113,13 @@ class Battle:
return point
except ValueError:
print(f'INVALID. SPECIFY TWO NUMBERS FROM 1 TO {Sea.WIDTH}, SEPARATED BY A COMMA.')
print(
f"INVALID. SPECIFY TWO NUMBERS FROM 1 TO {Sea.WIDTH}, SEPARATED BY A COMMA."
)
@property
def splash_hit_ratio(self) -> str:
return f'{self.splashes}/{self.hits}'
return f"{self.splashes}/{self.hits}"
@property
def _is_finished(self) -> bool:
@@ -126,8 +132,10 @@ class Battle:
# Get potential ship points
points = [start + vector * i for i in range(size)]
if not (all([point in self.sea for point in points]) and
not any([self.sea[point] for point in points])):
if not (
all([point in self.sea for point in points])
and not any([self.sea[point] for point in points])
):
# ship out of bounds or crosses other ship, trying again
continue
@@ -137,53 +145,59 @@ class Battle:
break
def loop(self):
while True:
target = self._next_target()
target_value = self.sea[target]
if target_value < 0:
print(f'YOU ALREADY PUT A HOLE IN SHIP NUMBER {abs(target_value)} AT THAT POINT.')
print(
f"YOU ALREADY PUT A HOLE IN SHIP NUMBER {abs(target_value)} AT THAT POINT."
)
if target_value <= 0:
print('SPLASH! TRY AGAIN.')
print("SPLASH! TRY AGAIN.")
self.splashes += 1
continue
print(f'A DIRECT HIT ON SHIP NUMBER {target_value}')
print(f"A DIRECT HIT ON SHIP NUMBER {target_value}")
self.hits += 1
self.sea[target] = -target_value
if not self.sea.has_ship(target_value):
print('AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS.')
print("AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS.")
self._display_sunk_report()
if self._is_finished:
self._display_game_end()
break
print(f'YOUR CURRENT SPLASH/HIT RATIO IS {self.splash_hit_ratio}')
print(f"YOUR CURRENT SPLASH/HIT RATIO IS {self.splash_hit_ratio}")
def _display_sunk_report(self):
print('SO FAR, THE BAD GUYS HAVE LOST',
f'{self.sea.count_sunk(1, 2)} DESTROYER(S),',
f'{self.sea.count_sunk(3, 4)} CRUISER(S),',
f'AND {self.sea.count_sunk(5, 6)} AIRCRAFT CARRIER(S).')
print(
"SO FAR, THE BAD GUYS HAVE LOST",
f"{self.sea.count_sunk(1, 2)} DESTROYER(S),",
f"{self.sea.count_sunk(3, 4)} CRUISER(S),",
f"AND {self.sea.count_sunk(5, 6)} AIRCRAFT CARRIER(S).",
)
def _display_game_end(self):
print('YOU HAVE TOTALLY WIPED OUT THE BAD GUYS\' FLEET '
f'WITH A FINAL SPLASH/HIT RATIO OF {self.splash_hit_ratio}')
print(
"YOU HAVE TOTALLY WIPED OUT THE BAD GUYS' FLEET "
f"WITH A FINAL SPLASH/HIT RATIO OF {self.splash_hit_ratio}"
)
if not self.splashes:
print('CONGRATULATIONS -- A DIRECT HIT EVERY TIME.')
print("CONGRATULATIONS -- A DIRECT HIT EVERY TIME.")
print("\n****************************")
def main() -> None:
game = Battle()
print(f'''
print(
f"""
BATTLE
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
@@ -195,7 +209,8 @@ HAS BEEN CAPTURED BUT NOT DECODED:
DE-CODE IT AND USE IT IF YOU CAN
BUT KEEP THE DE-CODING METHOD A SECRET.
START GAME''')
START GAME"""
)
game.loop()

View File

@@ -289,7 +289,7 @@
3125 PRINT "---TOTAL IS";AA
3130 PRINT
3140 REM--TALLY THE RESULT
3150 REM
3150 REM
3160 Z$="LOSES PUSHES WINS "
3165 PRINT
3170 FOR I=1 TO N

View File

@@ -12,10 +12,10 @@ 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");
@@ -217,7 +217,7 @@ async function main()
// --ta[i] IS THE TOTAL FOR PLAYER I, sa[i] IS THE TOTAL THIS HAND FOR
// --PLAYER I, ba[i] IS TH BET FOR HAND I
// --ra[i] IS THE LENGTH OF pa[I,*]
// --Program starts here
// --Initialize
for (i = 1; i <= 15; i++)
@@ -416,7 +416,7 @@ async function main()
if (pa[i][1] != 1) {
// --Now play the two hands
do {
print("HAND " + (i > d1 ? 2 : 1) + " ");
h1 = 5;
while (1) {
@@ -472,7 +472,7 @@ async function main()
if (aa <= 16) {
print("DRAWS");
do {
x = get_card();
alt_card_print(x);
add_card_to_row(i, x);

View File

@@ -0,0 +1,496 @@
"""
Blackjack
Ported by Martin Thoma in 2022,
using the rust implementation of AnthonyMichaelTDM
"""
import enum
import random
from dataclasses import dataclass
from typing import List, NamedTuple
class PlayerType(enum.Enum):
Player = "Player"
Dealer = "Dealer"
class Play(enum.Enum):
Stand = enum.auto()
Hit = enum.auto()
DoubleDown = enum.auto()
Split = enum.auto()
class Card(NamedTuple):
name: str
@property
def value(self) -> int:
"""
returns the value associated with a card with the passed name
return 0 if the passed card name doesn't exist
"""
return {
"ACE": 11,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
"JACK": 10,
"QUEEN": 10,
"KING": 10,
}.get(self.name, 0)
class Hand(NamedTuple):
cards: List[Card]
def add_card(self, card: Card) -> None:
"""add a passed card to this hand"""
self.cards.append(card)
def get_total(self) -> int:
"""returns the total points of the cards in this hand"""
total: int = 0
for card in self.cards:
total += int(card.value)
# if there is an ACE, and the hand would otherwise bust,
# treat the ace like it's worth 1
if total > 21 and any(card.name == "ACE" for card in self.cards):
total -= 10
return total
def discard_hand(self, deck: "Decks") -> None:
"""adds the cards in hand into the discard pile"""
_len = len(self.cards)
for _i in range(_len):
if len(self.cards) == 0:
raise ValueError("hand empty")
deck.discard_pile.append(self.cards.pop())
class Decks(NamedTuple):
deck: List[Card]
discard_pile: List[Card]
@classmethod
def new(cls) -> "Decks":
"""creates a new full and shuffled deck, and an empty discard pile"""
# returns a number of full decks of 52 cards, shuffles them
deck = Decks(deck=[], discard_pile=[])
number_of_decks = 3
# fill deck
for _n in range(number_of_decks):
# fill deck with number_of_decks decks worth of cards
for card_name in CARD_NAMES:
# add 4 of each card, totaling one deck with 4 of each card
for _ in range(4):
deck.deck.append(Card(name=card_name))
deck.shuffle()
return deck
def shuffle(self) -> None:
"""shuffles the deck"""
random.shuffle(self.deck)
def draw_card(self) -> Card:
"""
draw card from deck, and return it
if deck is empty, shuffles discard pile into it and tries again
"""
if len(self.deck) == 0:
_len = len(self.discard_pile)
if _len > 0:
# deck is empty, shuffle discard pile into deck and try again
print("deck is empty, shuffling")
for _i in range(_len):
if len(self.discard_pile) == 0:
raise ValueError("discard pile is empty")
self.deck.append(self.discard_pile.pop())
self.shuffle()
return self.draw_card()
else:
# discard pile and deck are empty, should never happen
raise Exception("discard pile empty")
else:
card = self.deck.pop()
return card
@dataclass
class Player:
hand: Hand
balance: int
bet: int
wins: int
player_type: PlayerType
index: int
@classmethod
def new(cls, player_type: PlayerType, index: int) -> "Player":
"""creates a new player of the given type"""
return Player(
hand=Hand(cards=[]),
balance=STARTING_BALANCE,
bet=0,
wins=0,
player_type=player_type,
index=index,
)
def get_name(self) -> str:
return f"{self.player_type}{self.index}"
def get_bet(self) -> None:
"""gets a bet from the player"""
if PlayerType.Player == self.player_type:
if self.balance < 1:
print(f"{self.get_name()} is out of money :(")
self.bet = 0
self.bet = get_number_from_user_input(
f"{self.get_name()}\tWhat is your bet", 1, self.balance
)
def hand_as_string(self, hide_dealer: bool) -> str:
"""
returns a string of the players hand
if player is a dealer, returns the first card in the hand followed
by *'s for every other card
if player is a player, returns every card and the total
"""
if not hide_dealer:
s = ""
for cards_in_hand in self.hand.cards[::-1]:
s += f"{cards_in_hand.name}\t"
s += f"total points = {self.hand.get_total()}"
return s
else:
if self.player_type == PlayerType.Dealer:
s = ""
for c in self.hand.cards[1::-1]:
s += f"{c.name}\t"
return s
elif self.player_type == PlayerType.Player:
s = ""
for cards_in_hand in self.hand.cards[::-1]:
s += f"{cards_in_hand.name}\t"
s += f"total points = {self.hand.get_total()}"
return s
raise Exception("This is unreachable")
def get_play(self) -> Play:
"""get the players 'play'"""
# do different things depending on what type of player this is:
# if it's a dealer, use an algorithm to determine the play
# if it's a player, ask user for input
if self.player_type == PlayerType.Dealer:
if self.hand.get_total() > 16:
return Play.Stand
else:
return Play.Hit
elif self.player_type == PlayerType.Player:
valid_results: List[str]
if len(self.hand.cards) > 2:
# if there are more than 2 cards in the hand,
# at least one turn has happened, so splitting and
# doubling down are not allowed
valid_results = ["s", "h"]
else:
valid_results = ["s", "h", "d", "/"]
play = get_char_from_user_input("\tWhat is your play?", valid_results)
if play == "s":
return Play.Stand
elif play == "h":
return Play.Hit
elif play == "d":
return Play.DoubleDown
elif play == "/":
return Play.Split
else:
raise ValueError(f"got invalid character {play}")
raise Exception("This is unreachable")
@dataclass
class Game:
players: List[Player] # last item in this is the dealer
decks: Decks
games_played: int
@classmethod
def new(cls, num_players: int) -> "Game":
players: List[Player] = []
# add dealer
players.append(Player.new(PlayerType.Dealer, 0))
# create human player(s) (at least one)
players.append(Player.new(PlayerType.Player, 1))
for i in range(2, num_players): # one less than num_players players
players.append(Player.new(PlayerType.Player, i))
if get_char_from_user_input("Do you want instructions", ["y", "n"]) == "y":
instructions()
print()
return Game(players=players, decks=Decks.new(), games_played=0)
def _print_stats(self) -> None:
"""prints the score of every player"""
print(f"{self.stats_as_string()}")
def stats_as_string(self) -> str:
"""returns a string of the wins, balance, and bets of every player"""
s = ""
for p in self.players:
# format the presentation of player stats
if p.player_type == PlayerType.Dealer:
s += f"{p.get_name()} Wins:\t{p.wins}\n"
elif p.player_type == PlayerType.Player:
s += f"{p.get_name()} "
s += f"Wins:\t{p.wins}\t\t"
s += f"Balance:\t{p.balance}\t\tBet\t{p.bet}\n"
return f"Scores:\n{s}"
def play_game(self) -> None:
"""plays a round of blackjack"""
game = self.games_played
player_hands_message: str = ""
# deal two cards to each player
for _i in range(2):
for player in self.players:
player.hand.add_card(self.decks.draw_card())
# get everyones bets
for player in self.players:
player.get_bet()
scores = self.stats_as_string()
# play game for each player
for player in self.players:
# turn loop, ends when player finishes their turn
while True:
clear()
welcome()
print(f"\n\t\t\tGame {game}")
print(scores)
print(player_hands_message)
print(f"{player.get_name()} Hand:\t{player.hand_as_string(True)}")
if PlayerType.Player == player.player_type:
# player isn't the dealer
if player.bet == 0: # player is out of money
break
# play through turn
# check their hand value for a blackjack(21) or bust
score = player.hand.get_total()
if score >= 21:
if score == 21:
print("\tBlackjack! (21 points)")
else:
print(f"\tBust ({score} points)")
break
# get player move
play = player.get_play()
# process play
if play == Play.Stand:
print(f"\t{play}")
break
elif play == Play.Hit:
print(f"\t{play}")
player.hand.add_card(self.decks.draw_card())
elif play == Play.DoubleDown:
print(f"\t{play}")
# double their balance if there's enough money,
# othewise go all-in
if player.bet * 2 < player.balance:
player.bet *= 2
else:
player.bet = player.balance
player.hand.add_card(self.decks.draw_card())
elif play == Play.Split:
pass
# add player to score cache thing
player_hands_message += (
f"{player.get_name()} Hand:\t{player.hand_as_string(True)}\n"
)
# determine winner
top_score = 0
# player with the highest points
num_winners = 1
non_burst_players = [
player for player in self.players if player.hand.get_total() <= 21
]
for player in non_burst_players:
score = player.hand.get_total()
if score > top_score:
top_score = score
num_winners = 1
elif score == top_score:
num_winners += 1
# show winner(s)
top_score_players = [
player
for player in non_burst_players
if player.hand.get_total() == top_score
]
for x in top_score_players:
print(f"{x.get_name()} ")
x.wins += 1
# increment their wins
if num_winners > 1:
print(f"all tie with {top_score}\n\n\n")
else:
print(
f"wins with {top_score}!\n\n\n",
)
# handle bets
# remove money from losers
losers = [
player for player in self.players if player.hand.get_total() != top_score
]
for loser in losers:
loser.balance -= loser.bet
# add money to winner
winners = [
player for player in self.players if player.hand.get_total() == top_score
]
for winner in winners:
winner.balance += winner.bet
# discard hands
for player in self.players:
player.hand.discard_hand(self.decks)
# increment games_played
self.games_played += 1
CARD_NAMES: List[str] = [
"ACE",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"JACK",
"QUEEN",
"KING",
]
STARTING_BALANCE: int = 100
def main() -> None:
game: Game
welcome()
# create game
game = Game.new(
get_number_from_user_input("How many players should there be", 1, 7)
)
# game loop, play game until user wants to stop
char = "y"
while char == "y":
game.play_game()
char = get_char_from_user_input("Play Again?", ["y", "n"])
def welcome() -> None:
"""prints the welcome screen"""
# welcome message
print(
"""
BLACK JACK
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
\n\n"""
)
def instructions() -> None:
"""prints the instructions"""
print(
"""
THIS IS THE GAME OF 21. AS MANY AS 7 PLAYERS MAY PLAY THE
GAME. ON EACH DEAL, BETS WILL BE ASKED FOR, AND THE
PLAYERS' BETS SHOULD BE TYPED IN. THE CARDS WILL THEN BE
DEALT, AND EACH PLAYER IN TURN PLAYS HIS HAND. THE
FIRST RESPONSE SHOULD BE EITHER 'D', INDICATING THAT THE
PLAYER IS DOUBLING DOWN, 'S', INDICATING THAT HE IS
STANDING, 'H', INDICATING HE WANTS ANOTHER CARD, OR '/',
INDICATING THAT HE WANTS TO SPLIT HIS CARDS. AFTER THE
INITIAL RESPONSE, ALL FURTHER RESPONSES SHOULD BE 'S' OR
'H', UNLESS THE CARDS WERE SPLIT, IN WHICH CASE DOUBLING
DOWN IS AGAIN PERMITTED. IN ORDER TO COLLECT FOR
BLACKJACK, THE INITIAL RESPONSE SHOULD BE 'S'.
NUMBER OF PLAYERS
NOTE:'/' (splitting) is not currently implemented, and does nothing
PRESS ENTER TO CONTINUE
"""
)
input()
def get_number_from_user_input(prompt: str, min_value: int, max_value: int) -> int:
"""gets a int integer from user input"""
# input loop
user_input = None
while user_input is None or user_input < min_value or user_input > max_value:
raw_input = input(prompt + f" ({min_value}-{max_value})? ")
try:
user_input = int(raw_input)
if user_input < min_value or user_input > max_value:
print("Invalid input, please try again")
except ValueError:
print("Invalid input, please try again")
return user_input
def get_char_from_user_input(prompt: str, valid_results: List[str]) -> str:
"""returns the first character they type"""
user_input = None
while user_input not in valid_results:
user_input = input(prompt + f" {valid_results}? ").lower()
if user_input not in valid_results:
print("Invalid input, please try again")
assert user_input is not None
return user_input
def clear() -> None:
"""clear std out"""
print("\x1b[2J\x1b[0;0H")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,9 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"

View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Rust](https://www.rust-lang.org/) by Anthony Rubick [AnthonyMichaelTDM](https://github.com/AnthonyMichaelTDM)

View File

@@ -0,0 +1,634 @@
use rand::{prelude::{thread_rng, SliceRandom}};
use std::{io, io::{stdout, Write}};
/**
* todo list:
*
* allow splitting
*/
//DATA
//enums
enum PlayerType {
Player,
Dealer,
}
impl ToString for PlayerType {
fn to_string(&self) -> String {
match self {
&PlayerType::Dealer => return String::from("Dealer"),
&PlayerType::Player => return String::from("Player"),
}
}
}
enum Play {
Stand,
Hit,
DoubleDown,
Split,
}
impl ToString for Play {
fn to_string(&self) -> String {
match self {
&Play::Hit => return String::from("Hit"),
&Play::Stand => return String::from("Stand"),
&Play::DoubleDown => return String::from("Double Down"),
&Play::Split => return String::from("Split")
}
}
}
//structs
struct CARD<'a> {
name: &'a str,
value: u8,
}
impl<'a> CARD<'a> {
/**
* creates a new card from the passed card name
*/
fn new(card_name: &str) -> CARD {
return CARD { name: card_name, value: CARD::determine_value_from_name(card_name) };
}
/**
* returns the value associated with a card with the passed name
* return 0 if the passed card name doesn't exist
*/
fn determine_value_from_name(card_name: &str) -> u8 {
//DATA
let value:u8;
match card_name.to_ascii_uppercase().as_str() {
"ACE" => value = 11,
"2" => value = 2,
"3" => value = 3,
"4" => value = 4,
"5" => value = 5,
"6" => value = 6,
"7" => value = 7,
"8" => value = 8,
"9" => value = 9,
"10" => value = 10,
"JACK" => value = 10,
"QUEEN" => value = 10,
"KING" => value = 10,
_ => value = 0,
}
return value;
}
}
struct HAND<'a> {
cards: Vec<CARD<'a>>,
}
impl<'a> HAND<'a> {
/**
* returns a new empty hand
*/
fn new() -> HAND<'a> {
return HAND { cards: Vec::new()};
}
/**
* add a passed card to this hand
*/
fn add_card(&mut self, card: CARD<'a>) {
self.cards.push(card);
}
/**
* returns the total points of the cards in this hand
*/
fn get_total(&self) -> usize {
let mut total:usize = 0;
for card in &self.cards {
total += card.value as usize;
}
//if there is an ACE, and the hand would otherwise bust, treat the ace like it's worth 1
if total > 21 && self.cards.iter().any(|c| -> bool {*c.name == *"ACE"}) {
total -= 10;
}
return total;
}
/**
* adds the cards in hand into the discard pile
*/
fn discard_hand(&mut self, deck: &mut DECKS<'a>) {
let len = self.cards.len();
for _i in 0..len {
deck.discard_pile.push(self.cards.pop().expect("hand empty"));
}
}
}
struct DECKS<'a> {
deck: Vec<CARD<'a>>, //cards in the deck
discard_pile: Vec<CARD<'a>> //decks discard pile
}
impl<'a> DECKS<'a> {
/**
* creates a new full and shuffled deck, and an empty discard pile
*/
fn new() -> DECKS<'a> {
//returns a number of full decks of 52 cards, shuffles them
//DATA
let mut deck = DECKS{deck: Vec::new(), discard_pile: Vec::new()};
let number_of_decks = 3;
//fill deck
for _n in 0..number_of_decks { //fill deck with number_of_decks decks worth of cards
for card_name in CARD_NAMES { //add 4 of each card, totaling one deck with 4 of each card
deck.deck.push( CARD::new(card_name) );
deck.deck.push( CARD::new(card_name) );
deck.deck.push( CARD::new(card_name) );
deck.deck.push( CARD::new(card_name) );
}
}
//shuffle deck
deck.shuffle();
//return deck
return deck;
}
/**
* shuffles the deck
*/
fn shuffle(&mut self) {
self.deck.shuffle(&mut thread_rng());
}
/**
* draw card from deck, and return it
* if deck is empty, shuffles discard pile into it and tries again
*/
fn draw_card(&mut self) -> CARD<'a> {
match self.deck.pop() {
Some(card) => return card,
None => {
let len = self.discard_pile.len();
if len > 0 {//deck is empty, shuffle discard pile into deck and try again
println!("deck is empty, shuffling");
for _i in 0..len {
self.deck.push( self.discard_pile.pop().expect("discard pile empty") )
}
self.shuffle();
return self.draw_card();
} else { //discard pile and deck are empty, should never happen
panic!("discard pile empty");
}
}
}
}
}
struct PLAYER<'a> {
hand: HAND<'a>,
balance: usize,
bet: usize,
wins: usize,
player_type: PlayerType,
index: usize,
}
impl<'a> PLAYER<'a> {
/**
* creates a new player of the given type
*/
fn new(player_type: PlayerType, index: usize) -> PLAYER<'a> {
return PLAYER { hand: HAND::new(), balance: STARTING_BALANCE, bet: 0, wins: 0, player_type: player_type, index: index};
}
fn get_name(&self) -> String {
format!("{}{}", self.player_type.to_string(),self.index)
}
/**
* gets a bet from the player
*/
fn get_bet(&mut self) {
if let PlayerType::Player = self.player_type {
if self.balance < 1 {
println!("{} is out of money :(", self.get_name());
self.bet = 0;
}
self.bet = get_number_from_user_input(format!("{}\tBet?",self.get_name()).as_str(), 1, self.balance);
}
}
/**
* returns a string of the players hand
*
* if player is a dealer, returns the first card in the hand followed by *'s for every other card
* if player is a player, returns every card and the total
*/
fn hand_as_string(&self, hide_dealer:bool) -> String {
if !hide_dealer {
return format!(
"{}\n\ttotal points = {}", //message
{ //cards in hand
let mut s:String = String::new();
for cards_in_hand in self.hand.cards.iter().rev() {
s += format!("{}\t", cards_in_hand.name).as_str();
}
s
},
self.hand.get_total() //total points in hand
);
}
else {
match &self.player_type {
&PlayerType::Dealer => { //if this is a dealer
return format!(
"{}*",//message
{ //*'s for other cards
let mut s:String = String::new();
let mut cards_in_hand = self.hand.cards.iter();
cards_in_hand.next();//consume first card drawn
for c in cards_in_hand.rev() {
s += format!("{}\t", c.name).as_str();
}
s
}
);
},
&PlayerType::Player => { //if this is a player
return format!(
"{}\n\ttotal points = {}", //message
{ //cards in hand
let mut s:String = String::new();
for cards_in_hand in self.hand.cards.iter().rev() {
s += format!("{}\t", cards_in_hand.name).as_str();
}
s
},
self.hand.get_total() //total points in hand
);
}
}
}
}
/**
* get the players 'play'
*/
fn get_play(&self) -> Play {
/*
do different things depending on what type of player this is:
if it's a dealer, use an algorithm to determine the play
if it's a player, ask user for input
*/
match &self.player_type {
&PlayerType::Dealer => {
if self.hand.get_total() > 16 { // if total value of hand is greater than 16, stand
return Play::Stand;
} else { //otherwise hit
return Play::Hit;
}
},
&PlayerType::Player => {
let valid_results:Vec<char>;
if self.hand.cards.len() > 2 {//if there are more than 2 cards in the hand, at least one turn has happened, so splitting and doubling down are not allowed
valid_results = vec!['s','S','h','H'];
} else {
valid_results = vec!['s','S','h','H','d','D','/'];
}
let play = get_char_from_user_input("\tWhat is your play?", &valid_results);
match play {
's' | 'S' => return Play::Stand,
'h' | 'H' => return Play::Hit,
'd' | 'D' => return Play::DoubleDown,
'/' => return Play::Split,
_ => panic!("get_char_from_user_input() returned invalid character"),
}
},
}
}
}
struct GAME<'a> {
players: Vec<PLAYER<'a>>, //last item in this is the dealer
decks: DECKS<'a>,
games_played:usize,
}
impl<'a> GAME<'a> {
/**
* creates a new game
*/
fn new(num_players:usize) -> GAME<'a> {
//DATA
let mut players: Vec<PLAYER> = Vec::new();
//add dealer
players.push(PLAYER::new(PlayerType::Dealer,0));
//create human player(s) (at least one)
players.push(PLAYER::new(PlayerType::Player,1));
for i in 2..=num_players { //one less than num_players players
players.push(PLAYER::new(PlayerType::Player,i));
}
//ask if they want instructions
if let 'y'|'Y' = get_char_from_user_input("Do you want instructions? (y/n)", &vec!['y','Y','n','N']) {
instructions();
}
println!();
//return a game
return GAME { players: players, decks: DECKS::new(), games_played: 0}
}
/**
* prints the score of every player
*/
fn _print_stats(&self) {
println!("{}", self.stats_as_string());
}
/**
* returns a string of the wins, balance, and bets of every player
*/
fn stats_as_string(&self) -> String {
format!("Scores:\n{}",{
let mut s = String::new();
self.players.iter().for_each(|p| {
//format the presentation of player stats
match p.player_type {
PlayerType::Player => s+= format!("{} Wins:\t{}\t\tBalance:\t{}\t\tBet\t{}\n",p.get_name(),p.wins,p.balance,p.bet).as_str(),
PlayerType::Dealer => s+= format!("{} Wins:\t{}\n",p.get_name(),p.wins).as_str()
}
});
s
})
}
/**
* plays a round of blackjack
*/
fn play_game(&mut self) {
//DATA
let scores;
let game = self.games_played; //save it here so we don't have borrowing issues
let mut player_hands_message: String = String::new();//cache it here so we don't have borrowing issues
//deal cards to each player
for _i in 0..2 { // do this twice
//draw card for each player
self.players.iter_mut().for_each(|player| {player.hand.add_card( self.decks.draw_card() );});
}
//get everyones bets
self.players.iter_mut().for_each(|player| player.get_bet());
scores = self.stats_as_string(); //save it here so we don't have borrowing issues later
//play game for each player
for player in self.players.iter_mut() {
//turn loop, ends when player finishes their turn
loop{
//clear screen
clear();
//print welcome
welcome();
//print game state
println!("\n\t\t\tGame {}", game);
//print scores
println!("{}",scores);
//print hands of all players
print!("{}", player_hands_message);
println!("{} Hand:\t{}", player.get_name(), player.hand_as_string(true));
if let PlayerType::Player = player.player_type { //player isn't the dealer
if player.bet == 0 {//player is out of money
break;//exit turn loop
}
}
//play through turn
//check their hand value for a blackjack(21) or bust
let score = player.hand.get_total();
if score >= 21 {
if score == 21 { // == 21
println!("\tBlackjack! (21 points)");
} else { // > 21
println!("\tBust ({} points)", score);
}
break; //end turn
}
//get player move
let play = player.get_play();
//process play
match play {
Play::Stand => {
println!("\t{}", play.to_string());
break; //end turn
},
Play::Hit => {
println!("\t{}", play.to_string());
//give them a card
player.hand.add_card( self.decks.draw_card() );
},
Play::DoubleDown => {
println!("\t{}", play.to_string());
//double their balance if there's enough money, othewise go all-in
if player.bet * 2 < player.balance {
player.bet *= 2;
}
else {
player.bet = player.balance;
}
//give them a card
player.hand.add_card( self.decks.draw_card() );
},
Play::Split => {
},
}
}
//add player to score cache thing
player_hands_message += format!("{} Hand:\t{}\n", player.get_name(), player.hand_as_string(true)).as_str();
}
//determine winner
let mut top_score = 0; //player with the highest points
let mut num_winners = 1;
for player in self.players.iter_mut().enumerate().filter( |x| -> bool {x.1.hand.get_total()<=21}) { //players_who_didnt_bust
let score = player.1.hand.get_total();
if score > top_score {
top_score = score;
num_winners = 1;
} else if score == top_score {
num_winners += 1;
}
}
//print winner(s)
self.players.iter_mut().filter(|x|->bool{x.hand.get_total()==top_score}).for_each(|x| {//for each player with the top score
print!("{} ", x.get_name());//print name
x.wins += 1;//increment their wins
});
if num_winners > 1 {println!("all tie with {}\n\n\n", top_score);}
else {println!("wins with {}!\n\n\n",top_score);}
//handle bets
//remove money from losers
self.players.iter_mut().filter(|p| p.hand.get_total()!=top_score).for_each( |p| p.balance -= p.bet); //for every player who didn't get the winning score, remove their bet from their balance
//add money to winner
self.players.iter_mut().filter(|p| p.hand.get_total()==top_score).for_each(|p| p.balance += p.bet); //for each player who got the winning score, add their bet to their balance
//discard hands
self.players.iter_mut().for_each(|player| {player.hand.discard_hand(&mut self.decks);});
//increment games_played
self.games_played += 1;
}
}
const CARD_NAMES: [&str;13] = ["ACE","2","3","4","5","6","7","8","9","10","JACK","QUEEN","KING"];
const STARTING_BALANCE: usize = 100;
fn main() {
//DATA
let mut game: GAME;
//print welcome message
welcome();
//create game
game = GAME::new( get_number_from_user_input("How many players should there be (at least 1)?", 1, 7) );
//game loop, play game until user wants to stop
loop {
//play round
game.play_game();
//ask if they want to play again
match get_char_from_user_input("Play Again? (y/n)", &vec!['y','Y','n','N']) {
'y' | 'Y' => continue,
'n' | 'N' => break,
_ => break,
}
}
}
/**
* prints the welcome screen
*/
fn welcome() {
//welcome message
print!("
BLACK JACK
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
\n\n");
}
/**
* prints the instructions
*/
fn instructions() {
println!("
THIS IS THE GAME OF 21. AS MANY AS 7 PLAYERS MAY PLAY THE
GAME. ON EACH DEAL, BETS WILL BE ASKED FOR, AND THE
PLAYERS' BETS SHOULD BE TYPED IN. THE CARDS WILL THEN BE
DEALT, AND EACH PLAYER IN TURN PLAYS HIS HAND. THE
FIRST RESPONSE SHOULD BE EITHER 'D', INDICATING THAT THE
PLAYER IS DOUBLING DOWN, 'S', INDICATING THAT HE IS
STANDING, 'H', INDICATING HE WANTS ANOTHER CARD, OR '/',
INDICATING THAT HE WANTS TO SPLIT HIS CARDS. AFTER THE
INITIAL RESPONSE, ALL FURTHER RESPONSES SHOULD BE 'S' OR
'H', UNLESS THE CARDS WERE SPLIT, IN WHICH CASE DOUBLING
DOWN IS AGAIN PERMITTED. IN ORDER TO COLLECT FOR
BLACKJACK, THE INITIAL RESPONSE SHOULD BE 'S'.
NUMBER OF PLAYERS
NOTE:'/' (splitting) is not currently implemented, and does nothing
PRESS ENTER TO CONTINUE
");
io::stdin().read_line(&mut String::new()).expect("Failed to read line");
}
/**
* gets a usize integer from user input
*/
fn get_number_from_user_input(prompt: &str, min:usize, max:usize) -> usize {
//input loop
return loop {
let mut raw_input = String::new(); // temporary variable for user input that can be parsed later
//print prompt
println!("{}", prompt);
stdout().flush().expect("Failed to flush to stdout.");
//read user input from standard input, and store it to raw_input
//raw_input.clear(); //clear input
io::stdin().read_line(&mut raw_input).expect( "CANNOT READ INPUT!");
//from input, try to read a number
match raw_input.trim().parse::<usize>() {
Ok(i) => {
if i < min || i > max { //input out of desired range
println!("INPUT OUT OF VALID RANGE. TRY AGAIN. {}-{}",min,max);
continue; // run the loop again
}
else {
break i;// this escapes the loop, returning i
}
},
Err(e) => {
println!("INVALID INPUT. TRY AGAIN. {}", e.to_string().to_uppercase());
continue; // run the loop again
}
};
};
}
/**
* gets a character from user input
* returns the first character they type
*/
fn get_char_from_user_input(prompt: &str, valid_results: &Vec<char>) -> char {
//input loop
return loop {
let mut raw_input = String::new(); // temporary variable for user input that can be parsed later
//print prompt
println!("{}", prompt);
stdout().flush().expect("Failed to flush to stdout.");
//read user input from standard input, and store it to raw_input
//raw_input.clear(); //clear input
io::stdin().read_line(&mut raw_input).expect( "CANNOT READ INPUT!");
//from input, try to read a valid character
match raw_input.trim().chars().nth(0) {
Some(i) => {
if !valid_results.contains(&i) { //input out of desired range
println!("INPUT IS NOT VALID CHARACTER. TRY AGAIN.");
continue; // run the loop again
}
else {
break i;// this escapes the loop, returning i
}
},
None => {
println!("INVALID INPUT. TRY AGAIN.");
continue; // run the loop again
}
};
};
}
/**
* clear std out
*/
fn clear() {
println!("\x1b[2J\x1b[0;0H");
}

View File

@@ -18,7 +18,7 @@ namespace Bombardment
private List<int> computerPositions = new List<int>();
private List<int> playerPositions = new List<int>();
private List<int> computerGuesses = new List<int>();
private void PrintStartingMessage()
{
Console.WriteLine("{0}BOMBARDMENT", new string(' ', 33));
@@ -26,7 +26,7 @@ namespace Bombardment
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("YOU ARE ON A BATTLEFIELD WITH 4 PLATOONS AND YOU");
Console.WriteLine("HAVE 25 OUTPOSTS AVAILABLE WHERE THEY MAY BE PLACED.");
Console.WriteLine("YOU CAN ONLY PLACE ONE PLATOON AT ANY ONE OUTPOST.");
@@ -51,9 +51,9 @@ namespace Bombardment
{
// The token replacement can be padded by using the format {tokenPosition, padding}
// Negative values for the padding cause the output to be left-aligned.
Console.WriteLine("{0,-3}{1,-3}{2,-3}{3,-3}{4,-3}", i, i + 1, i + 2, i + 3, i + 4);
Console.WriteLine("{0,-3}{1,-3}{2,-3}{3,-3}{4,-3}", i, i + 1, i + 2, i + 3, i + 4);
}
Console.WriteLine("\n");
}

View File

@@ -366,4 +366,4 @@ public class Bombardment {
return (int) (Math.random()
* (MAX_GRID_SIZE) + 1);
}
}
}

View File

@@ -12,10 +12,10 @@ 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");
@@ -103,7 +103,7 @@ async function main()
y = parseInt(await input());
} while (y < 0 || y > 25) ;
if (y == c || y == d || y == e || y == f) {
// The original game has a bug. You can shoot the same outpost
// several times. This solves it.
if (y == c)

View File

@@ -54,7 +54,7 @@ sub computer_turn {
else {
print "YOU'RE DEAD. YOUR LAST OUTPOST WAS AT $target. HA, HA, HA.\nBETTER LUCK NEXT TIME\n";
}
}
else {
print "I MISSED YOU, YOU DIRTY RAT. I PICKED $target. YOUR TURN:\n";

View File

@@ -2,6 +2,7 @@
import random
from functools import partial
def display_intro():
print("" * 33 + "BOMBARDMENT")
print("" * 15 + " CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
@@ -25,7 +26,7 @@ def display_intro():
def display_field():
for row in range(5):
initial = row * 5 + 1
print('\t'.join([str(initial + column) for column in range(5)]))
print("\t".join([str(initial + column) for column in range(5)]))
print("\n" * 9)
@@ -35,7 +36,7 @@ def positions_list():
def generate_enemy_positions():
""" Randomly choose 4 'positions' out of a range of 1 to 25 """
"""Randomly choose 4 'positions' out of a range of 1 to 25"""
positions = positions_list()
random.shuffle(positions)
return set(positions[:4])
@@ -49,13 +50,13 @@ def prompt_for_player_positions():
while True:
raw_positions = input("WHAT ARE YOUR FOUR POSITIONS? ")
positions = set(int(pos) for pos in raw_positions.split())
positions = {int(pos) for pos in raw_positions.split()}
# Verify user inputs (for example, if the player gives a
# a position for 26, the enemy can never hit it)
if (len(positions) != 4):
if len(positions) != 4:
print("PLEASE ENTER 4 UNIQUE POSITIONS\n")
continue
elif (any(not is_valid_position(pos) for pos in positions)):
elif any(not is_valid_position(pos) for pos in positions):
print("ALL POSITIONS MUST RANGE (1-25)\n")
continue
else:
@@ -74,7 +75,7 @@ def prompt_player_for_target():
def attack(target, positions, hit_message, miss_message, progress_messages):
""" Performs attack procedure returning True if we are to continue. """
"""Performs attack procedure returning True if we are to continue."""
if target in positions:
print(hit_message.format(target))
@@ -87,9 +88,9 @@ def attack(target, positions, hit_message, miss_message, progress_messages):
def init_enemy():
""" Returns a closure analogous to prompt_player_for_target. Will
choose from a unique sequence of positions to avoid picking the
same position twice. """
"""Returns a closure analogous to prompt_player_for_target. Will
choose from a unique sequence of positions to avoid picking the
same position twice."""
position_sequence = positions_list()
random.shuffle(position_sequence)
@@ -103,21 +104,19 @@ def init_enemy():
# Messages correspond to outposts remaining (3, 2, 1, 0)
PLAYER_PROGRESS_MESSAGES = (
"YOU GOT ME, I'M GOING FAST. BUT I'LL GET YOU WHEN\n"
"MY TRANSISTO&S RECUP%RA*E!",
"YOU GOT ME, I'M GOING FAST. BUT I'LL GET YOU WHEN\n" "MY TRANSISTO&S RECUP%RA*E!",
"THREE DOWN, ONE TO GO.\n\n",
"TWO DOWN, TWO TO GO.\n\n",
"ONE DOWN, THREE TO GO.\n\n"
)
"ONE DOWN, THREE TO GO.\n\n",
)
ENEMY_PROGRESS_MESSAGES = (
"YOU'RE DEAD. YOUR LAST OUTPOST WAS AT {}. HA, HA, HA.\n"
"BETTER LUCK NEXT TIME.",
"YOU'RE DEAD. YOUR LAST OUTPOST WAS AT {}. HA, HA, HA.\n" "BETTER LUCK NEXT TIME.",
"YOU HAVE ONLY ONE OUTPOST LEFT.\n\n",
"YOU HAVE ONLY TWO OUTPOSTS LEFT.\n\n",
"YOU HAVE ONLY THREE OUTPOSTS LEFT.\n\n",
)
)
def play():
@@ -128,22 +127,28 @@ def play():
player_positions = prompt_for_player_positions()
# Build partial functions only requiring the target as input
player_attacks = partial(attack,
positions=enemy_positions,
hit_message="YOU GOT ONE OF MY OUTPOSTS!",
miss_message="HA, HA YOU MISSED. MY TURN NOW:\n\n",
progress_messages=PLAYER_PROGRESS_MESSAGES)
player_attacks = partial(
attack,
positions=enemy_positions,
hit_message="YOU GOT ONE OF MY OUTPOSTS!",
miss_message="HA, HA YOU MISSED. MY TURN NOW:\n\n",
progress_messages=PLAYER_PROGRESS_MESSAGES,
)
enemy_attacks = partial(attack,
positions=player_positions,
hit_message="I GOT YOU. IT WON'T BE LONG NOW. POST {} WAS HIT.",
miss_message="I MISSED YOU, YOU DIRTY RAT. I PICKED {}. YOUR TURN:\n\n",
progress_messages=ENEMY_PROGRESS_MESSAGES)
enemy_attacks = partial(
attack,
positions=player_positions,
hit_message="I GOT YOU. IT WON'T BE LONG NOW. POST {} WAS HIT.",
miss_message="I MISSED YOU, YOU DIRTY RAT. I PICKED {}. YOUR TURN:\n\n",
progress_messages=ENEMY_PROGRESS_MESSAGES,
)
enemy_position_choice = init_enemy()
# Play as long as both player_attacks and enemy_attacks allow to continue
while player_attacks(prompt_player_for_target()) and enemy_attacks(enemy_position_choice()):
while player_attacks(prompt_player_for_target()) and enemy_attacks(
enemy_position_choice()
):
pass

View File

@@ -35,7 +35,7 @@
280 PRINT
285 INPUT "HOW MANY MISSIONS HAVE YOU FLOWN";D
290 IF D<160 THEN 300
292 PRINT "MISSIONS, NOT MILES..."
292 PRINT "MISSIONS, NOT MILES..."
295 PRINT "150 MISSIONS IS HIGH EVEN FOR OLD-TIMERS."
297 PRINT "NOW THEN, "; : GOTO 285
300 PRINT:IF D<100 THEN 310

View File

@@ -23,4 +23,3 @@ bool UserWantsToPlayAgain(IUserInterface ui)
return result;
}

View File

@@ -519,4 +519,4 @@ public class BombsAway {
return (Math.random()
* (range));
}
}
}

View File

@@ -12,10 +12,10 @@ 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");

View File

@@ -155,7 +155,7 @@ NOW THEN, ';
# and $guns_hit_rate here because the original BASIC code did not reset
# the associated variables (respectively T and S) at every mission, thus
# leaking state from one mission to the following ones.
#
#
# In particular, both are leaked to the Japan mission(s), and
# $guns_hit_rate is leaked to future "multiple()" missions that have
# missiles only.

Some files were not shown because too many files have changed in this diff Show More