Can anyone suggest a suitable way of figuring out a pieces allowable moves on a grid similar to the one in the image below.
任何人都可以建议一种合适的方法来计算网格上允许的移动,类似于下图中的那种。
Assuming piece1 is at position a1 and piece2 is at position c3, how can I figure out which grid squares are allowable moves if piece1 can move (say) 3 squares and piece2 can move 2?
假设piece1位于位置a1而piece2位于位置c3,如果piece1可以移动(比方说)3个方格而piece2可以移动2,我怎样才能确定哪个网格方格是允许的移动?
I've spent way too long developing text based MUDS it seems, I simply can't get my brain to take the next step into how to visualise potential movement even in the most simple of situations.
我花了太长时间开发基于MUDS的MUDS,即使在最简单的情况下,我也无法让我的大脑进行下一步如何可视化潜在的运动。
If it matters, I'm trying to do this in Javascript, but to be perfectly honest I think my failure here is a failure to conceptualise properly - not a failure in language comprehension.
如果它很重要,我试图用Javascript做这件事,但说实话,我认为我在这里的失败是不能正确地概念化 - 而不是语言理解的失败。
Update - I'm adding the first round of code written after the below responses were posted. I thought it might be useful to people in a similar situation as me to see the code
更新 - 我在发布以下回复后添加了第一轮代码。我认为在与我类似的情况下看到代码的人可能会有所帮助
It's sloppy and it only works for one item placed on the board so far, but at least the check_allowable_moves() function works for this initial run. For those of you wondering why the hell I'm creating those weird alphanumeric objects rather than just using numeric x axis and y axis - it's because an id in HTML can't start with a number. In fact pretending I could use numbers to start ids helped a great deal in making sense of the functionality and concepts described by the fantastic answers I got.
它很草率,它只适用于目前为止放在板上的一个项目,但至少check_allowable_moves()函数适用于此初始运行。对于那些你想知道我为什么要创建那些奇怪的字母数字对象而不仅仅是使用数字x轴和y轴的人 - 这是因为HTML中的id不能以数字开头。实际上假装我可以使用数字来启动id,这有助于理解我得到的奇妙答案所描述的功能和概念。
4 个解决方案
#1
Suppose piece p is at position x, y and can move n squares away to position x2, y2. This means that the sum of the absolute differences between (x - x2) and (y - y2) can be no greater than n.
假设片段p位于x,y位置并且可以移动n个方格到位置x2,y2。这意味着(x-x2)和(y-y2)之间的绝对差之和可以不大于n。
If you're going to show which squares can be moved to (rather than taking inputs x2 and y2), I think it'd be best to loop over all positions in a square around the piece. That is...
如果你要显示哪些方格可以移动到(而不是输入x2和y2),我认为最好绕过该方块周围的所有位置。那是...
for (x - n TO x + n): for (y - n TO x + n): if (abs(x - x2) + abs(y - y2) <= n): mark as okay.This answer assumes pieces can only move to adjacent squares and not diagonally.
这个答案假设碎片只能移动到相邻的正方形而不是对角线。
Edit: If you want diagonal movement, and moving along a diagonal costs just as much as moving horizontally or vertically, then the problem is actually much easier - the piece p can move between the ranges of (x - n, x + n) and (y - n, y + n).
编辑:如果你想要对角线移动,沿着对角线移动的成本与水平或垂直移动一样多,那么问题实际上要容易得多 - 片段p可以在(x - n,x + n)和(y - n,y + n)。
The answer becomes a lot more complex if moving diagonally doesn't cost as much as a horizontal + vertical movement (e.g., if diagonal costs 1.5, whereas h/v costs 1).
如果沿对角线移动的成本不如水平+垂直移动(例如,如果对角线成本为1.5,而h / v成本为1),则答案会变得复杂得多。
#2
In general such problems involve a reasonably limited grid of places one can possibly reach. Take a data structure of the size of the grid and whose elements can hold the number of remaining movement points with sufficient precision.
通常,这些问题涉及一个人们可能达到的合理有限的网格。采用网格大小的数据结构,其元素可以足够精确地保存剩余运动点的数量。
Initialize the grid to a not-visited value. This must not be in the range of zero to the maximum possible move speed. A negative value is ideal.
将网格初始化为未访问的值。这不得在零到最大可能移动速度的范围内。负值是理想的。
Initialize the starting location to the number of moves remaining.
将起始位置初始化为剩余的移动次数。
At this point there are three possible approaches:
此时有三种可能的方法:
1) Rescan the whole grid each step. Simple but slower. Termination is when no points yield a legal move.
1)每一步重新扫描整个网格。简单但速度较慢。终止是指没有任何积分产生合法举措。
2) Store points on a stack. Faster than #1 but still not the best. Termination is when the stack is empty.
2)将点存储在堆栈上。比#1快,但仍然不是最好的。终止是堆栈为空时。
3) Store points in a queue. This is the best. Termination is when the queue is empty.
3)将点存储在队列中。这是最好的。终止是队列为空时。
Repeat ObtainPoint {From queue, stack or brute force} For Each Neighbor do Remaining = Current - MovementCost If Remaining > CurrentValue[Neighbor] then CurrentValue[Neighbor] = Remaining Push or Queue NeighborUntil DoneNote that with the stack-based approach you will always have some cases where you end up throwing out the old calculations and doing them again. A queue-based approach will have this happen only if there are cases where going around bad terrain is cheaper than going through it.
请注意,使用基于堆栈的方法时,您总会遇到一些情况,最终会丢弃旧计算并再次执行。基于队列的方法只有在遇到不良地形比通过它更便宜的情况下才会发生这种情况。
Check the termination condition only at the end of the loop, or else terminate when ObtainPoint attempts to use an empty queue or stack. An empty queue/stack after ObtainPoint does NOT mean you're done!
仅在循环结束时检查终止条件,否则在ObtainPoint尝试使用空队列或堆栈时终止。 ObtainPoint之后的空队列/堆栈并不意味着你已经完成了!
(Note that is is a considerable expansion on Ian's answer.)
(请注意,Ian的回答是相当大的扩展。)
#3
This is purely on a conceptual level, but try this logic:
这纯粹是在概念层面,但尝试这个逻辑:
Take all possible locations one step away from your starting point and put them on the stack (Moves Taken =0)
将所有可能的位置从起点上移开一步并将它们放在堆叠上(Moves Taken = 0)
Pop one off the stack and repeat, using that new coordinate as your new starting point. (Moves Taken=1). You'll have to ensure that you don't put any duplicate coordinates on the stack
从堆栈弹出一个并重复,使用新坐标作为新的起点。 (移动采取= 1)。您必须确保不在堆栈上放置任何重复的坐标
Repeat 2 until you've exhausted all your piece's available moves.
重复2,直到你已经耗尽所有作品的可用动作。
I may not be explaining this to well, let me know if you have any questions about what I'm trying to say.
我可能不会很好地解释这一点,如果您对我想说的话有任何疑问,请告诉我。
#4
You could use the approach above but use recursion instead.
您可以使用上面的方法,但使用递归。
The recursion "depth" is the movement distance.
递归“深度”是移动距离。
Break out when depth > movement.
当深度>运动时爆发。
Each iteration should return a vector of spaces and add its own location.
每次迭代都应返回一个空格向量并添加自己的位置。
Remove duplicates