任何人都可以建议一种合适的方法来计算网格上允许的移动,类似于下图中的移动。
假设piece1位于位置a1而piece2位于位置c3,如果piece1可以移动(比方说)3个方格而piece2可以移动2,我怎样才能确定哪个网格方格是允许的移动?
我花了太长时间开发基于MUDS的MUDS,即使在最简单的情况下,我也无法让我的大脑进行下一步如何可视化潜在的运动。
如果重要的话,我试图用javascript来做这件事,但说实话,我认为我在这里的失败是不能正确地概念化 - 而不是语言理解的失败。
更新 - 我在发布以下回复后添加了第一轮代码。我认为对于处于类似情况的人来说,看看代码
可能会有用它很邋and,它只适用于目前为止放在主板上的一个项目,但至少check_allowable_moves()
功能适用于此初始运行。对于那些你想知道我为什么要创建那些奇怪的字母数字对象而不仅仅是使用数字x轴和y轴的人 - 这是因为HTML中的id不能以数字开头。实际上假装我可以使用数字来启动id,这有助于理解我得到的奇妙答案所描述的功能和概念。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml;utf-8"/>
<title>Test page</title>
<style>
#chessboard { clear: both; border:solid 1px black; height: 656px;
width:656px; /*width = 8*40 + 16 for border*/ }
#chessboard .row { overflow: auto; clear: both; }
#chessboard .row span { display: block; height: 80px;
width: 80px; float: left;
border:solid 1px black; }
.allowable { background: blue; }
</style>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("jquery", "1.2.6");
google.load("jqueryui", "1.5.3");
</script>
<script type="text/javascript">
$(document).ready(function() {
(function() {
var global = this;
global.Map = function(container) {
function render_board() {
var max_rows = 8;
var cols = new Array('a','b', 'c', 'd', 'e', 'f', 'g', 'h');
var jqMap = $('<div />');
jqMap.attr('id', 'chessboard');
var x=0;
for(x; x<max_rows; x++) {
var jqRow = $('<span />');
jqRow.addClass('row');
var i=0;
for(i; i<cols.length; i++) {
var jqCol = $('<span />');
jqCol.attr('id', cols[i]+(x+1));
jqCol.addClass(cols[i]);
jqRow.append(jqCol);
}
jqMap.append(jqRow);
}
$('#'+container).append(jqMap);
}
function add_piece(where, id) {
var jqPiece = $('<div>MY PIECE'+id+'</div>');
var jqWhere = $('#'+where);
jqPiece.attr('id', 'piece-'+id);
jqPiece.addClass('army');
jqPiece.draggable({cursor: 'move',
grid:[82, 82],
containment: '#chessboard',
revert: 'invalid',
stop: function(ev, ui) {
//console.log(ev.target.id);
}
});
jqWhere.append(jqPiece);
check_allowable_moves(where);
}
function check_allowable_moves(location) {
var x_axis = { 'a':1,'b':2, 'c':3, 'd':4, 'e':5, 'f':6, 'g':7, 'h':8 };
var x_axis_alpha = { 1:'a',2:'b', 3:'c', 4:'d', 5:'e', 6:'f', 7:'g', 8:'h' };
$('.allowable').droppable("destroy");
$('.allowable').removeClass('allowable');
//get the x,y values of the piece just placed
var x = parseInt(x_axis[location[0]], 10);
var y = parseInt(location[1], 10);
var x_min = x-2;
var y_min = y-2;
for(x_min; x_min<=x+2; x_min++) {
for(y_min; y_min<=y+2; y_min++) {
var jqCell = $('#'+x_axis_alpha[x_min]+y_min)
jqCell.addClass('allowable');
jqCell.droppable({ accept: '.army',
drop: function(ev, ui) {
//console.log(ev, ui, $(this));
//handle_drop(ev, ui, $(this));
check_allowable_moves($(this).attr('id'));
}
});
}
y_min = parseFloat(y)-2;
}
}
render_board();
add_piece('d5', '2');
}
})();
var map = new Map('content');
});
</script>
</head>
<body id="debug">
<div id="page">
<div id="content"> </div>
</div><!-- end page -->
</body>
</html>
答案 0 :(得分:3)
假设片p位于x,y位置,并且可以将n个方格移动到位置x2,y2。这意味着(x - x2)和(y - y2)之间的绝对差值之和不能大于n。
如果您要显示哪些方格可以移动到(而不是输入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.
这个答案假设碎片只能移动到相邻的方块而不是对角线。
编辑:如果你想要对角线移动,并且沿着对角线移动成本与水平或垂直移动一样多,那么问题实际上要容易得多 - 片段p可以在(x - n,x +)的范围之间移动n)和(y - n,y + n)。
如果沿对角线移动的成本不如水平+垂直移动(例如,如果对角线成本为1.5,而h / v成本为1),则答案会变得复杂得多。
答案 1 :(得分:2)
一般而言,这些问题涉及一个人们可能达到的合理有限的网格。获取网格大小的数据结构,其元素可以足够精确地保存剩余移动点的数量。
将网格初始化为未访问的值。这不得在零到最大可能移动速度的范围内。负值是理想的。
将起始位置初始化为剩余的移动次数。
此时有三种可能的方法:
1)每一步重新扫描整个网格。简单但速度较慢。终止时,没有任何一点可以产生合法的举动。
2)将点存储在堆栈上。比#1快,但仍然不是最好的。终止是指堆栈为空时。
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 Neighbor
Until Done
请注意,使用基于堆栈的方法时,您总会遇到一些情况,最终会丢弃旧计算并再次执行。基于队列的方法只有在出现恶劣地形的情况比通过它更便宜的情况下才会发生这种情况。
仅在循环结束时检查终止条件,否则在ObtainPoint尝试使用空队列或堆栈时终止。 ObtainPoint之后的空队列/堆栈 NOT 意味着你已经完成了!
(请注意,Ian的回答是相当大的扩展。)
答案 2 :(得分:1)
这纯粹是在概念层面,但尝试这个逻辑:
将所有可能的位置从起点上移开一步并将它们放在堆叠上(Moves Taken = 0)
从堆栈中弹出一个并重复,使用新坐标作为新的起点。 (移动采取= 1)。您必须确保不在堆栈上放置任何重复的坐标
重复2,直到你已经用完所有可用的动作为止。
我可能不会很好地解释这个问题,如果您对我想说的内容有任何疑问,请与我联系。
答案 3 :(得分:0)
您可以使用上述方法,但改为使用递归。
递归“深度”是移动距离。
深度时分解&gt;运动。
每次迭代都应返回一个空格向量并添加自己的位置。
删除重复项