diff --git a/00_Utilities/jvmTestUtils/kotlin/test/ConsoleTest.kt b/00_Utilities/jvmTestUtils/kotlin/test/ConsoleTest.kt
new file mode 100644
index 00000000..d58af170
--- /dev/null
+++ b/00_Utilities/jvmTestUtils/kotlin/test/ConsoleTest.kt
@@ -0,0 +1,37 @@
+package com.pcholt.console.testutils
+
+import com.google.common.truth.Truth
+import org.junit.Rule
+import org.junit.contrib.java.lang.system.SystemOutRule
+import org.junit.contrib.java.lang.system.TextFromStandardInputStream
+
+abstract class ConsoleTest {
+ @get:Rule
+ val inputRule = TextFromStandardInputStream.emptyStandardInputStream()
+
+ @get:Rule
+ val systemOutRule = SystemOutRule().enableLog()
+
+ val regexInputCommand = "\\{(.*)}".toRegex()
+
+ fun assertConversation(conversation: String, runMain: () -> Unit) {
+
+ inputRule.provideLines(*regexInputCommand
+ .findAll(conversation)
+ .map { it.groupValues[1] }
+ .toList().toTypedArray())
+
+ runMain()
+
+ Truth.assertThat(
+ systemOutRule.log.trimWhiteSpace()
+ )
+ .isEqualTo(
+ regexInputCommand
+ .replace(conversation, "").trimWhiteSpace()
+ )
+ }
+
+ private fun String.trimWhiteSpace() =
+ replace("[\\s]+".toRegex(), " ")
+}
\ No newline at end of file
diff --git a/03_Animal/java/Animal.java b/03_Animal/java/src/Animal.java
similarity index 98%
rename from 03_Animal/java/Animal.java
rename to 03_Animal/java/src/Animal.java
index 681425c1..c4222c5f 100644
--- a/03_Animal/java/Animal.java
+++ b/03_Animal/java/src/Animal.java
@@ -74,11 +74,11 @@ public class Animal {
private static void askForInformationAndSave(Scanner scan, AnimalNode current, QuestionNode previous, boolean previousToCurrentDecisionChoice) {
//Failed to get it right and ran out of questions
//Let's ask the user for the new information
- System.out.print("THE ANIMAL YOU WERE THINKING OF WAS A ");
+ System.out.print("THE ANIMAL YOU WERE THINKING OF WAS A ? ");
String animal = scan.nextLine();
- System.out.printf("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A %s FROM A %s ", animal, current.getAnimal());
+ System.out.printf("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A %s FROM A %s ? ", animal, current.getAnimal());
String newQuestion = scan.nextLine();
- System.out.printf("FOR A %s THE ANSWER WOULD BE ", animal);
+ System.out.printf("FOR A %s THE ANSWER WOULD BE ? ", animal);
boolean newAnswer = readYesOrNo(scan);
//Add it to our question store
addNewAnimal(current, previous, animal, newQuestion, newAnswer, previousToCurrentDecisionChoice);
diff --git a/03_Animal/java/test/AnimalJavaTest.kt b/03_Animal/java/test/AnimalJavaTest.kt
new file mode 100644
index 00000000..013655a3
--- /dev/null
+++ b/03_Animal/java/test/AnimalJavaTest.kt
@@ -0,0 +1,55 @@
+import com.pcholt.console.testutils.ConsoleTest
+import org.junit.Test
+
+class AnimalJavaTest : ConsoleTest() {
+
+ @Test
+ fun `given a standard setup, find the fish`() {
+ assertConversation(
+ """
+ $title
+ ARE YOU THINKING OF AN ANIMAL ? {YES}
+ DOES IT SWIM ? {YES}
+ IS IT A FISH ? {YES}
+ WHY NOT TRY ANOTHER ANIMAL?
+ ARE YOU THINKING OF AN ANIMAL ? {QUIT}
+ """
+ ) {
+ Animal.main(emptyArray())
+ }
+ }
+
+ @Test
+ fun `given a standard setup, create a cow, and verify`() {
+ assertConversation(
+ """
+ $title
+ ARE YOU THINKING OF AN ANIMAL ? {YES}
+ DOES IT SWIM ? {NO}
+ IS IT A BIRD ? {NO}
+ THE ANIMAL YOU WERE THINKING OF WAS A ? {COW}
+ PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A
+ COW FROM A BIRD
+ ? {DOES IT EAT GRASS}
+ FOR A COW THE ANSWER WOULD BE ? {YES}
+ ARE YOU THINKING OF AN ANIMAL ? {YES}
+ DOES IT SWIM ? {NO}
+ DOES IT EAT GRASS ? {YES}
+ IS IT A COW ? {YES}
+ WHY NOT TRY ANOTHER ANIMAL?
+ ARE YOU THINKING OF AN ANIMAL ? {QUIT}
+ """
+ ) {
+ Animal.main(emptyArray())
+ }
+ }
+
+ private val title = """
+ ANIMAL
+ CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
+
+ PLAY 'GUESS THE ANIMAL'
+ THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.
+ """
+}
+
diff --git a/03_Animal/kotlin/Animal.kt b/03_Animal/kotlin/src/Animal.kt
similarity index 100%
rename from 03_Animal/kotlin/Animal.kt
rename to 03_Animal/kotlin/src/Animal.kt
diff --git a/03_Animal/kotlin/test/AnimalKtTest.kt b/03_Animal/kotlin/test/AnimalKtTest.kt
new file mode 100644
index 00000000..e93857ea
--- /dev/null
+++ b/03_Animal/kotlin/test/AnimalKtTest.kt
@@ -0,0 +1,55 @@
+import com.pcholt.console.testutils.ConsoleTest
+import org.junit.Test
+
+class AnimalKtTest : ConsoleTest() {
+
+ @Test
+ fun `given a standard setup, find the fish`() {
+ assertConversation(
+ """
+ $title
+ ARE YOU THINKING OF AN ANIMAL? {YES}
+ DOES IT SWIM? {YES}
+ IS IT A FISH? {YES}
+ WHY NOT TRY ANOTHER ANIMAL?
+ ARE YOU THINKING OF AN ANIMAL? {QUIT}
+ """
+ ) {
+ main()
+ }
+ }
+
+ @Test
+ fun `given a standard setup, create a cow, and verify`() {
+ assertConversation(
+ """
+ $title
+ ARE YOU THINKING OF AN ANIMAL? {YES}
+ DOES IT SWIM? {NO}
+ IS IT A BIRD? {NO}
+ THE ANIMAL YOU WERE THINKING OF WAS A? {COW}
+ PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A
+ COW FROM A BIRD
+ ? {DOES IT EAT GRASS}
+ FOR A COW THE ANSWER WOULD BE? {YES}
+ ARE YOU THINKING OF AN ANIMAL? {YES}
+ DOES IT SWIM? {NO}
+ DOES IT EAT GRASS? {YES}
+ IS IT A COW? {YES}
+ WHY NOT TRY ANOTHER ANIMAL?
+ ARE YOU THINKING OF AN ANIMAL? {QUIT}
+ """
+ ) {
+ main()
+ }
+ }
+
+ private val title = """
+ ANIMAL
+ CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
+
+ PLAY 'GUESS THE ANIMAL'
+ THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.
+ """
+}
+
diff --git a/55_Life/java/README.md b/55_Life/java/README.md
index 51edd8d4..19a5ff38 100644
--- a/55_Life/java/README.md
+++ b/55_Life/java/README.md
@@ -1,3 +1,19 @@
+# Game of Life - Java version
+
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Oracle Java](https://openjdk.java.net/)
+
+## Requirements
+
+* Requires Java 17 (or later)
+
+## Notes
+
+The Java version of Game of Life tries to mimics the behaviour of the BASIC version.
+However, the Java code does not have much in common with the original.
+
+**Differences in behaviour:**
+* Input supports the ```.``` character, but it's optional.
+* Evaluation of ```DONE``` input string is case insensitive.
+* Run with the ```-s``` command line argument to halt the program after each generation, and continue when ```ENTER``` is pressed.
\ No newline at end of file
diff --git a/55_Life/java/src/java/Life.java b/55_Life/java/src/java/Life.java
new file mode 100644
index 00000000..2f5c184a
--- /dev/null
+++ b/55_Life/java/src/java/Life.java
@@ -0,0 +1,191 @@
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * The Game of Life class.
+ *
+ * Mimics the behaviour of the BASIC version, however the Java code does not have much in common with the original.
+ *
+ * Differences in behaviour:
+ *
-s: Stop after each generation (press enter to continue)+ * @throws Exception if something goes wrong. + */ + public static void main(String[] args) throws Exception { + new Life(args).start(); + } + +} + +/** + * Represents a state change for a single cell within the matrix. + * + * @param y the y coordinate (row) of the cell + * @param x the x coordinate (column) of the cell + * @param newState the new state of the cell (either DEAD or ALIVE) + */ +record Transition(int y, int x, byte newState) { } diff --git a/85_Synonym/csharp/Synonym.cs b/85_Synonym/csharp/Synonym.cs new file mode 100644 index 00000000..9d58da71 --- /dev/null +++ b/85_Synonym/csharp/Synonym.cs @@ -0,0 +1,149 @@ +using System.Text; + +namespace Synonym +{ + class Synonym + { + Random rand = new Random(); + + // Initialize list of corrent responses + private string[] Affirmations = { "Right", "Correct", "Fine", "Good!", "Check" }; + + // Initialize list of words and their synonyms + private string[][] Words = + { + new string[] {"first", "start", "beginning", "onset", "initial"}, + new string[] {"similar", "alike", "same", "like", "resembling"}, + new string[] {"model", "pattern", "prototype", "standard", "criterion"}, + new string[] {"small", "insignificant", "little", "tiny", "minute"}, + new string[] {"stop", "halt", "stay", "arrest", "check", "standstill"}, + new string[] {"house", "dwelling", "residence", "domicile", "lodging", "habitation"}, + new string[] {"pit", "hole", "hollow", "well", "gulf", "chasm", "abyss"}, + new string[] {"push", "shove", "thrust", "prod", "poke", "butt", "press"}, + new string[] {"red", "rouge", "scarlet", "crimson", "flame", "ruby"}, + new string[] {"pain", "suffering", "hurt", "misery", "distress", "ache", "discomfort"} + }; + + private void DisplayIntro() + { + Console.WriteLine(""); + Console.WriteLine("SYNONYM".PadLeft(23)); + Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(""); + Console.WriteLine("A synonym of a word means another word in the English"); + Console.WriteLine("language which has the same or very nearly the same meaning."); + Console.WriteLine("I choose a word -- you type a synonym."); + Console.WriteLine("If you can't think of a synonym, type the word 'help'"); + Console.WriteLine("and I will tell you a synonym."); + Console.WriteLine(""); + } + + private void DisplayOutro() + { + Console.WriteLine("Synonym drill completed."); + } + + private void RandomizeTheList() + { + // Randomize the list of Words to pick from + int[] Order = new int[Words.Length]; + foreach (int i in Order) + { + Order[i] = rand.Next(); + } + Array.Sort(Order, Words); + } + + private string GetAnAffirmation() + { + return Affirmations[rand.Next(Affirmations.Length)]; + } + + private bool CheckTheResponse(string WordName, int WordIndex, string LineInput, string[] WordList) + { + if (LineInput.Equals("help")) + { + // Choose a random correct synonym response that doesn't equal the current word given + int HelpIndex = rand.Next(WordList.Length); + while (HelpIndex == WordIndex) + { + HelpIndex = rand.Next(0, WordList.Length); + } + Console.WriteLine("**** A synonym of {0} is {1}.", WordName, WordList[HelpIndex]); + + return false; + } + else + { + // Check to see if the response is one of the listed synonyms and not the current word prompt + if (WordList.Contains(LineInput) && LineInput != WordName) + { + // Randomly display one of the five correct answer exclamations + Console.WriteLine(GetAnAffirmation()); + + return true; + } + else + { + // Incorrect response. Try again. + Console.WriteLine(" Try again.".PadLeft(5)); + + return false; + } + } + } + + private string PromptForSynonym(string WordName) + { + Console.Write(" What is a synonym of {0}? ", WordName); + string LineInput = Console.ReadLine().Trim().ToLower(); + + return LineInput; + } + + private void AskForSynonyms() + { + Random rand = new Random(); + + // Loop through the now randomized list of Words and display a random word from each to prompt for a synonym + foreach (string[] WordList in Words) + { + int WordIndex = rand.Next(WordList.Length); // random word position in the current list of words + string WordName = WordList[WordIndex]; // what is that actual word + bool Success = false; + + while (!Success) + { + // Ask for the synonym of the current word + string LineInput = PromptForSynonym(WordName); + + // Check the response + Success = CheckTheResponse(WordName, WordIndex, LineInput, WordList); + + // Add extra line space for formatting + Console.WriteLine(""); + } + } + } + + public void PlayTheGame() + { + RandomizeTheList(); + + DisplayIntro(); + + AskForSynonyms(); + + DisplayOutro(); + } + } + class Program + { + static void Main(string[] args) + { + + new Synonym().PlayTheGame(); + + } + } +} \ No newline at end of file diff --git a/85_Synonym/csharp/Synonym.csproj b/85_Synonym/csharp/Synonym.csproj index d3fe4757..1fd332a6 100644 --- a/85_Synonym/csharp/Synonym.csproj +++ b/85_Synonym/csharp/Synonym.csproj @@ -1,9 +1,10 @@ -