Pushing through to complete an educational Math game now despite having poor Math skills.
Game is called: “NumbersFall” and is M.I.T. Open-Source FOSS.
Basics of the game play is numbers and operators fall from the top.
Player must create valid equations from the fallen tiles.
I need help with the String based logic source code.
My source code to convert the selected fallen tiles into an equation is absolute garbage.
I won’t post to GitHub until Beta 1, so I apologize in advance for posting source code below.
Please help us to make below sample code better, thank you!
I guarantee there is a much better way to do it, but It would really help if you posted the full project to understand what it currently does and how to properly rewrite it, because trying to follow and understand this if-statement-monster raw is gonna be close to impossible. Especially that you plan on releasing this as FOSS, you shouldn’t have any issues releasing the source code early anyway.
EDIT: The easiest suggestion would be to look into this article about evaluating the expressions. Godot is able to handle things like that:
var expression = Expression.new()
expression.parse("20 + 10*2 - 5/2.0")
var result = expression.execute()
print(result) # 37.5
Expressing the problem algorithmically might give you more control over which expressions you allow and which ones you don’t.
In case of solving it algorithmically, there should be a simpler way to parse simple math equations (without parentheses, without exponentiation, without floating point notation).
Check this example’s algorithm. For building a parse tree with parenthesis only a loop and a simple rather simple if statement are needed.
I would break the problem of what is a valid expression down into these definitions:
a leave is a number with an optional unary prefix, e.g. 0, +43, -12
note here: you probably don’t want the numerical part to start with a zero, except if it is only one zero, so invalid would be 01 or -032.
between two leaves has to be one of these operators: *, /, + and -.
For the evaluation of operators you have to define the order of operation.
What happens to 4 * 3 / 6, is / going before *, or is the left one going before the right one?
I have the following code below, but not working yet:
Would be great if this works eventually, game will be finished when equation parse and check is working.
When the user clicks on a fallen tile, it already knows when to allow and not allow, ie: 01(bad) 10(good)
SS
var EquationString: String = “”
func ConvertTilesToString():
ThereIsAnOperator = false
ThereIsAnEqual = false
PlusIndex = -1
MinusIndex = -1
MultiplyIndex = -1
DivideIndex = -1
EqualIndex = -1
TheEnd = 0
CurrentClearedTiles = 0
EquationString = ""
var index = 0
while (index < 10 and SelectedTilePlayfieldX[index] != -1 and SelectedTilePlayfieldY[index] != -1):
var selX = SelectedTilePlayfieldX[index]
var selY = SelectedTilePlayfieldY[index]
if (Playfield[selX][selY] > -1 and Playfield[selX][selY] < 16):
CurrentClearedTiles+=1
var part = Playfield[selX][selY]
if (part == 0): EquationString+="0"
elif (part == 1): EquationString+="1"
elif (part == 2): EquationString+="2"
elif (part == 3): EquationString+="3"
elif (part == 4): EquationString+="4"
elif (part == 5): EquationString+="5"
elif (part == 6): EquationString+="6"
elif (part == 7): EquationString+="7"
elif (part == 8): EquationString+="8"
elif (part == 9): EquationString+="9"
elif (part == 10):
EquationString+="+"
PlusIndex = index
ThereIsAnOperator = true
elif (part == 11):
EquationString+="-"
MinusIndex = index
ThereIsAnOperator = true
elif (part == 12):
EquationString+="*"
ThereIsAnOperator = true
MultiplyIndex = index
elif (part == 13):
EquationString+="/"
ThereIsAnOperator = true
DivideIndex = index
elif (part == 14):
EquationString+="="
ThereIsAnEqual = true
EqualIndex = index
index+=1
TheEnd = index
EquationString+="E"
pass
func CheckEquationNewPerfect():
ConvertTilesToString()
print(EquationString) # 4/2+6*-9=8E ("E" = end of string, must be some better way?)
var expression = Expression.new()
expression.parse(EquationString)
var result = expression.execute()
print(result) # <null>
return(false) # Will return true in future when full equation equals the selected result
If you include parenthesis you could actually convert the code of the example I mentioned above to GDScript.
from pythonds.basic import Stack
from pythonds.trees import BinaryTree
def buildParseTree(fpexp):
fplist = fpexp.split()
pStack = Stack()
eTree = BinaryTree('')
pStack.push(eTree)
currentTree = eTree
for i in fplist:
if i == '(':
currentTree.insertLeft('')
pStack.push(currentTree)
currentTree = currentTree.getLeftChild()
elif i in ['+', '-', '*', '/']:
currentTree.setRootVal(i)
currentTree.insertRight('')
pStack.push(currentTree)
currentTree = currentTree.getRightChild()
elif i == ')':
currentTree = pStack.pop()
elif i not in ['+', '-', '*', '/', ')']:
try:
currentTree.setRootVal(int(i))
parent = pStack.pop()
currentTree = parent
except ValueError:
raise ValueError("token '{}' is not a valid integer".format(i))
return eTree
pt = buildParseTree("( ( 10 + 5 ) * 3 )")
pt.postorder() #defined and explained in the next section
For the stack data structure probably a normal Array in GDScript will do.
For the binary tree an Array of tuples and separate of Array of which branch got taken should do.
Your own code so far is a bit hard to understand. At least for these two reasons: It is mixing value to string conversion with other behavior; it is containing non-speaking numerical values such in elif (part == 11):, where 11 is the ID of some tile.
Instead of the function having side effect and operating on global variables, it would be easier to read if the function would return a value. It also has unnecessary indentation-depth, because the algorithm above achieves it with less – as far as I can tell, maybe I’m wrong on this.
Do you expect a single number after the equal sign? If that is the case – and if you know the expression is valid in general – you could just split the string at the equal sign and take the later half. The split is part of the String class, see the Godot docs on split(). Something like this…
var some_array = "4/2+6*-9=8".split("=", true, 0)
Otherwise, if you expect some more complicated pattern on the right side, you could try to match a regular expression (see Godot RegEx docs).