如何为游戏生成随机算术表达式
How to generate random arithmetic expressions for game
我想知道您是否可以帮我解决我游戏中的这个问题。我目前在我的代码中使用了很多开关、if-else 等,我一点也不喜欢它。
我想生成 2 个具有如下形式之一的随机算术表达式:
1)个数
例如:19
2) number操作数
例如:22 * 4
3)(number操作数)操作数
例如:(10 * 4) / 5
4)((number操作数)操作数)操作数
例如:((25 * 2) / 10) - 2
在我有 2 个算术表达式后,游戏就是匹配它们并确定哪个更大。
我想知道如何为每个算术表达式随机选择数字和运算以获得整数结果(不是浮点数)并且两个表达式的结果尽可能接近。个人人数不得超过30。
我的意思是,我不希望结果是 1000 而其他 14,因为它们可能太容易发现哪一侧更大,所以它们应该像:
表达式 1:((25 + 15) / 10) * 4(即 16)
表达式 2:(( 7 * 2) + 10) / 8(即 3)
结果(16 和 3)是整数,并且 彼此足够接近。
可能的操作是+、-、*和/
可以在两个不同形式的表达式之间进行匹配,例如
(( 7 * 2) + 10) / 8
和
(18 / 3) * 2
非常感谢您能给我的所有帮助。
提前致谢!!
此致。
我认为解决这个问题的合理方法是从总值开始,然后递归构建一个随机 expression tree 来达到该总值。您可以选择每个方程式中所需的运算符数量,并确保所有值都是整数。另外,您可以选择两个方程的值有多接近,如果您愿意,甚至可以让它们相等。我将使用上面的 表达式 1 作为示例。
((25 + 15) / 10) * 4 = 16
我们从总数 16
开始,并将其作为我们树的根:
16
为了扩展一个节点(叶子),我们select一个operator
并将其设置为节点的值,并创建两个children包含operands
.在这种情况下,我们选择乘法作为运算符。
乘法是唯一真正会给我们带来麻烦的运算符,因为我们试图让所有的操作数都保持整数。我们可以通过构造 [1..30]
范围内的整数除数 table 来满足此约束(或者可能更多,我们将在下面看到)。在这种情况下,我们的 table 会告诉我们 16
的约数是 {2,4,8}
。 (如果我们当前值的除数列表为空,我们可以选择不同的运算符,或者完全不同的叶子。)
我们选择一个随机除数,比如 4
并将其设置为我们节点的 right
child。左边的child显然是value/right
,也是一个整数。
*
/ \
4 4
现在我们需要 select 展开另一片叶子。我们可以随机选择一片叶子,随机遍历树直到我们到达一片叶子,从我们当前的 child 节点(left
)随机向上并向右走直到我们到达一片叶子,或其他任何方式。
在这种情况下,我们的 selection 算法选择扩展左侧 child 和除法运算符。在除法的情况下,我们为right
child生成一个随机数(本例为10
),并设置left
为value*right
。 (这里的顺序很重要!乘法不是这样。)
*
/ \
÷ 4
/ \
40 10
这说明了为什么我说除数 table 可能需要超出我们规定的范围,因为一些中间值可能比 30 稍大。您可以调整代码以避免这种情况,或者确保在到达最终方程之前进一步扩展较大的值。
在示例中,我们通过 select 最左边的 child 来使用加法运算符展开。在这种情况下,我们可以简单地 select [1..value-1]
范围内的随机整数 right
child 和 value-right
范围内的 left
。 =34=]
*
/ \
÷ 4
/ \
+ 10
/ \
25 15
您可以重复任意数量的操作。要重建最终方程,您只需对树执行 in-order 遍历。要像您的示例中那样加上括号,在遍历过程中离开任何内部(运算符)节点时,您将在整个方程周围放置括号,根除外。
我想知道您是否可以帮我解决我游戏中的这个问题。我目前在我的代码中使用了很多开关、if-else 等,我一点也不喜欢它。
我想生成 2 个具有如下形式之一的随机算术表达式:
1)个数
例如:19
2) number操作数
例如:22 * 4
3)(number操作数)操作数
例如:(10 * 4) / 5
4)((number操作数)操作数)操作数
例如:((25 * 2) / 10) - 2
在我有 2 个算术表达式后,游戏就是匹配它们并确定哪个更大。
我想知道如何为每个算术表达式随机选择数字和运算以获得整数结果(不是浮点数)并且两个表达式的结果尽可能接近。个人人数不得超过30。
我的意思是,我不希望结果是 1000 而其他 14,因为它们可能太容易发现哪一侧更大,所以它们应该像:
表达式 1:((25 + 15) / 10) * 4(即 16)
表达式 2:(( 7 * 2) + 10) / 8(即 3)
结果(16 和 3)是整数,并且 彼此足够接近。
可能的操作是+、-、*和/
可以在两个不同形式的表达式之间进行匹配,例如
(( 7 * 2) + 10) / 8 和 (18 / 3) * 2
非常感谢您能给我的所有帮助。 提前致谢!!
此致。
我认为解决这个问题的合理方法是从总值开始,然后递归构建一个随机 expression tree 来达到该总值。您可以选择每个方程式中所需的运算符数量,并确保所有值都是整数。另外,您可以选择两个方程的值有多接近,如果您愿意,甚至可以让它们相等。我将使用上面的 表达式 1 作为示例。
((25 + 15) / 10) * 4 = 16
我们从总数 16
开始,并将其作为我们树的根:
16
为了扩展一个节点(叶子),我们select一个operator
并将其设置为节点的值,并创建两个children包含operands
.在这种情况下,我们选择乘法作为运算符。
乘法是唯一真正会给我们带来麻烦的运算符,因为我们试图让所有的操作数都保持整数。我们可以通过构造 [1..30]
范围内的整数除数 table 来满足此约束(或者可能更多,我们将在下面看到)。在这种情况下,我们的 table 会告诉我们 16
的约数是 {2,4,8}
。 (如果我们当前值的除数列表为空,我们可以选择不同的运算符,或者完全不同的叶子。)
我们选择一个随机除数,比如 4
并将其设置为我们节点的 right
child。左边的child显然是value/right
,也是一个整数。
*
/ \
4 4
现在我们需要 select 展开另一片叶子。我们可以随机选择一片叶子,随机遍历树直到我们到达一片叶子,从我们当前的 child 节点(left
)随机向上并向右走直到我们到达一片叶子,或其他任何方式。
在这种情况下,我们的 selection 算法选择扩展左侧 child 和除法运算符。在除法的情况下,我们为right
child生成一个随机数(本例为10
),并设置left
为value*right
。 (这里的顺序很重要!乘法不是这样。)
*
/ \
÷ 4
/ \
40 10
这说明了为什么我说除数 table 可能需要超出我们规定的范围,因为一些中间值可能比 30 稍大。您可以调整代码以避免这种情况,或者确保在到达最终方程之前进一步扩展较大的值。
在示例中,我们通过 select 最左边的 child 来使用加法运算符展开。在这种情况下,我们可以简单地 select [1..value-1]
范围内的随机整数 right
child 和 value-right
范围内的 left
。 =34=]
*
/ \
÷ 4
/ \
+ 10
/ \
25 15
您可以重复任意数量的操作。要重建最终方程,您只需对树执行 in-order 遍历。要像您的示例中那样加上括号,在遍历过程中离开任何内部(运算符)节点时,您将在整个方程周围放置括号,根除外。