mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-12 07:40:50 -08:00
Merge pull request #900 from RFigCon/main
Implementation of Train in Lua and D
This commit is contained in:
3
00_Alternate_Languages/91_Train/D/README.md
Normal file
3
00_Alternate_Languages/91_Train/D/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html).
|
||||
|
||||
Conversion to [MiniScript](https://dlang.org).
|
||||
50
00_Alternate_Languages/91_Train/D/train.d
Normal file
50
00_Alternate_Languages/91_Train/D/train.d
Normal file
@@ -0,0 +1,50 @@
|
||||
import std.stdio;
|
||||
import std.random : uniform;
|
||||
|
||||
float abs(float num) {
|
||||
if(num<0){
|
||||
return num*-1;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
writeln("\nTIME - SPEED DISTANCE EXERCISE");
|
||||
|
||||
bool keep_playing = true;
|
||||
float error_margin = 5.0;
|
||||
|
||||
while(keep_playing){
|
||||
int car_speed = uniform!"[]"(40,65); //Random number between 40 and 65
|
||||
int delta_time = uniform!"(]"(4,20); //Between 5 and 20
|
||||
int train_speed = uniform!"[)"(20,40); //Between 20 and 39; This is the default if not specified: uniform(x,y)
|
||||
|
||||
writeln("\nA CAR TRAVELING AT ", car_speed, " MPH CAN MAKE A CERTAIN TRIP IN ", delta_time,
|
||||
" HOURS LESS THAN A TRAIN TRAVELING AT ", train_speed, "MPH." );
|
||||
|
||||
float input;
|
||||
write("HOW LONG DOES THE TRIP TAKE BY CAR? ");
|
||||
readf!"%f\n"(input);
|
||||
|
||||
float car_time = cast(float)delta_time * train_speed / (car_speed - train_speed);
|
||||
int percent = cast(int)( abs(car_time-input) * 100 / car_time + .5);
|
||||
|
||||
if(percent > error_margin){
|
||||
writeln("SORRY. YOU WERE OFF BY ", percent, " PERCENT.");
|
||||
}else{
|
||||
writeln("GOOD! ANSWER WITHIN ", percent, " PERCENT.");
|
||||
}
|
||||
writeln("CORRECT ANSWER IS ", car_time, " HOURS.");
|
||||
|
||||
string answer;
|
||||
write("\nANOTHER PROBLEM (YES OR NO)? ");
|
||||
readf!"%s\n"(answer);
|
||||
|
||||
if( !(answer == "YES" || answer == "Y" || answer == "yes" || answer == "y") ){
|
||||
keep_playing = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
268
90_Tower/lua/tower.lua
Normal file
268
90_Tower/lua/tower.lua
Normal file
@@ -0,0 +1,268 @@
|
||||
print [[
|
||||
|
||||
TOWERS
|
||||
CREATIVE COMPUTING MORRISTOWN, NEW JERSY
|
||||
|
||||
|
||||
]]
|
||||
|
||||
local MAX_DISKS <const> = 7
|
||||
local MAX_DISK_SIZE <const> = 15
|
||||
local MAX_MOVES <const> = 128
|
||||
local NUM_TOWERS <const> = 3
|
||||
|
||||
local towers = {
|
||||
{ size = 0, elem = {} },
|
||||
{ size = 0, elem = {} },
|
||||
{ size = 0, elem = {} },
|
||||
}
|
||||
|
||||
local total_disks
|
||||
function ask_how_many_disks()
|
||||
|
||||
local keep_asking = true
|
||||
local input
|
||||
local errors = 0
|
||||
|
||||
while keep_asking do
|
||||
|
||||
io.write(string.format("HOW MANY DISKS DO YOU WANT TO MOVE (%d IS MAX)? ", MAX_DISKS) )
|
||||
input = io.read("*number")
|
||||
io.read() --get rid of the remaining newline character
|
||||
|
||||
if input ~= nil and input>0 and input<=MAX_DISKS then
|
||||
keep_asking = false
|
||||
|
||||
else
|
||||
errors = errors + 1
|
||||
if errors > 2 then
|
||||
print "ALL RIGHT, WISE GUY, IF YOU CAN'T PLAY THE GAME RIGHT, I'LL"
|
||||
print "JUST TAKE MY PUZZLE AND GO HOME. SO LONG."
|
||||
os.exit()
|
||||
end
|
||||
|
||||
print "SORRY, BUT I CAN'T DO THAT JOB FOR YOU."
|
||||
end
|
||||
end
|
||||
total_disks = input
|
||||
end
|
||||
|
||||
function init_game()
|
||||
print("TOWERS OF HANOIR PUZZLE\n") --'\n' indicates a new line
|
||||
|
||||
print "YOU MUST TRANSFER THE DISKS FROM THE LEFT TO THE RIGHT TOWER,"
|
||||
print "ONE AT A TIME, NEVER PUTTING A LARGER DISK ON A SMALLER DISK.\n"
|
||||
|
||||
ask_how_many_disks()
|
||||
|
||||
print() -- print() already creates a new line at the end, so an empty print leaves an empty line
|
||||
print "IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE."
|
||||
print "3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE, 7 THE"
|
||||
print "NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH 2 DISKS,"
|
||||
print "THEIR CODE NAMES WOULD BE 13 AND 15, ETC. THE NEEDLES ARE"
|
||||
print "NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL START WITH THE"
|
||||
print "DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM TO NEEDLE 3.\n"
|
||||
|
||||
print "GOOD LUCK!\n"
|
||||
|
||||
local i = 1
|
||||
local max = MAX_DISK_SIZE
|
||||
while i<= total_disks do
|
||||
towers[1].elem[i] = max
|
||||
max = max-2
|
||||
i = i+1
|
||||
end
|
||||
|
||||
towers[1].size = total_disks
|
||||
|
||||
local idx = 2
|
||||
while idx <= NUM_TOWERS do
|
||||
towers[idx].size = 0
|
||||
end
|
||||
end
|
||||
|
||||
function print_towers()
|
||||
local line = MAX_DISKS
|
||||
|
||||
while line > 0 do
|
||||
local twr = 1
|
||||
|
||||
while twr <=3 do
|
||||
local rpt = 10
|
||||
local offset = 0
|
||||
if line <= towers[twr].size then
|
||||
offset = (towers[twr].elem[line] - 1) / 2
|
||||
rpt = rpt - offset
|
||||
end
|
||||
io.write( string.rep(' ', rpt) )
|
||||
io.write( string.rep('*', offset) )
|
||||
io.write '*'
|
||||
io.write( string.rep('*', offset) )
|
||||
io.write( string.rep(' ', rpt) )
|
||||
twr = twr + 1
|
||||
end
|
||||
print ''
|
||||
line = line - 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ask_which_disk()
|
||||
|
||||
local keep_asking = true
|
||||
local input
|
||||
local errors = 0
|
||||
while keep_asking do
|
||||
|
||||
io.write("WHICH DISK WOULD YOU LIKE TO MOVE? ")
|
||||
input = io.read("*number")
|
||||
io.read() --get rid of the remaining newline character
|
||||
|
||||
if input==nil or input > MAX_DISK_SIZE or input%2==0 or input <= MAX_DISK_SIZE-(total_disks*2) then
|
||||
print "ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13 or 15."
|
||||
errors = errors + 1
|
||||
if errors > 1 then
|
||||
print "STOP WASTING MY TIME. GO BOTHER SOMEONE ELSE."
|
||||
os.exit()
|
||||
end
|
||||
|
||||
--[[
|
||||
Since there are only 3 towers, it's easier to do an 'if' with three
|
||||
conditions than to do a loop
|
||||
]]
|
||||
elseif towers[1].elem[ towers[1].size ] ~= input and
|
||||
towers[2].elem[ towers[2].size ] ~= input and
|
||||
towers[3].elem[ towers[3].size ] ~= input then
|
||||
|
||||
print "THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE."
|
||||
else
|
||||
keep_asking = false
|
||||
end
|
||||
end
|
||||
|
||||
return input
|
||||
end
|
||||
|
||||
function ask_which_needle(dsk)
|
||||
|
||||
local keep_asking = true
|
||||
local input
|
||||
local errors = 0
|
||||
|
||||
while keep_asking do
|
||||
|
||||
io.write("PLACE DISK ON WHICH NEEDLE? ")
|
||||
input = io.read("*number")
|
||||
io.read() --get rid of the remaining newline character
|
||||
|
||||
if input~=nil and towers[input].size > 0 and towers[input].elem[ towers[input].size ] < dsk then
|
||||
print "YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE,"
|
||||
print "IT MIGHT CRUSH IT!"
|
||||
return 0
|
||||
|
||||
elseif input~=nil and input>=1 and input<=3 then
|
||||
keep_asking = false
|
||||
|
||||
else
|
||||
errors = errors + 1
|
||||
if errors > 1 then
|
||||
print "I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN."
|
||||
print "BYE BYE, BIG SHOT."
|
||||
os.exit() --Stop program
|
||||
else
|
||||
print "I'LL ASSUME YOU HIT THE WRONG KEY THIS TIME. BUT WATCH IT,"
|
||||
print "I ONLY ALLOW ONE MISTAKE."
|
||||
end
|
||||
end
|
||||
end
|
||||
return input
|
||||
end
|
||||
|
||||
function is_game_over()
|
||||
if towers[1].size == 0 and towers[2].size == 0 then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function game_loop()
|
||||
local moves = 0
|
||||
local dsk
|
||||
local twr_to
|
||||
local twr_fr
|
||||
|
||||
while not is_game_over() do
|
||||
moves = moves + 1
|
||||
|
||||
if moves > MAX_MOVES then
|
||||
print(string.format("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN %d MOVES.", MAX_MOVES))
|
||||
os.exit()
|
||||
end
|
||||
|
||||
|
||||
repeat
|
||||
dsk = ask_which_disk()
|
||||
twr_to = ask_which_needle(dsk)
|
||||
until twr_to ~= 0
|
||||
|
||||
|
||||
if towers[1].elem[ towers[1].size ] == dsk then
|
||||
twr_fr = 1
|
||||
elseif towers[2].elem[ towers[2].size ] == dsk then
|
||||
twr_fr = 2
|
||||
else
|
||||
twr_fr = 3
|
||||
end
|
||||
|
||||
towers[twr_fr].size = towers[twr_fr].size - 1
|
||||
|
||||
towers[twr_to].size = towers[twr_to].size + 1
|
||||
towers[twr_to].elem[ towers[twr_to].size ] = dsk
|
||||
|
||||
print_towers()
|
||||
end
|
||||
|
||||
return moves
|
||||
end
|
||||
|
||||
function keep_playing()
|
||||
|
||||
while true do
|
||||
io.write("TRY AGAIN (YES OR NO)? ")
|
||||
local input = io.read("*line")
|
||||
|
||||
if input == "YES" or input == "yes" then
|
||||
return true
|
||||
elseif input == "NO" or input == "no" then
|
||||
return false
|
||||
else
|
||||
print "'YES' OR 'NO' PLEASE"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function start_loop()
|
||||
|
||||
while true do
|
||||
init_game()
|
||||
print_towers()
|
||||
|
||||
local moves = game_loop()
|
||||
|
||||
--check ideal solution
|
||||
if moves == (2^total_disks) - 1 then
|
||||
print "CONGRATULATIONS!!"
|
||||
end
|
||||
|
||||
print ( string.format("YOU HAVE PERFORMED THE TASK IN %d MOVES.\n", moves) )
|
||||
|
||||
if not keep_playing() then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
print "\nTHANKS FOR THE GAME!"
|
||||
end
|
||||
|
||||
start_loop()
|
||||
59
91_Train/lua/train.lua
Normal file
59
91_Train/lua/train.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
print [[
|
||||
TRAIN
|
||||
CREATIVE COMPUTING MORRISTOWN, NEW JERSY
|
||||
|
||||
|
||||
|
||||
TIME - SPEED DISTANCE EXERCISE]]
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
local ERROR_MARGIN <const> = 5.0
|
||||
|
||||
function play()
|
||||
local car_speed = 25*math.random() + 40--Between 40 and 64
|
||||
local delta_time = 15*math.random() + 5--Between 5 and 19
|
||||
local train_speed = 19*math.random() + 20--Between 20 and 38
|
||||
|
||||
print( string.format("\nA CAR TRAVELING AT %u MPH CAN MAKE A CERTAIN TRIP IN %u HOURS LESS THAN A TRAIN TRAVELING AT %u MPH.", car_speed, delta_time, train_speed) )
|
||||
|
||||
local try = true
|
||||
local input
|
||||
while try do
|
||||
io.write("HOW LONG DOES THE TRIP TAKE BY CAR? ")
|
||||
input = io.read("n")
|
||||
if input == nil then
|
||||
print("<!>PLEASE INSERT A NUMBER<!>")
|
||||
else
|
||||
try = false
|
||||
end
|
||||
io.read()
|
||||
end
|
||||
|
||||
local car_time = delta_time * train_speed / (car_speed - train_speed)
|
||||
local percent = ( math.abs(car_time-input) * 100 / car_time + .5)
|
||||
|
||||
if percent > ERROR_MARGIN then
|
||||
print( string.format("SORRY. YOU WERE OFF BY %f PERCENT.", percent) )
|
||||
else
|
||||
print( string.format("GOOD! ANSWER WITHIN %f PERCENT.", percent) )
|
||||
end
|
||||
|
||||
print( string.format("CORRECT ANSWER IS %f HOURS.", car_time) )
|
||||
end
|
||||
|
||||
function game_loop()
|
||||
local keep_playing = true
|
||||
while keep_playing do
|
||||
play()
|
||||
io.write("\nANOTHER PROBLEM (YES OR NO)? ")
|
||||
answer = io.read("l")
|
||||
|
||||
if not (answer == "YES" or answer == "Y" or answer == "yes" or answer == "y") then
|
||||
keep_playing = false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
game_loop()
|
||||
Reference in New Issue
Block a user