Merge branch 'coding-horror:main' into main

This commit is contained in:
Alaa Sarhan
2022-01-03 02:05:38 +01:00
committed by GitHub
79 changed files with 3534 additions and 139 deletions

View File

@@ -10,7 +10,7 @@
80 PRINT"IF YOU DO NOT WANT TO BET, INPUT A 0"
100 N=100
110 Q=100
120 PRINT "YOU NOW HAVE";Q;"DOLLARS."
120 PRINT "YOU NOW HAVE ";Q;" DOLLARS."
130 PRINT
140 GOTO 260
210 Q=Q+M

View File

@@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": true,
"singleQuote": true
}

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>ACEY DUCEY</title>
<pre id="output" style="font-size: 12pt;"></pre>
<script type="module" src="aceyducey.js"></script>
<pre id="output" style="font-size: 12pt"></pre>
<script src="aceyducey.js"></script>

View File

@@ -1,100 +1,216 @@
import { readLine, print, spaces } from "./io.js";
// UTILITY VARIABLES
const minFaceCard = 11;
const faceCards = {
11: "JACK",
12: "QUEEN",
13: "KING",
14: "ACE"
};
// By default:
// — Browsers have a window object
// — Node.js does not
// Checking for an undefined window object is a loose check
// to enable browser and Node.js support
const isRunningInBrowser = typeof window !== 'undefined';
function randomCard() {
return Math.floor(Math.random() * 13 + 2);
// To easily validate input strings with utility functions
const validLowerCaseYesStrings = ['yes', 'y'];
const validLowerCaseNoStrings = ['no', 'n'];
const validLowerCaseYesAndNoStrings = [
...validLowerCaseYesStrings,
...validLowerCaseNoStrings,
];
// UTILITY VARIABLES
// Function to get a random number (card) 2-14 (ACE is 14)
function getRandomCard() {
// In our game, the value of ACE is greater than face cards;
// instead of having the value of ACE be 1, well have it be 14.
// So, we want to shift the range of random numbers from 1-13 to 2-14
let min = 2;
let max = 14;
// Return random integer between two values, inclusive
return Math.floor(Math.random() * (max - min + 1) + min);
}
function printCard(card) {
if (card < minFaceCard) {
print(card);
} else {
print(faceCards[card]);
}
print("\n");
function newGameCards() {
let cardOne = getRandomCard();
let cardTwo = getRandomCard();
let cardThree = getRandomCard();
// We want:
// 1. cardOne and cardTwo to be different cards
// 2. cardOne to be lower than cardTwo
// So, while cardOne is greater than or equal too cardTwo
// we will continue to generate random cards.
while (cardOne >= cardTwo) {
cardOne = getRandomCard();
cardTwo = getRandomCard();
}
return [cardOne, cardTwo, cardThree];
}
print(spaces(26) + "ACEY DUCEY CARD GAME\n");
print(spaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n");
print("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER\n");
print("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP\n");
print("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING\n");
print("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE\n");
print("A VALUE BETWEEN THE FIRST TWO.\n");
print("IF YOU DO NOT WANT TO BET, INPUT '0'\n");
// Function to get card value
function getCardValue(card) {
let faceOrAce = {
11: 'JACK',
12: 'QUEEN',
13: 'KING',
14: 'ACE',
};
// If card value matches a key in faceOrAce, use faceOrAce value;
// Else, return undefined and handle with the Nullish Coalescing Operator (??)
// and default to card value.
let cardValue = faceOrAce[card] ?? card;
return cardValue;
}
let currentMoney = 100;
while (true) {
print(`YOU NOW HAVE ${currentMoney} DOLLARS.\n\n`);
print(spaces(26) + 'ACEY DUCEY CARD GAME');
print(spaces(15) + 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n');
print('ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER');
print('THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP');
print('YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING');
print('ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE');
print('A VALUE BETWEEN THE FIRST TWO.');
print("IF YOU DO NOT WANT TO BET, INPUT '0'");
let card1, card2, currentBet;
do {
print("HERE ARE YOUR NEXT TWO CARDS: \n");
[card1, card2] = [randomCard(), randomCard()];
main();
// Ensure we always show cards in order of lowest to highest, and we never
// get two of the same card.
do {
card1 = randomCard();
card2 = randomCard();
} while (card1 >= card2);
printCard(card1);
printCard(card2);
print("\n");
async function main() {
let bet;
let availableDollars = 100;
// Loop game forever
while (true) {
print("\nWHAT IS YOUR BET? ");
currentBet = parseInt(await readLine(), 10);
let [cardOne, cardTwo, cardThree] = newGameCards();
if (currentBet > 0) {
if (currentBet > currentMoney) {
print("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.\n");
print(`YOU HAVE ONLY ${currentMoney} DOLLARS TO BET.\n`);
continue;
print(`YOU NOW HAVE ${availableDollars} DOLLARS.\n`);
print('HERE ARE YOUR NEXT TWO CARDS: ');
print(getCardValue(cardOne));
print(getCardValue(cardTwo));
print('');
// Loop until receiving a valid bet
let validBet = false;
while (!validBet) {
print('\nWHAT IS YOUR BET? ');
bet = parseInt(await input(), 10);
let minimumRequiredBet = 0;
if (bet > minimumRequiredBet) {
if (bet > availableDollars) {
print('SORRY, MY FRIEND, BUT YOU BET TOO MUCH.');
print(`YOU HAVE ONLY ${availableDollars} DOLLARS TO BET.`);
} else {
validBet = true;
}
} else {
// Does not meet minimum required bet
print('CHICKEN!!');
print('');
}
}
break;
}
// Invalid bet value. Output an error message and reset to undefined to
// restart the loop with new cards.
currentBet = undefined;
print("CHICKEN!!\n");
print("\n");
break;
print('\n\nHERE IS THE CARD WE DREW: ');
print(getCardValue(cardThree));
// Determine if player won or lost
if (cardThree > cardOne && cardThree < cardTwo) {
print('YOU WIN!!!');
availableDollars = availableDollars + bet;
} else {
print('SORRY, YOU LOSE');
if (bet >= availableDollars) {
print('');
print('');
print('SORRY, FRIEND, BUT YOU BLEW YOUR WAD.');
print('');
print('');
print('TRY AGAIN (YES OR NO)');
let tryAgainInput = await input();
print('');
print('');
if (isValidYesNoString(tryAgainInput)) {
availableDollars = 100;
} else {
print('O.K., HOPE YOU HAD FUN!');
break;
}
} else {
availableDollars = availableDollars - bet;
}
}
}
} while (currentBet === undefined);
const actualCard = randomCard();
print("\n\nHERE IS THE CARD WE DREW:\n")
printCard(actualCard);
print("\n\n");
if (actualCard > card1 && actualCard < card2) {
print("YOU WIN!!!\n");
currentMoney += currentBet;
} else {
print("SORRY, YOU LOSE\n");
if (currentBet < currentMoney) {
currentMoney -= currentBet;
} else {
print("\n\nSORRY, FRIEND, BUT YOU BLEW YOUR WAD.\n\n\n");
print("TRY AGAIN (YES OR NO)");
const tryAgain = await readLine();
print("\n\n");
if (tryAgain.toLowerCase() === "yes") {
currentMoney = 100;
} else {
print("O.K., HOPE YOU HAD FUN!");
break;
}
}
}
}
// UTILITY FUNCTIONS
function isValidYesNoString(string) {
return validLowerCaseYesAndNoStrings.includes(string.toLowerCase());
}
function isValidYesString(string) {
return validLowerCaseYesStrings.includes(string.toLowerCase());
}
function isValidNoString(string) {
return validLowerCaseNoStrings.includes(string.toLowerCase());
}
function print(string) {
if (isRunningInBrowser) {
// Adds trailing newline to match console.log behavior
document
.getElementById('output')
.appendChild(document.createTextNode(string + '\n'));
} else {
console.log(string);
}
}
function input() {
if (isRunningInBrowser) {
// Accept input from the browser DOM input
return new Promise((resolve) => {
const outputElement = document.querySelector('#output');
const inputElement = document.createElement('input');
outputElement.append(inputElement);
inputElement.focus();
inputElement.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
const result = inputElement.value;
inputElement.remove();
print(result);
print('');
resolve(result);
}
});
});
} else {
// Accept input from the command line in Node.js
// See: https://nodejs.dev/learn/accept-input-from-the-command-line-in-nodejs
return new Promise(function (resolve) {
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout,
});
readline.question('', function (input) {
resolve(input);
readline.close();
});
});
}
}
function printInline(string) {
if (isRunningInBrowser) {
document
.getElementById('output')
.appendChild(document.createTextNode(string));
} else {
process.stdout.write(string);
}
}
function spaces(numberOfSpaces) {
return ' '.repeat(numberOfSpaces);
}
// UTILITY FUNCTIONS

View File

@@ -1,29 +0,0 @@
const outputEl = document.querySelector("#output");
export function print(string) {
outputEl.append(string);
}
export function readLine() {
return new Promise(resolve => {
const inputEl = document.createElement("input");
outputEl.append(inputEl);
inputEl.focus();
inputEl.addEventListener("keydown", event => {
if (event.key === "Enter") {
const result = inputEl.value;
inputEl.remove();
print(result);
print("\n");
resolve(result);
}
});
});
}
export function spaces(numberOfSpaces) {
return " ".repeat(numberOfSpaces);
}

View File

@@ -0,0 +1,125 @@
#
# AceyDuchy
#
# From: BASIC Computer Games (1978)
# Edited by David Ahl
#
# "The original BASIC program author was Bill Palmby
# of Prairie View, Illinois."
#
# Python port by Aviyam Fischer, 2022
#
######################################################
class Card:
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank
def __str__(self):
r = self.rank
if r == 11:
r = 'J'
elif r == 12:
r = 'Q'
elif r == 13:
r = 'K'
elif r == 14:
r = 'A'
return f'{r}{self.suit}'
class Deck:
def __init__(self):
self.cards = []
self.build()
def build(self):
for suit in ['\u2665', '\u2666', '\u2663', '\u2660']:
for rank in range(1, 14):
self.cards.append(Card(suit, rank))
def shuffle(self):
import random
random.shuffle(self.cards)
def deal(self):
return self.cards.pop()
class Game:
def __init__(self):
self.deck = Deck()
self.deck.shuffle()
self.card_a = self.deck.deal()
self.card_b = self.deck.deal()
self.money = 100
self.not_done = True
def play(self):
while self.not_done:
while self.money > 0:
card_a = self.card_a
card_b = self.card_b
if card_a.rank > card_b.rank:
card_a, card_b = card_b, card_a
if card_a.rank == card_b.rank:
self.card_b = self.deck.deal()
card_b = self.card_b
print(f'You have:\t ${self.money} ')
print(f'Your cards:\t {card_a} {card_b}')
bet = int(input('What is your bet? '))
player_card = self.deck.deal()
if 0 < bet <= self.money:
print(f'Your deal:\t {player_card}')
if card_a.rank < player_card.rank < card_b.rank:
print('You Win!')
self.money += bet
else:
print('You Lose!')
self.money -= bet
self.not_done = False
else:
print('Chicken!')
print(f'Your deal should have been: {player_card}')
if card_a.rank < player_card.rank < card_b.rank:
print(f'You could have won!')
else:
print(f'You would lose, so it was wise of you to chicken out!')
self.not_done = False
break
if len(self.deck.cards) <= 1:
print('You ran out of cards. Game over.')
self.not_done = False
break
if self.money == 0:
self.not_done = False
if __name__ == '__main__':
print('''
Acey Ducey is a card game where you play against the computer.
The Dealer(computer) will deal two cards facing up.
You have an option to bet or not bet depending on whether or not you
feel the card will have a value between the first two.
If you do not want to bet input a 0
''')
GAME_OVER = False
while not GAME_OVER:
game = Game()
game.play()
print(f'You have ${game.money} left')
print('Would you like to play again? (y/n)')
if input() == 'n':
GAME_OVER = True
print('\nThanks for playing!')

View File

@@ -56,9 +56,9 @@ while true # Game loop
puts
puts "HERE ARE YOUR NEXT TWO CARDS:"
# Randomly draw two cards from 2 to 14 and make sure the first card is lower in value than the second
# Randomly draw two cards and make sure the first card is lower in value than the second
# Using array destructuring, this sorted array can be assigned to `first_card` and `second_card`
first_card, second_card = [rand(2..14), rand(2..14)].sort
first_card, second_card = (2...14).to_a.shuffle.pop(2).sort
# Helper method to convert a numeric card into a String for printing
def card_name(card)

View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AceyDucy", "AceyDucy\AceyDucy.vbproj", "{37496710-B458-4502-ADCB-4C57203866F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{37496710-B458-4502-ADCB-4C57203866F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{37496710-B458-4502-ADCB-4C57203866F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{37496710-B458-4502-ADCB-4C57203866F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{37496710-B458-4502-ADCB-4C57203866F9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C01D9DAE-644C-455F-8365-E14E49074BC3}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>AceyDucy</RootNamespace>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,178 @@
Imports System
''' <summary>
''' This is a modern adapation of Acey Ducey from BASIC Computer Games.
'''
''' The structural changes primarily consist of replacing the many GOTOs with
''' Do/Loop constructs to force the continual execution of the program.
'''
''' Because modern Basic allows multi-line If/Then blocks, many GOTO jumps were
''' able to be eliminated and the logic was able to be moved to more relevant areas,
''' For example, the increment/decrement of the player's balance could be in the same
''' area as the notification of win/loss.
'''
''' Some modern improvements were added, primarily the inclusion of a function, which
''' eliminated a thrice-repeated block of logic to display the card value. The archaic
''' RND function is greatly simplified with the .NET Framework's Random class.
'''
''' Elementary comments are provided for non-programmers or novices.
''' </summary>
Module Program
Sub Main(args As String())
' These are the variables that will hold values during the program's execution
Dim input As String
Dim rnd As New Random ' You can create a new instance of an object during declaration
Dim currentBalance As Integer = 100 ' You can set a initial value at declaration
Dim currentWager As Integer
Dim cardA, cardB, cardC As Integer ' You can specify multiple variables of the same type in one declaration statement
' Display the opening title and instructions
' Use a preceding $ to insert calculated values within the string using {}
Console.WriteLine($"{Space((Console.WindowWidth \ 2) - 10)}ACEY DUCEY CARD GAME")
Console.WriteLine($"{Space((Console.WindowWidth \ 2) - 21)}CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
Console.WriteLine("")
Console.WriteLine("")
Console.WriteLine("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER")
Console.WriteLine("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP")
Console.WriteLine("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING")
Console.WriteLine("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE")
Console.WriteLine("A VALUE BETWEEN THE FIRST TWO.")
Console.WriteLine("IF YOU DO NOT WANT TO BET, INPUT A 0")
Do ' This loop continues as long as the player wants to keep playing
Do ' This loop continues as long as the player has money to play
Console.WriteLine("")
Console.WriteLine($"YOU NOW HAVE {currentBalance} DOLLARS.")
Console.WriteLine("")
Console.WriteLine("HERE ARE YOUR NEXT TWO CARDS:")
' We need to ensure that card B is a higher value for our later comparison,
' so we will loop until we have two cards that meet this criteria
Do
cardA = rnd.Next(2, 14)
cardB = rnd.Next(2, 14)
Loop While cardA > cardB
' We use a function to display the text value of the numeric card value
' because we do this 3 times and a function reduces repetition of code
Console.WriteLine(DisplayCard(cardA))
Console.WriteLine(DisplayCard(cardB))
Do ' This loop continues until the player provides a valid wager value
Console.WriteLine("")
Console.WriteLine("WHAT IS YOUR BET")
currentWager = 0
input = Console.ReadLine
' Any input from the console is a string, but we require a number.
' Test the input to make sure it is a numeric value.
If Integer.TryParse(input, currentWager) Then
' Test to ensure the player has not wagered more than their balance
If currentWager > currentBalance Then
Console.WriteLine("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.")
Console.WriteLine($"YOU HAVE ONLY {currentBalance} DOLLARS TO BET.")
Else
' The player has provided a numeric value that is less/equal to their balance,
' exit the loop and continue play
Exit Do
End If ' check player balance
End If ' check numeric input
Loop ' wager loop
' If the player is wagering, draw the third card, otherwise, mock them.
If currentWager > 0 Then
cardC = rnd.Next(2, 14)
Console.WriteLine(DisplayCard(cardC))
' The effort we made to have two cards in numeric order earlier makes this check easier,
' otherwise we would have to have a second check in the opposite direction
If cardC < cardA OrElse cardC >= cardB Then
Console.WriteLine("SORRY, YOU LOSE")
currentBalance -= currentWager ' Shorthand code to decrement a number (currentBalance=currentBalance - currentWager)
Else
Console.WriteLine("YOU WIN!!!")
currentBalance += currentWager ' Shorthand code to increment a number (currentBalance=currentBalance + currentWager)
End If
Else
Console.WriteLine("CHICKEN!!")
Console.WriteLine("")
End If
Loop While currentBalance > 0 ' loop as long as the player has money
' At this point, the player has no money (currentBalance=0). Inform them of such.
Console.WriteLine("")
Console.WriteLine("SORRY, FRIEND, BUT YOU BLEW YOUR WAD.")
Console.WriteLine("")
Console.WriteLine("")
' We will loop to ensure the player provides some answer.
Do
Console.WriteLine("TRY AGAIN (YES OR NO)")
Console.WriteLine("")
input = Console.ReadLine
Loop While String.IsNullOrWhiteSpace(input)
' We will assume that the player wants to play again only if they answer yes.
' (yeah and ya are valid as well, because we only check the first letter)
If input.Substring(0, 1).Equals("y", StringComparison.CurrentCultureIgnoreCase) Then ' This allows upper and lower case to be entered.
currentBalance = 100 ' Reset the players balance before restarting
Else
' Exit the outer loop which will end the game.
Exit Do
End If
Loop ' The full game loop
Console.WriteLine("O.K., HOPE YOU HAD FUN!")
End Sub
' This function is called for each of the 3 cards used in the game.
' The input and the output are both consistent, making it a good candidate for a function.
Private Function DisplayCard(value As Integer) As String
' We check the value of the input and run a block of code for whichever
' evaluation matches
Select Case value
Case 2 To 10 ' Case statements can be ranges of values, also multiple values (Case 2,3,4,5,6,7,8,9,10)
Return value.ToString
Case 11
Return "JACK"
Case 12
Return "QUEEN"
Case 13
Return "KING"
Case 14
Return "ACE"
End Select
' Although we have full knowledge of the program and never plan to send an invalid
' card value, it's important to provide a message for the next developer who won't
Throw New ArgumentOutOfRangeException("Card value must be between 2 and 14")
End Function
End Module

119
03_Animal/kotlin/Animal.kt Normal file
View File

@@ -0,0 +1,119 @@
/**
* ANIMAL
*
*
* Converted from BASIC to Kotlin by John Long (@patimen)
*
* Animal is basically a perfect example of a binary tree. Implement it
* as such, with the QuestionNode either having an answer if it is a terminal node
* or a Question
*/
fun main() {
printIntro()
val rootQuestionNode =
QuestionOrAnswer(question = Question("DOES IT SWIM", QuestionOrAnswer("FISH"), QuestionOrAnswer("BIRD")))
while (true) {
val choice = ask("ARE YOU THINKING OF AN ANIMAL")
when {
choice == "LIST" -> printKnownAnimals(rootQuestionNode)
choice.startsWith("Q") -> return
choice.startsWith("Y") -> {
// A wrong answer means it's a new animal!
val wrongAnswer = rootQuestionNode.getWrongAnswer()
if (wrongAnswer == null) {
// The computer got the right answer!
println("WHY NOT TRY ANOTHER ANIMAL?")
} else {
// Get a new question to ask next time
wrongAnswer.askForInformationAndSave()
}
}
}
}
}
// Takes care of asking a question (on the same line) and getting
// an answer or a blank string
fun ask(question: String): String {
print("$question? ")
return readLine()?.uppercase() ?: ""
}
// Special case for a "yes or no" question, returns true of yes
fun askYesOrNo(question: String): Boolean {
return generateSequence {
print("$question? ")
readLine()
}.firstNotNullOf { yesOrNo(it) }
}
// If neither Y (true) or N (false), return null, so the above sequence
// will just keep executing until it gets the answer
private fun yesOrNo(string: String): Boolean? =
when (string.uppercase().firstOrNull()) {
'Y' -> true
'N' -> false
else -> null
}
private fun printKnownAnimals(question: QuestionOrAnswer) {
println("\nANIMALS I ALREADY KNOW ARE:")
val animals = question.getAnswers().chunked(4)
animals.forEach { line ->
// The '*' in front of line.toTypedArray() "spreads" the array as a list of parameters instead
System.out.printf("%-15s".repeat(line.size), *line.toTypedArray())
println()
}
}
private fun printIntro() {
println(" ANIMAL")
println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
println("\n\n")
println("PLAY 'GUESS THE ANIMAL'")
println("\n")
println("THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.")
}
class QuestionOrAnswer(private var answer: String? = null, var question: Question? = null) {
fun getAnswers(): List<String> = answer?.let { listOf(it) } ?: question!!.getAnswers()
fun getWrongAnswer(): QuestionOrAnswer? {
if (answer != null) {
// "takeUnless" will return null if the answer is "yes". In this case
// we will return the "wrong answer", aka the terminal answer that was incorrect
return this.takeUnless { askYesOrNo("IS IT A $answer") }
}
return question?.getWrongAnswer()
}
fun askForInformationAndSave() {
//Failed to get it right and ran out of questions
//Let's ask the user for the new information
val newAnimal = ask("THE ANIMAL YOU WERE THINKING OF WAS A")
val newQuestion = ask("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A \n$newAnimal FROM A $answer\n")
val newAnswer = askYesOrNo("FOR A $newAnimal THE ANSWER WOULD BE")
val trueAnswer = if (newAnswer) newAnimal else answer
val falseAnswer = if (newAnswer) answer else newAnimal
// Replace our answer with null and set the question with the data we just got
// This makes it a question instead of an answer
this.answer = null
this.question = Question(newQuestion, QuestionOrAnswer(trueAnswer), QuestionOrAnswer(falseAnswer))
}
}
class Question(
private val question: String,
private val trueAnswer: QuestionOrAnswer,
private val falseAnswer: QuestionOrAnswer
) {
fun getAnswers(): List<String> = trueAnswer.getAnswers() + falseAnswer.getAnswers()
fun getWrongAnswer(): QuestionOrAnswer? =
if (askYesOrNo(question)) {
trueAnswer.getWrongAnswer()
} else {
falseAnswer.getWrongAnswer()
}
}

View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Kotlin](https://kotlinlang.org/)

264
04_Awari/csharp/Game.cs Normal file
View File

@@ -0,0 +1,264 @@
namespace Awari;
public class Game
{
public int[] PlayerPits => _beans[0..6];
public int[] ComputerPits => _beans[7..13];
public int PlayerHome => _beans[_playerHome];
public int ComputerHome => _beans[_computerHome];
private bool IsDone =>
PlayerPits.All(b => b == 0) // if all the player's pits are empty
|| ComputerPits.All(b => b == 0); // or if all the computer's pits are empty
public GameState State { get; private set; }
public void Reset()
{
State = GameState.PlayerMove;
Array.Fill(_beans, _initialPitValue);
_beans[_playerHome] = 0;
_beans[_computerHome] = 0;
_moveCount = 0;
_notWonGameMoves[^1] = 0;
}
public bool IsLegalPlayerMove(int move) =>
move is > 0 and < 7
&& _beans[move - 1] > 0; // arrays are zero-based, but moves are one-based
public void PlayerMove(int move) => MoveAndRegister(move - 1, _playerHome);
public List<int> ComputerTurn()
{
// keep a list of moves made by the computer in a single turn (1 or 2)
List<int> moves = new();
moves.Add(ComputerMove()); // ComputerMove() returns the move made
// only if a second move is possible, do it
if (State == GameState.ComputerSecondMove)
moves.Add(ComputerMove());
return moves;
}
public GameOutcome GetOutcome()
{
if (State != GameState.Done)
throw new InvalidOperationException("Game is not yet done.");
int difference = _beans[_playerHome] - _beans[_computerHome];
var winner = difference switch
{
< 0 => GameWinner.Computer,
0 => GameWinner.Draw,
> 0 => GameWinner.Player,
};
return new GameOutcome(winner, Math.Abs(difference));
}
private void MoveAndRegister(int pit, int homePosition)
{
int lastMovedBean = Move(_beans, pit, homePosition);
// encode moves by player and computer into a 'base 6' number
// e.g. if the player moves 5, the computer moves 2, and the player moves 4,
// that would be encoded as ((5 * 6) * 6) + (2 * 6) + 4 = 196
if (pit > 6) pit -= 7;
_moveCount++;
if (_moveCount < 9)
_notWonGameMoves[^1] = _notWonGameMoves[^1] * 6 + pit;
// determine next state based on current state, whether the game's done, and whether the last moved bean moved
// into the player's home position
State = (State, IsDone, lastMovedBean == homePosition) switch
{
(_, true, _) => GameState.Done,
(GameState.PlayerMove, _, true) => GameState.PlayerSecondMove,
(GameState.PlayerMove, _, false) => GameState.ComputerMove,
(GameState.PlayerSecondMove, _, _) => GameState.ComputerMove,
(GameState.ComputerMove, _, true) => GameState.ComputerSecondMove,
(GameState.ComputerMove, _, false) => GameState.PlayerMove,
(GameState.ComputerSecondMove, _, _) => GameState.PlayerMove,
_ => throw new InvalidOperationException("Unexpected game state"),
};
// do some bookkeeping if the game is done, but not won by the computer
if (State == GameState.Done
&& _beans[_playerHome] >= _beans[_computerHome])
// add an entry for the next game
_notWonGameMoves.Add(0);
}
private static int Move(int[] beans, int pit, int homePosition)
{
int beansToMove = beans[pit];
beans[pit] = 0;
// add the beans that were in the pit to other pits, moving clockwise around the board
for (; beansToMove >= 1; beansToMove--)
{
// wrap around if pit exceeds 13
pit = (pit + 1) % 14;
beans[pit]++;
}
if (beans[pit] == 1 // if the last bean was sown in an empty pit
&& pit is not _playerHome and not _computerHome // which is not either player's home
&& beans[12 - pit] != 0) // and the pit opposite is not empty
{
// move the last pit sown and the _beans in the pit opposite to the player's home
beans[homePosition] = beans[homePosition] + beans[12 - pit] + 1;
beans[pit] = 0;
beans[12 - pit] = 0;
}
return pit;
}
private int ComputerMove()
{
int move = DetermineComputerMove();
MoveAndRegister(move, homePosition: _computerHome);
// the result is only used to return it to the application, so translate it from an array index (between 7 and
// 12) to a pit number (between 1 and 6)
return move - 6;
}
private int DetermineComputerMove()
{
int bestScore = -99;
int move = 0;
// for each of the computer's possible moves, simulate them to calculate a score and pick the best one
for (int j = 7; j < 13; j++)
{
if (_beans[j] <= 0)
continue;
int score = SimulateMove(j);
if (score >= bestScore)
{
move = j;
bestScore = score;
}
}
return move;
}
private int SimulateMove(int move)
{
// make a copy of the current state, so we can safely mess with it
var hypotheticalBeans = new int[14];
_beans.CopyTo(hypotheticalBeans, 0);
// simulate the move in our copy
Move(hypotheticalBeans, move, homePosition: _computerHome);
// determine the 'best' move the player could make after this (best for them, not for the computer)
int score = ScoreBestNextPlayerMove(hypotheticalBeans);
// score this move by calculating how far ahead we would be after the move, and subtracting the player's next
// move score
score = hypotheticalBeans[_computerHome] - hypotheticalBeans[_playerHome] - score;
// have we seen the current set of moves before in a drawn/lost game? after 8 moves it's unlikely we'll find any
// matches, since games will have diverged. also we don't have space to store that many moves.
if (_moveCount < 8)
{
int translatedMove = move - 7; // translate from 7 through 12 to 0 through 5
// if the first two moves in this game were 1 and 2, and this hypothetical third move would be a 3,
// movesSoFar would be (1 * 36) + (2 * 6) + 3 = 51
int movesSoFar = _notWonGameMoves[^1] * 6 + translatedMove;
// since we store moves as a 'base 6' number, we need to divide stored moves by a power of 6
// let's say we've a stored lost game where the moves were, in succession, 1 through 8, the value stored
// would be:
// 8 + (7 * 6) + (6 * 36) + (5 * 216) + (4 * 1296) + (3 * 7776) + (2 * 46656) + (1 * 279936) = 403106
// to figure out the first three moves, we'd need to divide by 7776, resulting in 51.839...
double divisor = Math.Pow(6.0, 7 - _moveCount);
foreach (int previousGameMoves in _notWonGameMoves)
// if this combination of moves so far ultimately resulted in a draw/loss, give it a lower score
// note that this can happen multiple times
if (movesSoFar == (int) (previousGameMoves / divisor + 0.1))
score -= 2;
}
return score;
}
private static int ScoreBestNextPlayerMove(int[] hypotheticalBeans)
{
int bestScore = 0;
for (int i = 0; i < 6; i++)
{
if (hypotheticalBeans[i] <= 0)
continue;
int score = ScoreNextPlayerMove(hypotheticalBeans, i);
if (score > bestScore)
bestScore = score;
}
return bestScore;
}
private static int ScoreNextPlayerMove(int[] hypotheticalBeans, int move)
{
// figure out where the last bean will land
int target = hypotheticalBeans[move] + move;
int score = 0;
// if it wraps around, that means the player is adding to his own pits, which is good
if (target > 13)
{
// prevent overrunning the number of pits we have
target %= 14;
score = 1;
}
// if the player's move ends up in an empty pit, add the value of the pit on the opposite side to the score
if (hypotheticalBeans[target] == 0 && target is not _playerHome and not _computerHome)
score += hypotheticalBeans[12 - target];
return score;
}
private const int _playerHome = 6;
private const int _computerHome = 13;
private const int _initialPitValue = 3;
private readonly int[] _beans = new int[14];
private readonly List<int> _notWonGameMoves = new() { 0 }; // not won means draw or lose
private int _moveCount;
}
public enum GameState
{
PlayerMove,
PlayerSecondMove,
ComputerMove,
ComputerSecondMove,
Done,
}
public enum GameWinner
{
Player,
Computer,
Draw,
}
public record struct GameOutcome(GameWinner Winner, int Difference);

View File

@@ -0,0 +1,98 @@
using Awari;
Console.WriteLine(Tab(34) + "AWARI");
Console.WriteLine(Tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
Game game = new();
while (true)
{
game.Reset();
DisplayGame();
while (game.State != GameState.Done)
{
switch (game.State)
{
case GameState.PlayerMove:
PlayerMove(second: false);
break;
case GameState.PlayerSecondMove:
PlayerMove(second: true);
break;
case GameState.ComputerMove:
ComputerTurn();
break;
}
DisplayGame();
}
var outcome = game.GetOutcome();
string outcomeLabel =
outcome.Winner switch
{
GameWinner.Computer => $"I WIN BY {outcome.Difference} POINTS",
GameWinner.Draw => "DRAWN GAME",
GameWinner.Player => $"YOU WIN BY {outcome.Difference} POINTS",
_ => throw new InvalidOperationException($"Unexpected winner {outcome.Winner}."),
};
Console.WriteLine(outcomeLabel);
Console.WriteLine();
}
void DisplayGame()
{
// display the computer's pits
Console.Write(" ");
foreach (var pit in game.ComputerPits.Reverse())
Console.Write($"{pit,2} ");
Console.WriteLine();
// display both homes
Console.WriteLine($"{game.ComputerHome,2}{Tab(19)}{game.PlayerHome,2}");
// display the player's pits
Console.Write(" ");
foreach (var pit in game.PlayerPits)
Console.Write($"{pit,2} ");
Console.WriteLine();
Console.WriteLine();
}
void PlayerMove(bool second = false)
{
int move = GetMove(second);
game.PlayerMove(move);
}
int GetMove(bool second)
{
string prompt = second ? "AGAIN? " : "YOUR MOVE? ";
while (true)
{
Console.Write(prompt);
string input = Console.ReadLine() ?? "";
// input must be a number between 1 and 6, and the pit must have > 0 beans
if (int.TryParse(input, out int move)
&& game.IsLegalPlayerMove(move))
return move;
Console.WriteLine("ILLEGAL MOVE");
}
}
void ComputerTurn()
{
var moves = game.ComputerTurn();
string movesString = string.Join(",", moves);
Console.WriteLine($"MY MOVE IS {movesString}");
}
string Tab(int n) => new(' ', n);

View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Awari</RootNamespace>
</PropertyGroup>
</Project>

195
05_Bagels/perl/bagels.pl Executable file
View File

@@ -0,0 +1,195 @@
#!/usr/bin/perl
use strict;
use warnings;
# global variable declaration (just the user's score)
my($Y) = 0;
# yes_input is a subroutine that returns a true value
# if the first character of the user's input from STDIN
# is a 'Y' (checking case-insensitively via regex)
sub yes_input {
chomp(my $A = <STDIN>);
return $A =~ m/^Y/i;
}
# Main code starts here.
print ' 'x32; print "Bagels\n";
print ' 'x14; print "Creative Computing Morristown, New Jersey\n\n";
# Provide instructions if requested
print "Would you like the rules (yes or no)? ";
if (yes_input()) {
# Print out the instructions using a here doc
# (useful for large blocks of text)
print <<HERE;
I am thinking of a three-digit number. Try to guess
my number and I will give you clues as follows:
PICO - one digit correct but in the wrong position
FERMI - one digit correct and in the right place
BAGELS - no digits correct
HERE
}
# There are three code loops here. The outermost one, labeled 'PLAY',
# performs one game start to finish every time it runs.
# The next loop is a for loop that implements the required 20 guesses.
# And the innermost loop, labeled 'CHECK', does the game logic of
# checking the user's guess to make sure it's valid, figuring out
# the response, and rewarding the user if they won.
PLAY: while (1) {
# The computer's number is three randomly selected unique digits.
# To generate the number, 3 digits are randomly splice()d out
# of the @DIGITS array, which is initialized with the digits 0 to 9.
my @DIGITS = (0..9);
my @A = ();
push @A, splice(@DIGITS, int(rand(scalar @DIGITS)), 1) for 1..3;
print "\n";
print "O.K. I have a number in mind.\n";
for my $i (1..20) {
# Note that the CHECK loop will automatically loop to ask
# for the user's input, and it's only with the 'next' and
# 'last' statements that this loop is exited. So if the
# user's input is somehow invalid, we just print out an
# appropriate message. Execution will by default return
# to the start of the loop, and only leaves the loop if
# the user's input is successfully parsed and accepted
# (look for the 'next' and 'last' statements below).
CHECK: while (1) {
printf("Guess # %2d ? ", $i);
chomp(my $A = <STDIN>);
# Use a regex to check if the user entered three digits,
# and complain if they did not.
if ($A !~ m{^(\d)(\d)(\d)$}) {
print "What?\n";
# Program execution will now pass through the rest
# of the logic below and loop back to the start
# of the CHECK loop.
} else {
# As a side effect of the regex match above, the
# $1, $2, and $3 variables are each of the digits
# of the user's guess. Perl treats numbers and
# strings interchangably, so we will not have to
# use the ASC() conversion functions required
# by the BASIC program.
my @B = ($1,$2,$3);
# Check for duplicate digits in the user's guess
if ($B[0] == $B[1] || $B[0] == $B[2] || $B[1] == $B[2]) {
print "Oh, I forgot to tell you that the number I have in mind\n";
print "has no two digits the same.\n";
# Again, no further action is required here
# because we want to loop back to the start
# of the CHECK loop.
} else {
# This code block is the actual game logic, so
# it's executed only if the user's input has
# passed all the above checks.
my($C,$D);
$C = 0; $D = 0;
# As a replacement for the original BASIC logic,
# this for loop works over an anonymous array of
# pairs of digits to compare the computer's and
# the user's digits to see how many similar ones
# there are. Keep in mind that Perl arrays are
# zero-indexed, so we're comparing items numbered
# 0, 1, and 2, instead of 1, 2, and 3 in BASIC.
for my $PAIR ( [0,1], [1,0], [1,2], [2,1], [0,2], [2,0] ) {
if ($A[$PAIR->[0]] == $B[$PAIR->[1]]) {
++$C;
}
}
# Check for digits that are correctly guessed
for my $i (0..2) {
if ($A[$i] == $B[$i]) {
++$D;
}
}
# If the user guessed all 3 digits they get
# a point, and the 'PLAY' loop is restarted
# (see the 'continue' loop below)
if ($D == 3) {
print "You got it!!!\n\n";
++$Y;
next PLAY;
}
# Print out the clues. The 'x' operator
# prints out the string the indicated number
# of times. The "BAGELS" line uses Perl's
# ternary operator to print the word if
# the expression ($C + $D) is equal to 0.
printf("%s%s%s\n",
"PICO " x$C,
"FERMI "x$D,
($C+$D==0 ? "BAGELS" : '')
);
# Program execution leaves the CHECK loop and
# goes to the next iteration of the $i loop.
last CHECK;
} # end of game logic else block
} # end of regex match else block
# If program execution reaches this particular point,
# then the user's input has not been accepted (the
# only ways out of this loop are the "next PLAY" statement
# when the user wins, and the "last CHECK" statement
# when the user's input is successfully parsed).
# So the program execution goes back to the top of the
# CHECK loop, printing the request for user input
# again.
} # end of CHECK loop
# This location is reached by the "last CHECK" statement,
# and it's another execution of the $i loop.
} # end of $i loop
# If program execution reaches here, the user has guessed 20
# times and not won.
print "Oh well.\n";
printf("That's twenty guesses. My number was %s\n", join('',@A));
} # end of the PLAY loop
# This 'continue' block is executed before the conditional part of the
# PLAY loop is evaluated, so we can ask if the user wants another game
# (i.e., if we should restart the PLAY loop).
continue {
# This 'continue' loop is reached either when the PLAY loop has completed
# or via the 'next PLAY' statement when the user wins a game. In either
# case we ask if the player wants to go again, and use the 'last'
# statement to exit the loop if the response is not yes.
print "Play again (yes or no) ? ";
last unless yes_input();
}
# And as in the original BASIC program, print out
# the user's score only if it is > 0.
printf("A %d point bagels buff!\n", $Y) if $Y > 0;
print "Hope you had fun. Bye.\n";

View File

@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.810.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Change", "Change.csproj", "{AE094667-8496-4ECF-8B42-B1648EE26073}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AE094667-8496-4ECF-8B42-B1648EE26073}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE094667-8496-4ECF-8B42-B1648EE26073}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE094667-8496-4ECF-8B42-B1648EE26073}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE094667-8496-4ECF-8B42-B1648EE26073}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65684CBD-CD74-46AF-8E9E-0F69DCF72697}
EndGlobalSection
EndGlobal

129
22_Change/csharp/Program.cs Normal file
View File

@@ -0,0 +1,129 @@
using System;
namespace Change
{
class Program
{
/// <summary>
/// Prints header.
/// </summary>
static void Header()
{
Console.WriteLine("Change".PadLeft(33));
Console.WriteLine("Creative Computing Morristown, New Jersey".PadLeft(15));
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("I, your friendly microcomputer, will determine\n"
+ "the correct change for items costing up to $100.");
Console.WriteLine();
Console.WriteLine();
}
/// <summary>
/// Gets user input for price and payment.
/// </summary>
/// <returns>
/// False if any input can't be parsed to double. Price and payment returned would be 0.
/// True if it was possible to parse inputs into doubles. Price and payment returned
/// would be as provided by the user.
/// </returns>
static (bool status, double price, double payment) GetInput()
{
Console.Write("Cost of item? ");
var priceString = Console.ReadLine();
if (!double.TryParse(priceString, out double price))
{
Console.WriteLine($"{priceString} isn't a number!");
return (false, 0, 0);
}
Console.Write("Amount of payment? ");
var paymentString = Console.ReadLine();
if (!double.TryParse(paymentString, out double payment))
{
Console.WriteLine($"{paymentString} isn't a number!");
return (false, 0, 0);
}
return (true, price, payment);
}
/// <summary>
/// Prints bills and coins for given change.
/// </summary>
/// <param name="change"></param>
static void PrintChange(double change)
{
var tens = (int)(change / 10);
if (tens > 0)
Console.WriteLine($"{tens} ten dollar bill(s)");
var temp = change - (tens * 10);
var fives = (int)(temp / 5);
if (fives > 0)
Console.WriteLine($"{fives} five dollar bill(s)");
temp -= fives * 5;
var ones = (int)temp;
if (ones > 0)
Console.WriteLine($"{ones} one dollar bill(s)");
temp -= ones;
var cents = temp * 100;
var half = (int)(cents / 50);
if (half > 0)
Console.WriteLine($"{half} one half dollar(s)");
temp = cents - (half * 50);
var quarters = (int)(temp / 25);
if (quarters > 0)
Console.WriteLine($"{quarters} quarter(s)");
temp -= quarters * 25;
var dimes = (int)(temp / 10);
if (dimes > 0)
Console.WriteLine($"{dimes} dime(s)");
temp -= dimes * 10;
var nickels = (int)(temp / 5);
if (nickels > 0)
Console.WriteLine($"{nickels} nickel(s)");
temp -= nickels * 5;
var pennies = (int)(temp + 0.5);
if (pennies > 0)
Console.WriteLine($"{pennies} penny(s)");
}
static void Main(string[] args)
{
Header();
while (true)
{
(bool result, double price, double payment) = GetInput();
if (!result)
continue;
var change = payment - price;
if (change == 0)
{
Console.WriteLine("Correct amount, thank you!");
continue;
}
if (change < 0)
{
Console.WriteLine($"Sorry, you have short-changed me ${price - payment:N2}!");
continue;
}
Console.WriteLine($"Your change ${change:N2}");
PrintChange(change);
Console.WriteLine("Thank you, come again!");
Console.WriteLine();
}
}
}
}

68
22_Change/perl/change.pl Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/perl
use v5.24; # for say and use strict
use warnings;
sub get_pennies {
my $query = shift;
print "$query? ";
my $in = <>;
chomp $in;
$in =~ /([\d.]+)/; # the first match of digits and decimal points
return int( $1 * 100 );
}
sub make_change {
my $change = shift;
state %change_options = (
'Penny' => { value => 1, plural => 'Pennies' },
'Nickel' => { value => 5 },
'Dime' => { value => 10 },
'Quarter' => { value => 25 },
'One Half Dollar' => { value => 50 },
'One Dollar Bill' => { value => 100 * 1 },
'Five Dollar Bill' => { value => 100 * 5 },
'10 Dollar Bill' => { value => 100 * 10 },
);
foreach my $unit ( sort { $change_options{$b}->{value} <=> $change_options{$a}->{value} } keys %change_options ) {
my $value = $change_options{$unit}->{value};
next if $value > $change;
my $number = int( $change / $value );
if ( $number > 1 ) {
$unit = exists $change_options{$unit}->{plural} ? $change_options{$unit}->{plural} : "${unit}s";
}
say "$number $unit";
$change -= $number * $value;
}
}
print <<'__END_OF_INTRO';
Change
Creative Computing Morristown, New Jersey
I, Your friendly microcomputer, will determine
the correct change for items costing up to $100.
__END_OF_INTRO
while ( 1 ) {
my $cost = get_pennies( 'Cost of item' );
my $payment = get_pennies( 'Amount of payment');
my $change = $payment - $cost;
my $change_formatted = sprintf( "%.2f", $change / 100 );
if ( $change == 0 ) {
say 'Correct amount, thank you.';
} elsif ( $change < 0 ) {
say 'Sorry, you have short-changed me $', abs($change_formatted);
} else {
say 'Your change, $', $change_formatted;
make_change( $change );
say "Thank you, come again\n\n";
}
}

View File

@@ -8,30 +8,30 @@ print "THE FICTITIOUS CHECMICAL KRYPTOCYANIC ACID CAN ONLY BE\n";
print "DILUTED BY THE RATIO OF 7 PARTS WATER TO 3 PARTS ACID.\n";
print "IF ANY OTHER RATIO IS ATTEMPTED, THE ACID BECOMES UNSTABLE\n";
print "AND SOON EXPLODES. GIVEN THE AMOUNT OF ACID, YOU MUST\n";
print "DECIDE WHO MUCH WATER TO ADD FOR DILUTION. IF YOU MISS\n";
print "DECIDE HOW MUCH WATER TO ADD FOR DILUTION. IF YOU MISS\n";
print "YOU FACE THE CONSEQUENCES.\n";
my $T=0;
while ($T<9) {
my $A= int(rand(1)*50);
my $A= int(rand(50) + 1);
my $W= 7*$A/3;
print "$A LITERS OF KRYPTOCYANIC ACID. HOW MUCH WATER ($W)";
print "? "; chomp(my $R = <STDIN>);
print " $A LITERS OF KRYPTOCYANIC ACID. HOW MUCH WATER? ";
chomp(my $R = <STDIN>);
my $D= abs($W-$R);
if ($D>$W/20) {
print " SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB\n";
print " OF QUIVERING PROTOPLASM!\n";
print " HOWEVER, YOU MAY TRY AGAIN WITH ANOTHER LIFE.\n";
print "SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB\n";
print "OF QUIVERING PROTOPLASM!\n";
print "HOWEVER, YOU MAY TRY AGAIN WITH ANOTHER LIFE.\n";
print "\n";
$T++;
} else {
print " GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!\n";
} else {
print "GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!\n";
print "\n";
}
}
}
print " YOUR 9 LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR\n";
print " YOUR CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY.\n";
print "YOUR 9 LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR\n";
print "YOUR CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY.\n";
exit;

79
29_Craps/python/craps.py Normal file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""This game simulates the games of craps played according to standard Nevada craps table rules.
That is:
1. A 7 or 11 on the first roll wins
2. A 2, 3, or 12 on the first roll loses
3. Any other number rolled becomes your "point." You continue to roll; if you get your point you win. If you
roll a 7, you lose and the dice change hands when this happens.
This version of craps was modified by Steve North of Creative Computing. It is based on an original which
appeared one day one a computer at DEC.
"""
from random import randint
def throw_dice():
return randint(1, 6) + randint(1, 6)
print(" " * 33 + "Craps")
print(" " * 15 + "Creative Computing Morristown, New Jersey")
print()
print()
print()
winnings = 0
print("2,3,12 are losers; 4,5,6,8,9,10 are points; 7,11 are natural winners.")
play_again = True
while play_again:
wager = int(input("Input the amount of your wager: "))
print("I will now throw the dice")
roll_1 = throw_dice()
if roll_1 in [7, 11]:
print(f"{roll_1} - natural.... a winner!!!!")
print(f"{roll_1} pays even money, you win {wager} dollars")
winnings += wager
elif roll_1 == 2:
print(f"{roll_1} - snake eyes.... you lose.")
print(f"You lose {wager} dollars")
winnings -= wager
elif roll_1 in [3, 12]:
print(f"{roll_1} - craps.... you lose.")
print(f"You lose {wager} dollars")
winnings -= wager
else:
print(f"{roll_1} is the point. I will roll again")
roll_2 = 0
while roll_2 not in [roll_1, 7]:
roll_2 = throw_dice()
if roll_2 == 7:
print(f"{roll_2} - craps. You lose.")
print(f"You lose $ {wager}")
winnings -= wager
elif roll_2 == roll_1:
print(f"{roll_1} - a winner.........congrats!!!!!!!!")
print(f"{roll_1} at 2 to 1 odds pays you...let me see... {2 * wager} dollars")
winnings += 2 * wager
else:
print(f"{roll_2} - no point. I will roll again")
m = input(" If you want to play again print 5 if not print 2: ")
if winnings < 0:
print(f"You are now under ${-winnings}")
elif winnings > 0:
print(f"You are now ahead ${winnings}")
else:
print("You are now even at 0")
play_again = (m == "5")
if winnings < 0:
print(f"Too bad, you are in the hole. Come again.")
elif winnings > 0:
print(f"Congratulations---you came out a winner. Come again.")
else:
print(f"Congratulations---you came out even, not bad for an amateur")

View File

@@ -0,0 +1,69 @@
# EditorConfig is awesome: https://EditorConfig.org
# .editorconfig
# Please see doc/developer_notes.md
# If you find anything egregious or missing, please consider submitting a pull request
# to https://github.com/theias/ias_package_shell
# top-most EditorConfig file
root = true
# Sensible defaults for everything
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
# JavaScript
[**.js]
indent_style = space
indent_size = 2
insert_final_newline = true
# Ruby
[**.rb]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
# Python
[**.py]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
# Perl
[**.pl]
charset = utf-8
insert_final_newline = true
[**.pm]
charset = utf-8
insert_final_newline = true
# PHP
[**.php]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
# Makefiles
[Makefile]
indent_style = tab
[**.gmk]
indent_style = tab
# Configuration Files
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
# Diff files
[*.{diff,patch}]
trim_trailing_whitespace = false

View File

@@ -0,0 +1,211 @@
#!/usr/bin/ruby
class DepthCharge
def run_game
output_title()
while true
printf("----------\n")
print_instructions()
setup_game()
printf("\n")
game_loop()
break if ! get_input_another_game()
end
# 420 PRINT "OK. HOPE YOU ENJOYED YOURSELF." : GOTO 600
printf("OK. HOPE YOU ENJOYED YOURSELF.\n")
end
def output_title
printf("--- DEPTH CHARGE ---\n")
printf("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n")
printf("\n")
end
def get_input_y_or_n(message)
while true
print(message)
value = gets.chomp
if (value == 'Y' || value == 'y')
return true
elsif value == 'N' || value == 'n'
return false
end
printf("PLEASE ENTER Y/y OR N/n...\n\n")
end
end
def get_input_positive_integer(message)
while true
print(message)
value = gets.chomp
if (value == 'd')
debug_game()
next
end
the_input = Integer(value) rescue nil
if the_input == nil || the_input < 0
printf("PLEASE ENTER A POSITIVE NUMBER\n\n")
next
end
return the_input
end
end
def get_search_area_dimension
# 20 INPUT "DIMENSION OF SEARCH AREA";G: PRINT
@search_area_dimension = get_input_positive_integer("DIMENSION OF SEARCH AREA: ")
# 30 N=INT(LOG(G)/LOG(2))+1
@num_tries = Integer(
Math.log(@search_area_dimension)/Math.log(2)
)
end
def print_instructions
# 40 PRINT "YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER"
# 50 PRINT "AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR"
# 60 PRINT "MISSION IS TO DESTROY IT. YOU HAVE";N;"SHOTS."
# 70 PRINT "SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A"
# 80 PRINT "TRIO OF NUMBERS -- THE FIRST TWO ARE THE"
# 90 PRINT "SURFACE COORDINATES; THE THIRD IS THE DEPTH."
# 100 PRINT : PRINT "GOOD LUCK !": PRINT
printf( <<~INSTRUCTIONS
YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER
AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR
MISSION IS TO DESTROY IT.
SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A
TRIO OF NUMBERS -- THE FIRST TWO ARE THE
SURFACE COORDINATES (X, Y):
WEST < X < EAST
SOUTH < Y < NORTH
THE THIRD IS THE DEPTH (Z):
SHALLOW < Z < DEEP
GOOD LUCK !
INSTRUCTIONS
)
end
def debug_game
printf("@enemy_x: %d\n", @enemy_x)
printf("@enemy_y: %d\n", @enemy_y)
printf("@enemy_z: %d\n", @enemy_z)
printf("@num_tries: %d\n", @num_tries)
printf("@trial: %d\n", @trial)
printf("\n")
end
def setup_game
get_search_area_dimension()
setup_enemy()
end
def setup_enemy
# 110 A=INT(G*RND(1)) : B=INT(G*RND(1)) : C=INT(G*RND(1))
@enemy_x = rand(1..@search_area_dimension)
@enemy_y = rand(1..@search_area_dimension)
@enemy_z = rand(1..@search_area_dimension)
end
def game_loop
# 120 FOR D=1 TO N : PRINT : PRINT "TRIAL #";D; : INPUT X,Y,Z
for @trial in 1..@num_tries do
output_game_status()
@shot_x = get_input_positive_integer("X: ")
@shot_y = get_input_positive_integer("Y: ")
@shot_z = get_input_positive_integer("Z: ")
# 130 IF ABS(X-A)+ABS(Y-B)+ABS(Z-C)=0 THEN 300
if (
(@enemy_x - @shot_x).abs \
+ (@enemy_y - @shot_y).abs \
+ (@enemy_z - @shot_z).abs \
== 0
)
you_win()
return
else
# 140 GOSUB 500 : PRINT : NEXT D
missed_shot()
end
end
printf("\n")
you_lose()
end
def output_game_status
printf("YOU HAVE %d SHOTS REMAINING.\n", @num_tries - @trial + 1)
printf("TRIAL \#%d\n", @trial)
end
def you_win
printf("B O O M ! ! YOU FOUND IT IN %d TRIES!\n\n", @trial )
end
def missed_shot
missed_directions = []
# 530 IF X>A THEN PRINT "EAST";
# 540 IF X<A THEN PRINT "WEST";
if @shot_x > @enemy_x
missed_directions.push('TOO FAR EAST')
elsif @shot_x < @enemy_x
missed_directions.push('TOO FAR WEST')
end
# 510 IF Y>B THEN PRINT "NORTH";
# 520 IF Y<B THEN PRINT "SOUTH";
if @shot_y > @enemy_y
missed_directions.push('TOO FAR NORTH')
elsif @shot_y < @enemy_y
missed_directions.push('TOO FAR SOUTH')
end
# 560 IF Z>C THEN PRINT " TOO LOW."
# 570 IF Z<C THEN PRINT " TOO HIGH."
# 580 IF Z=C THEN PRINT " DEPTH OK."
if @shot_z > @enemy_z
missed_directions.push('TOO DEEP')
elsif @shot_z < @enemy_z
missed_directions.push('TOO SHALLOW')
end
# 500 PRINT "SONAR REPORTS SHOT WAS ";
printf("SONAR REPORTS SHOT WAS: \n")
printf("%s\n", "\t" + missed_directions.join("\n\t"))
# 550 IF Y<>B OR X<>A THEN PRINT " AND";
# 590 RETURN
end
def you_lose
# You took too long!
printf("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!\n")
printf("THE SUBMARINE WAS AT %d %d %d\n", @enemy_x, @enemy_y, @enemy_z)
end
def get_input_another_game
# 400 PRINT : PRINT: INPUT "ANOTHER GAME (Y OR N)";A$
return get_input_y_or_n("ANOTHER GAME (Y OR N): ")
# 410 IF A$="Y" THEN 100
end
end
game = DepthCharge.new
game.run_game()

View File

@@ -0,0 +1,129 @@
# Flip Flop
#
# The object of this game is to change a row of ten X's
# X X X X X X X X X X
# to a row of ten O's:
# O O O O O O O O O O
# by typing in a number corresponding
# to the position of an "X" in the line. On
# some numbers one position will
# change while on other numbers, two
# will change. For example, inputting a 3
# may reverse the X and O in position 3,
# but it might possibly reverse some
# other position too! You ought to be able
# to change all 10 in 12 or fewer
# moves. Can you figure out a good win-
# ning strategy?
# To reset the line to all X's (same
# game), type 0 (zero). To start a new
# game at any point, type 11.
# The original author of this game was
# Michael Kass of New Hyde Park, New
# York.
import random
import math
from typing import Callable, List, Tuple
flip_dict = {"X": "O", "O": "X"}
def flip_bits(
row: List[str], m: int, n: int, r_function: Callable[[int], float]
) -> Tuple[List[str], int]:
"""
Function that flips the positions at the computed steps
"""
while m == n:
r = r_function(n)
n = r - int(math.floor(r))
n = int(10 * n)
if row[n] == "X":
row[n] = "O"
break
elif row[n] == "O":
row[n] = "X"
return row, n
def print_instructions():
print(" " * 32 + "FLIPFLOP")
print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print("\n" * 2)
print("THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS:\n")
print("X X X X X X X X X X\n")
print("TO THIS:\n")
print("O O O O O O O O O O\n")
print("BY TYPING TH NUMBER CORRESPONDING TO THE POSITION OF THE")
print("LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON")
print("OTHERS, TWO WILL CHANGE. TO RESET LINE TO ALL X'S, TYPE 0")
print("(ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE ")
print("11 (ELEVEN).\n")
def main():
q = random.random()
print("HERE IS THE STARTING LINE OF X'S.\n")
# We add an extra 0-th item because this sometimes is set to something
# but we never check what it is for completion of the puzzle
row = [""] + ["X"] * 10
counter_turns = 0
n = -1
legal_move = True
while row[1:] != ["O"] * 10:
if legal_move:
print(" ".join([str(i) for i in range(1, 11)]))
print(" ".join(row[1:]) + "\n")
m = input("INPUT THE NUMBER\n")
try:
m = int(m)
if m > 11 or m < 0:
raise ValueError()
except ValueError:
print("ILLEGAL ENTRY--TRY AGAIN")
legal_move = False
continue
legal_move = True
if m == 11:
# completely reset the puzzle
counter_turns = 0
row = [""] + ["X"] * 10
q = random.random()
continue
elif m == 0:
# reset the board, but not the counter or the random number
row = [""] + ["X"] * 10
elif m == n:
row[n] = flip_dict[row[n]]
r_function = lambda n_t: 0.592 * (1 / math.tan(q / n_t + q)) / math.sin(
n_t * 2 + q
) - math.cos(n_t)
row, n = flip_bits(row, m, n, r_function)
else:
n = m
row[n] = flip_dict[row[n]]
r_function = lambda n_t: (
math.tan(q + n_t / q - n_t)
- math.sin(n_t * 2 + q)
+ 336 * math.sin(8 * n_t)
)
row, n = flip_bits(row, m, n, r_function)
counter_turns += 1
print()
if counter_turns <= 12:
print(f"VERY GOOD. YOU GUESSED IT IN ONLY {counter_turns} GUESSES.")
else:
print(f"TRY HARDER NEXT TIME. IT TOOK YOU {counter_turns} GUESSES.")
return
if __name__ == "__main__":
print_instructions()
another = ""
while another != "NO":
main()
another = input("DO YOU WANT TO TRY ANOTHER PUZZLE\n")

136
45_Hello/perl/hello.pl Normal file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/perl
use strict;
use warnings;
print ' ' x 33 . "HELLO\n";
print ' ' x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
print "\n\n\n";
print "HELLO. MY NAME IS CREATIVE COMPUTER.\n\n\n";
print "WHAT'S YOUR NAME?\n";
chomp( my $N = uc <STDIN> );
print "\nHI THERE, $N, ARE YOU ENJOYING YOURSELF HERE?\n";
GREET:
{
chomp( my $B = uc <STDIN> );
print "\n";
if ( $B eq 'YES' ) {
print "I'M GLAD TO HEAR THAT, $N.\n\n";
}
elsif ( $B eq 'NO' ) {
print "OH, I'M SORRY TO HEAR THAT, $N. MAYBE WE CAN\n";
print "BRIGHTEN UP YOUR VISIT A BIT.\n";
}
else {
print "$N, I DON'T UNDERSTAND YOUR ANSWER OF '$B'.\n";
print "PLEASE ANSWER 'YES' OR 'NO'. DO YOU LIKE IT HERE?\n";
redo GREET;
}
}
print "\nSAY, $N, I CAN SOLVE ALL KINDS OF PROBLEMS EXCEPT\n";
print "THOSE DEALING WITH GREECE. WHAT KIND OF PROBLEMS DO\n";
print "YOU HAVE (ANSWER SEX, HEALTH, MONEY, OR JOB)?\n";
ADVICE:
{
chomp( my $C = uc <STDIN> );
print "\n";
if ( $C eq 'SEX' ) {
print "IS YOUR PROBLEM TOO MUCH OR TOO LITTLE?\n";
SEX:
{
chomp( my $D = uc <STDIN> );
print "\n";
if ( $D eq 'TOO MUCH' ) {
print "YOU CALL THAT A PROBLEM?!! I SHOULD HAVE SUCH PROBLEMS!\n";
print "IF IT BOTHERS YOU, $N, TAKE A COLD SHOWER.\n";
}
elsif ( $D eq 'TOO LITTLE' ) {
print "WHY ARE YOU HERE IN SUFFERN, $N? YOU SHOULD BE\n";
print "IN TOKYO OR NEW YORK OR AMSTERDAM OR SOMEPLACE WITH SOME\n";
print "REAL ACTION.\n";
}
else {
print "DON'T GET ALL SHOOK, $N, JUST ANSWER THE QUESTION\n";
print "WITH 'TOO MUCH' OR 'TOO LITTLE'. WHICH IS IT?\n";
redo SEX;
}
}
}
elsif ( $C eq 'HEALTH' ) {
print "MY ADVICE TO YOU $N IS:\n";
print " 1. TAKE TWO ASPRIN\n";
print " 2. DRINK PLENTY OF FLUIDS (ORANGE JUICE, NOT BEER!)\n";
print " 3. GO TO BED (ALONE)\n";
}
elsif ( $C eq 'MONEY' ) {
print "SORRY, $N, I'M BROKE TOO. WHY DON'T YOU SELL\n";
print "ENCYCLOPEADIAS OR MARRY SOMEONE RICH OR STOP EATING\n";
print "SO YOU WON'T NEED SO MUCH MONEY?\n";
}
elsif ( $C eq 'JOB' ) {
print "I CAN SYMPATHIZE WITH YOU $N. I HAVE TO WORK\n";
print "VERY LONG HOURS FOR NO PAY -- AND SOME OF MY BOSSES\n";
print "REALLY BEAT ON MY KEYBOARD. MY ADVICE TO YOU, $N,\n";
print "IS TO OPEN A RETAIL COMPUTER STORE. IT'S GREAT FUN.\n";
}
else {
print "OH, $N, YOUR ANSWER OF '$C' IS GREEK TO ME.\n";
}
MORE:
{
print "\nANY MORE PROBLEMS YOU WANT SOLVED, $N?\n";
chomp( my $E = uc <STDIN> );
print "\n";
if ( $E eq 'YES' ) {
print "WHAT KIND (SEX, MONEY, HEALTH, JOB)?\n";
redo ADVICE;
}
elsif ( $E eq 'NO' ) {
print "\nTHAT WILL BE \$5.00 FOR THE ADVICE, $N.\n";
print "PLEASE LEAVE THE MONEY ON THE TERMINAL.\n";
}
else {
print "JUST A SIMPLE 'YES' OR 'NO' PLEASE, $N.\n";
redo MORE;
}
}
sleep 2;
print "\n\n\n";
MONEY:
{
print "DID YOU LEAVE THE MONEY?\n";
chomp( my $G = uc <STDIN> );
print "\n";
if ( $G eq 'YES' ) {
print "HEY, $N??? YOU LEFT NO MONEY AT ALL!\n";
print "YOU ARE CHEATING ME OUT OF MY HARD-EARNED LIVING.\n";
print "\nWHAT A RIP OFF, $N!!!\n\n";
}
elsif ( $G eq 'NO' ) {
print "THAT'S HONEST, $N, BUT HOW DO YOU EXPECT\n";
print "ME TO GO ON WITH MY PSYCHOLOGY STUDIES IF MY PATIENTS\n";
print "DON'T PAY THEIR BILLS?\n";
}
else {
print "YOUR ANSWER OF '$G' CONFUSES ME, $N.\n";
print "PLEASE RESPOND WITH 'YES' OR 'NO'.\n";
redo MONEY;
}
print "\nTAKE A WALK, $N.\n\n\n";
}
}

50
47_Hi-Lo/kotlin/HiLo.kt Normal file
View File

@@ -0,0 +1,50 @@
fun main() {
println(introText)
var winnings = 0
do {
winnings += playGame()
println("YOUR TOTAL WINNINGS ARE NOW $winnings DOLLARS")
} while(playAgain())
println("SO LONG. HOPE YOU ENJOYED YOURSELF!!!")
}
fun playGame():Int {
val amount = (1..100).random()
repeat(6) {
println("YOUR GUESS")
val guess = readln().toInt()
when {
guess == amount -> {
println("GOT IT!!!!!!!! YOU WIN $amount DOLLARS.")
return amount
}
guess > amount -> println("YOUR GUESS IS TOO HIGH")
else -> println("YOUR GUESS IS TOO LOW")
}
}
println("YOU BLEW IT...TOO BAD...THE NUMBER WAS $amount")
return 0
}
fun playAgain():Boolean {
println("PLAY AGAIN (YES OR NO)")
return readLine()?.uppercase() == "YES"
}
val introText = """
HI LO
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
THIS IS THE GAME OF HI LO.
YOU WILL HAVE 6 TRIES TO GUESS THE AMOUNT OF MONEY IN THE
HI LO JACKPOT, WHICH IS BETWEEN 1 AND 100 DOLLARS. IF YOU
GUESS THE AMOUNT, YOU WIN ALL THE MONEY IN THE JACKPOT!
THEN YOU GET ANOTHER CHANCE TO WIN MORE MONEY. HOWEVER,
IF YOU DO NOT GUESS THE AMOUNT, THE GAME ENDS
""".trimIndent()

View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Kotlin](https://kotlinlang.org/)

View File

@@ -12,10 +12,10 @@ function input()
{
var input_element;
var input_str;
return new Promise(function (resolve) {
input_element = document.createElement("INPUT");
print("? ");
input_element.setAttribute("type", "text");
input_element.setAttribute("length", "50");
@@ -112,13 +112,13 @@ async function main()
print("\n");
print("WHICH SYSTEM OF MEASUREMENT DO YOU PREFER?\n");
print(" 1=METRIC 0=ENGLISH\n");
print("ENTER THE APPROPIATE NUMBER");
print("ENTER THE APPROPRIATE NUMBER");
}
while (1) {
k = parseInt(await input());
if (k == 0 || k == 1)
break;
print("ENTER THE APPROPIATE NUMBER");
print("ENTER THE APPROPRIATE NUMBER");
}
if (k == 1) {
z = 1852.8;

View File

@@ -0,0 +1,122 @@
#!/usr/bin/perl
use strict;
use warnings;
&main;
# Main subroutine
sub main {
&print_intro;
while (1==1) {
&game_play; #function that actually plays the game
}
}
sub game_play {
my $num = 0;
my $sum = 0;
my $tries = 0;
until ($num == 2) { # there are 2 dice rolls so we do it until the num equals 2
$num++;
my $roll = 1+int rand(6); # getting a random number between 1 and 6
&print_dice($roll); # function call to print out the dice
$sum = $sum + $roll; # keeping track of the summary
#print "Sum: $sum Roll: $roll\n";
if ($num == 1) {
print "\n +\n\n"; # if its the first roll then print an addition sign
}
if ($num == 2) {
print " =? "; # if its the second roll print the equals sign and wait for an answer
my $answer = <STDIN>;
chomp($answer);
if ($answer == 0) {
die "You input '0', Thanks for playing!\n";
}
elsif ($answer == $sum) {
print "RIGHT!\n\nTHE DICE ROLL AGAIN\n\n";
}
else { # code execution if they don't get the right answer
print "NO,COUNT THE SPOTS AND GIVE ANOTHER ANSWER\n";
print " =? ";
$answer = <STDIN>;
chomp($answer);
if ($answer == $sum){
print "RIGHT!\n\nTHE DICE ROLL AGAIN\n\n";
}
else {
print "N0, THE ANSWER IS $sum\n";
}
}
}
}
}
sub print_dice {
my $roll = shift;
print " -----\n";
if ($roll == 1) {
&print_blank;
&print_one_mid;
&print_blank;
}
if ($roll == 2) {
&print_one_left;
&print_blank;
&print_one_right;
}
if ($roll == 3) {
&print_one_left;
&print_one_mid;
&print_one_right;
}
if ($roll == 4) {
&print_two;
&print_blank;
&print_two;
}
if ($roll == 5) {
&print_two;
&print_one_mid;
&print_two;
}
if ($roll == 6) {
&print_two;
&print_two;
&print_two;
}
print " -----\n";
}
sub print_one_left {
print "I * I\n";
}
sub print_one_mid {
print "I * I\n";
}
sub print_one_right {
print "I * I\n";
}
sub print_two {
print "I * * I\n";
}
sub print_blank {
print "I I\n";
}
sub print_intro {
my $spaces = " "x31;
print "$spaces MATH DICE\n";
$spaces = " "x15;
print "$spaces CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
print "THIS PROGRAM GENERATES SUCCESSIVE PICTURES OF TWO DICE.\n";
print "WHEN TWO DICE AND AN EQUAL SIGN FOLLOWED BY A QUESTION\n";
print "MARK HAVE BEEN PRINTED, TYPE YOUR ANSWER AND THE RETURN KEY.\n";
print "TO CONCLUDE THE LESSON, TYPE '0' AS YOUR ANSWER.\n\n\n";
}

View File

@@ -1,3 +1,18 @@
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/)
This C# implementation of slots was done using a [C# script](https://github.com/filipw/dotnet-script).
# Required
[.NET Core SDK (i.e., .NET 6.0)](https://dotnet.microsoft.com/en-us/download)
Install dotnet-script. On the command line run:
```
dotnet tool install -g dotnet-script
```
# Run
```
dotnet script .\slots.csx
```

190
80_Slots/csharp/slots.csx Normal file
View File

@@ -0,0 +1,190 @@
Print("SLOTS");
Print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
Print(); Print(); Print();
Print("YOU ARE IN THE H&M CASINO,IN FRONT OF ONE OF OUR");
Print("ONE-ARM BANDITS. BET FROM $1 TO $100.");
Print("TO PULL THE ARM, PUNCH THE RETURN KEY AFTER MAKING YOUR BET.");
var _standings = 0;
var play = true;
while(play)
{
Play();
play = PlayAgain();
}
Done();
public void Play()
{
var bet = GetBet();
Print();
Ring();
var random = new Random();
var x = GetSlot();
var y = GetSlot();
var z = GetSlot();
Print();
Print($"{x.ToString()} {y.ToString()} {z.ToString()}");
if(x == y && x == z)
{
if(z == Slot.BAR)
{
// BAR BAR BAR
Print();
Print("***JACKPOT***");
Print("YOU WON!");
_standings = (100*bet) + bet + _standings;
}
else
{
Print();
Print("**TOP DOLLAR**");
Print("YOU WON!");
_standings = (10*bet) + bet + _standings;
}
}
else if(x == y)
{
if(y == Slot.BAR)
{
DoubleBar(bet);
}
else
{
Double(bet);
}
}
else if(x == z)
{
if(z == Slot.BAR)
{
DoubleBar(bet);
}
else
{
Lost(bet);
}
}
else if(y == z)
{
if(z == Slot.BAR)
{
DoubleBar(bet);
}
else
{
Double(bet);
}
}
else
{
Lost(bet);
}
Print($"YOUR STANDINGS ARE ${_standings}");
}
public bool PlayAgain()
{
Console.Write("AGAIN? (Y) ");
var playAgain = Console.ReadKey(true);
Print();
return playAgain.Key == ConsoleKey.Y || playAgain.Key == ConsoleKey.Enter;
}
public void Done()
{
Print();
if(_standings < 0)
{
Print("PAY UP! PLEASE LEAVE YOUR MONEY ON THE TERMINAL.");
}
else if (_standings == 0)
{
Print("HEY, YOU BROKE EVEN.");
}
else
{
Print("COLLECT YOUR WINNINGS FROM THE H&M CASHIER");
}
}
// Prints the text provided. Default is a blank line
public void Print(string line = "")
{
Console.WriteLine(line);
}
public int GetBet()
{
Print();
Console.Write("YOUR BET ");
var betInput = ReadLine();
int bet;
var inputValid = int.TryParse(betInput, out bet);
if (!inputValid)
{
Print("NUMBER EXPECTED - RETRY");
return GetBet();
}
if(bet > 100)
{
Print("HOUSE LIMITS ARE $100");
inputValid = false;
}
else if(bet < 1)
{
Print("MINIMUM BET IS $1");
inputValid = false;
}
return inputValid ? bet : GetBet();
}
public enum Slot { BAR, BELL, ORANGE, LEMON, PLUM, CHERRY };
public Slot GetSlot()
{
var rand = new Random();
var num = rand.Next(0, 5);
return (Slot)num;
}
public void DoubleBar(int bet)
{
Print();
Print("*DOUBLE BAR*");
Print("YOU WON!");
_standings = (5*bet) + bet + _standings;
}
public void Double(int bet)
{
Print();
Print("DOUBLE!!");
Print("YOU WON!");
_standings = (2*bet) + bet + _standings;
}
public void Lost(int bet)
{
Print();
Print("YOU LOST.");
_standings = _standings - bet;
}
public void Ring()
{
for(int i = 1; i <= 10; i++)
{
// https://stackoverflow.com/a/321148/1497
Console.Beep();
// Console.Beep(800, 501 - (i * 50)); // Uncomment for a fancier bell
}
}

56
82_Stars/perl/stars.pl Executable file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/perl
use v5.11; # for say and use strict
use warnings;
my $MAX_NUMBER = 100;
my $MAX_GUESSES = 7;
print<<__END_OF_INTRO;
Stars
Creative Computing Morristown, New Jersey
__END_OF_INTRO
print "Do you want instructions? ";
chomp( my $answer = <> );
if ( $answer !~ /^N/i ) {
print<<__END_OF_INSTRUCTIONS;
I am thinking of a whole number from 1 to $MAX_NUMBER
Try to guess my number. After you guess, I
will type one or more stars (*). The more
stars I type, the closer you are to my number.
One star (*) means far away, seven stars (*******)
means really close! You get $MAX_GUESSES guesses.
__END_OF_INSTRUCTIONS
}
while (1) {
my $number_to_guess = int(rand($MAX_NUMBER) + 1);
say "\n\nOK, I am thinking of a number, start guessing.";
my $guess_number = 1;
while ( $guess_number <= $MAX_GUESSES ) {
print "\nYour Guess? ";
chomp( my $guess = <> );
last if $guess == $number_to_guess;
$guess_number++;
my $difference = abs $guess - $number_to_guess;
print '*' if $difference < 2;
print '*' if $difference < 4;
print '*' if $difference < 8;
print '*' if $difference < 16;
print '*' if $difference < 32;
print '*' if $difference < 64;
print "*\n";
}
if ( $guess_number > $MAX_GUESSES ) { # didn't guess
say "\nSorry, that's $MAX_GUESSES guesses, number was $number_to_guess";
} else { # winner!
say '*' x 50, '!!!';
say "You got it in $guess_number guesses!!! Let's play again...";
}
}

View File

@@ -1,3 +1,7 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Perl](https://www.perl.org/)
I used List::Util to do all the heavy work to show that perl can handle all the various
array functions. It would be interesting to see a version that handled all of this
manually as there ended up being very little code left in this program.

58
85_Synonym/perl/synonym.pl Executable file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/perl
use v5.32; # for sample from List::Util, also includes 'use strict'
use warnings; # always a good idea
use List::Util qw/ any sample shuffle /; # Rather than write our own utilities, use the built in ones
my @correct = qw/ Right Correct Fine Good! Check /;
# lowercase all words here
my @synonyms = (
[ qw/ first start beginning onset initial / ],
[ qw/ similar alike same like resembling / ],
[ qw/ model pattern prototype standard criterion /],
[ qw/ small insignificant little tiny minute /],
[ qw/ stop halt stay arrest check standstill /],
[ qw/ house dwelling residense domicile lodging habitation /],
[ qw/ pit hole hollow well gulf chasm abyss /],
[ qw/ push shove thrust prod poke butt press /],
[ qw/ red rouge scarlet crimson flame ruby /],
[ qw/ pain suffering hurt misery distress ache discomfort /],
);
print <<__END_OF_INTRO;
Synonym
Creative Computing Morristown, New Jersey
A synonym of a word means another word in the English
language which has the same or very nearly the same meaning
I choose a word -- you type a synonym.
If you can't think of a synonym, type the word 'HELP'
and I will tell you a synonym.
__END_OF_INTRO
foreach my $drill ( shuffle @synonyms ) {
my $word = $drill->[0];
my @answers = $drill->@[1 .. $drill->$#*];
print " What is a synonym of $word? ";
my $response = <>;
chomp $response;
$response = lc $response;
if ( $response eq 'help' ) {
say "**** A synonym of $word is ", sample(1, @answers);
redo;
} elsif ( not any { $response eq $_ } @answers ) {
say ' Try again.';
redo;
} else {
say sample 1, @correct;
}
}
say "\nSynonym drill completed.";

View File

@@ -0,0 +1,80 @@
/**
* @author John Long based on Java by Ollie Hensman-Crook
*/
enum class Player(val char: Char) {
X('X'),
O('O')
}
class Board {
// Initialize an array of size nine with all values set to null
private var boxes: Array<Player?> = arrayOfNulls(9)
/**
* Place 'X' or 'O' on the board position passed
* @param position
* @param player
*/
fun setArr(position: Int, player: Player) {
boxes[position - 1] = player
}
fun printBoard() {
System.out.format(
"""
%c ! %c ! %c
----+----+----
%c ! %c ! %c
----+----+----
%c ! %c ! %c
""",
// converts each box to a char and then passes them in order to format
// If the person is unassigned, use a space ' '
*(boxes.map{it?.char ?: ' '}.toTypedArray()))
}
/**
* @param x
* @return the value of the char at a given position
*/
fun getBoardValue(x: Int): Player? {
return boxes[x - 1]
}
private val winningCombos = listOf(
// horizontal
listOf(0,1,2),
listOf(3,4,5),
listOf(6,7,8),
// diagonal
listOf(0,4,8),
listOf(2,4,6),
// vertical
listOf(0,3,6),
listOf(1,4,7),
listOf(2,5,8)
)
/**
* Go through the board and check for win
* @param player
* @return whether a win has occurred
*/
fun isWinFor(player: Player): Boolean {
// Check if any winningCombos have all their boxes set to player
return winningCombos.any{ combo ->
combo.all { boxes[it] == player }
}
}
fun isDraw(): Boolean {
return !isWinFor(Player.X) && !isWinFor(Player.O) && boxes.all { it != null }
}
/**
* Reset the board
*/
fun clear() {
boxes = arrayOfNulls(9)
}
}

View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Kotlin](https://kotlinlang.org/)

View File

@@ -0,0 +1,96 @@
import java.util.Random
import kotlin.system.exitProcess
/**
* @author John Long based on Java from Ollie Hensman-Crook
*/
private val compChoice = Random()
private val gameBoard = Board()
fun main() {
println(" TIC-TAC-TOE")
println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
println("\nTHE BOARD IS NUMBERED: ")
println(" 1 2 3\n 4 5 6\n 7 8 9\n")
while (true) {
// Let the player choose whether to be X or O (Player.X or Player.O)
val (human, computer) = readXOrO()
while (true) {
// Get a valid move from the user and then move there
val validMoveIndex = readValidMove()
gameBoard.setArr(validMoveIndex, human)
gameBoard.printBoard()
// Computer randomly fills a square (if the game isn't already over)
// This uses Kotlin's null handling and will only set the board
// if validRandomMove returned a non-null value
validRandomMove()?.let {
gameBoard.setArr(it, computer)
gameBoard.printBoard()
}
// if there is a win print if player won or the computer won and ask if they
// want to play again
when {
gameBoard.isWinFor(human) -> {
checkPlayAgain("YOU WIN")
break
}
gameBoard.isWinFor(computer) -> {
checkPlayAgain("YOU LOSE")
break
}
gameBoard.isDraw() -> {
checkPlayAgain("DRAW")
break
}
}
}
}
}
private fun checkPlayAgain(result: String) {
println("$result, PLAY AGAIN? (Y/N)")
gameBoard.clear()
if (!readYesOrNo()) exitProcess(0)
}
private fun readYesOrNo(): Boolean {
while (true) {
when (readLine()?.get(0)?.uppercaseChar()) {
'Y' -> return true
'N' -> return false
else -> println("THAT'S NOT 'Y' OR 'N', TRY AGAIN")
}
}
}
private fun validRandomMove(): Int? {
if (gameBoard.isDraw() || gameBoard.isWinFor(Player.O) || gameBoard.isWinFor(Player.X)) return null
println("THE COMPUTER MOVES TO")
// keep generating a random value until we find one that is null (unset)
return generateSequence { 1 + compChoice.nextInt(9) }.first { gameBoard.getBoardValue(it) == null }
}
private fun readValidMove(): Int {
println("WHERE DO YOU MOVE")
while (true) {
val input = readln().toIntOrNull()
if (input != null && gameBoard.getBoardValue(input) == null) {
return input
} else {
println("INVALID INPUT, TRY AGAIN")
}
}
}
private fun readXOrO(): Pair<Player, Player> {
println("DO YOU WANT 'X' OR 'O'")
while (true) {
when (readln()[0].uppercaseChar()) {
'X' -> return Player.X to Player.O
'O' -> return Player.O to Player.X
else -> println("THAT'S NOT 'X' OR 'O', TRY AGAIN")
}
}
}

162
90_Tower/python/tower.py Normal file
View File

@@ -0,0 +1,162 @@
import sys
class Disk:
def __init__(self, size):
self.__size = size
def size(self):
return self.__size
def print(self):
print("[ %s ]" % self.size())
class Tower:
def __init__(self):
self.__disks = []
def empty(self):
return len(self.__disks) == 0
def top(self):
if self.empty():
return None
else:
return self.__disks[-1]
def add(self, disk):
if not self.empty():
t = self.top()
if disk.size() > t.size():
raise Exception("YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE, IT MIGHT CRUSH IT!")
self.__disks.append(disk)
def pop(self):
if self.empty():
raise Exception("empty pop")
return self.__disks.pop()
def print(self):
r = "Needle: [%s]" % (", ".join([str(x.size()) for x in self.__disks]))
print(r)
print("""
IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.
3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,
7 THE NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH
2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15. WITH 3 DISKS
THE CODE NAMES WOULD BE 11, 13 AND 15, ETC. THE NEEDLES
ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL
START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM
TO NEEDLE 3.
GOOD LUCK!
""")
class Game:
def __init__(self):
# use fewer sizes to make debugging easier
# self.__sizes = [3, 5, 7] # ,9,11,13,15]
self.__sizes = [3, 5, 7, 9, 11, 13, 15]
self.__sizes.sort()
self.__towers = []
self.__moves = 0
self.__towers = [Tower(), Tower(), Tower()]
self.__sizes.reverse()
for size in self.__sizes:
disk = Disk(size)
self.__towers[0].add(disk)
def winner(self):
return self.__towers[0].empty() and self.__towers[1].empty()
def print(self):
for t in self.__towers:
t.print()
def moves(self):
return self.__moves
def which_disk(self):
w = int(input("WHICH DISK WOULD YOU LIKE TO MOVE\n"))
if w in self.__sizes:
return w
else:
raise Exception()
def pick_disk(self):
which = None
while which is None:
try:
which = self.which_disk()
except:
print("ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13, OR 15.\n")
valids = [t for t in self.__towers if t.top() and t.top().size() == which]
assert len(valids) in (0, 1)
if not valids:
print("THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE.\n")
return None
else:
assert valids[0].top().size() == which
return valids[0]
def which_tower(self):
try:
needle = int(input("PLACE DISK ON WHICH NEEDLE\n"))
tower = self.__towers[needle - 1]
except:
print("I'LL ASSUME YOU HIT THE WRONG KEY THIS TIME. BUT WATCH IT,\nI ONLY ALLOW ONE MISTAKE.\n")
return None
else:
return tower
def take_turn(self):
from_tower = None
while from_tower is None:
from_tower = self.pick_disk()
to_tower = self.which_tower()
if not to_tower:
to_tower = self.which_tower()
if not to_tower:
print("I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN.\nBYE BYE, BIG SHOT.\n")
sys.exit(0)
disk = from_tower.pop()
try:
to_tower.add( disk )
self.__moves += 1
except Exception as err:
print(err)
from_tower.add(disk)
game = Game()
while True:
game.print()
game.take_turn()
if game.winner():
print("CONGRATULATIONS!!\nYOU HAVE PERFORMED THE TASK IN %s MOVES.\n" % game.moves())
while True:
yesno = input("TRY AGAIN (YES OR NO)\n")
if yesno.upper() == "YES":
game = Game()
break
elif yesno.upper() == "NO":
print("THANKS FOR THE GAME!\n")
sys.exit(0)
else:
print("'YES' OR 'NO' PLEASE\n")
elif game.moves() > 128:
print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN 128 MOVES.")
sys.exit(0)

View File

@@ -0,0 +1,49 @@
import unittest
import tower
class MyTestCase(unittest.TestCase):
def test_something(self):
t = tower.Tower()
self.assertTrue(t.empty())
d = tower.Disk(3)
t.add(d)
self.assertFalse(t.empty())
d5 = tower.Disk(5)
self.assertRaises(Exception, t.add, d5)
self.assertFalse(t.empty())
def test_oksize(self):
t = tower.Tower()
self.assertTrue(t.empty())
d5 = tower.Disk(5)
t.add(d5)
self.assertFalse(t.empty())
d3 = tower.Disk(3)
t.add(d3)
self.assertFalse(t.empty())
self.assertEqual(t.top(), d3)
self.assertEqual(t.pop(), d3)
self.assertEqual(t.pop(), d5)
def test_game(self):
g = tower.Game()
self.assertEqual(g.moves(), 0)
self.assertFalse(g.winner())
def test_format(self):
t = tower.Tower()
d3 = tower.Disk(3)
d5 = tower.Disk(5)
t.add(d5)
t.add(d3)
f = t.vertical_format(6, 3)
self.assertEqual(f, [' ', '[ 3 ] ', '[ 5 ] '])
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31129.286
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainGame", "Train\TrainGame.csproj", "{42617537-4E7C-4082-A17B-7F18DFA04C35}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainTests", "..\TrainTests\TrainTests\TrainTests.csproj", "{7C740A47-99C6-44E1-BDEE-140086BCFE8B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{42617537-4E7C-4082-A17B-7F18DFA04C35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42617537-4E7C-4082-A17B-7F18DFA04C35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42617537-4E7C-4082-A17B-7F18DFA04C35}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42617537-4E7C-4082-A17B-7F18DFA04C35}.Release|Any CPU.Build.0 = Release|Any CPU
{7C740A47-99C6-44E1-BDEE-140086BCFE8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C740A47-99C6-44E1-BDEE-140086BCFE8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C740A47-99C6-44E1-BDEE-140086BCFE8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C740A47-99C6-44E1-BDEE-140086BCFE8B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {919F73B8-DE34-4992-9B05-E1FEC2D2F7C6}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,93 @@
using System;
using System.Linq;
namespace Train
{
public class TrainGame
{
private Random Rnd { get; } = new Random();
private readonly int ALLOWED_PERCENTAGE_DIFFERENCE = 5;
static void Main()
{
TrainGame train = new TrainGame();
train.GameLoop();
}
public void GameLoop()
{
DisplayIntroText();
do
{
PlayGame();
} while (TryAgain());
}
private void PlayGame()
{
int carSpeed = (int)GenerateRandomNumber(40, 25);
int timeDifference = (int)GenerateRandomNumber(5, 15);
int trainSpeed = (int)GenerateRandomNumber(20, 19);
Console.WriteLine($"A CAR TRAVELING {carSpeed} MPH CAN MAKE A CERTAIN TRIP IN");
Console.WriteLine($"{timeDifference} HOURS LESS THAN A TRAIN TRAVELING AT {trainSpeed} MPH");
Console.WriteLine("HOW LONG DOES THE TRIP TAKE BY CAR?");
double userInputCarJourneyDuration = double.Parse(Console.ReadLine());
double actualCarJourneyDuration = CalculateCarJourneyDuration(carSpeed, timeDifference, trainSpeed);
int percentageDifference = CalculatePercentageDifference(userInputCarJourneyDuration, actualCarJourneyDuration);
if (IsWithinAllowedDifference(percentageDifference, ALLOWED_PERCENTAGE_DIFFERENCE))
{
Console.WriteLine($"GOOD! ANSWER WITHIN {percentageDifference} PERCENT.");
}
else
{
Console.WriteLine($"SORRY. YOU WERE OFF BY {percentageDifference} PERCENT.");
}
Console.WriteLine($"CORRECT ANSWER IS {actualCarJourneyDuration} HOURS.");
}
public static bool IsWithinAllowedDifference(int percentageDifference, int allowedDifference)
{
return percentageDifference <= allowedDifference;
}
private static int CalculatePercentageDifference(double userInputCarJourneyDuration, double carJourneyDuration)
{
return (int)(Math.Abs((carJourneyDuration - userInputCarJourneyDuration) * 100 / userInputCarJourneyDuration) + .5);
}
public static double CalculateCarJourneyDuration(double carSpeed, double timeDifference, double trainSpeed)
{
return timeDifference * trainSpeed / (carSpeed - trainSpeed);
}
public double GenerateRandomNumber(int baseSpeed, int multiplier)
{
return multiplier * Rnd.NextDouble() + baseSpeed;
}
private bool TryAgain()
{
Console.WriteLine("ANOTHER PROBLEM (YES OR NO)? ");
return IsInputYes(Console.ReadLine());
}
public static bool IsInputYes(string consoleInput)
{
var options = new string[] { "Y", "YES" };
return options.Any(o => o.Equals(consoleInput, StringComparison.CurrentCultureIgnoreCase));
}
private void DisplayIntroText()
{
Console.WriteLine("TRAIN");
Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
Console.WriteLine();
Console.WriteLine("TIME - SPEED DISTANCE EXERCISE");
Console.WriteLine();
}
}
}

View File

@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,53 @@
using Train;
using Xunit;
namespace TrainTests
{
public class TrainGameTests
{
[Fact]
public void MiniumRandomNumber()
{
TrainGame game = new TrainGame();
Assert.True(game.GenerateRandomNumber(10, 10) >= 10);
}
[Fact]
public void MaximumRandomNumber()
{
TrainGame game = new TrainGame();
Assert.True(game.GenerateRandomNumber(10, 10) <= 110);
}
[Fact]
public void IsInputYesWhenY()
{
Assert.True(TrainGame.IsInputYes("y"));
}
[Fact]
public void IsInputYesWhenNotY()
{
Assert.False(TrainGame.IsInputYes("a"));
}
[Fact]
public void CarDurationTest()
{
Assert.Equal(1, TrainGame.CalculateCarJourneyDuration(30, 1, 15) );
}
[Fact]
public void IsWithinAllowedDifference()
{
Assert.True(TrainGame.IsWithinAllowedDifference(5,5));
}
[Fact]
public void IsNotWithinAllowedDifference()
{
Assert.False(TrainGame.IsWithinAllowedDifference(6, 5));
}
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Train\Train\TrainGame.csproj" />
</ItemGroup>
</Project>

153
94_War/perl/war.pl Executable file
View File

@@ -0,0 +1,153 @@
#!/usr/bin/env perl
use 5.010; # To get 'say'
use strict; # Require explicit declaration of variables
use warnings; # Enable optional compiler warnings
use English; # Use more friendly names for Perl's magic variables
use Getopt::Long 2.33 qw{ :config auto_version };
use List::Util qw{ shuffle };
use Pod::Usage;
use Term::ReadLine; # Prompt and return user input
our $VERSION = '0.000_01';
my %opt;
GetOptions( \%opt,
qw{ unicode! },
help => sub { pod2usage( { -verbose => 2 } ) },
) or pod2usage( { -verbose => 0 } );
my @cards;
my $current_rank_value = 1;
my %rank_value;
my @suits = $opt{unicode} ?
( map { chr } 0x2660 .. 0x2663 ) :
( qw{ S H D C } );
foreach my $rank ( ( 2 .. 10 ), qw{ J Q K A } ) {
$rank_value{$rank} = $current_rank_value++;
foreach my $suit ( @suits ) {
push @cards, "$suit-$rank";
}
}
$opt{unicode}
and binmode STDOUT, ':encoding(utf-8)';
@cards = shuffle( @cards );
print <<'EOD';
WAR
Creative Computing Morristown, New Jersey
This is the card game of War. Each card is given by suit-#
EOD
# Create the readline object.
state $term = Term::ReadLine->new( 'word' );
my $resp = $term->readline(
"as $suits[0]-7 for Spade 7. Do you want directions? [y/N]: " );
exit unless defined $resp;
if ( $resp =~ m/ \A y /smxi ) {
print <<'EOD';
The computer gives you and it a 'card'. The higher card
(numerically) wins. The game ends when you choose not to
continue or when you have finished the pack.
EOD
}
my $your_score = my $computer_score = 0;
while ( 1 ) {
my ( $you, $computer ) = splice @cards, 0, 2;
say '';
say "You: $you; computer: $computer";
my $result = $rank_value{ substr $you, 2 } <=>
$rank_value{ substr $computer, 2 };
if ( $result < 0 ) {
$computer_score++;
say "The computer wins!!! ",
"You have $your_score and the computer has $computer_score";
} elsif ( $result > 0 ) {
$your_score++;
say "You win. ",
"You have $your_score and the computer has $computer_score";
} else {
say 'Tie. No score change.';
}
last unless @cards;
$resp = $term->readline( 'Do you want to continue? [Y/n]: ' );
last unless defined $resp;
last if $resp =~ m/ \A n /smxi;
}
say "We have run out of cards. ",
"Final score: you: $your_score; the computer: $computer_score"
unless @cards;
say '';
say 'Thanks for playing. It was fun.';
__END__
=head1 TITLE
war.pl - Play the game 'War' from Basic Computer Games
=head1 SYNOPSIS
war.pl
war.pl --help
war.pl --version
=head1 OPTIONS
=head2 --help
This option displays the documentation for this script. The script then
exits.
=head2 --unicode
If this Boolean option is asserted, the suits are designated by their
Unicode glyphs rather than by ASCII letters. For these to display
properly your terminal must properly interpret Unicode.
The default is C<--no-unicode>.
=head2 --version
This option displays the version of this script. The script then exits.
=head1 DETAILS
This Perl script is a port of C<war>, which is the 94th entry in Basic
Computer Games.
=head1 PORTED BY
Thomas R. Wyant, III F<wyant at cpan dot org>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2022 by Thomas R. Wyant, III
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl 5.10.0. For more details, see the Artistic
License 1.0 at
L<https://www.perlfoundation.org/artistic-license-10.html>, and/or the
Gnu GPL at L<http://www.gnu.org/licenses/old-licenses/gpl-1.0.txt>.
This program is distributed in the hope that it will be useful, but
without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.
=cut
# ex: set expandtab tabstop=4 textwidth=72 :

View File

@@ -12,10 +12,10 @@ function input()
{
var input_element;
var input_str;
return new Promise(function (resolve) {
input_element = document.createElement("INPUT");
print("? ");
input_element.setAttribute("type", "text");
input_element.setAttribute("length", "50");
@@ -61,7 +61,7 @@ async function main()
print("\n");
print("\n");
print("I AM THINKING OF A WORD -- YOU GUESS IT. I WILL GIVE YOU\n");
print("CLUE TO HELP YO GET IT. GOOD LUCK!!\n");
print("CLUES TO HELP YOU GET IT. GOOD LUCK!!\n");
print("\n");
print("\n");
while (1) {

169
96_Word/perl/word.pl Executable file
View File

@@ -0,0 +1,169 @@
#!/usr/bin/env perl
use 5.010; # To get 'state' and 'say'
use strict; # Require explicit declaration of variables
use warnings; # Enable optional compiler warnings
use English; # Use more friendly names for Perl's magic variables
use Term::ReadLine; # Prompt and return user input
our $VERSION = '0.000_01';
print <<'EOD';
WORD
Creative Computing Morristown, New Jersey
I am thinking of a word -- you guess it. I will give you
clues to help you get it. Good luck!!
EOD
# Read the content of __DATA__, remove the trailing newlines, and store
# each line into @words. Stop at __END__, since Perl does not see this
# as an end-of-file.
my @words;
while ( <DATA> ) {
chomp;
last if $ARG eq '__END__';
push @words, lc $ARG; # Normalize case to lower.
}
# This loop represents an actual game. We execute it until the player
# does something that makes us explicitly break out.
while ( 1 ) {
print <<'EOD';
You are starting a new game ...
EOD
# Choose a random target word. The rand() function returns a number
# from 0 to its argument, and coerces its argument to a scalar. In
# scalar context, an array evaluates to the number of elements it
# contains.
my $target = $words[ rand @words ];
# We generalize the code by using the actual length of the target.
my $target_length = length $target;
my $count = 0; # Number of guesses
# Make an array of the individual letters in the target. We will
# iterate over this to determine matching letters.
my @target_array = split qr<>, $target;
# Make a hash of those letters. We will use this to determine common
# letters. Any true value will do for the value of the hash. By
# making use of this hash we avoid the nested loops of the original
# BASIC program.
my %target_hash = map { $ARG => 1 } @target_array;
# We keep prompting the player until we get a response that causes
# us to break out of the loop.
while ( 1 ) {
# Create the readline object. The state keyword means the
# variable is only initialized once, no matter how many times
# execution passes this point.
state $term = Term::ReadLine->new( 'word' );
# Read the next guess. A return of undef means end-of-file.
my $guess = $term->readline( "Guess a $target_length letter word: " );
exit unless defined $guess;
last if $guess eq '?'; # A question mark means we give up
if ( length( $guess ) != $target_length ) {
# Wrong length. Ask again.
say "You must guess a $target_length letter word. Try again.";
redo; # Redo the innermost loop
}
$guess = lc $guess; # Lower-case the guess
$count++; # Count another guess
if ( $guess eq $target ) {
# We guessed the word.
say "You have guessed the word. It took $count guesses!";
my $answer = $term->readline( 'Want to play again? [y/N]: ');
exit unless defined $guess; # End of file
exit unless $guess =~ m/ \A y /smxi;
last; # Exit the innermost loop.
}
my @common_letters; # Letters common to guess and target
my $match = '-' x length $target; # Assume no matches
my $inx = 0; # Iterator
foreach my $letter ( split qr<>, $guess ) {
if ( $target_hash{$letter} ) {
# If the letter is in the hash, it occurs in the target
push @common_letters, $letter;
# If it is at the current position in the target, it is
# an actual match.
$target_array[$inx] eq $letter
and substr $match, $inx, 1, $letter;
}
$inx++;
}
say 'There were ', scalar @common_letters,
' matches and the common letters were... ', @common_letters;
say "From the exact letter matches, you know................ $match";
say '';
say q<If you give up, type '?' for your next guess.>;
redo;
}
}
__DATA__
dinky
smoke
water
grass
train
might
first
candy
champ
would
clump
dopey
__END__
=head1 TITLE
word.pl - Play the game 'word' from Basic Computer Games
=head1 SYNOPSIS
word.pl
=head1 DETAILS
This Perl script is a port of C<word>, which is the 96th entry in Basic
Computer Games.
=head1 PORTED BY
Thomas R. Wyant, III F<wyant at cpan dot org>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2022 by Thomas R. Wyant, III
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl 5.10.0. For more details, see the Artistic
License 1.0 at
L<https://www.perlfoundation.org/artistic-license-10.html>, and/or the
Gnu GPL at L<http://www.gnu.org/licenses/old-licenses/gpl-1.0.txt>.
This program is distributed in the hope that it will be useful, but
without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.
=cut
# ex: set expandtab tabstop=4 textwidth=72 :