mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
Merge branch 'main' of github.com:AlaaSarhan/basic-computer-games
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
80 PRINT"IF YOU DO NOT WANT TO BET, INPUT A 0"
|
80 PRINT"IF YOU DO NOT WANT TO BET, INPUT A 0"
|
||||||
100 N=100
|
100 N=100
|
||||||
110 Q=100
|
110 Q=100
|
||||||
120 PRINT "YOU NOW HAVE";Q;"DOLLARS."
|
120 PRINT "YOU NOW HAVE ";Q;" DOLLARS."
|
||||||
130 PRINT
|
130 PRINT
|
||||||
140 GOTO 260
|
140 GOTO 260
|
||||||
210 Q=Q+M
|
210 Q=Q+M
|
||||||
|
|||||||
6
01_Acey_Ducey/javascript/.prettierrc.json
Normal file
6
01_Acey_Ducey/javascript/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 4,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width" />
|
||||||
<title>ACEY DUCEY</title>
|
<title>ACEY DUCEY</title>
|
||||||
|
|
||||||
<pre id="output" style="font-size: 12pt;"></pre>
|
<pre id="output" style="font-size: 12pt"></pre>
|
||||||
<script type="module" src="aceyducey.js"></script>
|
<script src="aceyducey.js"></script>
|
||||||
|
|||||||
@@ -1,100 +1,216 @@
|
|||||||
import { readLine, print, spaces } from "./io.js";
|
// UTILITY VARIABLES
|
||||||
|
|
||||||
const minFaceCard = 11;
|
// By default:
|
||||||
const faceCards = {
|
// — Browsers have a window object
|
||||||
11: "JACK",
|
// — Node.js does not
|
||||||
12: "QUEEN",
|
// Checking for an undefined window object is a loose check
|
||||||
13: "KING",
|
// to enable browser and Node.js support
|
||||||
14: "ACE"
|
const isRunningInBrowser = typeof window !== 'undefined';
|
||||||
};
|
|
||||||
|
|
||||||
function randomCard() {
|
// To easily validate input strings with utility functions
|
||||||
return Math.floor(Math.random() * 13 + 2);
|
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, we’ll 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) {
|
function newGameCards() {
|
||||||
if (card < minFaceCard) {
|
let cardOne = getRandomCard();
|
||||||
print(card);
|
let cardTwo = getRandomCard();
|
||||||
} else {
|
let cardThree = getRandomCard();
|
||||||
print(faceCards[card]);
|
// We want:
|
||||||
}
|
// 1. cardOne and cardTwo to be different cards
|
||||||
print("\n");
|
// 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");
|
// Function to get card value
|
||||||
print(spaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n");
|
function getCardValue(card) {
|
||||||
print("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER\n");
|
let faceOrAce = {
|
||||||
print("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP\n");
|
11: 'JACK',
|
||||||
print("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING\n");
|
12: 'QUEEN',
|
||||||
print("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE\n");
|
13: 'KING',
|
||||||
print("A VALUE BETWEEN THE FIRST TWO.\n");
|
14: 'ACE',
|
||||||
print("IF YOU DO NOT WANT TO BET, INPUT '0'\n");
|
};
|
||||||
|
// 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;
|
print(spaces(26) + 'ACEY DUCEY CARD GAME');
|
||||||
while (true) {
|
print(spaces(15) + 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n');
|
||||||
print(`YOU NOW HAVE ${currentMoney} DOLLARS.\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;
|
main();
|
||||||
do {
|
|
||||||
print("HERE ARE YOUR NEXT TWO CARDS: \n");
|
|
||||||
[card1, card2] = [randomCard(), randomCard()];
|
|
||||||
|
|
||||||
// Ensure we always show cards in order of lowest to highest, and we never
|
async function main() {
|
||||||
// get two of the same card.
|
let bet;
|
||||||
do {
|
let availableDollars = 100;
|
||||||
card1 = randomCard();
|
|
||||||
card2 = randomCard();
|
|
||||||
} while (card1 >= card2);
|
|
||||||
|
|
||||||
printCard(card1);
|
|
||||||
printCard(card2);
|
|
||||||
print("\n");
|
|
||||||
|
|
||||||
|
// Loop game forever
|
||||||
while (true) {
|
while (true) {
|
||||||
print("\nWHAT IS YOUR BET? ");
|
let [cardOne, cardTwo, cardThree] = newGameCards();
|
||||||
currentBet = parseInt(await readLine(), 10);
|
|
||||||
|
|
||||||
if (currentBet > 0) {
|
print(`YOU NOW HAVE ${availableDollars} DOLLARS.\n`);
|
||||||
if (currentBet > currentMoney) {
|
|
||||||
print("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.\n");
|
print('HERE ARE YOUR NEXT TWO CARDS: ');
|
||||||
print(`YOU HAVE ONLY ${currentMoney} DOLLARS TO BET.\n`);
|
print(getCardValue(cardOne));
|
||||||
continue;
|
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
|
print('\n\nHERE IS THE CARD WE DREW: ');
|
||||||
// restart the loop with new cards.
|
print(getCardValue(cardThree));
|
||||||
currentBet = undefined;
|
|
||||||
print("CHICKEN!!\n");
|
// Determine if player won or lost
|
||||||
print("\n");
|
if (cardThree > cardOne && cardThree < cardTwo) {
|
||||||
break;
|
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
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
125
01_Acey_Ducey/python/acey_ducey_oo.py
Normal file
125
01_Acey_Ducey/python/acey_ducey_oo.py
Normal 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!')
|
||||||
@@ -56,9 +56,9 @@ while true # Game loop
|
|||||||
puts
|
puts
|
||||||
puts "HERE ARE YOUR NEXT TWO CARDS:"
|
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`
|
# 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
|
# Helper method to convert a numeric card into a String for printing
|
||||||
def card_name(card)
|
def card_name(card)
|
||||||
|
|||||||
25
01_Acey_Ducey/vbnet/AceyDucy.sln
Normal file
25
01_Acey_Ducey/vbnet/AceyDucy.sln
Normal 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
|
||||||
9
01_Acey_Ducey/vbnet/AceyDucy/AceyDucy.vbproj
Normal file
9
01_Acey_Ducey/vbnet/AceyDucy/AceyDucy.vbproj
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>AceyDucy</RootNamespace>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
178
01_Acey_Ducey/vbnet/AceyDucy/Program.vb
Normal file
178
01_Acey_Ducey/vbnet/AceyDucy/Program.vb
Normal 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
119
03_Animal/kotlin/Animal.kt
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
3
03_Animal/kotlin/README.md
Normal file
3
03_Animal/kotlin/README.md
Normal 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
264
04_Awari/csharp/Game.cs
Normal 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);
|
||||||
98
04_Awari/csharp/Program.cs
Normal file
98
04_Awari/csharp/Program.cs
Normal 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);
|
||||||
11
04_Awari/csharp/csharp.csproj
Normal file
11
04_Awari/csharp/csharp.csproj
Normal 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
195
05_Bagels/perl/bagels.pl
Executable 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";
|
||||||
8
22_Change/csharp/Change.csproj
Normal file
8
22_Change/csharp/Change.csproj
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
25
22_Change/csharp/Change.sln
Normal file
25
22_Change/csharp/Change.sln
Normal 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
129
22_Change/csharp/Program.cs
Normal 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
68
22_Change/perl/change.pl
Executable 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";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 "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 "IF ANY OTHER RATIO IS ATTEMPTED, THE ACID BECOMES UNSTABLE\n";
|
||||||
print "AND SOON EXPLODES. GIVEN THE AMOUNT OF ACID, YOU MUST\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";
|
print "YOU FACE THE CONSEQUENCES.\n";
|
||||||
|
|
||||||
my $T=0;
|
my $T=0;
|
||||||
while ($T<9) {
|
while ($T<9) {
|
||||||
my $A= int(rand(1)*50);
|
my $A= int(rand(50) + 1);
|
||||||
my $W= 7*$A/3;
|
my $W= 7*$A/3;
|
||||||
print "$A LITERS OF KRYPTOCYANIC ACID. HOW MUCH WATER ($W)";
|
print " $A LITERS OF KRYPTOCYANIC ACID. HOW MUCH WATER? ";
|
||||||
print "? "; chomp(my $R = <STDIN>);
|
chomp(my $R = <STDIN>);
|
||||||
my $D= abs($W-$R);
|
my $D= abs($W-$R);
|
||||||
if ($D>$W/20) {
|
if ($D>$W/20) {
|
||||||
print " SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB\n";
|
print "SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB\n";
|
||||||
print " OF QUIVERING PROTOPLASM!\n";
|
print "OF QUIVERING PROTOPLASM!\n";
|
||||||
print " HOWEVER, YOU MAY TRY AGAIN WITH ANOTHER LIFE.\n";
|
print "HOWEVER, YOU MAY TRY AGAIN WITH ANOTHER LIFE.\n";
|
||||||
print "\n";
|
print "\n";
|
||||||
$T++;
|
$T++;
|
||||||
} else {
|
} else {
|
||||||
print " GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!\n";
|
print "GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!\n";
|
||||||
print "\n";
|
print "\n";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
print " YOUR 9 LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR\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 CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY.\n";
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
|
||||||
79
29_Craps/python/craps.py
Normal file
79
29_Craps/python/craps.py
Normal 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")
|
||||||
69
31_Depth_Charge/ruby/.editorconfig
Normal file
69
31_Depth_Charge/ruby/.editorconfig
Normal 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
|
||||||
211
31_Depth_Charge/ruby/depthcharge.rb
Executable file
211
31_Depth_Charge/ruby/depthcharge.rb
Executable 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()
|
||||||
129
36_Flip_Flop/python/flipflop.py
Normal file
129
36_Flip_Flop/python/flipflop.py
Normal 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
136
45_Hello/perl/hello.pl
Normal 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
50
47_Hi-Lo/kotlin/HiLo.kt
Normal 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()
|
||||||
3
47_Hi-Lo/kotlin/README.md
Normal file
3
47_Hi-Lo/kotlin/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||||
|
|
||||||
|
Conversion to [Kotlin](https://kotlinlang.org/)
|
||||||
@@ -112,13 +112,13 @@ async function main()
|
|||||||
print("\n");
|
print("\n");
|
||||||
print("WHICH SYSTEM OF MEASUREMENT DO YOU PREFER?\n");
|
print("WHICH SYSTEM OF MEASUREMENT DO YOU PREFER?\n");
|
||||||
print(" 1=METRIC 0=ENGLISH\n");
|
print(" 1=METRIC 0=ENGLISH\n");
|
||||||
print("ENTER THE APPROPIATE NUMBER");
|
print("ENTER THE APPROPRIATE NUMBER");
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
k = parseInt(await input());
|
k = parseInt(await input());
|
||||||
if (k == 0 || k == 1)
|
if (k == 0 || k == 1)
|
||||||
break;
|
break;
|
||||||
print("ENTER THE APPROPIATE NUMBER");
|
print("ENTER THE APPROPRIATE NUMBER");
|
||||||
}
|
}
|
||||||
if (k == 1) {
|
if (k == 1) {
|
||||||
z = 1852.8;
|
z = 1852.8;
|
||||||
|
|||||||
122
61_Math_Dice/perl/mathdice.pl
Normal file
122
61_Math_Dice/perl/mathdice.pl
Normal 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";
|
||||||
|
}
|
||||||
@@ -1,3 +1,18 @@
|
|||||||
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
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/)
|
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
190
80_Slots/csharp/slots.csx
Normal 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
56
82_Stars/perl/stars.pl
Executable 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...";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||||
|
|
||||||
Conversion to [Perl](https://www.perl.org/)
|
Conversion to [Perl](https://www.perl.org/)
|
||||||
|
|
||||||
|
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
58
85_Synonym/perl/synonym.pl
Executable 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.";
|
||||||
|
|
||||||
80
89_Tic-Tac-Toe/kotlin/Board.kt
Normal file
80
89_Tic-Tac-Toe/kotlin/Board.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
3
89_Tic-Tac-Toe/kotlin/README.md
Normal file
3
89_Tic-Tac-Toe/kotlin/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||||
|
|
||||||
|
Conversion to [Kotlin](https://kotlinlang.org/)
|
||||||
96
89_Tic-Tac-Toe/kotlin/TicTacToe2.kt
Normal file
96
89_Tic-Tac-Toe/kotlin/TicTacToe2.kt
Normal 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
162
90_Tower/python/tower.py
Normal 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)
|
||||||
49
90_Tower/python/tower_test.py
Normal file
49
90_Tower/python/tower_test.py
Normal 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()
|
||||||
31
91_Train/csharp/Train/Train.sln
Normal file
31
91_Train/csharp/Train/Train.sln
Normal 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
|
||||||
93
91_Train/csharp/Train/Train/TrainGame.cs
Normal file
93
91_Train/csharp/Train/Train/TrainGame.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
91_Train/csharp/Train/Train/TrainGame.csproj
Normal file
8
91_Train/csharp/Train/Train/TrainGame.csproj
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
53
91_Train/csharp/TrainTests/TrainTests/TrainGameTests.cs
Normal file
53
91_Train/csharp/TrainTests/TrainTests/TrainGameTests.cs
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
91_Train/csharp/TrainTests/TrainTests/TrainTests.csproj
Normal file
26
91_Train/csharp/TrainTests/TrainTests/TrainTests.csproj
Normal 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
153
94_War/perl/war.pl
Executable 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 :
|
||||||
@@ -61,7 +61,7 @@ async function main()
|
|||||||
print("\n");
|
print("\n");
|
||||||
print("\n");
|
print("\n");
|
||||||
print("I AM THINKING OF A WORD -- YOU GUESS IT. I WILL GIVE YOU\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");
|
||||||
print("\n");
|
print("\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|||||||
169
96_Word/perl/word.pl
Executable file
169
96_Word/perl/word.pl
Executable 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 :
|
||||||
Reference in New Issue
Block a user