161 lines
4.5 KiB
Plaintext
161 lines
4.5 KiB
Plaintext
#digitCount = 4
|
|
Global Dim digits(#digitCount - 1) ;holds random digits
|
|
|
|
Procedure showDigits()
|
|
Print(#CRLF$ + "These are your four digits: ")
|
|
Protected i
|
|
For i = 0 To #digitCount - 1
|
|
Print(Str(digits(i)))
|
|
If i < (#digitCount - 1)
|
|
Print(", ")
|
|
Else
|
|
PrintN("")
|
|
EndIf
|
|
Next
|
|
Print("24 = ")
|
|
EndProcedure
|
|
|
|
Procedure playAgain()
|
|
Protected answer.s
|
|
Repeat
|
|
Print("Play again (y/n)? ")
|
|
answer = LCase(Left(Trim(Input()), 1))
|
|
Select answer
|
|
Case "n"
|
|
ProcedureReturn #False
|
|
Case "y"
|
|
ProcedureReturn #True
|
|
Default
|
|
PrintN("")
|
|
Continue
|
|
EndSelect
|
|
ForEver
|
|
EndProcedure
|
|
|
|
Procedure allDigitsUsed()
|
|
Protected i
|
|
For i = 0 To #digitCount - 1
|
|
If digits(i) <> 0
|
|
ProcedureReturn #False
|
|
EndIf
|
|
Next
|
|
ProcedureReturn #True
|
|
EndProcedure
|
|
|
|
Procedure isValidDigit(d)
|
|
For i = 0 To #digitCount - 1
|
|
If digits(i) = d
|
|
digits(i) = 0
|
|
ProcedureReturn #True
|
|
EndIf
|
|
Next
|
|
ProcedureReturn #False
|
|
EndProcedure
|
|
|
|
Procedure doOperation(List op.c(), List operand.f())
|
|
Protected x.f, y.f, op.c
|
|
op = op(): DeleteElement(op())
|
|
If op = '('
|
|
ProcedureReturn #False ;end of sub-expression
|
|
EndIf
|
|
|
|
y = operand(): DeleteElement(operand())
|
|
x = operand()
|
|
Select op
|
|
Case '+'
|
|
x + y
|
|
Case '-'
|
|
x - y
|
|
Case '*'
|
|
x * y
|
|
Case '/'
|
|
x / y
|
|
EndSelect
|
|
operand() = x
|
|
ProcedureReturn #True ;operation completed
|
|
EndProcedure
|
|
|
|
;returns error if present and the expression results in *result\f
|
|
Procedure.s parseExpression(expr.s, *result.Float)
|
|
NewList op.c()
|
|
NewList operand.f()
|
|
expr = ReplaceString(expr, " ", "") ;remove spaces
|
|
|
|
If Len(expr) = 0: *result\f = 0: ProcedureReturn "": EndIf ;no expression, return zero
|
|
|
|
Protected *ech.Character = @expr, lastWasDigit, lastWasOper, parenCheck, c.c
|
|
While *ech\c
|
|
c = *ech\c
|
|
Select c
|
|
Case '*', '/', '-', '+'
|
|
If Not lastWasDigit: ProcedureReturn "Improper syntax, need a digit between operators.": EndIf
|
|
If ListSize(op()) And (FindString("*/", Chr(op()), 1) Or (FindString("+-", Chr(op()), 1) And FindString("+-", Chr(c), 1)))
|
|
doOperation(op(), operand())
|
|
EndIf
|
|
AddElement(op()): op() = c
|
|
lastWasOper = #True: lastWasDigit = #False
|
|
Case '('
|
|
If lastWasDigit: ProcedureReturn "Improper syntax, need an operator before left paren.": EndIf
|
|
AddElement(op()): op() = c
|
|
parenCheck + 1: lastWasOper = #False
|
|
Case ')'
|
|
parenCheck - 1: If parenCheck < 0: ProcedureReturn "Improper syntax, missing a left paren.": EndIf
|
|
If Not lastWasDigit: ProcedureReturn "Improper syntax, missing a digit before right paren.": EndIf
|
|
Repeat: Until Not doOperation(op(),operand())
|
|
lastWasDigit = #True
|
|
Case '1' To '9'
|
|
If lastWasDigit: ProcedureReturn "Improper syntax, need an operator between digits.": EndIf
|
|
AddElement(operand()): operand() = c - '0'
|
|
If Not isValidDigit(operand()): ProcedureReturn "'" + Chr(c) + "' is not a valid digit.": EndIf
|
|
lastWasDigit = #True: lastWasOper = #False
|
|
Default
|
|
ProcedureReturn "'" + Chr(c) + "' is not allowed in the expression."
|
|
EndSelect
|
|
*ech + SizeOf(Character)
|
|
Wend
|
|
|
|
If parenCheck <> 0 Or lastWasOper: ProcedureReturn "Improper syntax, missing a right paren or digit.": EndIf
|
|
Repeat
|
|
If Not ListSize(op()): Break: EndIf
|
|
Until Not doOperation(op(),operand())
|
|
*result\f = operand()
|
|
ProcedureReturn "" ;no error
|
|
EndProcedure
|
|
|
|
Define success, failure, result.f, error.s, i
|
|
If OpenConsole()
|
|
PrintN("The 24 Game" + #CRLF$)
|
|
PrintN("Given four digits and using just the +, -, *, and / operators; and the")
|
|
PrintN("possible use of brackets, (), enter an expression that equates to 24.")
|
|
Repeat
|
|
For i = 0 To #digitCount - 1
|
|
digits(i) = 1 + Random(8)
|
|
Next
|
|
|
|
showDigits()
|
|
error = parseExpression(Input(), @result)
|
|
If error = ""
|
|
If Not allDigitsUsed()
|
|
PrintN( "Wrong! (you didn't use all digits)"): failure + 1
|
|
ElseIf result = 24.0
|
|
PrintN("Correct!"): success + 1
|
|
Else
|
|
Print("Wrong! (you got ")
|
|
If result <> Int(result)
|
|
PrintN(StrF(result, 2) + ")")
|
|
Else
|
|
PrintN(Str(result) + ")")
|
|
EndIf
|
|
failure + 1
|
|
EndIf
|
|
Else
|
|
PrintN(error): failure + 1
|
|
EndIf
|
|
Until Not playAgain()
|
|
|
|
PrintN("success:" + Str(success) + " failure:" + Str(failure) + " total:" + Str(success + failure))
|
|
|
|
Print(#CRLF$ + "Press ENTER to exit"): Input()
|
|
CloseConsole()
|
|
EndIf
|