From 47ec385b6b2449219b7cb5e71b98a38386b4f5d4 Mon Sep 17 00:00:00 2001
From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com>
Date: Sat, 24 Apr 2021 18:40:00 -0400
Subject: [PATCH 01/15] Ported Bounce to Java.
---
13 Bounce/java/Bounce.java | 169 +++++++++++++++++++++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 13 Bounce/java/Bounce.java
diff --git a/13 Bounce/java/Bounce.java b/13 Bounce/java/Bounce.java
new file mode 100644
index 00000000..6d39daa2
--- /dev/null
+++ b/13 Bounce/java/Bounce.java
@@ -0,0 +1,169 @@
+import java.util.Scanner;
+import java.lang.Math;
+
+/**
+ * Game of Bounce
+ *
+ * Based on the BASIC game of Bounce here
+ * https://github.com/coding-horror/basic-computer-games/blob/main/13%20Bounce/bounce.bas
+ *
+ * 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 Bounce {
+
+ private final Scanner scan; // For user input
+
+ public Bounce() {
+
+ scan = new Scanner(System.in);
+
+ } // End of constructor Bounce
+
+ public void play() {
+
+ showIntro();
+ startGame();
+
+ } // End of method play
+
+ private void showIntro() {
+
+ System.out.println(" ".repeat(32) + "BOUNCE");
+ System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
+ System.out.println("\n\n");
+
+ } // End of method showIntro
+
+ private void startGame() {
+
+ double coefficient = 0;
+ double height = 0;
+ double timeIncrement = 0;
+ double timeIndex = 0;
+ double timeTotal = 0;
+ double velocity = 0;
+
+ double[] timeData = new double[21];
+
+ int heightInt = 0;
+ int index = 0;
+ int maxData = 0;
+
+ String lineContent = "";
+
+ System.out.println("THIS SIMULATION LETS YOU SPECIFY THE INITIAL VELOCITY");
+ System.out.println("OF A BALL THROWN STRAIGHT UP, AND THE COEFFICIENT OF");
+ System.out.println("ELASTICITY OF THE BALL. PLEASE USE A DECIMAL FRACTION");
+ System.out.println("COEFFICIENCY (LESS THAN 1).");
+ System.out.println("");
+ System.out.println("YOU ALSO SPECIFY THE TIME INCREMENT TO BE USED IN");
+ System.out.println("'STROBING' THE BALL'S FLIGHT (TRY .1 INITIALLY).");
+ System.out.println("");
+
+ // Begin outer while loop
+ while (true) {
+
+ System.out.print("TIME INCREMENT (SEC)? ");
+ timeIncrement = Double.parseDouble(scan.nextLine());
+ System.out.println("");
+
+ System.out.print("VELOCITY (FPS)? ");
+ velocity = Double.parseDouble(scan.nextLine());
+ System.out.println("");
+
+ System.out.print("COEFFICIENT? ");
+ coefficient = Double.parseDouble(scan.nextLine());
+ System.out.println("");
+
+ System.out.println("FEET");
+ System.out.println("");
+
+ maxData = (int)(70 / (velocity / (16 * timeIncrement)));
+
+ for (index = 1; index <= maxData; index++) {
+ timeData[index] = velocity * Math.pow(coefficient, index - 1) / 16;
+ }
+
+ // Begin loop through all rows of y-axis data
+ for (heightInt = (int)(-16 * Math.pow(velocity / 32, 2) + Math.pow(velocity, 2) / 32 + 0.5) * 10;
+ heightInt >= 0; heightInt -= 5) {
+
+ height = heightInt / 10.0;
+
+ lineContent = "";
+
+ if ((int)(Math.floor(height)) == height) {
+
+ lineContent += " " + (int)(height) + " ";
+ }
+
+ timeTotal = 0;
+
+ for (index = 1; index <= maxData; index++) {
+
+ for (timeIndex = 0; timeIndex <= timeData[index]; timeIndex += timeIncrement) {
+
+ timeTotal += timeIncrement;
+
+ if (Math.abs(height - (0.5 * (-32) * Math.pow(timeIndex, 2) + velocity
+ * Math.pow(coefficient, index - 1) * timeIndex)) <= 0.25) {
+
+ while (lineContent.length() < (timeTotal / timeIncrement) - 1) {
+ lineContent += " ";
+ }
+ lineContent += "0";
+ }
+ }
+
+ timeIndex = timeData[index + 1] / 2;
+
+ if (-16 * Math.pow(timeIndex, 2) + velocity * Math.pow(coefficient, index - 1) * timeIndex < height) {
+
+ break;
+ }
+ }
+
+ System.out.println(lineContent);
+
+ } // End loop through all rows of y-axis data
+
+ lineContent = "";
+
+ // Show the x-axis
+ for (index = 1; index <= (int)(timeTotal + 1) / timeIncrement + 1; index++) {
+
+ lineContent += ".";
+ }
+
+ System.out.println(lineContent);
+
+ lineContent = " 0";
+
+ for (index = 1; index <= (int)(timeTotal + 0.9995); index++) {
+
+ while (lineContent.length() < (int)(index / timeIncrement)) {
+ lineContent += " ";
+ }
+ lineContent += index;
+ }
+
+ System.out.println(lineContent);
+
+ System.out.println(" ".repeat((int)((timeTotal + 1) / (2 * timeIncrement) - 3)) + "SECONDS");
+
+ } // End outer while loop
+
+ } // End of method startGame
+
+ public static void main(String[] args) {
+
+ Bounce game = new Bounce();
+ game.play();
+
+ } // End of method main
+
+} // End of class Bounce
From d195ab8151ca2b6018e39c52d1066f75260c56ef Mon Sep 17 00:00:00 2001
From: jason
Date: Sat, 24 Apr 2021 20:21:04 -0400
Subject: [PATCH 02/15] Golf in C#. Source, plus 2 pre-compiled executables
---
39 Golf/csharp/Program.cs | 1142 +++++++++++++++++++++++++++++++++++++
39 Golf/csharp/README.md | 12 +
2 files changed, 1154 insertions(+)
create mode 100644 39 Golf/csharp/Program.cs
diff --git a/39 Golf/csharp/Program.cs b/39 Golf/csharp/Program.cs
new file mode 100644
index 00000000..abbbaf6b
--- /dev/null
+++ b/39 Golf/csharp/Program.cs
@@ -0,0 +1,1142 @@
+//
+// 8""""8 8"""88 8 8""""
+// 8 " 8 8 8 8
+// 8e 8 8 8e 8eeee
+// 88 ee 8 8 88 88
+// 88 8 8 8 88 88
+// 88eee8 8eeee8 88eee 88
+//
+// GOLF
+//
+// C#
+// .NET Core
+// TargetFramework: netcoreapp 3.1
+//
+// Run source:
+// dotnet run
+//
+// Linux compile:
+// dotnet publish --self-contained -c Release -r linux-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true
+//
+// Windows compile:
+// dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true
+//
+//
+// INDEX
+// ----------------- methods
+// constructor
+// NewHole
+// TeeUp
+// Stroke
+// PlotBall
+// InterpretResults
+// ReportCurrentScore
+// FindBall
+// IsOnFairway
+// IsOnGreen
+// IsInHazard
+// IsInRough
+// IsOutOfBounds
+// ScoreCardNewHole
+// ScoreCardRecordStroke
+// ScoreCardGetPreviousStroke
+// ScoreCardGetTotal
+// Ask
+// Wait
+// ReviewBag
+// Quit
+// GameOver
+// ----------------- DATA
+// Clubs
+// CourseInfo
+// ----------------- classes
+// HoleInfo
+// CircleGameObj
+// RectGameObj
+// HoleGeometry
+// Plot
+// ----------------- helper methods
+// GetDistance
+// IsInRectangle
+// ToRadians
+// ToDegrees360
+// Odds
+//
+// Despite being a text based game, the code uses simple geometry to simulate a course.
+// Fairways are 40 yard wide rectangles, surrounded by 5 yards of rough around the perimeter.
+// The green is a circle of 10 yards radius around the cup.
+// The cup is always at point (0,0).
+//
+// Using basic trigonometry we can plot the ball's location using the distance of the stroke and
+// and the angle of deviation (hook/slice).
+//
+// The stroke distances are based on real world averages of different club types.
+// Lots of randomization, "business rules", and luck influence the game play.
+// Probabilities are commented in the code.
+//
+// note: 'courseInfo', 'clubs', & 'scoreCard' arrays each include an empty object so indexing
+// can begin at 1. Like all good programmers we count from zero, but in this context,
+// it's more natural when hole number one is at index one
+//
+//
+// |-----------------------------|
+// | rough |
+// | ---------------------- |
+// | | | |
+// | r | = = | r |
+// | o | = = | o |
+// | u | = . = | u |
+// | g | = green = | g |
+// | h | = = | h |
+// | | = = | |
+// | | | |
+// | | | |
+// | | Fairway | |
+// | | | |
+// | | ------ |
+// | | -- -- |
+// | | -- hazard --|
+// | | -- -- |
+// | | ------ |
+// | | | |
+// | | | | out
+// | | | | of
+// | | | | bounds
+// | | | |
+// | | | |
+// | tee |
+//
+//
+// Typical green size: 20-30 yards
+// Typical golf course fairways are 35 to 45 yards wide
+// Our fairway extends 5 yards past green
+// Our rough is a 5 yard perimeter around fairway
+//
+// We calculate the new position of the ball given the ball's point, the distance
+// of the stroke, and degrees off line (hook or slice).
+//
+// Degrees off (for a right handed golfer):
+// Slice: positive degrees = ball goes right
+// Hook: negative degrees = left goes left
+//
+// The cup is always at point: 0,0.
+// We use atan2 to compute the angle between the cup and the ball.
+// Setting the cup's vector to 0,-1 on a 360 circle is equivalent to:
+// 0 deg = 12 o'clock; 90 deg = 3 o'clock; 180 deg = 6 o'clock; 270 = 9 o'clock
+// The reverse angle between the cup and the ball is a difference of PI (using radians).
+//
+// Given the angle and stroke distance (hypotenuse), we use cosine to compute
+// the opposite and adjacent sides of the triangle, which, is the ball's new position.
+//
+// 0
+// |
+// 270 - cup - 90
+// |
+// 180
+//
+//
+// cup
+// |
+// |
+// | opp
+// |-----* new position
+// | /
+// | /
+// adj | /
+// | / hyp
+// |/
+// tee
+//
+// <- hook slice ->
+//
+//
+// Given the large number of combinations needed to describe a particular stroke / ball location,
+// we use the technique of "bitwise masking" to describe stroke results.
+// With bit masking, multiple flags (bits) are combined into a single binary number that can be
+// tested by applying a mask. A mask is another binary number that isolates a particular bit that
+// you are interested in. You can then apply your language's bitwise opeartors to test or
+// set a flag.
+//
+// Game design by Jason Bonthron, 2021
+// www.bonthron.com
+// for my father, Raymond Bonthron, an avid golfer
+//
+// Inspired by the 1978 "Golf" from "Basic Computer Games"
+// by Steve North, who modified an existing golf game by an unknown author
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Threading;
+
+
+namespace Golf
+{
+ using Ball = Golf.CircleGameObj;
+ using Hazard = Golf.CircleGameObj;
+
+ // --------------------------------------------------------------------------- Program
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Golf g = new Golf();
+ }
+ }
+
+
+ // --------------------------------------------------------------------------- Golf
+ public class Golf
+ {
+ Ball BALL;
+ int HOLE_NUM = 0;
+ int STROKE_NUM = 0;
+ int Handicap = 0;
+ int PlayerDifficulty = 0;
+ HoleGeometry holeGeometry;
+
+ // all fairways are 40 yards wide, extend 5 yards beyond the cup, and
+ // have 5 yards of rough around the perimeter
+ const int FairwayWidth = 40;
+ const int FairwayExtension = 5;
+ const int RoughAmt = 5;
+
+ // ScoreCard records the ball position after each stroke
+ // a new list for each hole
+ // include a blank list so index 1 == hole 1
+
+ List> ScoreCard = new List> { new List() };
+
+ static void w(string s) { Console.WriteLine(s); } // WRITE
+ Random RANDOM = new Random();
+
+
+ // --------------------------------------------------------------- constructor
+ public Golf()
+ {
+ Console.Clear();
+ w(" ");
+ w(" 8\"\"\"\"8 8\"\"\"88 8 8\"\"\"\" ");
+ w(" 8 \" 8 8 8 8 ");
+ w(" 8e 8 8 8e 8eeee ");
+ w(" 88 ee 8 8 88 88 ");
+ w(" 88 8 8 8 88 88 ");
+ w(" 88eee8 8eeee8 88eee 88 ");
+ w(" ");
+ w("Welcome to the Creative Computing Country Club,");
+ w("an eighteen hole championship layout located a short");
+ w("distance from scenic downtown Lambertville, New Jersey.");
+ w("The game will be explained as you play.");
+ w("Enjoy your game! See you at the 19th hole...");
+ w(" ");
+ w("Type QUIT at any time to leave the game.");
+ w("Type BAG at any time to review the clubs in your bag.");
+ w(" ");
+
+ Wait((z) =>
+ {
+ w(" ");
+ w(" YOUR BAG");
+ ReviewBag();
+ w("Type BAG at any time to review the clubs in your bag.");
+ w(" ");
+
+ Wait((zz) =>
+ {
+ w(" ");
+
+ Ask("PGA handicaps range from 0 to 30.\nWhat is your handicap?", 0, 30, (i) =>
+ {
+ Handicap = i;
+ w(" ");
+
+ Ask("Common difficulties at golf include:\n1=Hook, 2=Slice, 3=Poor Distance, 4=Trap Shots, 5=Putting\nWhich one is your worst?", 1, 5, (j) =>
+ {
+ PlayerDifficulty = j;
+ Console.Clear();
+ NewHole();
+ });
+ });
+ });
+ });
+ }
+
+
+ // --------------------------------------------------------------- NewHole
+ void NewHole()
+ {
+ HOLE_NUM++;
+ STROKE_NUM = 0;
+
+ HoleInfo info = CourseInfo[HOLE_NUM];
+
+ int yards = info.Yards; // from tee to cup
+ int par = info.Par;
+ var cup = new CircleGameObj(0, 0, 0, GameObjType.CUP);
+ var green = new CircleGameObj(0, 0, 10, GameObjType.GREEN);
+
+ var fairway = new RectGameObj(0 - (FairwayWidth / 2),
+ 0 - (green.Radius + FairwayExtension),
+ FairwayWidth,
+ yards + (green.Radius + FairwayExtension) + 1,
+ GameObjType.FAIRWAY);
+
+ var rough = new RectGameObj(fairway.X - RoughAmt,
+ fairway.Y - RoughAmt,
+ fairway.Width + (2 * RoughAmt),
+ fairway.Length + (2 * RoughAmt),
+ GameObjType.ROUGH);
+
+ BALL = new Ball(0, yards, 0, GameObjType.BALL);
+
+ ScoreCardStartNewHole();
+
+ holeGeometry = new HoleGeometry(cup, green, fairway, rough, info.Hazard);
+
+ w(" |> " + HOLE_NUM);
+ w(" | ");
+ w(" | ");
+ w(" ^^^^^^^^^^^^^^^");
+
+ Console.WriteLine("Hole #{0}. You are at the tee. Distance {1} yards, par {2}.", HOLE_NUM, info.Yards, info.Par);
+ w(info.Description);
+
+ TeeUp();
+ }
+
+
+ // --------------------------------------------------------------- TeeUp
+ // on the green? automatically select putter
+ // otherwise Ask club and swing strength
+
+ void TeeUp()
+ {
+ if (IsOnGreen(BALL) && !IsInHazard(BALL, GameObjType.SAND))
+ {
+ var putt = 10;
+ w("[PUTTER: average 10 yards]");
+ var msg = Odds(20) ? "Keep your head down.\n" : "";
+
+ Ask(msg + "Choose your putt potency. (1-10)", 1, 10, (strength) =>
+ {
+ var putter = Clubs[putt];
+ Stroke(Convert.ToDouble((double)putter.Item2 * ((double)strength / 10.0)), putt);
+ });
+ }
+ else
+ {
+ Ask("What club do you choose? (1-10)", 1, 10, (c) =>
+ {
+ var club = Clubs[c];
+
+ w(" ");
+ Console.WriteLine("[{0}: average {1} yards]", club.Item1.ToUpper(), club.Item2);
+
+ Ask("Now gauge your distance by a percentage of a full swing. (1-10)", 1, 10, (strength) =>
+ {
+ Stroke(Convert.ToDouble((double)club.Item2 * ((double)strength / 10.0)), c);
+ });
+ });
+ };
+ }
+
+
+ // -------------------------------------------------------- bitwise Flags
+ int dub = 0b00000000000001;
+ int hook = 0b00000000000010;
+ int slice = 0b00000000000100;
+ int passedCup = 0b00000000001000;
+ int inCup = 0b00000000010000;
+ int onFairway = 0b00000000100000;
+ int onGreen = 0b00000001000000;
+ int inRough = 0b00000010000000;
+ int inSand = 0b00000100000000;
+ int inTrees = 0b00001000000000;
+ int inWater = 0b00010000000000;
+ int outOfBounds = 0b00100000000000;
+ int luck = 0b01000000000000;
+ int ace = 0b10000000000000;
+
+
+ // --------------------------------------------------------------- Stroke
+ void Stroke(double clubAmt, int clubIndex)
+ {
+ STROKE_NUM++;
+
+ var flags = 0b000000000000;
+
+ // fore! only when driving
+ if ((STROKE_NUM == 1) && (clubAmt > 210) && Odds(30)) { w("\"...Fore !\""); };
+
+ // dub
+ if (Odds(5)) { flags |= dub; }; // there's always a 5% chance of dubbing it
+
+ // if you're in the rough, or sand, you really should be using a wedge
+ if ((IsInRough(BALL) || IsInHazard(BALL, GameObjType.SAND)) &&
+ !(clubIndex == 8 || clubIndex == 9))
+ {
+ if (Odds(40)) { flags |= dub; };
+ };
+
+ // trap difficulty
+ if (IsInHazard(BALL, GameObjType.SAND) && PlayerDifficulty == 4)
+ {
+ if (Odds(20)) { flags |= dub; };
+ }
+
+ // hook/slice
+ // There's 10% chance of a hook or slice
+ // if it's a known playerDifficulty then increase chance to 30%
+ // if it's a putt & putting is a playerDifficulty increase to 30%
+
+ bool randHookSlice = (PlayerDifficulty == 1 ||
+ PlayerDifficulty == 2 ||
+ (PlayerDifficulty == 5 && IsOnGreen(BALL))) ? Odds(30) : Odds(10);
+
+ if (randHookSlice)
+ {
+ if (PlayerDifficulty == 1)
+ {
+ if (Odds(80)) { flags |= hook; } else { flags |= slice; };
+ }
+ else if (PlayerDifficulty == 2)
+ {
+ if (Odds(80)) { flags |= slice; } else { flags |= hook; };
+ }
+ else
+ {
+ if (Odds(50)) { flags |= hook; } else { flags |= slice; };
+ };
+ };
+
+ // beginner's luck !
+ // If handicap is greater than 15, there's a 10% chance of avoiding all errors
+ if ((Handicap > 15) && (Odds(10))) { flags |= luck; };
+
+ // ace
+ // there's a 10% chance of an Ace on a par 3
+ if (CourseInfo[HOLE_NUM].Par == 3 && Odds(10) && STROKE_NUM == 1) { flags |= ace; };
+
+ // distance:
+ // If handicap is < 15, there a 50% chance of reaching club average,
+ // a 25% of exceeding it, and a 25% of falling short
+ // If handicap is > 15, there's a 25% chance of reaching club average,
+ // and 75% chance of falling short
+ // The greater the handicap, the more the ball falls short
+ // If poor distance is a known playerDifficulty, then reduce distance by 10%
+
+ double distance;
+ int rnd = RANDOM.Next(1, 101);
+
+ if (Handicap < 15)
+ {
+ if (rnd <= 25)
+ {
+ distance = clubAmt - (clubAmt * ((double)Handicap / 100.0));
+ }
+ else if (rnd > 25 && rnd <= 75)
+ {
+ distance = clubAmt;
+ }
+ else
+ {
+ distance = clubAmt + (clubAmt * 0.10);
+ };
+ }
+ else
+ {
+ if (rnd <= 75)
+ {
+ distance = clubAmt - (clubAmt * ((double)Handicap / 100.0));
+ }
+ else
+ {
+ distance = clubAmt;
+ };
+ };
+
+ if (PlayerDifficulty == 3) // poor distance
+ {
+ if (Odds(80)) { distance = (distance * 0.80); };
+ };
+
+ if ((flags & luck) == luck) { distance = clubAmt; }
+
+ // angle
+ // For all strokes, there's a possible "drift" of 4 degrees
+ // a hooks or slice increases the angle between 5-10 degrees, hook uses negative degrees
+ int angle = RANDOM.Next(0, 5);
+ if ((flags & slice) == slice) { angle = RANDOM.Next(5, 11); };
+ if ((flags & hook) == hook) { angle = 0 - RANDOM.Next(5, 11); };
+ if ((flags & luck) == luck) { angle = 0; };
+
+ var plot = PlotBall(BALL, distance, Convert.ToDouble(angle)); // calculate a new location
+ if ((flags & luck) == luck) { if(plot.Y > 0){ plot.Y = 2; }; };
+
+ flags = FindBall(new Ball(plot.X, plot.Y, plot.Offline, GameObjType.BALL), flags);
+
+ InterpretResults(plot, flags);
+ }
+
+
+ // --------------------------------------------------------------- plotBall
+ Plot PlotBall(Ball ball, double strokeDistance, double degreesOff)
+ {
+ var cupVector = new Point(0, -1);
+ double radFromCup = Math.Atan2((double)ball.Y, (double)ball.X) - Math.Atan2((double)cupVector.Y, (double)cupVector.X);
+ double radFromBall = radFromCup - Math.PI;
+
+ var hypotenuse = strokeDistance;
+ var adjacent = Math.Cos(radFromBall + ToRadians(degreesOff)) * hypotenuse;
+ var opposite = Math.Sqrt(Math.Pow(hypotenuse, 2) - Math.Pow(adjacent, 2));
+
+ Point newPos;
+ if (ToDegrees360(radFromBall + ToRadians(degreesOff)) > 180)
+ {
+ newPos = new Point(Convert.ToInt32(ball.X - opposite),
+ Convert.ToInt32(ball.Y - adjacent));
+ }
+ else
+ {
+ newPos = new Point(Convert.ToInt32(ball.X + opposite),
+ Convert.ToInt32(ball.Y - adjacent));
+ }
+
+ return new Plot(newPos.X, newPos.Y, Convert.ToInt32(opposite));
+ }
+
+
+ // --------------------------------------------------------------- InterpretResults
+ void InterpretResults(Plot plot, int flags)
+ {
+ int cupDistance = Convert.ToInt32(GetDistance(new Point(plot.X, plot.Y),
+ new Point(holeGeometry.Cup.X, holeGeometry.Cup.Y)));
+ int travelDistance = Convert.ToInt32(GetDistance(new Point(plot.X, plot.Y),
+ new Point(BALL.X, BALL.Y)));
+
+ w(" ");
+
+ if ((flags & ace) == ace)
+ {
+ w("Hole in One! You aced it.");
+ ScoreCardRecordStroke(new Ball(0, 0, 0, GameObjType.BALL));
+ ReportCurrentScore();
+ return;
+ };
+
+ if ((flags & inTrees) == inTrees)
+ {
+ w("Your ball is lost in the trees. Take a penalty stroke.");
+ ScoreCardRecordStroke(BALL);
+ TeeUp();
+ return;
+ };
+
+ if ((flags & inWater) == inWater)
+ {
+ var msg = Odds(50) ? "Your ball has gone to a watery grave." : "Your ball is lost in the water.";
+ w(msg + " Take a penalty stroke.");
+ ScoreCardRecordStroke(BALL);
+ TeeUp();
+ return;
+ };
+
+ if ((flags & outOfBounds) == outOfBounds)
+ {
+ w("Out of bounds. Take a penalty stroke.");
+ ScoreCardRecordStroke(BALL);
+ TeeUp();
+ return;
+ };
+
+ if ((flags & dub) == dub)
+ {
+ w("You dubbed it.");
+ ScoreCardRecordStroke(BALL);
+ TeeUp();
+ return;
+ };
+
+ if ((flags & inCup) == inCup)
+ {
+ var msg = Odds(50) ? "You holed it." : "It's in!";
+ w(msg);
+ ScoreCardRecordStroke(new Ball(plot.X, plot.Y, 0, GameObjType.BALL));
+ ReportCurrentScore();
+ return;
+ };
+
+ if (((flags & slice) == slice) &&
+ !((flags & onGreen) == onGreen))
+ {
+ var bad = ((flags & outOfBounds) == outOfBounds) ? " badly" : "";
+ Console.WriteLine("You sliced{0}: {1} yards offline.", bad, plot.Offline);
+ };
+
+ if (((flags & hook) == hook) &&
+ !((flags & onGreen) == onGreen))
+ {
+ var bad = ((flags & outOfBounds) == outOfBounds) ? " badly" : "";
+ Console.WriteLine("You hooked{0}: {1} yards offline.", bad, plot.Offline);
+ };
+
+ if (STROKE_NUM > 1)
+ {
+ var prevBall = ScoreCardGetPreviousStroke();
+ var d1 = GetDistance(new Point(prevBall.X, prevBall.Y),
+ new Point(holeGeometry.Cup.X, holeGeometry.Cup.Y));
+ var d2 = cupDistance;
+ if (d2 > d1) { w("Too much club."); };
+ };
+
+ if ((flags & inRough) == inRough) { w("You're in the rough."); };
+
+ if ((flags & inSand) == inSand) { w("You're in a sand trap."); };
+
+ if ((flags & onGreen) == onGreen)
+ {
+ var pd = (cupDistance < 4) ? ((cupDistance * 3) + " feet") : (cupDistance + " yards");
+ Console.WriteLine("You're on the green. It's {0} from the pin.", pd);
+ };
+
+ if (((flags & onFairway) == onFairway) ||
+ ((flags & inRough) == inRough))
+ {
+ Console.WriteLine("Shot went {0} yards. It's {1} yards from the cup.", travelDistance, cupDistance);
+ };
+
+ ScoreCardRecordStroke(new Ball(plot.X, plot.Y, 0, GameObjType.BALL));
+
+ BALL = new Ball(plot.X, plot.Y, 0, GameObjType.BALL);
+
+ TeeUp();
+ }
+
+
+ // --------------------------------------------------------------- ReportCurrentScore
+ void ReportCurrentScore()
+ {
+ var par = CourseInfo[HOLE_NUM].Par;
+ if (ScoreCard[HOLE_NUM].Count == par + 1) { w("A bogey. One above par."); };
+ if (ScoreCard[HOLE_NUM].Count == par) { w("Par. Nice."); };
+ if (ScoreCard[HOLE_NUM].Count == (par - 1)) { w("A birdie! One below par."); };
+ if (ScoreCard[HOLE_NUM].Count == (par - 2)) { w("An Eagle! Two below par."); };
+ if (ScoreCard[HOLE_NUM].Count == (par - 3)) { w("Double Eagle! Unbelievable."); };
+
+ int totalPar = 0;
+ for (var i = 1; i <= HOLE_NUM; i++) { totalPar += CourseInfo[i].Par; };
+
+ w(" ");
+ w("-----------------------------------------------------");
+ Console.WriteLine(" Total par for {0} hole{1} is: {2}. Your total is: {3}.",
+ HOLE_NUM,
+ ((HOLE_NUM > 1) ? "s" : ""), //plural
+ totalPar,
+ ScoreCardGetTotal());
+ w("-----------------------------------------------------");
+ w(" ");
+
+ if (HOLE_NUM == 18)
+ {
+ GameOver();
+ }
+ else
+ {
+ Thread.Sleep(2000);
+ NewHole();
+ };
+ }
+
+
+ // --------------------------------------------------------------- FindBall
+ int FindBall(Ball ball, int flags)
+ {
+ if (IsOnFairway(ball) && !IsOnGreen(ball)) { flags |= onFairway; }
+ if (IsOnGreen(ball)) { flags |= onGreen; }
+ if (IsInRough(ball)) { flags |= inRough; }
+ if (IsOutOfBounds(ball)) { flags |= outOfBounds; }
+ if (IsInHazard(ball, GameObjType.WATER)) { flags |= inWater; }
+ if (IsInHazard(ball, GameObjType.TREES)) { flags |= inTrees; }
+ if (IsInHazard(ball, GameObjType.SAND)) { flags |= inSand; }
+
+ if (ball.Y < 0) { flags |= passedCup; }
+
+ // less than 2, it's in the cup
+ var d = GetDistance(new Point(ball.X, ball.Y),
+ new Point(holeGeometry.Cup.X, holeGeometry.Cup.Y));
+ if (d < 2) { flags |= inCup; };
+
+ return flags;
+ }
+
+
+ // --------------------------------------------------------------- IsOnFairway
+ bool IsOnFairway(Ball ball)
+ {
+ return IsInRectangle(ball, holeGeometry.Fairway);
+ }
+
+
+ // --------------------------------------------------------------- IsOngreen
+ bool IsOnGreen(Ball ball)
+ {
+ var d = GetDistance(new Point(ball.X, ball.Y),
+ new Point(holeGeometry.Cup.X, holeGeometry.Cup.Y));
+ return d < holeGeometry.Green.Radius;
+ }
+
+
+ // --------------------------------------------------------------- IsInHazard
+ bool IsInHazard(Ball ball, GameObjType hazard)
+ {
+ bool result = false;
+ Array.ForEach(holeGeometry.Hazards, (Hazard h) =>
+ {
+ var d = GetDistance(new Point(ball.X, ball.Y), new Point(h.X, h.Y));
+ if ((d < h.Radius) && h.Type == hazard) { result = true; };
+ });
+ return result;
+ }
+
+
+ // --------------------------------------------------------------- IsInRough
+ bool IsInRough(Ball ball)
+ {
+ return IsInRectangle(ball, holeGeometry.Rough) &&
+ (IsInRectangle(ball, holeGeometry.Fairway) == false);
+ }
+
+
+ // --------------------------------------------------------------- IsOutOfBounds
+ bool IsOutOfBounds(Ball ball)
+ {
+ return (IsOnFairway(ball) == false) && (IsInRough(ball) == false);
+ }
+
+
+ // --------------------------------------------------------------- ScoreCardNewHole
+ void ScoreCardStartNewHole()
+ {
+ ScoreCard.Add(new List());
+ }
+
+
+ // --------------------------------------------------------------- ScoreCardRecordStroke
+ void ScoreCardRecordStroke(Ball ball)
+ {
+ var clone = new Ball(ball.X, ball.Y, 0, GameObjType.BALL);
+ ScoreCard[HOLE_NUM].Add(clone);
+ }
+
+
+ // ------------------------------------------------------------ ScoreCardGetPreviousStroke
+ Ball ScoreCardGetPreviousStroke()
+ {
+ return ScoreCard[HOLE_NUM][ScoreCard[HOLE_NUM].Count - 1];
+ }
+
+
+ // --------------------------------------------------------------- ScoreCardGetTotal
+ int ScoreCardGetTotal()
+ {
+ int total = 0;
+ ScoreCard.ForEach((h) => { total += h.Count; });
+ return total;
+ }
+
+
+ // --------------------------------------------------------------- Ask
+ // input from console is always an integer passed to a callback
+ // or "quit" to end game
+
+ void Ask(string question, int min, int max, Action callback)
+ {
+ w(question);
+ string i = Console.ReadLine().Trim().ToLower();
+ if (i == "quit") { Quit(); return; };
+ if (i == "bag") { ReviewBag(); };
+
+ int n;
+ bool success = Int32.TryParse(i, out n);
+
+ if (success)
+ {
+ if (n >= min && n <= max)
+ {
+ callback(n);
+ }
+ else
+ {
+ Ask(question, min, max, callback);
+ }
+ }
+ else
+ {
+ Ask(question, min, max, callback);
+ };
+ }
+
+
+ // --------------------------------------------------------------- Wait
+ void Wait(Action callback)
+ {
+ w("Press any key to continue.");
+
+ ConsoleKeyInfo keyinfo;
+ do { keyinfo = Console.ReadKey(true); }
+ while (keyinfo.KeyChar < 0);
+ Console.Clear();
+ callback(0);
+ }
+
+
+ // --------------------------------------------------------------- ReviewBag
+ void ReviewBag()
+ {
+ w(" ");
+ w(" # Club Average Yardage");
+ w("-----------------------------------");
+ w(" 1 Driver 250");
+ w(" 2 3 Wood 225");
+ w(" 3 5 Wood 200");
+ w(" 4 Hybrid 190");
+ w(" 5 4 Iron 170");
+ w(" 6 7 Iron 150");
+ w(" 7 9 Iron 125");
+ w(" 8 Pitching wedge 110");
+ w(" 9 Sand wedge 75");
+ w(" 10 Putter 10");
+ w(" ");
+ }
+
+
+ // --------------------------------------------------------------- Quit
+ void Quit()
+ {
+ w("");
+ w("Looks like rain. Goodbye!");
+ w("");
+ Wait((z) => { });
+ return;
+ }
+
+
+ // --------------------------------------------------------------- GameOver
+ void GameOver()
+ {
+ var net = ScoreCardGetTotal() - Handicap;
+ w("Good game!");
+ w("Your net score is: " + net);
+ w("Let's visit the pro shop...");
+ w(" ");
+ Wait((z) => { });
+ return;
+ }
+
+
+ // YOUR BAG
+ // ======================================================== Clubs
+ (string, int)[] Clubs = new (string, int)[] {
+ ("",0),
+
+ // name, average yardage
+ ("Driver", 250),
+ ("3 Wood", 225),
+ ("5 Wood", 200),
+ ("Hybrid", 190),
+ ("4 Iron", 170),
+ ("7 Iron", 150),
+ ("9 Iron", 125),
+ ("Pitching wedge", 110),
+ ("Sand wedge", 75),
+ ("Putter", 10)
+ };
+
+
+ // THE COURSE
+ // ======================================================== CourseInfo
+
+ HoleInfo[] CourseInfo = new HoleInfo[]{
+ new HoleInfo(0, 0, 0, new Hazard[]{}, ""), // include a blank so index 1 == hole 1
+
+
+ // -------------------------------------------------------- front 9
+ // hole, yards, par, hazards, (description)
+
+ new HoleInfo(1, 361, 4,
+ new Hazard[]{
+ new Hazard( 20, 100, 10, GameObjType.TREES),
+ new Hazard(-20, 80, 10, GameObjType.TREES),
+ new Hazard(-20, 100, 10, GameObjType.TREES)
+ },
+ "There are a couple of trees on the left and right."),
+
+ new HoleInfo(2, 389, 4,
+ new Hazard[]{
+ new Hazard(0, 160, 20, GameObjType.WATER)
+ },
+ "There is a large water hazard across the fairway about 150 yards."),
+
+ new HoleInfo(3, 206, 3,
+ new Hazard[]{
+ new Hazard( 20, 20, 5, GameObjType.WATER),
+ new Hazard(-20, 160, 10, GameObjType.WATER),
+ new Hazard( 10, 12, 5, GameObjType.SAND)
+ },
+ "There is some sand and water near the green."),
+
+ new HoleInfo(4, 500, 5,
+ new Hazard[]{
+ new Hazard(-14, 12, 12, GameObjType.SAND)
+ },
+ "There's a bunker to the left of the green."),
+
+ new HoleInfo(5, 408, 4,
+ new Hazard[]{
+ new Hazard(20, 120, 20, GameObjType.TREES),
+ new Hazard(20, 160, 20, GameObjType.TREES),
+ new Hazard(10, 20, 5, GameObjType.SAND)
+ },
+ "There are some trees to your right."),
+
+ new HoleInfo(6, 359, 4,
+ new Hazard[]{
+ new Hazard( 14, 0, 4, GameObjType.SAND),
+ new Hazard(-14, 0, 4, GameObjType.SAND)
+ },
+ ""),
+
+ new HoleInfo(7, 424, 5,
+ new Hazard[]{
+ new Hazard(20, 200, 10, GameObjType.SAND),
+ new Hazard(10, 180, 10, GameObjType.SAND),
+ new Hazard(20, 160, 10, GameObjType.SAND)
+ },
+ "There are several sand traps along your right."),
+
+ new HoleInfo(8, 388, 4,
+ new Hazard[]{
+ new Hazard(-20, 340, 10, GameObjType.TREES)
+ },
+ ""),
+
+ new HoleInfo(9, 196, 3,
+ new Hazard[]{
+ new Hazard(-30, 180, 20, GameObjType.TREES),
+ new Hazard( 14, -8, 5, GameObjType.SAND)
+ },
+ ""),
+
+ // -------------------------------------------------------- back 9
+ // hole, yards, par, hazards, (description)
+
+ new HoleInfo(10, 400, 4,
+ new Hazard[]{
+ new Hazard(-14, -8, 5, GameObjType.SAND),
+ new Hazard( 14, -8, 5, GameObjType.SAND)
+ },
+ ""),
+
+ new HoleInfo(11, 560, 5,
+ new Hazard[]{
+ new Hazard(-20, 400, 10, GameObjType.TREES),
+ new Hazard(-10, 380, 10, GameObjType.TREES),
+ new Hazard(-20, 260, 10, GameObjType.TREES),
+ new Hazard(-20, 200, 10, GameObjType.TREES),
+ new Hazard(-10, 180, 10, GameObjType.TREES),
+ new Hazard(-20, 160, 10, GameObjType.TREES)
+ },
+ "Lots of trees along the left of the fairway."),
+
+ new HoleInfo(12, 132, 3,
+ new Hazard[]{
+ new Hazard(-10, 120, 10, GameObjType.WATER),
+ new Hazard( -5, 100, 10, GameObjType.SAND)
+ },
+ "There is water and sand directly in front of you. A good drive should clear both."),
+
+ new HoleInfo(13, 357, 4,
+ new Hazard[]{
+ new Hazard(-20, 200, 10, GameObjType.TREES),
+ new Hazard(-10, 180, 10, GameObjType.TREES),
+ new Hazard(-20, 160, 10, GameObjType.TREES),
+ new Hazard( 14, 12, 8, GameObjType.SAND)
+ },
+ ""),
+
+ new HoleInfo(14, 294, 4,
+ new Hazard[]{
+ new Hazard(0, 20, 10, GameObjType.SAND)
+ },
+ ""),
+
+ new HoleInfo(15, 475, 5,
+ new Hazard[]{
+ new Hazard(-20, 20, 10, GameObjType.WATER),
+ new Hazard( 10, 20, 10, GameObjType.SAND)
+ },
+ "Some sand and water near the green."),
+
+ new HoleInfo(16, 375, 4,
+ new Hazard[]{
+ new Hazard(-14, -8, 5, GameObjType.SAND)
+ },
+ ""),
+
+ new HoleInfo(17, 180, 3,
+ new Hazard[]{
+ new Hazard( 20, 100, 10, GameObjType.TREES),
+ new Hazard(-20, 80, 10, GameObjType.TREES)
+ },
+ ""),
+
+ new HoleInfo(18, 550, 5,
+ new Hazard[]{
+ new Hazard(20, 30, 15, GameObjType.WATER)
+ },
+ "There is a water hazard near the green.")
+ };
+
+
+ // -------------------------------------------------------- HoleInfo
+ class HoleInfo
+ {
+ public int Hole { get; }
+ public int Yards { get; }
+ public int Par { get; }
+ public Hazard[] Hazard { get; }
+ public string Description { get; }
+
+ public HoleInfo(int hole, int yards, int par, Hazard[] hazard, string description)
+ {
+ Hole = hole;
+ Yards = yards;
+ Par = par;
+ Hazard = hazard;
+ Description = description;
+ }
+ }
+
+
+ public enum GameObjType { BALL, CUP, GREEN, FAIRWAY, ROUGH, TREES, WATER, SAND }
+
+
+ // -------------------------------------------------------- CircleGameObj
+ public class CircleGameObj
+ {
+ public GameObjType Type { get; }
+ public int X { get; }
+ public int Y { get; }
+ public int Radius { get; }
+
+ public CircleGameObj(int x, int y, int r, GameObjType type)
+ {
+ Type = type;
+ X = x;
+ Y = y;
+ Radius = r;
+ }
+ }
+
+
+ // -------------------------------------------------------- RectGameObj
+ public class RectGameObj
+ {
+ public GameObjType Type { get; }
+ public int X { get; }
+ public int Y { get; }
+ public int Width { get; }
+ public int Length { get; }
+
+ public RectGameObj(int x, int y, int w, int l, GameObjType type)
+ {
+ Type = type;
+ X = x;
+ Y = y;
+ Width = w;
+ Length = l;
+ }
+ }
+
+
+ // -------------------------------------------------------- HoleGeometry
+ public class HoleGeometry
+ {
+ public CircleGameObj Cup { get; }
+ public CircleGameObj Green { get; }
+ public RectGameObj Fairway { get; }
+ public RectGameObj Rough { get; }
+ public Hazard[] Hazards { get; }
+
+ public HoleGeometry(CircleGameObj cup, CircleGameObj green, RectGameObj fairway, RectGameObj rough, Hazard[] haz)
+ {
+ Cup = cup;
+ Green = green;
+ Fairway = fairway;
+ Rough = rough;
+ Hazards = haz;
+ }
+ }
+
+
+ // -------------------------------------------------------- Plot
+ public class Plot
+ {
+ public int X { get; }
+ public int Y { get; set; }
+ public int Offline { get; }
+
+ public Plot(int x, int y, int offline)
+ {
+ X = x;
+ Y = y;
+ Offline = offline;
+ }
+ }
+
+
+ // -------------------------------------------------------- GetDistance
+ // distance between 2 points
+ double GetDistance(Point pt1, Point pt2)
+ {
+ return Math.Sqrt(Math.Pow((pt2.X - pt1.X), 2) + Math.Pow((pt2.Y - pt1.Y), 2));
+ }
+
+
+ // -------------------------------------------------------- IsInRectangle
+ bool IsInRectangle(CircleGameObj pt, RectGameObj rect)
+ {
+ return ((pt.X > rect.X) &&
+ (pt.X < rect.X + rect.Width) &&
+ (pt.Y > rect.Y) &&
+ (pt.Y < rect.Y + rect.Length));
+ }
+
+
+ // -------------------------------------------------------- ToRadians
+ double ToRadians(double angle) { return angle * (Math.PI / 180.0); }
+
+
+ // -------------------------------------------------------- ToDegrees360
+ // radians to 360 degrees
+ double ToDegrees360(double angle)
+ {
+ double deg = angle * (180.0 / Math.PI);
+ if (deg < 0.0) { deg += 360.0; }
+ return deg;
+ }
+
+
+ // -------------------------------------------------------- Odds
+ // chance an integer is <= the given argument
+ // between 1-100
+ Random RND = new Random();
+
+ bool Odds(int x)
+ {
+ return RND.Next(1, 101) <= x;
+ }
+ }
+}
diff --git a/39 Golf/csharp/README.md b/39 Golf/csharp/README.md
index 4daabb5c..126658a1 100644
--- a/39 Golf/csharp/README.md
+++ b/39 Golf/csharp/README.md
@@ -1,3 +1,15 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/)
+
+There are 2 compiled executables in the compiled/ directory (windows and linux) that you can play right away!
+
+Program.cs contains the C# source code.
+It has been written for .NET Core 3.1
+
+The source code is well documented.
+
+
+
+
+
From a8436342616c9cf71eb8f03a71e9f08b3a4cc346 Mon Sep 17 00:00:00 2001
From: Peter
Date: Sun, 25 Apr 2021 13:09:27 -0400
Subject: [PATCH 03/15] Ported Depth Charge to C#
---
31 Depth Charge/csharp/DepthCharge.sln | 25 +++++
31 Depth Charge/csharp/Game.csproj | 9 ++
31 Depth Charge/csharp/src/Controller.cs | 85 ++++++++++++++++
31 Depth Charge/csharp/src/Program.cs | 47 +++++++++
31 Depth Charge/csharp/src/View.cs | 121 +++++++++++++++++++++++
5 files changed, 287 insertions(+)
create mode 100644 31 Depth Charge/csharp/DepthCharge.sln
create mode 100644 31 Depth Charge/csharp/Game.csproj
create mode 100644 31 Depth Charge/csharp/src/Controller.cs
create mode 100644 31 Depth Charge/csharp/src/Program.cs
create mode 100644 31 Depth Charge/csharp/src/View.cs
diff --git a/31 Depth Charge/csharp/DepthCharge.sln b/31 Depth Charge/csharp/DepthCharge.sln
new file mode 100644
index 00000000..8d56c717
--- /dev/null
+++ b/31 Depth Charge/csharp/DepthCharge.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31129.286
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Game", "Game.csproj", "{CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {738F08DD-89E9-44C5-B5AC-3F21C6AEEFA1}
+ EndGlobalSection
+EndGlobal
diff --git a/31 Depth Charge/csharp/Game.csproj b/31 Depth Charge/csharp/Game.csproj
new file mode 100644
index 00000000..3028f277
--- /dev/null
+++ b/31 Depth Charge/csharp/Game.csproj
@@ -0,0 +1,9 @@
+
+
+
+ Exe
+ net5.0
+ DepthCharge
+
+
+
diff --git a/31 Depth Charge/csharp/src/Controller.cs b/31 Depth Charge/csharp/src/Controller.cs
new file mode 100644
index 00000000..7669e67c
--- /dev/null
+++ b/31 Depth Charge/csharp/src/Controller.cs
@@ -0,0 +1,85 @@
+using System;
+
+namespace DepthCharge
+{
+ ///
+ /// Contains functions for reading input from the user.
+ ///
+ static class Controller
+ {
+ ///
+ /// Retrives a dimension for the play area from the user.
+ ///
+ ///
+ /// Note that the original BASIC version would allow dimension values
+ /// of 0 or less. We're doing a little extra validation here in order
+ /// to avoid strange behaviour.
+ ///
+ public static int InputDimension()
+ {
+ View.PromptDimension();
+
+ while (true)
+ {
+ if (!Int32.TryParse(Console.ReadLine(), out var dimension))
+ View.ShowInvalidNumber();
+ else
+ if (dimension < 1)
+ View.ShowInvalidDimension();
+ else
+ return dimension;
+ }
+ }
+
+ ///
+ /// Retrieves a set of coordinates from the user.
+ ///
+ ///
+ /// The current trail number.
+ ///
+ public static (int x, int y, int depth) InputCoordinates(int trailNumber)
+ {
+ View.PromptGuess(trailNumber);
+
+ while (true)
+ {
+ var coordinates = Console.ReadLine().Split(',');
+
+ if (coordinates.Length < 3)
+ View.ShowTooFewCoordinates();
+ else
+ if (coordinates.Length > 3)
+ View.ShowTooManyCoordinates();
+ else
+ if (!Int32.TryParse(coordinates[0], out var x) ||
+ !Int32.TryParse(coordinates[1], out var y) ||
+ !Int32.TryParse(coordinates[2], out var depth))
+ View.ShowInvalidNumber();
+ else
+ return (x, y, depth);
+ }
+ }
+
+ ///
+ /// Retrieves the user's intention to play again (or not).
+ ///
+ public static bool InputPlayAgain()
+ {
+ View.PromptPlayAgain();
+
+ while (true)
+ {
+ switch (Console.ReadLine())
+ {
+ case "Y":
+ return true;
+ case "N":
+ return false;
+ default:
+ View.ShowInvalidYesOrNo();
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/31 Depth Charge/csharp/src/Program.cs b/31 Depth Charge/csharp/src/Program.cs
new file mode 100644
index 00000000..de3db6d9
--- /dev/null
+++ b/31 Depth Charge/csharp/src/Program.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace DepthCharge
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ var random = new Random();
+
+ View.ShowBanner();
+
+ var dimension = Controller.InputDimension();
+ var maximumGuesses = CalculateMaximumGuesses();
+
+ View.ShowInstructions(maximumGuesses);
+
+ do
+ {
+ View.ShowStartGame();
+
+ var submarineCoordinates = PlaceSubmarine();
+ var trailNumber = 1;
+ var guess = (0, 0, 0);
+
+ do
+ {
+ guess = Controller.InputCoordinates(trailNumber);
+ if (guess != submarineCoordinates)
+ View.ShowGuessPlacement(submarineCoordinates, guess);
+ }
+ while (guess != submarineCoordinates && trailNumber++ < maximumGuesses);
+
+ View.ShowGameResult(submarineCoordinates, guess, trailNumber);
+ }
+ while (Controller.InputPlayAgain());
+
+ View.ShowFarewell();
+
+ int CalculateMaximumGuesses() =>
+ (int)Math.Log2(dimension) + 1;
+
+ (int x, int y, int depth) PlaceSubmarine() =>
+ (random.Next(dimension), random.Next(dimension), random.Next(dimension));
+ }
+ }
+}
diff --git a/31 Depth Charge/csharp/src/View.cs b/31 Depth Charge/csharp/src/View.cs
new file mode 100644
index 00000000..71e83a9f
--- /dev/null
+++ b/31 Depth Charge/csharp/src/View.cs
@@ -0,0 +1,121 @@
+using System;
+
+namespace DepthCharge
+{
+ ///
+ /// Contains methods for displaying information to the user.
+ ///
+ static class View
+ {
+ public static void ShowBanner()
+ {
+ Console.WriteLine(" DEPTH CHARGE");
+ Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
+ Console.WriteLine();
+ Console.WriteLine();
+ Console.WriteLine();
+ }
+
+ public static void ShowInstructions(int maximumGuesses)
+ {
+ Console.WriteLine("YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER");
+ Console.WriteLine("AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR");
+ Console.WriteLine($"MISSION IS TO DESTROY IT. YOU HAVE {maximumGuesses} SHOTS.");
+ Console.WriteLine("SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A");
+ Console.WriteLine("TRIO OF NUMBERS -- THE FIRST TWO ARE THE");
+ Console.WriteLine("SURFACE COORDINATES; THE THIRD IS THE DEPTH.");
+ Console.WriteLine();
+ }
+
+ public static void ShowStartGame()
+ {
+ Console.WriteLine("GOOD LUCK !");
+ Console.WriteLine();
+ }
+
+ public static void ShowGuessPlacement((int x, int y, int depth) actual, (int x, int y, int depth) guess)
+ {
+ Console.Write("SONAR REPORTS SHOT WAS ");
+ if (guess.y > actual.y)
+ Console.Write("NORTH");
+ if (guess.y < actual.y)
+ Console.Write("SOUTH");
+ if (guess.x > actual.x)
+ Console.Write("EAST");
+ if (guess.x < actual.x)
+ Console.Write("WEST");
+ if (guess.y != actual.y || guess.x != actual.y)
+ Console.Write(" AND");
+ if (guess.depth > actual.depth)
+ Console.Write (" TOO LOW.");
+ if (guess.depth < actual.depth)
+ Console.Write(" TOO HIGH.");
+ if (guess.depth == actual.depth)
+ Console.Write(" DEPTH OK.");
+
+ Console.WriteLine();
+ }
+
+ public static void ShowGameResult((int x, int y, int depth) submarineLocation, (int x, int y, int depth) finalGuess, int trailNumber)
+ {
+ Console.WriteLine();
+
+ if (submarineLocation == finalGuess)
+ {
+ Console.WriteLine($"B O O M ! ! YOU FOUND IT IN {trailNumber} TRIES!");
+ }
+ else
+ {
+ Console.WriteLine("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!");
+ Console.WriteLine($"THE SUBMARINE WAS AT {submarineLocation.x}, {submarineLocation.y}, {submarineLocation.depth}");
+ }
+ }
+
+ public static void ShowFarewell()
+ {
+ Console.WriteLine ("OK. HOPE YOU ENJOYED YOURSELF.");
+ }
+
+ public static void ShowInvalidNumber()
+ {
+ Console.WriteLine("PLEASE ENTER A NUMBER");
+ }
+
+ public static void ShowInvalidDimension()
+ {
+ Console.WriteLine("PLEASE ENTER A VALID DIMENSION");
+ }
+
+ public static void ShowTooFewCoordinates()
+ {
+ Console.WriteLine("TOO FEW COORDINATES");
+ }
+
+ public static void ShowTooManyCoordinates()
+ {
+ Console.WriteLine("TOO MANY COORDINATES");
+ }
+
+ public static void ShowInvalidYesOrNo()
+ {
+ Console.WriteLine("PLEASE ENTER Y OR N");
+ }
+
+ public static void PromptDimension()
+ {
+ Console.Write("DIMENSION OF SEARCH AREA? ");
+ }
+
+ public static void PromptGuess(int trailNumber)
+ {
+ Console.WriteLine();
+ Console.Write($"TRIAL #{trailNumber}? ");
+ }
+
+ public static void PromptPlayAgain()
+ {
+ Console.WriteLine();
+ Console.Write("ANOTHER GAME (Y OR N)? ");
+ }
+ }
+}
From 81e36428b2a7151dda28f657ca73b17d852b2c2d Mon Sep 17 00:00:00 2001
From: Peter
Date: Mon, 26 Apr 2021 19:06:01 -0400
Subject: [PATCH 04/15] Minor quality improvements and fixes * Improved names
and fixed inconsistent spacing * Update year at the start of the turn instead
of the end * Input functions work more like the BASIC versions * Display city
summary before end game results (as in the original version)
---
43 Hammurabi/csharp/src/Controller.cs | 43 +++++++++++++--------------
43 Hammurabi/csharp/src/GameResult.cs | 2 +-
43 Hammurabi/csharp/src/GameState.cs | 2 +-
43 Hammurabi/csharp/src/Program.cs | 15 ++++++----
43 Hammurabi/csharp/src/Rules.cs | 16 +++++-----
43 Hammurabi/csharp/src/View.cs | 12 ++++----
6 files changed, 46 insertions(+), 44 deletions(-)
diff --git a/43 Hammurabi/csharp/src/Controller.cs b/43 Hammurabi/csharp/src/Controller.cs
index 91d1b64f..afdb83d2 100644
--- a/43 Hammurabi/csharp/src/Controller.cs
+++ b/43 Hammurabi/csharp/src/Controller.cs
@@ -23,7 +23,7 @@ namespace Hammurabi
///
/// The updated game state.
///
- public static GameState TryUntilSuccess(
+ public static GameState UpdateGameState(
GameState state,
Action prompt,
Func rule)
@@ -35,29 +35,28 @@ namespace Hammurabi
if (!Int32.TryParse(Console.ReadLine(), out var amount))
{
View.ShowInvalidNumber();
+ continue;
}
- else
- {
- var (newState, result) = rule(state, amount);
- switch (result)
- {
- case ActionResult.InsufficientLand:
- View.ShowInsufficientLand(state);
- break;
- case ActionResult.InsufficientPopulation:
- View.ShowInsufficientPopulation(state);
- break;
- case ActionResult.InsufficientStores:
- View.ShowInsufficientStores(state);
- break;
- case ActionResult.Offense:
- // Not sure why we have to blow up the game here...
- // Maybe this made sense in the 70's.
- throw new GreatOffence();
- default:
- return newState;
- }
+ var (newState, result) = rule(state, amount);
+
+ switch (result)
+ {
+ case ActionResult.InsufficientLand:
+ View.ShowInsufficientLand(state);
+ break;
+ case ActionResult.InsufficientPopulation:
+ View.ShowInsufficientPopulation(state);
+ break;
+ case ActionResult.InsufficientStores:
+ View.ShowInsufficientStores(state);
+ break;
+ case ActionResult.Offense:
+ // Not sure why we have to blow up the game here...
+ // Maybe this made sense in the 70's.
+ throw new GreatOffence();
+ default:
+ return newState;
}
}
}
diff --git a/43 Hammurabi/csharp/src/GameResult.cs b/43 Hammurabi/csharp/src/GameResult.cs
index 23dfbe28..9c143375 100644
--- a/43 Hammurabi/csharp/src/GameResult.cs
+++ b/43 Hammurabi/csharp/src/GameResult.cs
@@ -40,6 +40,6 @@
/// Gets a flag indicating whether the player was impeached for
/// starving too many people.
///
- public bool WasImpeached { get; init; }
+ public bool WasPlayerImpeached { get; init; }
}
}
diff --git a/43 Hammurabi/csharp/src/GameState.cs b/43 Hammurabi/csharp/src/GameState.cs
index 3e2d1eb2..41e6fe11 100644
--- a/43 Hammurabi/csharp/src/GameState.cs
+++ b/43 Hammurabi/csharp/src/GameState.cs
@@ -68,6 +68,6 @@
///
/// Gets a flag indicating whether the player has been impeached.
///
- public bool IsImpeached { get; init; }
+ public bool IsPlayerImpeached { get; init; }
}
}
diff --git a/43 Hammurabi/csharp/src/Program.cs b/43 Hammurabi/csharp/src/Program.cs
index 45d5b101..8f158839 100644
--- a/43 Hammurabi/csharp/src/Program.cs
+++ b/43 Hammurabi/csharp/src/Program.cs
@@ -9,7 +9,7 @@ namespace Hammurabi
public static void Main(string[] args)
{
- var random = new Random ((int) (DateTime.UtcNow.Ticks / 10000)) ;
+ var random = new Random() ;
var state = Rules.BeginGame();
var history = ImmutableList.Empty;
@@ -17,21 +17,24 @@ namespace Hammurabi
try
{
- while (state.Year <= GameLength && !state.IsImpeached)
+ while (!state.IsPlayerImpeached)
{
state = Rules.BeginTurn(state, random);
View.ShowCitySummary(state);
+ if (state.Year > GameLength)
+ break;
+
View.ShowLandPrice(state);
- var newState = Controller.TryUntilSuccess(state, View.PromptBuyLand, Rules.BuyLand);
+ var newState = Controller.UpdateGameState(state, View.PromptBuyLand, Rules.BuyLand);
state = newState.Acres != state.Acres ?
- newState : Controller.TryUntilSuccess(state, View.PromptSellLand, Rules.SellLand);
+ newState : Controller.UpdateGameState(state, View.PromptSellLand, Rules.SellLand);
View.ShowSeparator();
- state = Controller.TryUntilSuccess(state, View.PromptFeedPeople, Rules.FeedPeople);
+ state = Controller.UpdateGameState(state, View.PromptFeedPeople, Rules.FeedPeople);
View.ShowSeparator();
- state = Controller.TryUntilSuccess(state, View.PromptPlantCrops, Rules.PlantCrops);
+ state = Controller.UpdateGameState(state, View.PromptPlantCrops, Rules.PlantCrops);
state = Rules.EndTurn(state, random);
history = history.Add(state);
diff --git a/43 Hammurabi/csharp/src/Rules.cs b/43 Hammurabi/csharp/src/Rules.cs
index 56a59d96..36fc9c50 100644
--- a/43 Hammurabi/csharp/src/Rules.cs
+++ b/43 Hammurabi/csharp/src/Rules.cs
@@ -12,7 +12,7 @@ namespace Hammurabi
public static GameState BeginGame() =>
new GameState
{
- Year = 1,
+ Year = 0,
Population = 95,
PopulationIncrease = 5,
Starvation = 0,
@@ -22,7 +22,7 @@ namespace Hammurabi
Productivity = 3,
Spoilage = 200,
IsPlagueYear = false,
- IsImpeached = false
+ IsPlayerImpeached = false
};
///
@@ -31,6 +31,7 @@ namespace Hammurabi
public static GameState BeginTurn(GameState state, Random random) =>
state with
{
+ Year = state.Year + 1,
Population = (state.Population + state.PopulationIncrease - state.Starvation) / (state.IsPlagueYear ? 2 : 1),
LandPrice = random.Next(10) + 17,
Stores = state.Stores + (state.AcresPlanted * state.Productivity) - state.Spoilage,
@@ -139,23 +140,22 @@ namespace Hammurabi
_ => 0
};
- var populationIncrease= (int)((double) random.Next(1, 6) * (20 * state.Acres + state.Stores + harvest - spoilage) / state.Population / 100 + 1);
+ var populationIncrease= (int)((double)random.Next(1, 6) * (20 * state.Acres + state.Stores + harvest - spoilage) / state.Population / 100 + 1);
var plagueYear = random.Next(20) < 3;
- var peopleFed = state.FoodDistributed / 20;
+ var peopleFed = state.FoodDistributed / 20;
var starvation = peopleFed < state.Population ? state.Population - peopleFed : 0;
var impeached = starvation > state.Population * 0.45;
return state with
{
- Year = state.Year + 1,
Productivity = productivity,
Spoilage = spoilage,
PopulationIncrease = populationIncrease,
Starvation = starvation,
IsPlagueYear = plagueYear,
- IsImpeached = impeached
+ IsPlayerImpeached = impeached
};
}
@@ -176,7 +176,7 @@ namespace Hammurabi
var acresPerPerson = finalState.Acres / finalState.Population;
- var rating = finalState.IsImpeached ?
+ var rating = finalState.IsPlayerImpeached ?
PerformanceRating.Disgraceful :
(averageStarvationRate, acresPerPerson) switch
{
@@ -200,7 +200,7 @@ namespace Hammurabi
TotalStarvation = totalStarvation,
AverageStarvationRate = averageStarvationRate,
Assassins = assassins,
- WasImpeached = finalState.IsImpeached
+ WasPlayerImpeached = finalState.IsPlayerImpeached
};
}
}
diff --git a/43 Hammurabi/csharp/src/View.cs b/43 Hammurabi/csharp/src/View.cs
index be10af32..fcfb4cd5 100644
--- a/43 Hammurabi/csharp/src/View.cs
+++ b/43 Hammurabi/csharp/src/View.cs
@@ -110,7 +110,7 @@ namespace Hammurabi
///
public static void ShowGameResult(GameResult result)
{
- if (!result.WasImpeached)
+ if (!result.WasPlayerImpeached)
{
Console.WriteLine($"IN YOUR 10-YEAR TERM OF OFFICE, {result.AverageStarvationRate} PERCENT OF THE");
Console.WriteLine("POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF");
@@ -124,7 +124,7 @@ namespace Hammurabi
switch (result.Rating)
{
case PerformanceRating.Disgraceful:
- if (result.WasImpeached)
+ if (result.WasPlayerImpeached)
Console.WriteLine($"YOU STARVED {result.FinalStarvation} PEOPLE IN ONE YEAR!!!");
Console.WriteLine("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY");
@@ -163,7 +163,7 @@ namespace Hammurabi
///
public static void PromptBuyLand()
{
- Console.WriteLine ("HOW MANY ACRES DO YOU WISH TO BUY");
+ Console.Write("HOW MANY ACRES DO YOU WISH TO BUY? ");
}
///
@@ -171,7 +171,7 @@ namespace Hammurabi
///
public static void PromptSellLand()
{
- Console.WriteLine("HOW MANY ACRES DO YOU WISH TO SELL");
+ Console.Write("HOW MANY ACRES DO YOU WISH TO SELL? ");
}
///
@@ -179,7 +179,7 @@ namespace Hammurabi
///
public static void PromptFeedPeople()
{
- Console.WriteLine("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE");
+ Console.Write("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE? ");
}
///
@@ -187,7 +187,7 @@ namespace Hammurabi
///
public static void PromptPlantCrops()
{
- Console.WriteLine("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED");
+ Console.Write("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED? ");
}
}
}
From 6cf5b3948a10ebdcddc6c8bb2088baef1946b69b Mon Sep 17 00:00:00 2001
From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com>
Date: Tue, 27 Apr 2021 20:01:34 -0400
Subject: [PATCH 05/15] Ported Bowling to Java.
---
14 Bowling/java/Bowling.java | 282 +++++++++++++++++++++++++++++++++++
1 file changed, 282 insertions(+)
create mode 100644 14 Bowling/java/Bowling.java
diff --git a/14 Bowling/java/Bowling.java b/14 Bowling/java/Bowling.java
new file mode 100644
index 00000000..e443246a
--- /dev/null
+++ b/14 Bowling/java/Bowling.java
@@ -0,0 +1,282 @@
+import java.util.Scanner;
+import java.lang.Math;
+
+/**
+ * Game of Bowling
+ *
+ * Based on the BASIC game of Bowling here
+ * https://github.com/coding-horror/basic-computer-games/blob/main/14%20Bowling/bowling.bas
+ *
+ * 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 Bowling {
+
+ private final Scanner scan; // For user input
+
+ public Bowling() {
+
+ scan = new Scanner(System.in);
+
+ } // End of constructor Bowling
+
+ public void play() {
+
+ showIntro();
+ startGame();
+
+ } // End of method play
+
+ private static void showIntro() {
+
+ System.out.println(" ".repeat(33) + "BOWL");
+ System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
+ System.out.println("\n\n");
+
+ } // End of method showIntro
+
+ private void startGame() {
+
+ int ball = 0;
+ int bell = 0;
+ int frame = 0;
+ int ii = 0; // Loop iterator
+ int jj = 0; // Loop iterator
+ int kk = 0; // Loop iterator
+ int numPlayers = 0;
+ int pinsDownBefore = 0;
+ int pinsDownNow = 0;
+ int player = 0;
+ int randVal = 0;
+ int result = 0;
+
+ int[] pins = new int[16];
+
+ int[][] scores = new int[101][7];
+
+ String userResponse = "";
+
+ System.out.println("WELCOME TO THE ALLEY");
+ System.out.println("BRING YOUR FRIENDS");
+ System.out.println("OKAY LET'S FIRST GET ACQUAINTED");
+ System.out.println("");
+ System.out.println("THE INSTRUCTIONS (Y/N)");
+ System.out.print("? ");
+
+ userResponse = scan.nextLine();
+
+ if (userResponse.toUpperCase().equals("Y")) {
+ printRules();
+ }
+
+ System.out.print("FIRST OF ALL...HOW MANY ARE PLAYING? ");
+ numPlayers = Integer.parseInt(scan.nextLine());
+
+ System.out.println("");
+ System.out.println("VERY GOOD...");
+
+ // Begin outer while loop
+ while (true) {
+
+ for (ii = 1; ii <= 100; ii++) {
+ for (jj = 1; jj <= 6; jj++) {
+ scores[ii][jj] = 0;
+ }
+ }
+
+ frame = 1;
+
+ // Begin frame while loop
+ while (frame < 11) {
+
+ // Begin loop through all players
+ for (player = 1; player <= numPlayers; player++) {
+
+ pinsDownBefore = 0;
+ ball = 1;
+ result = 0;
+
+ for (ii = 1; ii <= 15; ii++) {
+ pins[ii] = 0;
+ }
+
+ while (true) {
+
+ // Ball generator using mod '15' system
+
+ System.out.println("TYPE ROLL TO GET THE BALL GOING.");
+ System.out.print("? ");
+ scan.nextLine();
+
+ kk = 0;
+ pinsDownNow = 0;
+
+ for (ii = 1; ii <= 20; ii++) {
+
+ randVal = (int)(Math.random() * 100) + 1;
+
+ for (jj = 1; jj <= 10; jj++) {
+
+ if (randVal < 15 * jj) {
+ break;
+ }
+ }
+ pins[15 * jj - randVal] = 1;
+ }
+
+ // Pin diagram
+
+ System.out.println("PLAYER: " + player + " FRAME: " + frame + " BALL: " + ball);
+
+ for (ii = 0; ii <= 3; ii++) {
+
+ System.out.println("");
+
+ System.out.print(" ".repeat(ii));
+
+ for (jj = 1; jj <= 4 - ii; jj++) {
+
+ kk++;
+
+ if (pins[kk] == 1) {
+
+ System.out.print("O ");
+
+ } else {
+
+ System.out.print("+ ");
+ }
+ }
+ }
+
+ System.out.println("");
+
+ // Roll analysis
+
+ for (ii = 1; ii <= 10; ii++) {
+ pinsDownNow += pins[ii];
+ }
+
+ if (pinsDownNow - pinsDownBefore == 0) {
+ System.out.println("GUTTER!!");
+ }
+
+ if (ball == 1 && pinsDownNow == 10) {
+ System.out.println("STRIKE!!!!!");
+
+ // Ring bell
+ for (bell = 1; bell <= 4; bell++) {
+ System.out.print("\007");
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ result = 3;
+ }
+
+ if (ball == 2 && pinsDownNow == 10) {
+ System.out.println("SPARE!!!!");
+ result = 2;
+ }
+
+ if (ball == 2 && pinsDownNow < 10) {
+ System.out.println("ERROR!!!");
+ result = 1;
+ }
+
+ if (ball == 1 && pinsDownNow < 10) {
+ System.out.println("ROLL YOUR 2ND BALL");
+ }
+
+ // Storage of the scores
+
+ System.out.println("");
+
+ scores[frame * player][ball] = pinsDownNow;
+
+ if (ball != 2) {
+ ball = 2;
+ pinsDownBefore = pinsDownNow;
+
+ if (result != 3) {
+ scores[frame * player][ball] = pinsDownNow - pinsDownBefore;
+ if (result == 0) {
+ continue;
+ }
+ } else {
+ scores[frame * player][ball] = pinsDownNow;
+ }
+
+ }
+ break;
+ }
+
+ scores[frame * player][3] = result;
+
+ } // End loop through all players
+
+ frame++;
+
+ } // End frame while loop
+
+ System.out.println("FRAMES");
+
+ System.out.print(" ");
+ for (ii = 1; ii <= 10; ii++) {
+ System.out.print(ii + " ");
+ }
+
+ System.out.println("");
+
+ for (player = 1; player <= numPlayers; player++) {
+ for (ii = 1; ii <= 3; ii++) {
+ System.out.print(" ");
+ for (jj = 1; jj <= 10; jj++) {
+ System.out.print (scores[jj * player][ii] + " ");
+ }
+ System.out.println("");
+ }
+ System.out.println("");
+ }
+
+ System.out.println("DO YOU WANT ANOTHER GAME");
+ System.out.print("? ");
+
+ userResponse = scan.nextLine();
+
+ if (!String.valueOf(userResponse.toUpperCase().charAt(0)).equals("Y")) {
+ break;
+ }
+
+ } // End outer while loop
+
+ } // End of method startGame
+
+ public void printBoard(int[] board) {
+
+ } // End of method printBoard
+
+ public static void printRules() {
+
+ System.out.println("THE GAME OF BOWLING TAKES MIND AND SKILL.DURING THE GAME");
+ System.out.println("THE COMPUTER WILL KEEP SCORE.YOU MAY COMPETE WITH");
+ System.out.println("OTHER PLAYERS[UP TO FOUR].YOU WILL BE PLAYING TEN FRAMES");
+ System.out.println("ON THE PIN DIAGRAM 'O' MEANS THE PIN IS DOWN...'+' MEANS THE");
+ System.out.println("PIN IS STANDING.AFTER THE GAME THE COMPUTER WILL SHOW YOUR");
+ System.out.println("SCORES .");
+
+ } // End of method printRules
+
+ public static void main(String[] args) {
+
+ Bowling game = new Bowling();
+ game.play();
+
+ } // End of method main
+
+} // End of class Bowling
From 3af97fd180ecf67a240ebdcbc0e39ffacba3906c Mon Sep 17 00:00:00 2001
From: Nezumi Ronin
Date: Wed, 28 Apr 2021 00:56:48 -0500
Subject: [PATCH 06/15] Create litquiz.pl
Made with Perl!
---
57 Literature Quiz/perl/litquiz.pl | 82 ++++++++++++++++++++++++++++++
1 file changed, 82 insertions(+)
create mode 100644 57 Literature Quiz/perl/litquiz.pl
diff --git a/57 Literature Quiz/perl/litquiz.pl b/57 Literature Quiz/perl/litquiz.pl
new file mode 100644
index 00000000..f7d41075
--- /dev/null
+++ b/57 Literature Quiz/perl/litquiz.pl
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+use strict;
+
+
+print ' 'x 25 . "LITERATURE QUIZ\n";
+print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n"; print "\n"; print "\n";
+print "TEST YOUR KNOWLEDGE OF CHILDREN'S LITERATURE.\n";
+print "\n"; print "THIS IS A MULTIPLE-CHOICE QUIZ.\n";
+print "TYPE A 1, 2, 3, OR 4 AFTER THE QUESTION MARK.\n";
+print "\n"; print "GOOD LUCK!\n";
+my $R=0;
+
+
+print "\n"; print "\n";
+print "IN PINOCCHIO, WHAT WAS THE NAME OF THE CAT\n";
+print "1)TIGGER, 2)CICERO, 3)FIGARO, 4)GUIPETTO";
+print "? "; chomp(my $A = );
+
+if ($A eq 3) {
+ $R++;
+ print "VERY GOOD! HERE'S ANOTHER.\n";
+ } else {
+ print "SORRY...FIGARO WAS HIS NAME.\n";
+ }
+
+
+print "\n"; print "\n";
+print "FROM WHOSE GARDEN DID BUGS BUNNY STEAL THE CARROTS?\n";
+print "1)MR. NIXON'S, 2)ELMER FUDD'S, 3)CLEM JUDD'S, 4)STROMBOLI'S";
+print "? "; chomp($A = );
+
+if ($A eq 2) {
+ print "PRETTY GOOD!\n";
+ $R=$R+1;
+ } else {
+ print "TOO BAD...IT WAS ELMER FUDD'S GARDEN.\n";
+ }
+
+
+print "\n"; print "\n";
+print "IN THE WIZARD OF OS, DOROTHY'S DOG WAS NAMED\n";
+print "1)CICERO, 2)TRIXIA, 3)KING, 4)TOTO";
+print "? "; chomp($A = );
+if ($A eq 4) {
+ print "YEA! YOU'RE A REAL LITERATURE GIANT.\n";
+ $R=$R+1;
+ } else {
+ print "BACK TO THE BOOKS,...TOTO WAS HIS NAME.\n";
+ }
+
+
+print "\n"; print "\n";
+print "WHO WAS THE FAIR MAIDEN WHO ATE THE POISON APPLE\n";
+print "1)SLEEPING BEAUTY, 2)CINDERELLA, 3)SNOW WHITE, 4)WENDY";
+print "? "; chomp($A = );
+if ($A eq 3) {
+ print "GOOD MEMORY!\n";
+ $R=$R+1;
+ } else {
+ print "OH, COME ON NOW...IT WAS SNOW WHITE.\n";
+ }
+
+
+print "\n"; print "\n";
+if ($R eq 4) {
+ print "WOW! THAT'S SUPER! YOU REALLY KNOW YOUR NURSERY\n";
+ print "YOUR NEXT QUIZ WILL BE ON 2ND CENTURY CHINESE\n";
+ print "LITERATURE (HA, HA, HA)\n";
+ exit
+ }
+if ($R<2) {
+ print "UGH. THAT WAS DEFINITELY NOT TOO SWIFT. BACK TO\n";
+ print "NURSERY SCHOOL FOR YOU, MY FRIEND.\n";
+ exit;
+ }
+
+print "NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME\n";
+print "READING THE NURSERY GREATS.\n";
+exit;
+
+
From 31c34129076e26af2f68b8141fbdf1b3e612d91a Mon Sep 17 00:00:00 2001
From: Aldrin Misquitta
Date: Sat, 1 May 2021 10:31:14 +0400
Subject: [PATCH 07/15] Ported 86 Target to Java
---
86 Target/java/Target.java | 146 +++++++++++++++++++++++++++++++++++++
1 file changed, 146 insertions(+)
create mode 100644 86 Target/java/Target.java
diff --git a/86 Target/java/Target.java b/86 Target/java/Target.java
new file mode 100644
index 00000000..869c443a
--- /dev/null
+++ b/86 Target/java/Target.java
@@ -0,0 +1,146 @@
+import java.util.Scanner;
+
+/**
+ * TARGET
+ *
+ * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm)
+ */
+public class Target {
+
+ private static final double RADIAN = 180 / Math.PI;
+
+ public static void main(String[] args) {
+ Scanner scan = new Scanner(System.in);
+
+ printIntro();
+
+ //continue till the user aborts
+ while (true) {
+ int numberShots = 0;
+
+ final double xAxisInRadians = Math.random() * 2 * Math.PI;
+ final double yAxisInRadians = Math.random() * 2 * Math.PI;
+ System.out.printf("RADIANS FROM X AXIS = %.7f FROM Z AXIS = %.7f\n", xAxisInRadians, yAxisInRadians);
+
+ final double p1 = 100000 * Math.random() + Math.random();
+ final double x = Math.sin(yAxisInRadians) * Math.cos(xAxisInRadians) * p1;
+ final double y = Math.sin(yAxisInRadians) * Math.sin(xAxisInRadians) * p1;
+ final double z = Math.cos(yAxisInRadians) * p1;
+ System.out.printf("TARGET SIGHTED: APPROXIMATE COORDINATES: X=%.3f Y=%.3f Z=%.3f\n", x, y, z);
+ boolean targetOrSelfDestroyed = false;
+ while (!targetOrSelfDestroyed) {
+ numberShots++;
+ int estimatedDistance = 0;
+ switch (numberShots) {
+ case 1:
+ estimatedDistance = (int) (p1 * .05) * 20;
+ break;
+ case 2:
+ estimatedDistance = (int) (p1 * .1) * 10;
+ break;
+ case 3:
+ estimatedDistance = (int) (p1 * .5) * 2;
+ break;
+ case 4:
+ case 5:
+ estimatedDistance = (int) (p1);
+ break;
+ }
+
+ System.out.printf(" ESTIMATED DISTANCE: %s\n\n", estimatedDistance);
+
+ final TargetAttempt targetAttempt = readInput(scan);
+ if (targetAttempt.distance < 20) {
+ System.out.println("YOU BLEW YOURSELF UP!!");
+ targetOrSelfDestroyed = true;
+ } else {
+ final double a1 = targetAttempt.xDeviation / RADIAN;
+ final double b1 = targetAttempt.zDeviation / RADIAN;
+ System.out.printf("RADIANS FROM X AXIS = %.7f FROM Z AXIS = %.7f\n", a1, b1);
+
+ final double x1 = targetAttempt.distance * Math.sin(b1) * Math.cos(a1);
+ final double y1 = targetAttempt.distance * Math.sin(b1) * Math.sin(a1);
+ final double z1 = targetAttempt.distance * Math.cos(b1);
+
+ double distance = Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y) + (z1 - z) * (z1 - z));
+ if (distance > 20) {
+ double X2 = x1 - x;
+ double Y2 = y1 - y;
+ double Z2 = z1 - z;
+ if (X2 < 0) {
+ System.out.printf("SHOT BEHIND TARGET %.7f KILOMETERS.\n", -X2);
+ } else {
+ System.out.printf("SHOT IN FRONT OF TARGET %.7f KILOMETERS.\n", X2);
+ }
+ if (Y2 < 0) {
+ System.out.printf("SHOT TO RIGHT OF TARGET %.7f KILOMETERS.\n", -Y2);
+ } else {
+ System.out.printf("SHOT TO LEFT OF TARGET %.7f KILOMETERS.\n", Y2);
+ }
+ if (Z2 < 0) {
+ System.out.printf("SHOT BELOW TARGET %.7f KILOMETERS.\n", -Z2);
+ } else {
+ System.out.printf("SHOT ABOVE TARGET %.7f KILOMETERS.\n", Z2);
+ }
+ System.out.printf("APPROX POSITION OF EXPLOSION: X=%.7f Y=%.7f Z=%.7f\n", x1, y1, z1);
+ System.out.printf(" DISTANCE FROM TARGET =%.7f\n\n\n\n", distance);
+ } else {
+ System.out.println(" * * * HIT * * * TARGET IS NON-FUNCTIONAL");
+ System.out.printf("DISTANCE OF EXPLOSION FROM TARGET WAS %.5f KILOMETERS.\n", distance);
+ System.out.printf("MISSION ACCOMPLISHED IN %s SHOTS.\n", numberShots);
+ targetOrSelfDestroyed = true;
+ }
+ }
+ }
+ System.out.println("\n\n\n\n\nNEXT TARGET...\n");
+ }
+ }
+
+ private static TargetAttempt readInput(Scanner scan) {
+ System.out.println("INPUT ANGLE DEVIATION FROM X, DEVIATION FROM Z, DISTANCE ");
+ boolean validInput = false;
+ TargetAttempt targetAttempt = new TargetAttempt();
+ while (!validInput) {
+ String input = scan.nextLine();
+ final String[] split = input.split(",");
+ try {
+ targetAttempt.xDeviation = Float.parseFloat(split[0]);
+ targetAttempt.zDeviation = Float.parseFloat(split[1]);
+ targetAttempt.distance = Float.parseFloat(split[2]);
+ validInput = true;
+ } catch (NumberFormatException nfe) {
+ System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE\n? ");
+ }
+
+ }
+ return targetAttempt;
+ }
+
+ private static void printIntro() {
+ System.out.println(" TARGET");
+ System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
+ System.out.println("\n\n");
+ System.out.println("YOU ARE THE WEAPONS OFFICER ON THE STARSHIP ENTERPRISE");
+ System.out.println("AND THIS IS A TEST TO SEE HOW ACCURATE A SHOT YOU");
+ System.out.println("ARE IN A THREE-DIMENSIONAL RANGE. YOU WILL BE TOLD");
+ System.out.println("THE RADIAN OFFSET FOR THE X AND Z AXES, THE LOCATION");
+ System.out.println("OF THE TARGET IN THREE DIMENSIONAL RECTANGULAR COORDINATES,");
+ System.out.println("THE APPROXIMATE NUMBER OF DEGREES FROM THE X AND Z");
+ System.out.println("AXES, AND THE APPROXIMATE DISTANCE TO THE TARGET.");
+ System.out.println("YOU WILL THEN PROCEED TO SHOOT AT THE TARGET UNTIL IT IS");
+ System.out.println("DESTROYED!");
+ System.out.println("\nGOOD LUCK!!\n\n");
+ }
+
+ /**
+ * Represents the user input
+ */
+ private static class TargetAttempt {
+
+ double xDeviation;
+ double zDeviation;
+ double distance;
+ }
+}
+
+
From 31080089ff7eec8a6421c9ed970108df8da71457 Mon Sep 17 00:00:00 2001
From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com>
Date: Sun, 2 May 2021 15:29:08 -0400
Subject: [PATCH 08/15] Remove unused method in Bowling.java.
---
14 Bowling/java/Bowling.java | 4 ----
1 file changed, 4 deletions(-)
diff --git a/14 Bowling/java/Bowling.java b/14 Bowling/java/Bowling.java
index e443246a..998f4fb3 100644
--- a/14 Bowling/java/Bowling.java
+++ b/14 Bowling/java/Bowling.java
@@ -256,10 +256,6 @@ public class Bowling {
} // End outer while loop
} // End of method startGame
-
- public void printBoard(int[] board) {
-
- } // End of method printBoard
public static void printRules() {
From e6cc8305d43c44d53c3d479d2cd9a9a89507c806 Mon Sep 17 00:00:00 2001
From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com>
Date: Tue, 4 May 2021 20:53:23 -0400
Subject: [PATCH 09/15] Ported FlipFlop to Java.
---
36 Flip Flop/java/FlipFlop.java | 287 ++++++++++++++++++++++++++++++++
1 file changed, 287 insertions(+)
create mode 100644 36 Flip Flop/java/FlipFlop.java
diff --git a/36 Flip Flop/java/FlipFlop.java b/36 Flip Flop/java/FlipFlop.java
new file mode 100644
index 00000000..afca236f
--- /dev/null
+++ b/36 Flip Flop/java/FlipFlop.java
@@ -0,0 +1,287 @@
+import java.util.Scanner;
+import java.lang.Math;
+
+/**
+ * Game of FlipFlop
+ *
+ * Based on the BASIC game of FlipFlop here
+ * https://github.com/coding-horror/basic-computer-games/blob/main/36%20Flip%20Flop/flipflop.bas
+ *
+ * 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 FlipFlop {
+
+ private final Scanner scan; // For user input
+
+ private enum Step {
+ RANDOMIZE, INIT_BOARD, GET_NUMBER, ILLEGAL_ENTRY, FLIP_POSITION, SET_X_FIRST, SET_X_SECOND,
+ GENERATE_R_FIRST, GENERATE_R_SECOND, PRINT_BOARD, QUERY_RETRY
+ }
+
+ public FlipFlop() {
+
+ scan = new Scanner(System.in);
+
+ } // End of constructor FlipFlop
+
+ public void play() {
+
+ showIntro();
+ startGame();
+
+ } // End of method play
+
+ private static void showIntro() {
+
+ System.out.println(" ".repeat(31) + "FLIPFLOP");
+ System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
+ System.out.println("");
+
+ } // End of method showIntro
+
+ private void startGame() {
+
+ double mathVal = 0;
+ double randVal = 0;
+ double tmpVal = 0;
+
+ int index = 0;
+ int match = 0;
+ int numFlip = 0;
+ int numGuesses = 0;
+
+ Step nextStep = Step.RANDOMIZE;
+
+ String userResponse = "";
+
+ String[] board = new String[21];
+
+ System.out.println("THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS:");
+ System.out.println("");
+ System.out.println("X X X X X X X X X X");
+ System.out.println("");
+ System.out.println("TO THIS:");
+ System.out.println("");
+ System.out.println("O O O O O O O O O O");
+ System.out.println("");
+ System.out.println("BY TYPING THE NUMBER CORRESPONDING TO THE POSITION OF THE");
+ System.out.println("LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON");
+ System.out.println("OTHERS, TWO WILL CHANGE. TO RESET LINE TO ALL X'S, TYPE 0");
+ System.out.println("(ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE ");
+ System.out.println("11 (ELEVEN).");
+ System.out.println("");
+
+ // Begin outer while loop
+ while (true) {
+
+ // Begin switch
+ switch (nextStep) {
+
+ case RANDOMIZE:
+
+ randVal = Math.random();
+
+ System.out.println("HERE IS THE STARTING LINE OF X'S.");
+ System.out.println("");
+
+ numGuesses = 0;
+ nextStep = Step.INIT_BOARD;
+ break;
+
+ case INIT_BOARD:
+
+ System.out.println("1 2 3 4 5 6 7 8 9 10");
+ System.out.println("X X X X X X X X X X");
+ System.out.println("");
+
+ // Avoid out of bounds error by starting at zero
+ for (index = 0; index <= 10; index++) {
+ board[index] = "X";
+ }
+
+ nextStep = Step.GET_NUMBER;
+ break;
+
+ case GET_NUMBER:
+
+ System.out.print("INPUT THE NUMBER? ");
+ userResponse = scan.nextLine();
+
+ try {
+ numFlip = Integer.parseInt(userResponse);
+ }
+ catch (NumberFormatException ex) {
+ nextStep = Step.ILLEGAL_ENTRY;
+ break;
+ }
+
+ // Command to start a new game
+ if (numFlip == 11) {
+ nextStep = Step.RANDOMIZE;
+ break;
+ }
+
+ if (numFlip > 11) {
+ nextStep = Step.ILLEGAL_ENTRY;
+ break;
+ }
+
+ // Command to reset the board
+ if (numFlip == 0) {
+ nextStep = Step.INIT_BOARD;
+ break;
+ }
+
+ if (match == numFlip) {
+ nextStep = Step.FLIP_POSITION;
+ break;
+ }
+
+ match = numFlip;
+
+ if (board[numFlip].equals("O")) {
+ nextStep = Step.SET_X_FIRST;
+ break;
+ }
+
+ board[numFlip] = "O";
+ nextStep = Step.GENERATE_R_FIRST;
+ break;
+
+ case ILLEGAL_ENTRY:
+ System.out.println("ILLEGAL ENTRY--TRY AGAIN.");
+ nextStep = Step.GET_NUMBER;
+ break;
+
+ case GENERATE_R_FIRST:
+
+ mathVal = Math.tan(randVal + numFlip / randVal - numFlip) - Math.sin(randVal / numFlip) + 336
+ * Math.sin(8 * numFlip);
+
+ tmpVal = mathVal - (int)Math.floor(mathVal);
+
+ numFlip = (int)(10 * tmpVal);
+
+ if (board[numFlip].equals("O")) {
+ nextStep = Step.SET_X_FIRST;
+ break;
+ }
+
+ board[numFlip] = "O";
+ nextStep = Step.PRINT_BOARD;
+ break;
+
+ case SET_X_FIRST:
+ board[numFlip] = "X";
+
+ if (match == numFlip) {
+ nextStep = Step.GENERATE_R_FIRST;
+ } else {
+ nextStep = Step.PRINT_BOARD;
+ }
+ break;
+
+ case FLIP_POSITION:
+
+ if (board[numFlip].equals("O")) {
+ nextStep = Step.SET_X_SECOND;
+ break;
+ }
+
+ board[numFlip] = "O";
+ nextStep = Step.GENERATE_R_SECOND;
+ break;
+
+ case GENERATE_R_SECOND:
+
+ mathVal = 0.592 * (1 / Math.tan(randVal / numFlip + randVal)) / Math.sin(numFlip * 2 + randVal)
+ - Math.cos(numFlip);
+
+ tmpVal = mathVal - (int)mathVal;
+ numFlip = (int)(10 * tmpVal);
+
+ if (board[numFlip].equals("O")) {
+ nextStep = Step.SET_X_SECOND;
+ break;
+ }
+
+ board[numFlip] = "O";
+ nextStep = Step.PRINT_BOARD;
+ break;
+
+ case SET_X_SECOND:
+
+ board[numFlip] = "X";
+ if (match == numFlip) {
+ nextStep = Step.GENERATE_R_SECOND;
+ break;
+ }
+
+ nextStep = Step.PRINT_BOARD;
+ break;
+
+ case PRINT_BOARD:
+ System.out.println("1 2 3 4 5 6 7 8 9 10");
+
+ for (index = 1; index <= 10; index++) {
+ System.out.print(board[index] + " ");
+ }
+
+ numGuesses++;
+
+ System.out.println("");
+
+ for (index = 1; index <= 10; index++) {
+ if (!board[index].equals("O")) {
+ nextStep = Step.GET_NUMBER;
+ break;
+ }
+ }
+
+ if (nextStep == Step.GET_NUMBER) {
+ break;
+ }
+
+ if (numGuesses > 12) {
+ System.out.println("TRY HARDER NEXT TIME. IT TOOK YOU " + numGuesses + " GUESSES.");
+ } else {
+ System.out.println("VERY GOOD. YOU GUESSED IT IN ONLY " + numGuesses + " GUESSES.");
+ }
+ nextStep = Step.QUERY_RETRY;
+ break;
+
+ case QUERY_RETRY:
+
+ System.out.print("DO YOU WANT TO TRY ANOTHER PUZZLE? ");
+ userResponse = scan.nextLine();
+
+ if (userResponse.toUpperCase().charAt(0) == 'N') {
+ return;
+ }
+ System.out.println("");
+ nextStep = Step.RANDOMIZE;
+ break;
+
+ default:
+ System.out.println("INVALID STEP");
+ nextStep = Step.QUERY_RETRY;
+ break;
+
+ } // End of switch
+
+ } // End outer while loop
+
+ } // End of method startGame
+
+ public static void main(String[] args) {
+
+ FlipFlop game = new FlipFlop();
+ game.play();
+
+ } // End of method main
+
+} // End of class FlipFlop
From c9e779bbca9d6947bf31868072923fac63615da4 Mon Sep 17 00:00:00 2001
From: beyonddream <43626691+beyonddream@users.noreply.github.com>
Date: Sat, 15 May 2021 15:55:32 -0700
Subject: [PATCH 10/15] Add Hammurabi game port to C and Rust
---
43 Hammurabi/README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/43 Hammurabi/README.md b/43 Hammurabi/README.md
index 1e5db404..22378ac0 100644
--- a/43 Hammurabi/README.md
+++ b/43 Hammurabi/README.md
@@ -5,3 +5,7 @@ https://www.atariarchives.org/basicgames/showpage.php?page=78
Downloaded from Vintage Basic at
http://www.vintage-basic.net/games.html
+
+[Port to C language](https://github.com/beyonddream/hamurabi)
+
+[Port to Rust language](https://github.com/beyonddream/hamurabi.rs)
From d403bd0b1b22c3915233aa60c167e5171dd273e1 Mon Sep 17 00:00:00 2001
From: Nezumi Ronin
Date: Thu, 20 May 2021 01:38:50 -0500
Subject: [PATCH 11/15] Create trap.pl
Made with Perl!
---
92 Trap/perl/trap.pl | 62 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 92 Trap/perl/trap.pl
diff --git a/92 Trap/perl/trap.pl b/92 Trap/perl/trap.pl
new file mode 100644
index 00000000..80349056
--- /dev/null
+++ b/92 Trap/perl/trap.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+use strict;
+
+print ' 'x 34 . "TRAP\n";
+print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n"; print "\n"; print "\n";
+my $G=6;
+my $N=100;
+# REM-TRAP;
+# REM-STEVE ULLMAN, 8-1-72;
+
+print "INSTRUCTIONS";
+print "? "; chomp(my $Z = uc());
+if (substr($Z,0,1) eq "Y") {
+ print "I AM THINKING OF A NUMBER BETWEEN 1 AND $N\n";
+ print "TRY TO GUESS MY NUMBER. ON EACH GUESS,\n";
+ print "YOU ARE TO ENTER 2 NUMBERS, TRYING TO TRAP\n";
+ print "MY NUMBER BETWEEN THE TWO NUMBERS. I WILL\n";
+ print "TELL YOU IF YOU HAVE TRAPPED MY NUMBER, IF MY\n";
+ print "NUMBER IS LARGER THAN YOUR TWO NUMBERS, OR IF\n";
+ print "MY NUMBER IS SMALLER THAN YOUR TWO NUMBERS.\n";
+ print "IF YOU WANT TO GUESS ONE SINGLE NUMBER, TYPE\n";
+ print "YOUR GUESS FOR BOTH YOUR TRAP NUMBERS.\n";
+ print "YOU GET $G GUESSES TO GET MY NUMBER.\n";
+ }
+
+while (1) {
+ my $Flag= 0;
+ my $X=int($N*rand(1))+1;
+ for (my $Q=1; $Q<=$G; $Q++) {
+ print "\n";
+ print "GUESS #$Q ";
+ print "? "; chomp(my $Pair= uc());
+ my ($A, $B)= split(",", $Pair);
+ if ($A eq $B && $X eq $A) { $Flag=1; last; }
+
+ if ($A>$B) { ($A,$B)= ($B,$A); }
+ if ($X>$B) {
+ print "MY NUMBER IS LARGER THAN YOUR TRAP NUMBERS.\n";
+ next;
+ }
+ if ($X<$A) {
+ print "MY NUMBER IS SMALLER THAN YOUR TRAP NUMBERS.\n";
+ next;
+ }
+ print "YOU HAVE TRAPPED MY NUMBER.\n";
+ }
+
+ if ($Flag==0) {
+ print "SORRY, THAT'S $G GUESSES. THE NUMBER WAS $X\n";
+ } else {
+ print "YOU GOT IT!!!\n";
+ }
+
+ print "\n";
+ print "TRY AGAIN.\n";
+ print "\n";
+ }
+
+exit;
+
+
From b9dd50f6e411a0a57fba1a19ac90c5fb363cd0ba Mon Sep 17 00:00:00 2001
From: Aldrin Misquitta
Date: Sat, 22 May 2021 11:53:20 +0400
Subject: [PATCH 12/15] Ported 40 Gomoko to Java
---
40 Gomoko/java/Gomoko.java | 211 +++++++++++++++++++++++++++++++++++++
1 file changed, 211 insertions(+)
create mode 100644 40 Gomoko/java/Gomoko.java
diff --git a/40 Gomoko/java/Gomoko.java b/40 Gomoko/java/Gomoko.java
new file mode 100644
index 00000000..64ad7c74
--- /dev/null
+++ b/40 Gomoko/java/Gomoko.java
@@ -0,0 +1,211 @@
+import java.util.Arrays;
+import java.util.InputMismatchException;
+import java.util.Scanner;
+
+/**
+ * GOMOKO
+ *
+ * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm)
+ */
+public class Gomoko {
+
+ private static final int MIN_BOARD_SIZE = 7;
+ private static final int MAX_BOARD_SIZE = 19;
+
+ public static void main(String[] args) {
+ printIntro();
+ Scanner scan = new Scanner(System.in);
+ int boardSize = readBoardSize(scan);
+
+ boolean continuePlay = true;
+ while (continuePlay) {
+ int[][] board = new int[boardSize][boardSize];
+ //initialize the board elements to 0
+ for (int[] ints : board) {
+ Arrays.fill(ints, 0);
+ }
+
+ System.out.println("\n\nWE ALTERNATE MOVES. YOU GO FIRST...");
+
+ boolean doneRound = false;
+ while (!doneRound) {
+ Move playerMove = null;
+ boolean validMove = false;
+ while (!validMove) {
+ playerMove = readMove(scan);
+ if (playerMove.i == -1 || playerMove.j == -1) {
+ doneRound = true;
+ System.out.println("\nTHANKS FOR THE GAME!!");
+ System.out.print("PLAY AGAIN (1 FOR YES, 0 FOR NO)? ");
+ final int playAgain = scan.nextInt();
+ scan.nextLine();
+ if (playAgain == 1) {
+ continuePlay = true;
+ break;
+ } else {
+ continuePlay = false;
+ break;
+ }
+ } else if (!isLegalMove(playerMove, boardSize)) {
+ System.out.println("ILLEGAL MOVE. TRY AGAIN...");
+ } else if (board[playerMove.i - 1][playerMove.j - 1] != 0) {
+ System.out.println("SQUARE OCCUPIED. TRY AGAIN...");
+ } else {
+ validMove = true;
+ }
+ }
+
+ if (!doneRound) {
+ board[playerMove.i - 1][playerMove.j - 1] = 1;
+ Move computerMove = getComputerMove(playerMove, board, boardSize);
+ if (computerMove == null) {
+ computerMove = getRandomMove(board, boardSize);
+ }
+ board[computerMove.i - 1][computerMove.j - 1] = 2;
+
+ printBoard(board);
+ }
+ }
+
+ }
+ }
+
+ //*** COMPUTER TRIES AN INTELLIGENT MOVE ***
+ private static Move getComputerMove(Move playerMove, int[][] board, int boardSize) {
+ for (int e = -1; e <= 1; e++) {
+ for (int f = -1; f <= 1; f++) {
+ if ((e + f - e * f) != 0) {
+ var x = playerMove.i + f;
+ var y = playerMove.j + f;
+ final Move newMove = new Move(x, y);
+ if (isLegalMove(newMove, boardSize)) {
+ if (board[newMove.i - 1][newMove.j - 1] != 0) {
+ newMove.i = newMove.i - e;
+ newMove.i = newMove.j - f;
+ if (!isLegalMove(newMove, boardSize)) {
+ return null;
+ } else {
+ if (board[newMove.i - 1][newMove.j - 1] == 0) {
+ return newMove;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private static void printBoard(int[][] board) {
+ for (int[] ints : board) {
+ for (int cell : ints) {
+ System.out.printf(" %s", cell);
+ }
+ System.out.println();
+ }
+ }
+
+ //*** COMPUTER TRIES A RANDOM MOVE ***
+ private static Move getRandomMove(int[][] board, int boardSize) {
+ boolean legalMove = false;
+ Move randomMove = null;
+ while (!legalMove) {
+ randomMove = randomMove(boardSize);
+ legalMove = isLegalMove(randomMove, boardSize) && board[randomMove.i - 1][randomMove.j - 1] == 0;
+
+ }
+ return randomMove;
+ }
+
+ private static Move randomMove(int boardSize) {
+ int x = (int) (boardSize * Math.random() + 1);
+ int y = (int) (boardSize * Math.random() + 1);
+ return new Move(x, y);
+ }
+
+ private static boolean isLegalMove(Move move, int boardSize) {
+ return (move.i >= 1) && (move.i <= boardSize) && (move.j >= 1) && (move.j <= boardSize);
+ }
+
+ private static void printIntro() {
+ System.out.println(" GOMOKO");
+ System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
+ System.out.println("\n\n");
+ System.out.println("WELCOME TO THE ORIENTAL GAME OF GOMOKO.");
+ System.out.println("\n");
+ System.out.println("THE GAME IS PLAYED ON AN N BY N GRID OF A SIZE");
+ System.out.println("THAT YOU SPECIFY. DURING YOUR PLAY, YOU MAY COVER ONE GRID");
+ System.out.println("INTERSECTION WITH A MARKER. THE OBJECT OF THE GAME IS TO GET");
+ System.out.println("5 ADJACENT MARKERS IN A ROW -- HORIZONTALLY, VERTICALLY, OR");
+ System.out.println("DIAGONALLY. ON THE BOARD DIAGRAM, YOUR MOVES ARE MARKED");
+ System.out.println("WITH A '1' AND THE COMPUTER MOVES WITH A '2'.");
+ System.out.println("\nTHE COMPUTER DOES NOT KEEP TRACK OF WHO HAS WON.");
+ System.out.println("TO END THE GAME, TYPE -1,-1 FOR YOUR MOVE.\n ");
+ }
+
+ private static int readBoardSize(Scanner scan) {
+ System.out.print("WHAT IS YOUR BOARD SIZE (MIN 7/ MAX 19)? ");
+
+ boolean validInput = false;
+ int input = 0;
+ while (!validInput) {
+ try {
+ input = scan.nextInt();
+ if (input < MIN_BOARD_SIZE || input > MAX_BOARD_SIZE) {
+ System.out.printf("I SAID, THE MINIMUM IS %s, THE MAXIMUM IS %s.\n", MIN_BOARD_SIZE, MAX_BOARD_SIZE);
+ } else {
+ validInput = true;
+ }
+ } catch (InputMismatchException ex) {
+ System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE\n");
+ validInput = false;
+ } finally {
+ scan.nextLine();
+ }
+ }
+ return input;
+ }
+
+ private static Move readMove(Scanner scan) {
+ System.out.print("YOUR PLAY (I,J)? ");
+ boolean validInput = false;
+ Move move = new Move();
+ while (!validInput) {
+ String input = scan.nextLine();
+ final String[] split = input.split(",");
+ try {
+ move.i = Integer.parseInt(split[0]);
+ move.j = Integer.parseInt(split[1]);
+ validInput = true;
+ } catch (NumberFormatException nfe) {
+ System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE\n? ");
+ }
+
+ }
+ return move;
+ }
+
+ private static class Move {
+ int i;
+ int j;
+
+ public Move() {
+ }
+
+ public Move(int i, int j) {
+ this.i = i;
+ this.j = j;
+ }
+
+ @Override
+ public String toString() {
+ return "Move{" +
+ "i=" + i +
+ ", j=" + j +
+ '}';
+ }
+ }
+
+}
+
From 4bf4f1da28c630dcff51ed4aaab183b53de41622 Mon Sep 17 00:00:00 2001
From: Aldrin Misquitta
Date: Sat, 29 May 2021 11:37:31 +0400
Subject: [PATCH 13/15] Ported 34 Digits to Java
---
34 Digits/java/Digits.java | 186 +++++++++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
create mode 100644 34 Digits/java/Digits.java
diff --git a/34 Digits/java/Digits.java b/34 Digits/java/Digits.java
new file mode 100644
index 00000000..36ee58ae
--- /dev/null
+++ b/34 Digits/java/Digits.java
@@ -0,0 +1,186 @@
+import java.util.Arrays;
+import java.util.InputMismatchException;
+import java.util.Scanner;
+
+/**
+ * DIGITS
+ *
+ * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm)
+ */
+public class Digits {
+
+ public static void main(String[] args) {
+ printIntro();
+ Scanner scan = new Scanner(System.in);
+
+ boolean showInstructions = readInstructionChoice(scan);
+ if (showInstructions) {
+ printInstructions();
+ }
+
+ int a = 0, b = 1, c = 3;
+ int[][] m = new int[27][3];
+ int[][] k = new int[3][3];
+ int[][] l = new int[9][3];
+
+ boolean continueGame = true;
+ while (continueGame) {
+ for (int[] ints : m) {
+ Arrays.fill(ints, 1);
+ }
+ for (int[] ints : k) {
+ Arrays.fill(ints, 9);
+ }
+ for (int[] ints : l) {
+ Arrays.fill(ints, 3);
+ }
+
+ l[0][0] = 2;
+ l[4][1] = 2;
+ l[8][2] = 2;
+
+ int z = 26, z1 = 8, z2 = 2, runningCorrect = 0;
+
+ for (int t = 1; t <= 3; t++) {
+ boolean validNumbers = false;
+ int[] numbers = new int[0];
+ while (!validNumbers) {
+ System.out.println();
+ numbers = read10Numbers(scan);
+ validNumbers = true;
+ for (int number : numbers) {
+ if (number < 0 || number > 2) {
+ System.out.println("ONLY USE THE DIGITS '0', '1', OR '2'.");
+ System.out.println("LET'S TRY AGAIN.");
+ validNumbers = false;
+ break;
+ }
+ }
+ }
+
+ System.out.printf("\n%-14s%-14s%-14s%-14s", "MY GUESS", "YOUR NO.", "RESULT", "NO. RIGHT");
+ for (int number : numbers) {
+ int s = 0;
+ int myGuess = 0;
+ for (int j = 0; j <= 2; j++) {
+ //What did the original author have in mind ? The first expression always results in 0 because a is always 0
+ int s1 = a * k[z2][j] + b * l[z1][j] + c * m[z][j];
+ if (s < s1) {
+ s = s1;
+ myGuess = j;
+ } else if (s1 == s) {
+ if (Math.random() >= 0.5) {
+ myGuess = j;
+ }
+ }
+ }
+
+ String result;
+ if (myGuess != number) {
+ result = "WRONG";
+ } else {
+ runningCorrect++;
+ result = "RIGHT";
+ m[z][number] = m[z][number] + 1;
+ l[z1][number] = l[z1][number] + 1;
+ k[z2][number] = k[z2][number] + 1;
+ z = z - (z / 9) * 9;
+ z = 3 * z + number;
+ }
+ System.out.printf("\n%-14d%-14d%-14s%-14d", myGuess, number, result, runningCorrect);
+
+ z1 = z - (z / 9) * 9;
+ z2 = number;
+ }
+ }
+
+ //print summary report
+ System.out.println();
+ if (runningCorrect > 10) {
+ System.out.println();
+ System.out.println("I GUESSED MORE THAN 1/3 OF YOUR NUMBERS.");
+ System.out.println("I WIN.\u0007");
+ } else if (runningCorrect < 10) {
+ System.out.println("I GUESSED LESS THAN 1/3 OF YOUR NUMBERS.");
+ System.out.println("YOU BEAT ME. CONGRATULATIONS *****");
+ } else {
+ System.out.println("I GUESSED EXACTLY 1/3 OF YOUR NUMBERS.");
+ System.out.println("IT'S A TIE GAME.");
+ }
+
+ continueGame = readContinueChoice(scan);
+ }
+
+ System.out.println("\nTHANKS FOR THE GAME.");
+ }
+
+ private static boolean readContinueChoice(Scanner scan) {
+ System.out.print("\nDO YOU WANT TO TRY AGAIN (1 FOR YES, 0 FOR NO) ? ");
+ int choice;
+ try {
+ choice = scan.nextInt();
+ return choice == 1;
+ } catch (InputMismatchException ex) {
+ return false;
+ } finally {
+ scan.nextLine();
+ }
+ }
+
+ private static int[] read10Numbers(Scanner scan) {
+ System.out.print("TEN NUMBERS, PLEASE ? ");
+ int[] numbers = new int[10];
+
+ for (int i = 0; i < numbers.length; i++) {
+ boolean validInput = false;
+ while (!validInput) {
+ try {
+ int n = scan.nextInt();
+ validInput = true;
+ numbers[i] = n;
+ } catch (InputMismatchException ex) {
+ System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE");
+ } finally {
+ scan.nextLine();
+ }
+ }
+ }
+
+ return numbers;
+ }
+
+ private static void printInstructions() {
+ System.out.println("\n");
+ System.out.println("PLEASE TAKE A PIECE OF PAPER AND WRITE DOWN");
+ System.out.println("THE DIGITS '0', '1', OR '2' THIRTY TIMES AT RANDOM.");
+ System.out.println("ARRANGE THEM IN THREE LINES OF TEN DIGITS EACH.");
+ System.out.println("I WILL ASK FOR THEN TEN AT A TIME.");
+ System.out.println("I WILL ALWAYS GUESS THEM FIRST AND THEN LOOK AT YOUR");
+ System.out.println("NEXT NUMBER TO SEE IF I WAS RIGHT. BY PURE LUCK,");
+ System.out.println("I OUGHT TO BE RIGHT TEN TIMES. BUT I HOPE TO DO BETTER");
+ System.out.println("THAN THAT *****");
+ System.out.println();
+ }
+
+ private static boolean readInstructionChoice(Scanner scan) {
+ System.out.print("FOR INSTRUCTIONS, TYPE '1', ELSE TYPE '0' ? ");
+ int choice;
+ try {
+ choice = scan.nextInt();
+ return choice == 1;
+ } catch (InputMismatchException ex) {
+ return false;
+ } finally {
+ scan.nextLine();
+ }
+ }
+
+ private static void printIntro() {
+ System.out.println(" DIGITS");
+ System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
+ System.out.println("\n\n");
+ System.out.println("THIS IS A GAME OF GUESSING.");
+ }
+
+}
+
From 2cf4ad8a73715bb6f7120b381b82c149997a014c Mon Sep 17 00:00:00 2001
From: Joe Walter
Date: Sat, 29 May 2021 15:08:32 -0400
Subject: [PATCH 14/15] Port banner to C#
---
06 Banner/csharp/banner.cs | 251 +++++++++++++++++++++++++++++++++
06 Banner/csharp/banner.csproj | 8 ++
06 Banner/csharp/banner.sln | 25 ++++
3 files changed, 284 insertions(+)
create mode 100644 06 Banner/csharp/banner.cs
create mode 100644 06 Banner/csharp/banner.csproj
create mode 100644 06 Banner/csharp/banner.sln
diff --git a/06 Banner/csharp/banner.cs b/06 Banner/csharp/banner.cs
new file mode 100644
index 00000000..6b0ff142
--- /dev/null
+++ b/06 Banner/csharp/banner.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace banner
+{
+ class Banner
+ {
+ private int Horizontal { get; set; }
+ private int Vertical { get; set; }
+ private bool Centered { get; set; }
+ private string Character { get; set; }
+ private string Statement { get; set; }
+
+ // This provides a bit-ended representation of each symbol
+ // that can be output. Each symbol is defined by 7 parts -
+ // where each part is an integer value that, when converted to
+ // the binary representation, shows which section is filled in
+ // with values and which are spaces. i.e., the 'filled in'
+ // parts represent the actual symbol on the paper.
+ Dictionary letters = new Dictionary()
+ {
+ {' ', new int[] { 0, 0, 0, 0, 0, 0, 0 } },
+ {'A', new int[] {505, 37, 35, 34, 35, 37, 505} },
+ {'B', new int[] {512, 274, 274, 274, 274, 274, 239} },
+ {'C', new int[] {125, 131, 258, 258, 258, 131, 69} },
+ {'D', new int[] {512, 258, 258, 258, 258, 131, 125} },
+ {'E', new int[] {512, 274, 274, 274, 274, 258, 258} },
+ {'F', new int[] {512, 18, 18, 18, 18, 2, 2} },
+ {'G', new int[] {125, 131, 258, 258, 290, 163, 101} },
+ {'H', new int[] {512, 17, 17, 17, 17, 17, 512} },
+ {'I', new int[] {258, 258, 258, 512, 258, 258, 258} },
+ {'J', new int[] {65, 129, 257, 257, 257, 129, 128} },
+ {'K', new int[] {512, 17, 17, 41, 69, 131, 258} },
+ {'L', new int[] {512, 257, 257, 257, 257, 257, 257} },
+ {'M', new int[] {512, 7, 13, 25, 13, 7, 512} },
+ {'N', new int[] {512, 7, 9, 17, 33, 193, 512} },
+ {'O', new int[] {125, 131, 258, 258, 258, 131, 125} },
+ {'P', new int[] {512, 18, 18, 18, 18, 18, 15} },
+ {'Q', new int[] {125, 131, 258, 258, 322, 131, 381} },
+ {'R', new int[] {512, 18, 18, 50, 82, 146, 271} },
+ {'S', new int[] {69, 139, 274, 274, 274, 163, 69} },
+ {'T', new int[] {2, 2, 2, 512, 2, 2, 2} },
+ {'U', new int[] {128, 129, 257, 257, 257, 129, 128} },
+ {'V', new int[] {64, 65, 129, 257, 129, 65, 64} },
+ {'W', new int[] {256, 257, 129, 65, 129, 257, 256} },
+ {'X', new int[] {388, 69, 41, 17, 41, 69, 388} },
+ {'Y', new int[] {8, 9, 17, 481, 17, 9, 8} },
+ {'Z', new int[] {386, 322, 290, 274, 266, 262, 260} },
+ {'0', new int[] {57, 69, 131, 258, 131, 69, 57} },
+ {'1', new int[] {0, 0, 261, 259, 512, 257, 257} },
+ {'2', new int[] {261, 387, 322, 290, 274, 267, 261} },
+ {'3', new int[] {66, 130, 258, 274, 266, 150, 100} },
+ {'4', new int[] {33, 49, 41, 37, 35, 512, 33} },
+ {'5', new int[] {160, 274, 274, 274, 274, 274, 226} },
+ {'6', new int[] {194, 291, 293, 297, 305, 289, 193} },
+ {'7', new int[] {258, 130, 66, 34, 18, 10, 8} },
+ {'8', new int[] {69, 171, 274, 274, 274, 171, 69} },
+ {'9', new int[] {263, 138, 74, 42, 26, 10, 7} },
+ {'?', new int[] {5, 3, 2, 354, 18, 11, 5} },
+ {'*', new int[] {69, 41, 17, 512, 17, 41, 69} },
+ {'=', new int[] {41, 41, 41, 41, 41, 41, 41} },
+ {'!', new int[] {1, 1, 1, 384, 1, 1, 1} },
+ {'.', new int[] {1, 1, 129, 449, 129, 1, 1} }
+ };
+
+
+ ///
+ /// This displays the provided text on the screen and then waits for the user
+ /// to enter a integer value greater than 0.
+ ///
+ /// Text to display on the screen asking for the input
+ /// The integer value entered by the user
+ private int GetNumber(string DisplayText)
+ {
+ Console.Write(DisplayText);
+ string TempStr = Console.ReadLine();
+
+ Int32.TryParse(TempStr, out int TempInt);
+
+ if (TempInt <= 0)
+ {
+ throw new ArgumentException($"{DisplayText} must be greater than zero");
+ }
+
+ return TempInt;
+ }
+
+ ///
+ /// This displays the provided text on the screen and then waits for the user
+ /// to enter a Y or N. It cheats by just looking for a 'y' and returning that
+ /// as true. Anything else that the user enters is returned as false.
+ ///
+ /// Text to display on the screen asking for the input
+ /// Returns true or false
+ private bool GetBool(string DisplayText)
+ {
+ Console.Write(DisplayText);
+ return (Console.ReadLine().StartsWith("y", StringComparison.InvariantCultureIgnoreCase));
+ }
+
+ ///
+ /// This displays the provided text on the screen and then waits for the user
+ /// to enter an arbitrary string. That string is then returned 'as-is'.
+ ///
+ /// Text to display on the screen asking for the input
+ /// The string entered by the user.
+ private string GetString(string DisplayText)
+ {
+ Console.Write(DisplayText);
+ return (Console.ReadLine().ToUpper());
+ }
+
+ ///
+ /// This queries the user for the various inputs needed by the program.
+ ///
+ private void GetInput()
+ {
+ Horizontal = GetNumber("Horizontal ");
+ Vertical = GetNumber("Vertical ");
+ Centered = GetBool("Centered ");
+ Character = GetString("Character (type 'ALL' if you want character being printed) ");
+ Statement = GetString("Statement ");
+ // We don't care about what the user enters here. This is just telling them
+ // to set the page in the printer.
+ _ = GetString("Set page ");
+ }
+
+ ///
+ /// This prints out a single character of the banner - adding
+ /// a few blanks lines as a spacer between characters.
+ ///
+ private void PrintChar(char ch)
+ {
+ // In the trivial case (a space character), just print out the spaces
+ if (ch.Equals(' '))
+ {
+ Console.WriteLine(new string('\n', 7 * Horizontal));
+ return;
+ }
+
+ // If a specific character to be printed was provided by the user,
+ // then user that as our ouput character - otherwise take the
+ // current character
+ char outCh = Character == "ALL" ? ch : Character[0];
+ int[] letter = new int[7];
+ try
+ {
+ letters[outCh].CopyTo(letter, 0);
+ }
+ catch (KeyNotFoundException)
+ {
+ throw new KeyNotFoundException($"The provided letter {outCh} was not found in the letters list");
+ }
+
+ // New int array declarations default to zeros
+ // 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
+ // character gets filled in with the character or with blanks
+ int[] fillInSection = new int[9];
+
+ // This iterates through each of the parts that make up
+ // each letter. Each part represents 1 * Horizontal lines
+ // of actual output.
+ for (int idx = 0; idx < 7; idx++)
+ {
+ // This uses the value in each part to decide which
+ // sections are empty spaces in the letter or filled in
+ // spaces. For each section marked with 1 in fillInSection,
+ // that will correspond to 1 * Vertical characters actually
+ // being output.
+ for (int exp = 8; exp >= 0; exp--)
+ {
+ if (Math.Pow(2, exp) < letter[idx])
+ {
+ fillInSection[8 - exp] = 1;
+ letter[idx] -= (int)Math.Pow(2, exp);
+ if (letter[idx] == 1)
+ {
+ // Once we've exhausted all of the sections
+ // defined in this part of the letter, then
+ // we marked that number and break out of this
+ // for loop.
+ numSections[idx] = 8 - exp;
+ break;
+ }
+ }
+ }
+
+ // Now that we know which sections of this part of the letter
+ // are filled in or spaces, we can actually create the string
+ // to print out.
+ string lineStr = "";
+
+ if (Centered)
+ lineStr += new string(' ', (int)(63 - 4.5 * Vertical) * 1 / 1 + 1);
+
+ for (int idx2 = 0; idx2 <= numSections[idx]; idx2++)
+ {
+ lineStr = lineStr + new string(fillInSection[idx2] == 0 ? ' ' : outCh, Vertical);
+ }
+
+ // Then we print that string out 1 * Horizontal number of times
+ for (int lineidx = 1; lineidx <= Horizontal; lineidx++)
+ {
+ Console.WriteLine(lineStr);
+ }
+ }
+
+ // Finally, add a little spacer after each character for readability.
+ Console.WriteLine(new string('\n', 2 * Horizontal - 1));
+ }
+
+ ///
+ /// This prints the entire banner based in the parameters
+ /// the user provided.
+ ///
+ private void PrintBanner()
+ {
+ // Iterate through each character in the statement
+ foreach (char ch in Statement)
+ {
+ PrintChar(ch);
+ }
+
+ // In the original version, it would print an additional 75 blank
+ // lines in order to feed the printer paper...don't really need this
+ // since we're not actually printing.
+ Console.WriteLine(new string('\n', 75));
+ }
+
+ ///
+ /// Main entry point into the banner class and handles the main loop.
+ ///
+ public void Play()
+ {
+ GetInput();
+ PrintBanner();
+ }
+ }
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ new Banner().Play();
+ }
+ }
+}
diff --git a/06 Banner/csharp/banner.csproj b/06 Banner/csharp/banner.csproj
new file mode 100644
index 00000000..c73e0d16
--- /dev/null
+++ b/06 Banner/csharp/banner.csproj
@@ -0,0 +1,8 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
diff --git a/06 Banner/csharp/banner.sln b/06 Banner/csharp/banner.sln
new file mode 100644
index 00000000..34f63984
--- /dev/null
+++ b/06 Banner/csharp/banner.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31321.278
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "banner", "banner.csproj", "{9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {FF2A268C-9C4A-457F-8733-2E8931E07A1D}
+ EndGlobalSection
+EndGlobal
From dea43e1d308de98d03db94eccb8c848ec7f8c75b Mon Sep 17 00:00:00 2001
From: Joe Walter
Date: Sat, 29 May 2021 15:48:10 -0400
Subject: [PATCH 15/15] Port banner to VB
---
06 Banner/csharp/banner.cs | 18 +--
06 Banner/vbnet/banner.sln | 25 ++++
06 Banner/vbnet/banner.vb | 226 ++++++++++++++++++++++++++++++++++
06 Banner/vbnet/banner.vbproj | 9 ++
4 files changed, 269 insertions(+), 9 deletions(-)
create mode 100644 06 Banner/vbnet/banner.sln
create mode 100644 06 Banner/vbnet/banner.vb
create mode 100644 06 Banner/vbnet/banner.vbproj
diff --git a/06 Banner/csharp/banner.cs b/06 Banner/csharp/banner.cs
index 6b0ff142..e3e59b4b 100644
--- a/06 Banner/csharp/banner.cs
+++ b/06 Banner/csharp/banner.cs
@@ -153,19 +153,19 @@ namespace banner
throw new KeyNotFoundException($"The provided letter {outCh} was not found in the letters list");
}
- // New int array declarations default to zeros
- // 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
- // character gets filled in with the character or with blanks
- int[] fillInSection = new int[9];
-
// This iterates through each of the parts that make up
// each letter. Each part represents 1 * Horizontal lines
// of actual output.
for (int idx = 0; idx < 7; idx++)
{
+ // New int array declarations default to zeros
+ // 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
+ // character gets filled in with the character or with blanks
+ int[] fillInSection = new int[9];
+
// This uses the value in each part to decide which
// sections are empty spaces in the letter or filled in
// spaces. For each section marked with 1 in fillInSection,
@@ -228,7 +228,7 @@ namespace banner
// In the original version, it would print an additional 75 blank
// lines in order to feed the printer paper...don't really need this
// since we're not actually printing.
- Console.WriteLine(new string('\n', 75));
+ // Console.WriteLine(new string('\n', 75));
}
///
diff --git a/06 Banner/vbnet/banner.sln b/06 Banner/vbnet/banner.sln
new file mode 100644
index 00000000..5fdc8737
--- /dev/null
+++ b/06 Banner/vbnet/banner.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31321.278
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "banner", "banner.vbproj", "{1738D297-A04C-4E6E-8219-D9E72982C39D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1738D297-A04C-4E6E-8219-D9E72982C39D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1738D297-A04C-4E6E-8219-D9E72982C39D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1738D297-A04C-4E6E-8219-D9E72982C39D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1738D297-A04C-4E6E-8219-D9E72982C39D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {04E18CE1-1C55-432F-A15A-DC2FA9DDC0F1}
+ EndGlobalSection
+EndGlobal
diff --git a/06 Banner/vbnet/banner.vb b/06 Banner/vbnet/banner.vb
new file mode 100644
index 00000000..90e183b8
--- /dev/null
+++ b/06 Banner/vbnet/banner.vb
@@ -0,0 +1,226 @@
+Imports System
+
+Module Banner
+ Private Horizontal As Integer
+ Private Vertical As Integer
+ Private Centered As Boolean
+ Private Character As String
+ Private Statement As String
+
+ ' This provides a bit-ended representation of each symbol
+ ' that can be output. Each symbol Is defined by 7 parts -
+ ' where each part Is an integer value that, when converted to
+ ' the binary representation, shows which section Is filled in
+ ' with values And which are spaces. i.e., the 'filled in'
+ ' parts represent the actual symbol on the paper.
+ Private letters As Dictionary(Of Char, Integer()) = New Dictionary(Of Char, Integer()) From
+ {
+ {" ", {0, 0, 0, 0, 0, 0, 0}},
+ {"A", {505, 37, 35, 34, 35, 37, 505}},
+ {"B", {512, 274, 274, 274, 274, 274, 239}},
+ {"C", {125, 131, 258, 258, 258, 131, 69}},
+ {"D", {512, 258, 258, 258, 258, 131, 125}},
+ {"E", {512, 274, 274, 274, 274, 258, 258}},
+ {"F", {512, 18, 18, 18, 18, 2, 2}},
+ {"G", {125, 131, 258, 258, 290, 163, 101}},
+ {"H", {512, 17, 17, 17, 17, 17, 512}},
+ {"I", {258, 258, 258, 512, 258, 258, 258}},
+ {"J", {65, 129, 257, 257, 257, 129, 128}},
+ {"K", {512, 17, 17, 41, 69, 131, 258}},
+ {"L", {512, 257, 257, 257, 257, 257, 257}},
+ {"M", {512, 7, 13, 25, 13, 7, 512}},
+ {"N", {512, 7, 9, 17, 33, 193, 512}},
+ {"O", {125, 131, 258, 258, 258, 131, 125}},
+ {"P", {512, 18, 18, 18, 18, 18, 15}},
+ {"Q", {125, 131, 258, 258, 322, 131, 381}},
+ {"R", {512, 18, 18, 50, 82, 146, 271}},
+ {"S", {69, 139, 274, 274, 274, 163, 69}},
+ {"T", {2, 2, 2, 512, 2, 2, 2}},
+ {"U", {128, 129, 257, 257, 257, 129, 128}},
+ {"V", {64, 65, 129, 257, 129, 65, 64}},
+ {"W", {256, 257, 129, 65, 129, 257, 256}},
+ {"X", {388, 69, 41, 17, 41, 69, 388}},
+ {"Y", {8, 9, 17, 481, 17, 9, 8}},
+ {"Z", {386, 322, 290, 274, 266, 262, 260}},
+ {"0", {57, 69, 131, 258, 131, 69, 57}},
+ {"1", {0, 0, 261, 259, 512, 257, 257}},
+ {"2", {261, 387, 322, 290, 274, 267, 261}},
+ {"3", {66, 130, 258, 274, 266, 150, 100}},
+ {"4", {33, 49, 41, 37, 35, 512, 33}},
+ {"5", {160, 274, 274, 274, 274, 274, 226}},
+ {"6", {194, 291, 293, 297, 305, 289, 193}},
+ {"7", {258, 130, 66, 34, 18, 10, 8}},
+ {"8", {69, 171, 274, 274, 274, 171, 69}},
+ {"9", {263, 138, 74, 42, 26, 10, 7}},
+ {"?", {5, 3, 2, 354, 18, 11, 5}},
+ {"*", {69, 41, 17, 512, 17, 41, 69}},
+ {"=", {41, 41, 41, 41, 41, 41, 41}},
+ {"!", {1, 1, 1, 384, 1, 1, 1}},
+ {".", {1, 1, 129, 449, 129, 1, 1}}
+ }
+
+ '
+ ' This displays the provided text on the screen And then waits for the user
+ ' to enter a integer value greater than 0.
+ '
+ ' Text to display on the screen asking for the input
+ ' The integer value entered by the user
+ Private Function GetNumber(DisplayText As String) As Integer
+ Console.Write(DisplayText)
+ Dim TempStr As String = Console.ReadLine()
+ Dim TempInt As Integer
+
+ Int32.TryParse(TempStr, TempInt)
+
+ If (TempInt <= 0) Then
+ Throw New ArgumentException($"{DisplayText} must be greater than zero")
+ End If
+
+ Return TempInt
+ End Function
+
+ '
+ ' This displays the provided text on the screen And then waits for the user
+ ' to enter a Y Or N. It cheats by just looking for a 'y' and returning that
+ ' as true. Anything else that the user enters Is returned as false.
+ '
+ ' Text to display on the screen asking for the input
+ ' Returns true Or false
+ Private Function GetBool(DisplayText As String) As Boolean
+ Console.Write(DisplayText)
+ Return Console.ReadLine().StartsWith("y", StringComparison.InvariantCultureIgnoreCase)
+ End Function
+
+ '
+ ' This displays the provided text on the screen And then waits for the user
+ ' to enter an arbitrary string. That string Is then returned 'as-is'.
+ '
+ ' Text to display on the screen asking for the input
+ ' The string entered by the user.
+ Private Function GetString(DisplayText As String) As String
+ Console.Write(DisplayText)
+ Return (Console.ReadLine().ToUpper())
+ End Function
+
+ '
+ ' This queries the user for the various inputs needed by the program.
+ '
+ Private Sub GetInput()
+ Horizontal = GetNumber("Horizontal ")
+ Vertical = GetNumber("Vertical ")
+ Centered = GetBool("Centered ")
+ Character = GetString("Character (type 'ALL' if you want character being printed) ")
+ Statement = GetString("Statement ")
+ ' We don't care about what the user enters here. This is just telling them
+ ' to set the page in the printer.
+ GetString("Set page ")
+ End Sub
+
+ '
+ ' This prints out a single character of the banner - adding
+ ' a few blanks lines as a spacer between characters.
+ '
+ Private Sub PrintChar(ch As Char)
+ ' In the trivial case (a space character), just print out the spaces
+ If ch.Equals(" ") Then
+ Console.WriteLine(New String("\n", 7 * Horizontal))
+ Return
+ End If
+
+ ' If a specific character to be printed was provided by the user,
+ ' then user that as our ouput character - otherwise take the
+ ' current character
+ Dim outCh As Char = IIf(Character.Equals("ALL"), ch, Character.Substring(0, 1))
+ Dim letter(7) As Integer
+ Try
+ letters(outCh).CopyTo(letter, 0)
+ Catch ex As KeyNotFoundException
+ Throw New KeyNotFoundException($"The provided letter {outCh} was not found in the letters list")
+ End Try
+
+ ' This iterates through each of the parts that make up
+ ' each letter. Each part represents 1 * Horizontal lines
+ ' of actual output.
+ For idx As Integer = 0 To 7
+ ' New int array declarations default to zeros
+ ' 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
+ ' character gets filled in with the character Or with blanks
+ Dim fillInSection(9) As Integer
+
+ ' This uses the value in each part to decide which
+ ' sections are empty spaces in the letter Or filled in
+ ' spaces. For each section marked with 1 in fillInSection,
+ ' that will correspond to 1 * Vertical characters actually
+ ' being output.
+ For exp As Integer = 8 To 0 Step -1
+ If (Math.Pow(2, exp) < letter(idx)) Then
+ fillInSection(8 - exp) = 1
+ letter(idx) -= Math.Pow(2, exp)
+ If (letter(idx) = 1) Then
+ ' Once we've exhausted all of the sections
+ ' defined in this part of the letter, then
+ ' we marked that number And break out of this
+ ' for loop.
+ numSections(idx) = 8 - exp
+ Exit For
+ End If
+ End If
+ Next exp
+
+ ' Now that we know which sections of this part of the letter
+ ' are filled in Or spaces, we can actually create the string
+ ' to print out.
+ Dim lineStr As String = ""
+
+ If (Centered) Then
+ lineStr += New String(" ", (63 - 4.5 * Vertical) * 1 / 1 + 1)
+ End If
+
+ For idx2 As Integer = 0 To numSections(idx)
+ lineStr = lineStr + New String(IIf(fillInSection(idx2) = 0, " ", outCh), Vertical)
+ Next idx2
+
+ ' Then we print that string out 1 * Horizontal number of times
+ For lineIdx As Integer = 1 To Horizontal
+ Console.WriteLine(lineStr)
+ Next lineIdx
+ Next idx
+
+
+ ' Finally, add a little spacer after each character for readability.
+ Console.WriteLine(New String(Environment.NewLine, 2 * Horizontal - 1))
+ End Sub
+
+ '
+ ' This prints the entire banner based in the parameters
+ ' the user provided.
+ '
+ Private Sub PrintBanner()
+ ' Iterate through each character in the statement
+ For Each ch As Char In Statement
+ PrintChar(ch)
+ Next ch
+
+ ' In the original version, it would print an additional 75 blank
+ ' lines in order to feed the printer paper...don't really need this
+ ' since we're not actually printing.
+ Console.WriteLine(New String(Environment.NewLine, 75))
+ End Sub
+
+ '
+ ' Main entry point into the banner class And handles the main loop.
+ '
+ Public Sub Play()
+ GetInput()
+ PrintBanner()
+ End Sub
+End Module
+
+Module Program
+ Sub Main(args As String())
+ Banner.Play()
+ End Sub
+End Module
diff --git a/06 Banner/vbnet/banner.vbproj b/06 Banner/vbnet/banner.vbproj
new file mode 100644
index 00000000..659fea7b
--- /dev/null
+++ b/06 Banner/vbnet/banner.vbproj
@@ -0,0 +1,9 @@
+
+
+
+ Exe
+ banner
+ netcoreapp3.1
+
+
+