diff --git a/01 Acey Ducey/README.md b/01 Acey Ducey/README.md index ad0bdbad..11c6b1a8 100644 --- a/01 Acey Ducey/README.md +++ b/01 Acey Ducey/README.md @@ -5,3 +5,7 @@ https://www.atariarchives.org/basicgames/showpage.php?page=2 Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html + +#### Other languages: + +- [Pascal/Object Pascal](https://github.com/gcarreno/basic-computer-games-in-pascal/tree/main/01%20Acey%20Ducey) \ No newline at end of file diff --git a/03 Animal/csharp/Animal.csproj b/03 Animal/csharp/Animal.csproj new file mode 100644 index 00000000..20827042 --- /dev/null +++ b/03 Animal/csharp/Animal.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + diff --git a/03 Animal/csharp/Animal.sln b/03 Animal/csharp/Animal.sln new file mode 100644 index 00000000..1d81e643 --- /dev/null +++ b/03 Animal/csharp/Animal.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30907.101 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Animal", "Animal.csproj", "{D9A8DAB5-1B29-44A9-B13F-CED17B5A22B9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D9A8DAB5-1B29-44A9-B13F-CED17B5A22B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9A8DAB5-1B29-44A9-B13F-CED17B5A22B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9A8DAB5-1B29-44A9-B13F-CED17B5A22B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9A8DAB5-1B29-44A9-B13F-CED17B5A22B9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {064879D3-A288-4980-8DC4-59653D5EE2DD} + EndGlobalSection +EndGlobal diff --git a/03 Animal/csharp/Branch.cs b/03 Animal/csharp/Branch.cs new file mode 100644 index 00000000..52c13037 --- /dev/null +++ b/03 Animal/csharp/Branch.cs @@ -0,0 +1,18 @@ +namespace Animal +{ + public class Branch + { + public string Text { get; set; } + + public bool IsEnd => Yes == null && No == null; + + public Branch Yes { get; set; } + + public Branch No { get; set; } + + public override string ToString() + { + return $"{Text} : IsEnd {IsEnd}"; + } + } +} \ No newline at end of file diff --git a/03 Animal/csharp/Program.cs b/03 Animal/csharp/Program.cs new file mode 100644 index 00000000..0d159724 --- /dev/null +++ b/03 Animal/csharp/Program.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using Animal; + +Console.WriteLine(new string(' ', 32) + "ANIMAL"); +Console.WriteLine(new string(' ', 15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); +Console.WriteLine(); +Console.WriteLine(); +Console.WriteLine(); +Console.WriteLine("PLAY 'GUESS THE ANIMAL'"); +Console.WriteLine(); +Console.WriteLine("THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT."); +Console.WriteLine(); + +// Root of the question and answer tree +Branch rootBranch = new Branch +{ + Text = "DOES IT SWIM", + Yes = new Branch { Text = "FISH" }, + No = new Branch { Text = "BIRD" } +}; + +string[] TRUE_INPUTS = { "Y", "YES", "T", "TRUE" }; +string[] FALSE_INPUTS = { "N", "NO", "F", "FALSE" }; + + +while (true) +{ + MainGameLoop(); +} + +void MainGameLoop() +{ + // Wait fora YES or LIST command + string input = null; + while (true) + { + input = GetInput("ARE YOU THINKING OF AN ANIMAL"); + if (IsInputListCommand(input)) + { + ListKnownAnimals(rootBranch); + } + else if (IsInputYes(input)) + { + break; + } + } + + // Walk through the tree following the YES and NO + // branches based on user input. + Branch currentBranch = rootBranch; + while (!currentBranch.IsEnd) + { + while (true) + { + input = GetInput(currentBranch.Text); + if (IsInputYes(input)) + { + currentBranch = currentBranch.Yes; + break; + } + else if (IsInputNo(input)) + { + currentBranch = currentBranch.No; + break; + } + } + } + + // Was the answer correct? + input = GetInput($"IS IT A {currentBranch.Text}"); + if (IsInputYes(input)) + { + Console.WriteLine("WHY NOT TRY ANOTHER ANIMAL?"); + return; + } + + // Interview the user to add a new question and answer + // branch to the tree + string newAnimal = GetInput("THE ANIMAL YOU WERE THINKING OF WAS A"); + string newQuestion = GetInput($"PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A {newAnimal} FROM A {currentBranch.Text}"); + string newAnswer = null; + while (true) + { + newAnswer = GetInput($"FOR A {newAnimal} THE ANSWER WOULD BE"); + if (IsInputNo(newAnswer)) + { + currentBranch.No = new Branch { Text = newAnimal }; + currentBranch.Yes = new Branch { Text = currentBranch.Text }; + currentBranch.Text = newQuestion; + break; + } + else if (IsInputYes(newAnswer)) + { + currentBranch.Yes = new Branch { Text = newAnimal }; + currentBranch.No = new Branch { Text = currentBranch.Text }; + currentBranch.Text = newQuestion; + break; + } + } +} + +string GetInput(string prompt) +{ + Console.Write($"{prompt}? "); + string result = Console.ReadLine(); + if (string.IsNullOrWhiteSpace(result)) + { + return GetInput(prompt); + } + + return result.Trim().ToUpper(); +} + +bool IsInputYes(string input) => TRUE_INPUTS.Contains(input.ToUpperInvariant().Trim()); + +bool IsInputNo(string input) => FALSE_INPUTS.Contains(input.ToUpperInvariant().Trim()); + +bool IsInputListCommand(string input) => input.ToUpperInvariant().Trim() == "LIST"; + +string[] GetKnownAnimals(Branch branch) +{ + List result = new List(); + if (branch.IsEnd) + { + return new[] { branch.Text }; + } + else + { + result.AddRange(GetKnownAnimals(branch.Yes)); + result.AddRange(GetKnownAnimals(branch.No)); + return result.ToArray(); + } +} + +void ListKnownAnimals(Branch branch) +{ + string[] animals = GetKnownAnimals(branch); + for (int x = 0; x < animals.Length; x++) + { + int column = (x % 4); + if (column == 0) + { + Console.WriteLine(); + } + + Console.Write(new string(' ', column == 0 ? 0 : 15) + animals[x]); + } + Console.WriteLine(); +} diff --git a/05 Bagels/bagels.bas b/05 Bagels/bagels.bas index 3136955b..d16c20c3 100644 --- a/05 Bagels/bagels.bas +++ b/05 Bagels/bagels.bas @@ -3,7 +3,7 @@ 15 REM *** BAGLES NUMBER GUESSING GAME 20 REM *** ORIGINAL SOURCE UNKNOWN BUT SUSPECTED TO BE 25 REM *** LAWRENCE HALL OF SCIENCE, U.C. BERKELY -30 DIM A1(6),A(3),B(3) +30 DIM A1(3),A(3),B(3) 40 Y=0:T=255 50 PRINT:PRINT:PRINT 70 INPUT "WOULD YOU LIKE THE RULES (YES OR NO)";A$ @@ -66,7 +66,7 @@ 600 PRINT 605 NEXT I 610 PRINT "OH WELL." -615 PRINT "THAT'S TWNETY GUESSES. MY NUMBER WAS";100*A(1)+10*A(2)+A(3) +615 PRINT "THAT'S TWENTY GUESSES. MY NUMBER WAS";100*A(1)+10*A(2)+A(3) 620 GOTO 700 630 PRINT "TRY GUESSING A THREE-DIGIT NUMBER.":GOTO 230 650 PRINT "OH, I FORGOT TO TELL YOU THAT THE NUMBER I HAVE IN MIND" @@ -74,7 +74,7 @@ 680 PRINT "YOU GOT IT!!!":PRINT 690 Y=Y+1 700 INPUT "PLAY AGAIN (YES OR NO)";A$ -720 IF LEFT$(A$,1)="YES" THEN 150 +720 IF LEFT$(A$,1)="Y" THEN 150 730 IF Y=0 THEN 750 740 PRINT:PRINT "A";Y;"POINT BAGELS BUFF!!" 750 PRINT "HOPE YOU HAD FUN. BYE." diff --git a/05 Bagels/javascript/bagels.html b/05 Bagels/javascript/bagels.html new file mode 100644 index 00000000..714c3c9a --- /dev/null +++ b/05 Bagels/javascript/bagels.html @@ -0,0 +1,9 @@ + + +BAGELS + + +

