用回溯解决骑士之旅 (javascript)

发布于 2024-11-17 06:53:30 字数 2403 浏览 2 评论 0原文

我正在尝试用 javascript 编写一个算法来使用回溯来解决 Knight's Tour 问题,但它不起作用。基本上,该函数应该输出一个名为 visited 的数组,其中包含每个移动的位置。但是,没有位置附加到数组中,数组仍为 [[0,0]]。这是我的代码。有什么线索吗?

var unit = 75;

function m1(position) { position[0] += unit; position[1] += 2*unit; return [position[0],position[1]]}
function m2(position) { position[0] -= unit; position[1] += 2*unit; return [position[0],position[1]]}
function m3(position) { position[0] += 2*unit; position[1] += unit; return [position[0],position[1]]}
function m4(position) { position[0] -= 2*unit; position[1] += unit; return [position[0],position[1]]}
function m5(position) { position[0] += unit; position[1] -= 2*unit; return [position[0],position[1]]}
function m6(position) { position[0] -= unit; position[1] -= 2*unit; return [position[0],position[1]]}
function m7(position) { position[0] += 2*unit; position[1] -= unit; return [position[0],position[1]]}
function m8(position) { position[0] -= 2*unit; position[1] -= unit; return [position[0],position[1]]}

var moves = [m1, m2, m3, m4, m5, m6, m7, m8];   
var currentPosition = [0, 0];
var visited = [currentPosition];

function knightour(currentPosition)
{

    var j; 

    if (promising(currentPosition))
    {

        if (visited.length == 64)
        {
            return visited;
        } 
        else 
        {
            for (j=0; j<moves.length; j++)
            {
                context.drawImage(knight, currentPosition[0], currentPosition[1]);
                alert("NEXT");
                visited.push(moves[j](currentPosition));
                knightour(currentPosition);
            }
        }
    } 
}  

function promising(currentPosition)
{
    if (currentPosition[0] < 600 && currentPosition[0] >= 0 &&
        currentPosition[1] < 600 && currentPosition[1] >= 0 &&
        isVisited(currentPosition, visited))
        {
        return true;
    } else {
        return false;
    }

} 

function isVisited(position, visited)               // visited is an array of size n of array of size 2 ([x,y])
{                                                       // currentPosition is an array of size 2 ([x,y])
    for (var i=0; i<visited.length; i++)
    {
        if (position[0] == visited[i][0] && position[1] == visited[i][1])
        {
            return true;
        }
    }
    return false;

} 

谢谢。

I am trying to write an algorithm in javascript to solve the Knight's Tour problem using Backtracking, but it doesn't work. Basically, the function is supposed to output an array called visited, which contains the locations of each moves. However, no location is appended to the array, which remains as [[0,0]]. Here is my code. Any clue?

var unit = 75;

function m1(position) { position[0] += unit; position[1] += 2*unit; return [position[0],position[1]]}
function m2(position) { position[0] -= unit; position[1] += 2*unit; return [position[0],position[1]]}
function m3(position) { position[0] += 2*unit; position[1] += unit; return [position[0],position[1]]}
function m4(position) { position[0] -= 2*unit; position[1] += unit; return [position[0],position[1]]}
function m5(position) { position[0] += unit; position[1] -= 2*unit; return [position[0],position[1]]}
function m6(position) { position[0] -= unit; position[1] -= 2*unit; return [position[0],position[1]]}
function m7(position) { position[0] += 2*unit; position[1] -= unit; return [position[0],position[1]]}
function m8(position) { position[0] -= 2*unit; position[1] -= unit; return [position[0],position[1]]}

var moves = [m1, m2, m3, m4, m5, m6, m7, m8];   
var currentPosition = [0, 0];
var visited = [currentPosition];

function knightour(currentPosition)
{

    var j; 

    if (promising(currentPosition))
    {

        if (visited.length == 64)
        {
            return visited;
        } 
        else 
        {
            for (j=0; j<moves.length; j++)
            {
                context.drawImage(knight, currentPosition[0], currentPosition[1]);
                alert("NEXT");
                visited.push(moves[j](currentPosition));
                knightour(currentPosition);
            }
        }
    } 
}  

function promising(currentPosition)
{
    if (currentPosition[0] < 600 && currentPosition[0] >= 0 &&
        currentPosition[1] < 600 && currentPosition[1] >= 0 &&
        isVisited(currentPosition, visited))
        {
        return true;
    } else {
        return false;
    }

} 

function isVisited(position, visited)               // visited is an array of size n of array of size 2 ([x,y])
{                                                       // currentPosition is an array of size 2 ([x,y])
    for (var i=0; i<visited.length; i++)
    {
        if (position[0] == visited[i][0] && position[1] == visited[i][1])
        {
            return true;
        }
    }
    return false;

} 

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月朦胧 2024-11-24 06:53:30

你必须退后一步:你甚至还没有整理出回溯算法,并且你已经将你显示的板与算法所需的板混为一谈了。最好的办法是重新开始,解决算法,然后担心这一切的显示。有了这个想法,您应该首先用伪代码解决算法,然后将该伪代码翻译为 JavaScript。 (提示:在您的代码中,您似乎从未更改当前位置。)

我看到的整体过程是这样的:

findAllKnightsTours:
  for every board position
    set path = empty
    set board = all false
    findKnightsTour(currentPosition, path, board)

将路径作为堆栈非常棒。每次搜索它以查看是否访问过某个方块是很痛苦的,所以我会使用一个单独的“板”。该板应该是布尔值矩阵(false==未访问,true=访问),尽管为了简单起见,我将使用一个简单的数组。

findKnightsTour(position, path, board):
  push position onto path
  set board[position] to true

  if path.length == 64
    print out path
  else
    for each of the eight moves
      next = calculate new position based on move
      if validPosition(next, board)
        findKnightsTour(next, path, board)

  set board[position] to false
  pop position off path

validPosition 例程检查该位置是否在棋盘限制内并且当前未被访问(即 true)。

如果您查看此例程,您会发现它将当前位置添加到路径和板上,执行操作,然后将其从路径和板上删除。这是算法的回溯部分:保存一些状态,尝试一些东西,然后恢复旧状态。

我将 JavaScript 转换作为读者的简单练习。

You've got to step back: you haven't even got the backtracking algorithm sorted out and you're already conflating the board you display with the board the algorithm requires. Best bet is to start over, solve the algorithm, and then worry about the display of it all. With that thought, you should solve the algorithm with pseudocode first, and then translate that pseudocode to JavaScript. (Hint: in your code, you never seem to change the current position.)

I see the overall process like this:

findAllKnightsTours:
  for every board position
    set path = empty
    set board = all false
    findKnightsTour(currentPosition, path, board)

Having the path as a stack is great. Searching through it every time to see if a square has been visited is a pain, so I'd use a separate "board". The board should be a matrix of boolean values (false==not visited, true=visited) although for simplicity I would use a simple array.

findKnightsTour(position, path, board):
  push position onto path
  set board[position] to true

  if path.length == 64
    print out path
  else
    for each of the eight moves
      next = calculate new position based on move
      if validPosition(next, board)
        findKnightsTour(next, path, board)

  set board[position] to false
  pop position off path

The validPosition routine checks to see if the position is within the board limits and is not currently visited (that is, true).

If you look at this routine, you'll see that it adds the current position to the path and to the board, does stuff, and then removes it from the path and board. This is the backtracking part of the algorithm: save some state, try something, and then restore the old state.

I leave the JavaScript conversion as an easy exercise for the Reader.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文