+
+
+
diff --git a/05 Bagels/javascript/bagels.js b/05 Bagels/javascript/bagels.js
new file mode 100644
index 00000000..37fa3665
--- /dev/null
+++ b/05 Bagels/javascript/bagels.js	
@@ -0,0 +1,160 @@
+// BAGELS
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+print(tab(33) + "BAGELS\n");
+print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+
+// *** Bagles number guessing game
+// *** Original source unknown but suspected to be
+// *** Lawrence Hall of Science, U.C. Berkeley
+
+a1 = [0,0,0,0];
+a = [0,0,0,0];
+b = [0,0,0,0];
+
+y = 0;
+t = 255;
+
+print("\n");
+print("\n");
+print("\n");
+
+// Main program
+async function main()
+{
+    while (1) {
+        print("WOULD YOU LIKE THE RULES (YES OR NO)");
+        str = await input();
+        if (str.substr(0, 1) != "N") {
+            print("\n");
+            print("I AM THINKING OF A THREE-DIGIT NUMBER.  TRY TO GUESS\n");
+            print("MY NUMBER AND I WILL GIVE YOU CLUES AS FOLLOWS:\n");
+            print("   PICO   - ONE DIGIT CORRECT BUT IN THE WRONG POSITION\n");
+            print("   FERMI  - ONE DIGIT CORRECT AND IN THE RIGHT POSITION\n");
+            print("   BAGELS - NO DIGITS CORRECT\n");
+        }
+        for (i = 1; i <= 3; i++) {
+            do {
+                a[i] = Math.floor(Math.random() * 10);
+                for (j = i - 1; j >= 1; j--) {
+                    if (a[i] == a[j])
+                        break;
+                }
+            } while (j >= 1) ;
+        }
+        print("\n");
+        print("O.K.  I HAVE A NUMBER IN MIND.\n");
+        for (i = 1; i <= 20; i++) {
+            while (1) {
+                print("GUESS #" + i);
+                str = await input();
+                if (str.length != 3) {
+                    print("TRY GUESSING A THREE-DIGIT NUMBER.\n");
+                    continue;
+                }
+                for (z = 1; z <= 3; z++)
+                    a1[z] = str.charCodeAt(z - 1);
+                for (j = 1; j <= 3; j++) {
+                    if (a1[j] < 48 || a1[j] > 57)
+                        break;
+                    b[j] = a1[j] - 48;
+                }
+                if (j <= 3) {
+                    print("WHAT?");
+                    continue;
+                }
+                if (b[1] == b[2] || b[2] == b[3] || b[3] == b[1]) {
+                    print("OH, I FORGOT TO TELL YOU THAT THE NUMBER I HAVE IN MIND\n");
+                    print("HAS NO TWO DIGITS THE SAME.\n");
+                    continue;
+                }
+                break;
+            }
+            c = 0;
+            d = 0;
+            for (j = 1; j <= 2; j++) {
+                if (a[j] == b[j + 1])
+                    c++;
+                if (a[j + 1] == b[j])
+                    c++;
+            }
+            if (a[1] == b[3])
+                c++;
+            if (a[3] == b[1])
+                c++;
+            for (j = 1; j <= 3; j++) {
+                if (a[j] == b[j])
+                    d++;
+            }
+            if (d == 3)
+                break;
+            for (j = 0; j < c; j++)
+                print("PICO ");
+            for (j = 0; j < d; j++)
+                print("FERMI ");
+            if (c + d == 0)
+                print("BAGELS");
+            print("\n");
+        }
+        if (i <= 20) {
+            print("YOU GOT IT!!!\n");
+            print("\n");
+        } else {
+            print("OH WELL.\n");
+            print("THAT'S A TWENTY GUESS.  MY NUMBER WAS " + a[1] + a[2] + a[3]);
+        }
+        y++;
+        print("PLAY AGAIN (YES OR NO)");
+        str = await input();
+        if (str.substr(0, 1) != "Y")
+            break;
+    }
+    if (y == 0)
+        print("HOPE YOU HAD FUN.  BYE.\n");
+    else
+        print("\nA " + y + " POINT BAGELS BUFF!!\n");
+    
+}
+
+main();
diff --git a/06 Banner/javascript/banner.html b/06 Banner/javascript/banner.html
new file mode 100644
index 00000000..62f1bca8
--- /dev/null
+++ b/06 Banner/javascript/banner.html	
@@ -0,0 +1,9 @@
+
+
+BANNER
+
+
+

+
+
+
diff --git a/06 Banner/javascript/banner.js b/06 Banner/javascript/banner.js
new file mode 100644
index 00000000..ca360487
--- /dev/null
+++ b/06 Banner/javascript/banner.js	
@@ -0,0 +1,168 @@
+// BANNER
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var letters = [" ",0,0,0,0,0,0,0,
+               "A",505,37,35,34,35,37,505,
+               "G",125,131,258,258,290,163,101,
+               "E",512,274,274,274,274,258,258,
+               "T",2,2,2,512,2,2,2,
+               "W",256,257,129,65,129,257,256,
+               "L",512,257,257,257,257,257,257,
+               "S",69,139,274,274,274,163,69,
+               "O",125,131,258,258,258,131,125,
+               "N",512,7,9,17,33,193,512,
+               "F",512,18,18,18,18,2,2,
+               "K",512,17,17,41,69,131,258,
+               "B",512,274,274,274,274,274,239,
+               "D",512,258,258,258,258,131,125,
+               "H",512,17,17,17,17,17,512,
+               "M",512,7,13,25,13,7,512,
+               "?",5,3,2,354,18,11,5,
+               "U",128,129,257,257,257,129,128,
+               "R",512,18,18,50,82,146,271,
+               "P",512,18,18,18,18,18,15,
+               "Q",125,131,258,258,322,131,381,
+               "Y",8,9,17,481,17,9,8,
+               "V",64,65,129,257,129,65,64,
+               "X",388,69,41,17,41,69,388,
+               "Z",386,322,290,274,266,262,260,
+               "I",258,258,258,512,258,258,258,
+               "C",125,131,258,258,258,131,69,
+               "J",65,129,257,257,257,129,128,
+               "1",0,0,261,259,512,257,257,
+               "2",261,387,322,290,274,267,261,
+               "*",69,41,17,512,17,41,69,
+               "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,
+               "=",41,41,41,41,41,41,41,
+               "!",1,1,1,384,1,1,1,
+               "0",57,69,131,258,131,69,57,
+               ".",1,1,129,449,129,1,1];
+
+f = [];
+j = [];
+s = [];
+
+// Main program
+async function main()
+{
+    print("HORIZONTAL");
+    x = parseInt(await input());
+    print("VERTICAL");
+    y = parseInt(await input());
+    print("CENTERED");
+    ls = await input();
+    g1 = 0;
+    if (ls > "P")
+        g1 = 1;
+    print("CHARACTER (TYPE 'ALL' IF YOU WANT CHARACTER BEING PRINTED)");
+    ms = await input();
+    print("STATEMENT");
+    as = await input();
+    print("SET PAGE");	// This means to prepare printer, just press Enter
+    os = await input();
+    
+    for (t = 0; t < as.length; t++) {
+        ps = as.substr(t, 1);
+        for (o = 0; o < 50 * 8; o += 8) {
+            if (letters[o] == ps) {
+                for (u = 1; u <= 7; u++)
+                    s[u] = letters[o + u];
+                break;
+            }
+        }
+        if (o == 50 * 8) {
+            ps = " ";
+            o = 0;
+        }
+//      print("Doing " + o + "\n");
+        if (o == 0) {
+            for (h = 1; h <= 7 * x; h++)
+                print("\n");
+        } else {
+            xs = ms;
+            if (ms == "ALL")
+                xs = ps;
+            for (u = 1; u <= 7; u++) {
+                // An inefficient way of extracting bits
+                // but good enough in BASIC because there
+                // aren't bit shifting operators.
+                for (k = 8; k >= 0; k--) {
+                    if (Math.pow(2, k) >= s[u]) {
+                        j[9 - k] = 0;
+                    } else {
+                        j[9 - k] = 1;
+                        s[u] -= Math.pow(2, k);
+                        if (s[u] == 1) {
+                            f[u] = 9 - k;
+                            break;
+                        }
+                    }
+                }
+                for (t1 = 1; t1 <= x; t1++) {
+                    str = tab((63 - 4.5 * y) * g1 / xs.length + 1);
+                    for (b = 1; b <= f[u]; b++) {
+                        if (j[b] == 0) {
+                            for (i = 1; i <= y; i++)
+                                str += tab(xs.length);
+                        } else {
+                            for (i = 1; i <= y; i++)
+                                str += xs;
+                        }
+                    }
+                    print(str + "\n");	
+                }
+            }
+            for (h = 1; h <= 2 * x; h++) 
+                print("\n");
+        }
+    }    
+}
+
+main();
diff --git a/18 Bullseye/java/src/Bullseye.java b/18 Bullseye/java/src/Bullseye.java
new file mode 100644
index 00000000..06090351
--- /dev/null
+++ b/18 Bullseye/java/src/Bullseye.java	
@@ -0,0 +1,248 @@
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class Bullseye {
+
+    public static final int FIRST_IDENT = 10;
+    public static final int SECOND_IDENT = 30;
+    public static final int THIRD_INDENT = 30;
+
+    public static final double[] SHOT_ONE = new double[] { .65, .55, .5, .5};
+    public static final double[] SHOT_TWO = new double[] { .99, .77, .43,.01};
+    public static final double[] SHOT_THREE = new double[] { .95, .75, .45, .05 };
+
+    private enum GAME_STATE {
+        STARTING,
+        START_GAME,
+        PLAYING,
+        GAME_OVER
+    }
+
+    private GAME_STATE gameState;
+
+    private ArrayList players;
+
+    private Shot[] shots;
+
+    // Used for keyboard input
+    private Scanner kbScanner;
+
+    private int numberOfPlayers;
+
+    private int round;
+
+    public Bullseye() {
+
+        gameState = GAME_STATE.STARTING;
+        players = new ArrayList<>();
+
+        // Save the random chances of points based on shot type
+
+        shots = new Shot[3];
+        shots[0] = new Shot(SHOT_ONE);
+        shots[1] = new Shot(SHOT_TWO);
+        shots[2] = new Shot(SHOT_THREE);
+
+        // Initialise kb scanner
+        kbScanner = new Scanner(System.in);
+    }
+
+    /**
+     * Main game loop
+     *
+     */
+    public void play() {
+
+        do {
+            switch (gameState) {
+
+                // Show an introduction the first time the game is played.
+                case STARTING:
+                    intro();
+                    gameState = GAME_STATE.START_GAME;
+                    break;
+
+                // Start the game, set the number of players, names and round
+                case START_GAME:
+
+                    this.numberOfPlayers = chooseNumberOfPlayers();
+
+                    for(int i=0; i= p1) {
+            System.out.println("BULLSEYE!!  40 POINTS!");
+            points = 40;
+            // If the throw was 1 (bullseye or missed, then make it missed
+            // N.B. This is a fix for the basic code which for shot type 1
+            // allowed a bullseye but did not make the score zero if a bullseye
+            // was not made (which it should have done).
+        } else if (playerThrow == 1) {
+            System.out.println("MISSED THE TARGET!  TOO BAD.");
+            points = 0;
+        } else if(random >= p2) {
+            System.out.println("30-POINT ZONE!");
+            points = 30;
+        } else if(random >= p3) {
+            System.out.println("20-POINT ZONE");
+            points = 20;
+        } else if(random >= p4) {
+            System.out.println("WHEW!  10 POINTS.");
+            points = 10;
+        } else {
+            System.out.println("MISSED THE TARGET!  TOO BAD.");
+            points = 0;
+        }
+
+        return points;
+    }
+
+    /**
+     * Get players shot 1,2, or 3 - ask again if invalid input
+     *
+     * @param player
+     * @return 1,2, or 3 indicating the players shot
+     */
+    private int getPlayersThrow(Player player) {
+        boolean inputCorrect = false;
+        String theThrow;
+        do {
+            theThrow = displayTextAndGetInput(player.getName() + "'S THROW ");
+            if(theThrow.equals("1") || theThrow.equals("2") || theThrow.equals("3")) {
+                inputCorrect = true;
+            } else {
+                System.out.println("INPUT 1, 2, OR 3!");
+            }
+
+        } while(!inputCorrect);
+
+        return Integer.valueOf(theThrow);
+    }
+
+
+    /**
+     * Get players guess from kb
+     *
+     * @return players guess as an int
+     */
+    private int chooseNumberOfPlayers() {
+
+        return Integer.valueOf((displayTextAndGetInput("HOW MANY PLAYERS? ")));
+    }
+    /*
+     * Print a message on the screen, then accept input from Keyboard.
+     *
+     * @param text message to be displayed on screen.
+     * @return what was typed by the player.
+     */
+    private String displayTextAndGetInput(String text) {
+        System.out.print(text);
+        return kbScanner.next();
+    }
+
+    /**
+     * Format three strings to a given number of spaces
+     * Replacing the original basic code which used tabs
+     *
+     * @param first String to print in pos 1
+     * @param second String to print in pos 2
+     * @param third String to print in pos 3
+     * @return formatted string
+     */
+    private String paddedString(String first, String second, String third) {
+        String output = String.format("%1$" + FIRST_IDENT + "s", first);
+        output += String.format("%1$" + SECOND_IDENT + "s", second);
+        output += String.format("%1$" + THIRD_INDENT + "s", third);
+        return output;
+    }
+}
diff --git a/18 Bullseye/java/src/BullseyeGame.java b/18 Bullseye/java/src/BullseyeGame.java
new file mode 100644
index 00000000..19be8fec
--- /dev/null
+++ b/18 Bullseye/java/src/BullseyeGame.java	
@@ -0,0 +1,8 @@
+public class BullseyeGame {
+
+    public static void main(String[] args) {
+
+        Bullseye bullseye = new Bullseye();
+        bullseye.play();
+    }
+}
diff --git a/18 Bullseye/java/src/Player.java b/18 Bullseye/java/src/Player.java
new file mode 100644
index 00000000..b67b9309
--- /dev/null
+++ b/18 Bullseye/java/src/Player.java	
@@ -0,0 +1,26 @@
+/**
+ * A Player in the game - consists of name and score
+ *
+ */
+public class Player {
+
+    private String name;
+    private int score;
+
+    Player(String name) {
+        this.name = name;
+        this.score = 0;
+    }
+
+    public void addScore(int score) {
+        this.score += score;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getScore() {
+        return score;
+    }
+}
diff --git a/18 Bullseye/java/src/Shot.java b/18 Bullseye/java/src/Shot.java
new file mode 100644
index 00000000..01d8b283
--- /dev/null
+++ b/18 Bullseye/java/src/Shot.java	
@@ -0,0 +1,21 @@
+/**
+ * This class records the percentage chance of a given type of shot
+ * scoring specific points
+ * see Bullseye class points calculation method where its used
+ */
+public class Shot {
+
+    double[] chances;
+
+    // Array of doubles are passed for a specific type of shot
+    Shot(double[] shots) {
+        chances = new double[shots.length];
+        for(int i=0; i
+
+  
+    Exe
+    net5.0
+  
+
+
diff --git a/24 Chemist/csharp/Chemist/Chemist/Program.cs b/24 Chemist/csharp/Chemist/Chemist/Program.cs
new file mode 100644
index 00000000..64466bff
--- /dev/null
+++ b/24 Chemist/csharp/Chemist/Chemist/Program.cs	
@@ -0,0 +1,49 @@
+using System;
+const int maxLives = 9;
+
+WriteCentred("Chemist");
+WriteCentred("Creative Computing, Morristown, New Jersey");
+Console.WriteLine(@"
+
+
+The fictitious chemical kryptocyanic acid can only be
+diluted by the ratio of 7 parts water to 3 parts acid.
+If any other ratio is attempted, the acid becomes unstable
+and soon explodes.  Given the amount of acid, you must
+decide who much water to add for dilution.  If you miss
+you face the consequences.
+");
+
+var random = new Random();
+int livesUsed = 0;
+while (livesUsed < maxLives)
+{
+    int krypto = random.Next(1, 50);
+    double water = krypto * 7.0 / 3.0;
+
+    Console.WriteLine($"{krypto} Liters of kryptocyanic acid.  How much water?");
+    double answer = double.Parse(Console.ReadLine());
+
+    double diff = Math.Abs(answer - water);
+    if (diff <= water / 20)
+    {
+        Console.WriteLine("Good job! You may breathe now, but don't inhale the fumes"!);
+        Console.WriteLine();
+    }
+    else
+    {
+        Console.WriteLine("Sizzle!  You have just been desalinated into a blob\nof quivering protoplasm!");
+        Console.WriteLine();
+        livesUsed++;
+
+        if (livesUsed < maxLives)
+            Console.WriteLine("However, you may try again with another life.");
+    }
+}
+Console.WriteLine($"Your {maxLives} lives are used, but you will be long remembered for\nyour contributions to the field of comic book chemistry.");
+
+static void WriteCentred(string text)
+{
+    int indent = (Console.WindowWidth + text.Length) / 2;
+    Console.WriteLine($"{{0,{indent}}}", text);
+}
diff --git a/25 Chief/java/src/Chief.java b/25 Chief/java/src/Chief.java
new file mode 100644
index 00000000..d7fbbc08
--- /dev/null
+++ b/25 Chief/java/src/Chief.java	
@@ -0,0 +1,196 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+public class Chief {
+
+    private enum GAME_STATE {
+        STARTING,
+        READY_TO_START,
+        ENTER_NUMBER,
+        CALCULATE_AND_SHOW,
+        END_GAME,
+        GAME_OVER
+    }
+
+    private GAME_STATE gameState;
+
+    private double calculatedNumber;
+
+    // Used for keyboard input
+    private final Scanner kbScanner;
+
+    public Chief() {
+
+        gameState = GAME_STATE.STARTING;
+
+        // Initialise kb scanner
+        kbScanner = new Scanner(System.in);
+    }
+
+    /**
+     * Main game loop
+     */
+    public void play() {
+
+        do {
+            switch (gameState) {
+
+                // Show an introduction the first time the game is played.
+                case STARTING:
+                    intro();
+                    gameState = GAME_STATE.READY_TO_START;
+                    break;
+
+                // show an message to start
+                case READY_TO_START:
+                    if(!yesEntered(displayTextAndGetInput("ARE YOU READY TO TAKE THE TEST YOU CALLED ME OUT FOR? "))) {
+                        System.out.println("SHUT UP, PALE FACE WITH WISE TONGUE.");
+                    }
+
+                    instructions();
+                    gameState = GAME_STATE.ENTER_NUMBER;
+                    break;
+
+                // Enter the number to be used to calculate
+                case ENTER_NUMBER:
+                    double playerNumber = Double.parseDouble(
+                            displayTextAndGetInput(" WHAT DO YOU HAVE? "));
+
+                    // Exact same formula used in the original game to calculate the players original number
+                    this.calculatedNumber = (playerNumber +1-5)*5/8*5-3;
+
+                    this.gameState = GAME_STATE.CALCULATE_AND_SHOW;
+                    break;
+
+                // Enter the number to be used to calculate
+                case CALCULATE_AND_SHOW:
+                    if(yesEntered(
+                            displayTextAndGetInput("I BET YOUR NUMBER WAS " + this.calculatedNumber
+                            + ". AM I RIGHT? "))) {
+                        this.gameState = GAME_STATE.END_GAME;
+
+                    } else {
+                        // Player did not agree, so show the breakdown
+                        double number = Double.parseDouble(
+                                displayTextAndGetInput(" WHAT WAS YOUR ORIGINAL NUMBER? "));
+                        double f = number + 3;
+                        double g = f / 5;
+                        double h = g * 8;
+                        double i = h/5 + 5;
+                        double j = i -1;
+                        System.out.println("SO YOU THINK YOU'RE SO SMART, EH?");
+                        System.out.println("NOW WATCH.");
+                        System.out.println(number +" PLUS 3 EQUALS " + f +  ". THIS DIVIDED BY 5 EQUALS " + g);
+                        System.out.println("THIS TIMES 8 EQUALS " + h + ". IF WE DIVIDE BY 5 AND ADD 5,");
+                        System.out.println("WE GET " + i + ", WHICH, MINUS 1, EQUALS " + j + ".");
+                        if(yesEntered(displayTextAndGetInput("NOW DO YOU BELIEVE ME? "))) {
+                            this.gameState = GAME_STATE.END_GAME;
+                        } else {
+                            // Time for a lightning bolt.
+                            System.out.println("YOU HAVE MADE ME MAD!!!");
+                            System.out.println("THERE MUST BE A GREAT LIGHTNING BOLT!");
+                            System.out.println();
+                            for(int x=30; x>=22; x--) {
+                                System.out.println(tabbedSpaces(x) + "X X");
+                            }
+                            System.out.println(tabbedSpaces(21) + "X XXX");
+                            System.out.println(tabbedSpaces(20) + "X   X");
+                            System.out.println(tabbedSpaces(19) + "XX X");
+                            for(int y=20; y>=13; y--) {
+                                System.out.println(tabbedSpaces(y) + "X X");
+                            }
+                            System.out.println(tabbedSpaces(12) + "XX");
+                            System.out.println(tabbedSpaces(11) + "X");
+                            System.out.println(tabbedSpaces(10) + "*");
+                            System.out.println();
+                            System.out.println("#########################");
+                            System.out.println();
+                            System.out.println("I HOPE YOU BELIEVE ME NOW, FOR YOUR SAKE!!");
+                            this.gameState = GAME_STATE.GAME_OVER;
+                        }
+
+                    }
+                    break;
+
+                // Sign off message for cases where the Chief is not upset
+                case END_GAME:
+                    System.out.println("BYE!!!");
+                    this.gameState = GAME_STATE.GAME_OVER;
+                    break;
+
+                // GAME_OVER State does not specifically have a case
+            }
+        } while (gameState != GAME_STATE.GAME_OVER);
+    }
+
+    /**
+     * Simulate tabs by building up a string of spaces
+     *
+     * @param spaces how many spaces are there to be
+     * @return a string with the requested number of spaces
+     */
+    private String tabbedSpaces(int spaces) {
+        char[] repeat = new char[spaces];
+        Arrays.fill(repeat, ' ');
+        return new String(repeat);
+    }
+    private void instructions() {
+        System.out.println(" TAKE A NUMBER AND ADD 3. DIVIDE THIS NUMBER BY 5 AND");
+        System.out.println("MULTIPLY BY 8. DIVIDE BY 5 AND ADD THE SAME. SUBTRACT 1.");
+    }
+
+    /**
+     * Basic information about the game
+     *
+     */
+    private void intro() {
+        System.out.println("CHIEF");
+        System.out.println("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+        System.out.println();
+        System.out.println("I AM CHIEF NUMBERS FREEK, THE GREAT INDIAN MATH GOD.");
+    }
+
+    /**
+     * Returns true if a given string is equal to at least one of the values specified in the call
+     * to the stringIsAnyValue method
+     *
+     * @param text string to search
+     * @return true if string is equal to one of the varargs
+     */
+    private boolean yesEntered(String text) {
+        return stringIsAnyValue(text, "Y", "YES");
+    }
+
+    /**
+     * Returns true if a given string contains at least one of the varargs (2nd parameter).
+     * Note: Case insensitive comparison.
+     *
+     * @param text string to search
+     * @param values varargs of type string containing values to compare
+     * @return true if one of the varargs arguments was found in text
+     */
+    private boolean stringIsAnyValue(String text, String... values) {
+
+        // Cycle through the variable number of values and test each
+        for(String val:values) {
+            if(text.equalsIgnoreCase(val)) {
+                return true;
+            }
+        }
+
+        // no matches
+        return false;
+    }
+
+    /*
+     * Print a message on the screen, then accept input from Keyboard.
+     *
+     * @param text message to be displayed on screen.
+     * @return what was typed by the player.
+     */
+    private String displayTextAndGetInput(String text) {
+        System.out.print(text);
+        return kbScanner.next();
+    }
+
+}
\ No newline at end of file
diff --git a/25 Chief/java/src/ChiefGame.java b/25 Chief/java/src/ChiefGame.java
new file mode 100644
index 00000000..25ebc1bc
--- /dev/null
+++ b/25 Chief/java/src/ChiefGame.java	
@@ -0,0 +1,8 @@
+public class ChiefGame {
+
+    public static void main(String[] args) {
+
+        Chief chief = new Chief();
+        chief.play();
+    }
+}
\ No newline at end of file
diff --git a/44 Hangman/python/hangman.py b/44 Hangman/python/hangman.py
index 0387e267..2b42a121 100755
--- a/44 Hangman/python/hangman.py	
+++ b/44 Hangman/python/hangman.py	
@@ -1,6 +1,11 @@
 #!/usr/bin/env python3
+# HANGMAN
+#
+# Converted from BASIC to Python by Trevor Hobson and Daniel Piron
+
 import random
 
+
 class Canvas:
     ''' For drawing text-based figures '''
 
@@ -33,6 +38,14 @@ class Canvas:
         self._buffer[y][x] = s[0]
 
 
+def draw_gallows(canvas):
+    for i in range(12):
+        canvas.put('X', 0, i)
+    for i in range(7):
+        canvas.put('X', i, 0)
+    canvas.put('X', 6, 1)
+
+
 def draw_head(canvas):
     canvas.put('-', 5, 2)
     canvas.put('-', 6, 2)
@@ -46,14 +59,6 @@ def draw_head(canvas):
     canvas.put('-', 7, 4)
 
 
-def draw_gallows(canvas):
-    for i in range(12):
-        canvas.put('X', 0, i)
-    for i in range(7):
-        canvas.put('X', i, 0)
-    canvas.put('X', 6, 1)
-
-
 def draw_body(canvas):
     for i in range(5, 9, 1):
         canvas.put('X', 6, i)
@@ -100,112 +105,109 @@ def draw_right_foot(canvas):
 
 
 PHASES = (
-    ("FIRST, WE DRAW A HEAD", draw_head),
-    ("NOW WE DRAW A BODY.", draw_body),
-    ("NEXT WE DRAW AN ARM.", draw_right_arm),
-    ("THIS TIME IT'S THE OTHER ARM.", draw_left_arm),
-    ("NOW, LET'S DRAW THE RIGHT LEG.", draw_right_leg),
-    ("THIS TIME WE DRAW THE LEFT LEG.", draw_left_leg),
-    ("NOW WE PUT UP A HAND.", draw_left_hand),
-    ("NEXT THE OTHER HAND.", draw_right_hand),
-    ("NOW WE DRAW ONE FOOT", draw_left_foot),
-    ("HERE'S THE OTHER FOOT -- YOU'RE HUNG!!", draw_right_foot)
+    ("First, we draw a head", draw_head),
+    ("Now we draw a body.", draw_body),
+    ("Next we draw an arm.", draw_right_arm),
+    ("this time it's the other arm.", draw_left_arm),
+    ("Now, let's draw the right leg.", draw_right_leg),
+    ("This time we draw the left leg.", draw_left_leg),
+    ("Now we put up a hand.", draw_left_hand),
+    ("Next the other hand.", draw_right_hand),
+    ("Now we draw one foot", draw_left_foot),
+    ("Here's the other foot -- you're hung!!", draw_right_foot)
 )
 
-WORDS = ('GUM','SIN','FOR','CRY','LUG','BYE','FLY',
-         'UGLY','EACH','FROM','WORK','TALK','WITH','SELF',
-         'PIZZA','THING','FEIGN','FIEND','ELBOW','FAULT','DIRTY',
-         'BUDGET','SPIRIT','QUAINT','MAIDEN','ESCORT','PICKAX',
-         'EXAMPLE','TENSION','QUININE','KIDNEY','REPLICA','SLEEPER',
-         'TRIANGLE','KANGAROO','MAHOGANY','SERGEANT','SEQUENCE',
-         'MOUSTACHE','DANGEROUS','SCIENTIST','DIFFERENT','QUIESCENT',
-         'MAGISTRATE','ERRONEOUSLY','LOUDSPEAKER','PHYTOTOXIC',
-         'MATRIMONIAL','PARASYMPATHOMIMETIC','THIGMOTROPISM')
 
-QUESTION_PROMPT = '? '
+print(" " * 32 + "HANGMAN")
+print(" " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n")
+
+words = ["GUM", "SIN", "FOR", "CRY", "LUG", "BYE", "FLY",
+         "UGLY", "EACH", "FROM", "WORK", "TALK", "WITH", "SELF",
+         "PIZZA", "THING", "FEIGN", "FIEND", "ELBOW", "FAULT", "DIRTY",
+         "BUDGET", "SPIRIT", "QUAINT", "MAIDEN", "ESCORT", "PICKAX",
+         "EXAMPLE", "TENSION", "QUININE", "KIDNEY", "REPLICA", "SLEEPER",
+         "TRIANGLE", "KANGAROO", "MAHOGANY", "SERGEANT", "SEQUENCE",
+         "MOUSTACHE", "DANGEROUS", "SCIENTIST", "DIFFERENT", "QUIESCENT",
+         "MAGISTRATE", "ERRONEOUSLY", "LOUDSPEAKER", "PHYTOTOXIC",
+         "MATRIMONIAL", "PARASYMPATHOMIMETIC", "THIGMOTROPISM"]
 
 
-def revealed_word(word, letters_used):
-    return ''.join(letter if letter in letters_used else '-'
-                  for letter in word)
+def play_game(guessTarget):
+    """Play the game"""
+    guessWrong = 0
+    guessProgress = ["-"] * len(guessTarget)
+    guessList = []
 
+    gallows = Canvas()
+    draw_gallows(gallows)
 
-def play():
-
-    print('HANGMAN')
-    print('CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n\n\n')
-
-    words_available = set(WORDS)
+    guessCount = 0
     while True:
-
-        if len(words_available) == 0:
-            print('YOU DID ALL THE WORDS!!')
-            break
-
-        # Initize game state for this round
-        canvas = Canvas()
-        draw_gallows(canvas)
-
-        word = random.choice(list(words_available))
-        letters_used = set()
-        guesses_count = 0
-        fail_count = 0
-
-        while True:
-            print('HERE ARE THE LETTERS YOU USED:')
-            print(', '.join(sorted(letters_used)))
-            print('\n')
-
-            print(revealed_word(word, letters_used))
-            print('\n')
-
-            print('WHAT IS YOUR GUESS', end=QUESTION_PROMPT)
-            guess = input().upper()
-
-            if guess in letters_used:
-                print('YOU GUESSED THAT LETTER BEFORE!')
-                continue
-
-            guesses_count += 1
-
-            if guess not in word:
-                comment, draw_function = PHASES[fail_count]
-                print('\n\nSORRY, THAT LETTER ISN\'T IN THE WORD.')
-                print(comment)
-                draw_function(canvas)
-                print(canvas.render())
-
-                fail_count += 1
-                if fail_count == len(PHASES):
-                   print('SORRY, YOU LOSE.  THE WORD WAS', word)
-                   print('YOU MISSED THAT ONE.  DO YOU', end=' ')
-                   break
-
-            letters_used.add(guess)
-            if '-' not in revealed_word(word, letters_used):
-                print("YOU FOUND THE WORD!")
-                words_available.remove(word)
+        print("Here are the letters you used:")
+        print(",".join(guessList) + "\n")
+        print("".join(guessProgress) + "\n")
+        guessLetter = ""
+        guessWord = ""
+        while guessLetter == "":
+            guessLetter = input("What is your guess? ").upper()[0]
+            if not guessLetter.isalpha():
+                guessLetter = ""
+                print("Only letters are allowed!")
+            elif guessLetter in guessList:
+                guessLetter = ""
+                print("You guessed that letter before!")
+        guessList.append(guessLetter)
+        guessCount = guessCount + 1
+        if guessLetter in guessTarget:
+            indices = [i for i, letter in enumerate(guessTarget) if letter == guessLetter]
+            for i in indices:
+                guessProgress[i] = guessLetter
+            if guessProgress == guessTarget:
+                print("You found the word!")
                 break
             else:
-                print('\n' + revealed_word(word, letters_used))
-                print('\n\nWHAT IS YOUR GUESS FOR THE WORD', end=QUESTION_PROMPT)
-                guessed_word = input().upper()
+                print("\n" + "".join(guessProgress) + "\n")
+                while guessWord == "":
+                    guessWord = input("What is your guess for the word? ").upper()
+                    if not guessWord.isalpha():
+                        guessWord = ""
+                        print("Only words are allowed!")
+                if guessWord == guessTarget:
+                    print("Right!! It took you", guessCount, "guesses!")
+                    break
+        else:
+            comment, drawingBodyPart = PHASES[guessWrong]
 
-                if guessed_word != word:
-                    print('WRONG.  TRY ANOTHER LETTER.\n')
-                    continue
+            print(comment)
+            drawingBodyPart(gallows)
+            print(gallows.render())
 
-                print('RIGHT!!  IT TOOK YOU {} GUESSES!'.format(guesses_count))
-                words_available.remove(word)
+            guessWrong = guessWrong + 1
+            print("Sorry, that letter isn't in the word.")
+
+            if guessWrong == 10:
+                print("Sorry, you lose. The word was " + guessTarget)
                 break
 
-        print('WANT ANOTHER WORD', end=QUESTION_PROMPT)
-        reply = input().upper()
-        if reply != 'YES':
-            break
 
-    print('\nIT\'S BEEN FUN!  BYE FOR NOW.')
+def main():
+    """Main"""
+
+    random.shuffle(words)
+    wordCurrent = 0
+    wordCount = 49
+
+    keep_playing = True
+    while keep_playing:
+        play_game(words[wordCurrent])
+        wordCurrent = wordCurrent + 1
+        if wordCurrent >= wordCount:
+            print("You did all the words!!")
+            keep_playing = False
+        else:
+            keep_playing = input("Want another word? (yes or no) ").lower().startswith("y")
+    print("It's been fun! Bye for now.")
 
 
-if __name__ == '__main__':
-    play()
+if __name__ == "__main__":
+    main()
diff --git a/47 Hi-Lo/java/src/HiLo.java b/47 Hi-Lo/java/src/HiLo.java
new file mode 100644
index 00000000..36f44ee5
--- /dev/null
+++ b/47 Hi-Lo/java/src/HiLo.java	
@@ -0,0 +1,214 @@
+import java.util.Scanner;
+
+/**
+ * Game of HiLo
+ *
+ * Based on the Basic game of Hi-Lo here
+ * https://github.com/coding-horror/basic-computer-games/blob/main/47%20Hi-Lo/hi-lo.bas
+ *
+ * Note:  The idea was to create a version of this 1970's Basic game in Java, without introducing
+ *        new features - no additional text, error checking, etc has been added.
+ */
+public class HiLo {
+
+    public static final int LOW_NUMBER_RANGE = 1;
+    public static final int HIGH_NUMBER_RANGE = 100;
+    public static final int MAX_GUESSES = 6;
+
+    private enum GAME_STATE {
+        STARTING,
+        START_GAME,
+        GUESSING,
+        PLAY_AGAIN,
+        GAME_OVER
+    }
+
+    // Used for keyboard input
+    private Scanner kbScanner;
+
+    // Current game state
+    private GAME_STATE gameState;
+
+    // Players Winnings
+    private int playerAmountWon;
+
+    // Players guess count;
+    private int playersGuesses;
+
+    // Computers random number
+    private int computersNumber;
+
+    public HiLo() {
+
+        this.gameState = GAME_STATE.STARTING;
+        this.playerAmountWon = 0;
+
+        // Initialise kb scanner
+        kbScanner = new Scanner(System.in);
+    }
+
+    /**
+     * Main game loop
+     *
+     */
+    public void play() {
+
+        do {
+            switch (gameState) {
+
+                // Show an introduction the first time the game is played.
+                case STARTING:
+                    intro();
+                    gameState = GAME_STATE.START_GAME;
+                    break;
+
+                // Generate computers number for player to guess, etc.
+                case START_GAME:
+                    init();
+                    System.out.println("O.K.  I HAVE A NUMBER IN MIND.");
+                    this.gameState = GAME_STATE.GUESSING;
+                    break;
+
+                // Player guesses the number until they get it or run out of guesses
+                case GUESSING:
+                    int guess = playerGuess();
+
+                    // Check if the player guessed the number
+                    if(validateGuess(guess)) {
+                        System.out.println("GOT IT!!!!!!!!!!   YOU WIN " + this.computersNumber
+                                + " DOLLARS.");
+                        this.playerAmountWon += this.computersNumber;
+                        System.out.println("YOUR TOTAL WINNINGS ARE NOW "
+                                + this.playerAmountWon + " DOLLARS.");
+                        this.gameState = GAME_STATE.PLAY_AGAIN;
+                    } else {
+                        // incorrect guess
+                        this.playersGuesses++;
+                        // Ran out of guesses?
+                        if (this.playersGuesses == MAX_GUESSES) {
+                            System.out.println("YOU BLEW IT...TOO BAD...THE NUMBER WAS "
+                                    + this.computersNumber);
+                            this.playerAmountWon = 0;
+                            this.gameState = GAME_STATE.PLAY_AGAIN;
+                        }
+                    }
+                    break;
+
+                // Play again, or exit game?
+                case PLAY_AGAIN:
+                    System.out.println();
+                    if(yesEntered(displayTextAndGetInput("PLAY AGAIN (YES OR NO) "))) {
+                        this.gameState = GAME_STATE.START_GAME;
+                    } else {
+                        // Chose not to play again
+                        System.out.println("SO LONG.  HOPE YOU ENJOYED YOURSELF!!!");
+                        this.gameState = GAME_STATE.GAME_OVER;
+                    }
+            }
+        } while (gameState != GAME_STATE.GAME_OVER);
+    }
+
+    /**
+     * Checks the players guess against the computers randomly generated number
+     *
+     * @param theGuess
+     * @return true if the player guessed correctly, false otherwise
+     */
+    private boolean validateGuess(int theGuess) {
+
+        // Correct guess?
+        if(theGuess == this.computersNumber) {
+            return true;
+        }
+
+        if(theGuess > this.computersNumber) {
+            System.out.println("YOUR GUESS IS TOO HIGH.");
+        } else {
+            System.out.println("YOUR GUESS IS TOO LOW.");
+        }
+
+        return false;
+    }
+
+    private void init() {
+        this.playersGuesses = 0;
+        this.computersNumber = randomNumber();
+    }
+
+    public void intro() {
+        System.out.println("HI LO");
+        System.out.println("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+        System.out.println();
+        System.out.println();
+        System.out.println("THIS IS THE GAME OF HI LO.");
+        System.out.println();
+        System.out.println("YOU WILL HAVE 6 TRIES TO GUESS THE AMOUNT OF MONEY IN THE");
+        System.out.println("HI LO JACKPOT, WHICH IS BETWEEN 1 AND 100 DOLLARS.  IF YOU");
+        System.out.println("GUESS THE AMOUNT, YOU WIN ALL THE MONEY IN THE JACKPOT!");
+        System.out.println("THEN YOU GET ANOTHER CHANCE TO WIN MORE MONEY.  HOWEVER,");
+        System.out.println("IF YOU DO NOT GUESS THE AMOUNT, THE GAME ENDS.");
+    }
+
+    /**
+     * Get players guess from kb
+     *
+     * @return players guess as an int
+     */
+    private int playerGuess() {
+        return Integer.valueOf((displayTextAndGetInput("YOUR GUESS? ")));
+    }
+
+    /**
+     * Checks whether player entered Y or YES to a question.
+     *
+     * @param text  player string from kb
+     * @return true of Y or YES was entered, otherwise false
+     */
+    private boolean yesEntered(String text) {
+        return stringIsAnyValue(text, new String[] {"Y", "YES"});
+    }
+
+    /**
+     * Check whether a string equals one of a variable number of values
+     * Useful to check for Y or YES for example
+     * Comparison is case insensitive.
+     *
+     * @param text source string
+     * @param values a range of values to compare against the source string
+     * @return true if a comparison was found in one of the variable number of strings passed
+     */
+    private boolean stringIsAnyValue(String text, String... values) {
+
+        // Cycle through the variable number of values and test each
+        for(String val:values) {
+            if(text.equalsIgnoreCase(val)) {
+                return true;
+            }
+        }
+
+        // no matches
+        return false;
+    }
+
+    /*
+     * Print a message on the screen, then accept input from Keyboard.
+     *
+     * @param text message to be displayed on screen.
+     * @return what was typed by the player.
+     */
+    private String displayTextAndGetInput(String text) {
+        System.out.print(text);
+        return kbScanner.next();
+    }
+
+    /**
+     * Generate random number
+     * Used as a single digit of the computer player
+     *
+     * @return random number
+     */
+    private int randomNumber() {
+        return (int) (Math.random()
+                * (HIGH_NUMBER_RANGE - LOW_NUMBER_RANGE + 1) + LOW_NUMBER_RANGE);
+    }
+}
\ No newline at end of file
diff --git a/47 Hi-Lo/java/src/HiLoGame.java b/47 Hi-Lo/java/src/HiLoGame.java
new file mode 100644
index 00000000..314606c4
--- /dev/null
+++ b/47 Hi-Lo/java/src/HiLoGame.java	
@@ -0,0 +1,8 @@
+public class HiLoGame {
+
+    public static void main(String[] args) {
+
+        HiLo hiLo = new HiLo();
+        hiLo.play();
+    }
+}
diff --git a/51 Hurkle/java/src/Hurkle.java b/51 Hurkle/java/src/Hurkle.java
new file mode 100644
index 00000000..8af8732f
--- /dev/null
+++ b/51 Hurkle/java/src/Hurkle.java	
@@ -0,0 +1,186 @@
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class Hurkle {
+
+    public static final int GRID_SIZE = 10;
+    public static final int MAX_GUESSES = 5;
+
+    private enum GAME_STATE {
+        STARTING,
+        START_GAME,
+        GUESSING,
+        PLAY_AGAIN,
+        GAME_OVER
+    }
+
+    private GAME_STATE gameState;
+
+    // Used for keyboard input
+    private Scanner kbScanner;
+
+    private int guesses;
+
+    // hurkle position
+    private int hurkleXPos;
+    private int hurkleYPos;
+
+    // player guess
+    private int playerGuessXPos;
+    private int playerGuessYPos;
+
+    public Hurkle() {
+
+        gameState = GAME_STATE.STARTING;
+
+        // Initialise kb scanner
+        kbScanner = new Scanner(System.in);
+    }
+
+    /**
+     * Main game loop
+     */
+    public void play() {
+
+        do {
+            switch (gameState) {
+
+                // Show an introduction the first time the game is played.
+                case STARTING:
+                    intro();
+                    gameState = GAME_STATE.START_GAME;
+                    break;
+
+                // Start the game, set the number of players, names and round
+                case START_GAME:
+
+                    this.hurkleXPos = randomNumber();
+                    this.hurkleYPos = randomNumber();
+                    System.out.println("HURKLE AT : " + this.hurkleXPos + "," + this.hurkleYPos);
+
+                    this.guesses = 1;
+                    gameState = GAME_STATE.GUESSING;
+
+                    break;
+
+                // Guess an x,y position of the hurkle
+                case GUESSING:
+                    String guess = displayTextAndGetInput("GUESS #" + this.guesses + "? ");
+                    this.playerGuessXPos = getDelimitedValue(guess, 0);
+                    this.playerGuessYPos = getDelimitedValue(guess, 1);
+                    if (foundHurkle()) {
+                        this.gameState = GAME_STATE.PLAY_AGAIN;
+                    } else {
+                        showDirectionOfHurkle();
+                        this.guesses++;
+                        if(this.guesses > MAX_GUESSES) {
+                            System.out.println("SORRY, THAT'S "
+                                    + MAX_GUESSES + " GUESSES.");
+                            System.out.println("THE HURKLE IS AT "
+                                    + this.hurkleXPos + "," + this.hurkleYPos);
+                            System.out.println();
+                            this.gameState = GAME_STATE.PLAY_AGAIN;
+                        }
+                    }
+
+                    break;
+
+                case PLAY_AGAIN:
+                    System.out.println("LET'S PLAY AGAIN, HURKLE IS HIDING.");
+                    System.out.println();
+                    this.gameState = GAME_STATE.START_GAME;
+                    break;
+            }
+            // Effectively an endless loop because the game never quits as per
+            // the original basic code.
+        } while (gameState != GAME_STATE.GAME_OVER);
+    }
+
+    private void showDirectionOfHurkle() {
+        System.out.print("GO ");
+        if(this.playerGuessYPos == this.hurkleYPos) {
+            // don't print North or South because the player has chosen the
+            // same y grid pos as the hurkle
+        } else if (this.playerGuessYPos < this.hurkleYPos) {
+            System.out.print("NORTH");
+        } else if(this.playerGuessYPos > this.hurkleYPos) {
+            System.out.print("SOUTH");
+        }
+
+        if(this.playerGuessXPos == this.hurkleXPos) {
+            // don't print East or West because the player has chosen the
+            // same x grid pos as the hurkle
+        } else if(this.playerGuessXPos < this.hurkleXPos) {
+            System.out.print("EAST");
+        } else if(this.playerGuessXPos > this.hurkleXPos) {
+            System.out.print("WEST");
+        }
+        System.out.println();
+        return;
+    }
+
+    private boolean foundHurkle() {
+        if ((this.playerGuessXPos - this.hurkleXPos)
+                - (this.playerGuessYPos - this.hurkleYPos) == 0) {
+            System.out.println("YOU FOUND HIM IN " + this.guesses + " GUESSES.");
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Display info about the game
+     */
+    private void intro() {
+        System.out.println("HURKLE");
+        System.out.println("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+        System.out.println();
+        System.out.println("A HURKLE IS HIDING ON A " + GRID_SIZE + " BY "
+                + GRID_SIZE + " GRID. HOMEBASE");
+        System.out.println("ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,");
+        System.out.println("AND ANY POINT ON THE GRID IS DESIGNATED BY A");
+        System.out.println("PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST");
+        System.out.println("NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER");
+        System.out.println("IS THE VERTICAL POSITION. YOU MUST TRY TO");
+        System.out.println("GUESS THE HURKLE'S GRIDPOINT. YOU GET "
+                + MAX_GUESSES + " TRIES.");
+        System.out.println("AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE");
+        System.out.println("DIRECTION TO GO TO LOOK FOR THE HURKLE.");
+    }
+
+    /**
+     * Generate random number
+     * Used to create one part of an x,y grid position
+     *
+     * @return random number
+     */
+    private int randomNumber() {
+        return (int) (Math.random()
+                * (GRID_SIZE) + 1);
+    }
+
+    /*
+     * Print a message on the screen, then accept input from Keyboard.
+     *
+     * @param text message to be displayed on screen.
+     * @return what was typed by the player.
+     */
+    private String displayTextAndGetInput(String text) {
+        System.out.print(text);
+        return kbScanner.next();
+    }
+
+    /**
+     * Accepts a string delimited by comma's and returns the pos'th delimited
+     * value (starting at count 0).
+     *
+     * @param text - text with values separated by comma's
+     * @param pos  - which position to return a value for
+     * @return the int representation of the value
+     */
+    private int getDelimitedValue(String text, int pos) {
+        String[] tokens = text.split(",");
+        return Integer.parseInt(tokens[pos]);
+    }
+}
diff --git a/51 Hurkle/java/src/HurkleGame.java b/51 Hurkle/java/src/HurkleGame.java
new file mode 100644
index 00000000..c582885e
--- /dev/null
+++ b/51 Hurkle/java/src/HurkleGame.java	
@@ -0,0 +1,7 @@
+public class HurkleGame {
+
+    public static void main(String[] args) {
+	    Hurkle hurkle = new Hurkle();
+	    hurkle.play();
+    }
+}
diff --git a/78 Sine Wave/csharp/SineWave/SineWave.sln b/78 Sine Wave/csharp/SineWave/SineWave.sln
new file mode 100644
index 00000000..f32a06cd
--- /dev/null
+++ b/78 Sine Wave/csharp/SineWave/SineWave.sln	
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31005.135
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SineWave", "SineWave\SineWave.csproj", "{B316DD7F-5755-4216-AFDC-D83720F8ACA2}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B316DD7F-5755-4216-AFDC-D83720F8ACA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B316DD7F-5755-4216-AFDC-D83720F8ACA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B316DD7F-5755-4216-AFDC-D83720F8ACA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B316DD7F-5755-4216-AFDC-D83720F8ACA2}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {32A37343-2955-4124-8765-9143F6C529DC}
+	EndGlobalSection
+EndGlobal
diff --git a/78 Sine Wave/csharp/SineWave/SineWave/Program.cs b/78 Sine Wave/csharp/SineWave/SineWave/Program.cs
new file mode 100644
index 00000000..6f44f8d5
--- /dev/null
+++ b/78 Sine Wave/csharp/SineWave/SineWave/Program.cs	
@@ -0,0 +1,15 @@
+using System;
+
+Console.WriteLine(Tab(30) + "Sine Wave");
+Console.WriteLine(Tab(15) + "Creative Computing Morristown, New Jersey\n\n\n\n\n");
+
+bool isCreative = true;
+for (double t = 0.0; t <= 40.0; t += 0.25)
+{
+    int a = (int)(26 + 25 * Math.Sin(t));
+    string word = isCreative ? "Creative" : "Computing";
+    Console.WriteLine($"{Tab(a)}{word}");
+    isCreative = !isCreative;
+}
+
+static string Tab(int n) => new string(' ', n);
\ No newline at end of file
diff --git a/78 Sine Wave/csharp/SineWave/SineWave/SineWave.csproj b/78 Sine Wave/csharp/SineWave/SineWave/SineWave.csproj
new file mode 100644
index 00000000..20827042
--- /dev/null
+++ b/78 Sine Wave/csharp/SineWave/SineWave/SineWave.csproj	
@@ -0,0 +1,8 @@
+
+
+  
+    Exe
+    net5.0
+  
+
+
diff --git a/78 Sine Wave/java/SineWave.java b/78 Sine Wave/java/SineWave.java
new file mode 100644
index 00000000..7d917a75
--- /dev/null
+++ b/78 Sine Wave/java/SineWave.java	
@@ -0,0 +1,35 @@
+import java.util.Arrays;
+
+/**
+ * Sine Wave
+ *
+ * Based on the Sine Wave program here
+ * https://github.com/coding-horror/basic-computer-games/blob/main/78%20Sine%20Wave/sinewave.bas
+ *
+ * Note:  The idea was to create a version of this 1970's Basic program in Java, without introducing
+ *        new features - no additional text, error checking, etc has been added.
+ */
+public class SineWave {
+
+    public static void main(String[] args) {
+
+        System.out.println("SINE WAVE");
+        System.out.println("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+        System.out.println();
+
+        int toggle = 0;
+        for(double t = 0; t<40; t += .25) {
+            int a = 26 + (int) (25 * Math.sin(t));
+            char[] repeat = new char[a];
+            Arrays.fill(repeat,' ');
+            System.out.print(new String(repeat));
+            if (toggle == 1) {
+                System.out.println("COMPUTING");
+                toggle = 0;
+            } else {
+                System.out.println("CREATIVE");
+                toggle = 1;
+            }
+        }
+    }
+}