我的项目object有一个核心SudokuBoardSudokuBoard唯一的字段是2D arraySudokuBoard的所有原型功能都包含2D array,并且始终需要其可见性。

问题:

在即将出现的算法中,我需要某种方式来制作SudokuBoard的副本。这是强制性功能。每当我尝试制作副本时,它的2D数组只是对旧数组的引用。我不知道为什么。

我了解到cloneJavascript中绝对是一场噩梦,所以我有点担心。我是一个初学者,所以我要做的最后一件事是安装Jquery或使用一些外部库来解决此问题。我提供了以下文件;他们应该没有错误地运行。

SudokuBoard.js

/**
 * Constructs a SudokuBoard object.
 * Initializes the board with the numbers
 * provided to the constructor.
 * @param nums array, must be BOARD_SIZE^2 length.
 * @constructor
 */

function SudokuBoard(nums)
{
    // Private Fields:

    var BOARD_SIZE = 9;
    // The Sudoku board, represented as a 2D array.
    var gameboard = [];

    if (nums.length != BOARD_SIZE * BOARD_SIZE)
    {
        document.write("InvalidSizeError");
        throw "InvalidSizeError";
    }

    var counter = 0;
    for (var i = 0; i < BOARD_SIZE; i++)
    {
        var row = [];

        // Each row has a set amount of elements.
        while (row.length < BOARD_SIZE)
        {
            row.push(nums[counter]);
            counter++;
        }

        // Add the row to the board.
        gameboard.push(row);
    }

    SudokuBoard.prototype.getBoard = function()
    {
        return gameboard;
    }
}

/**
 * Gets all values within a row of the 2D array.
 * The Y coordinate works on the typical number
 * scale, meaning indexes start from 1, not 0.
 * Y corresponds to the vertical axis. The bottom
 * left of the board is at 1,1. The bottom right
 * of the board is at 9,1.
 * @param y coordinate of the row.
 * @returns {Array}
 */
SudokuBoard.prototype.getRow = function(y)
{
    return this.getBoard()[this.getBoard().length - y];
};

/**
 * Gets all values within a column of the 2D array.
 * The X coordinate works on the typical number
 * scale, meaning indexes start from 1, not 0.
 * X corresponds to the horizontal axis. The bottom
 * left of the board is at 1,1. The bottom right
 * of the board is at 9,1.
 * @param x coordinate of the column.
 * @returns {Array}
 */
SudokuBoard.prototype.getColumn = function(x)
{
    var column = [];

    for (var i = 1; i <= this.getBoard().length; i++)
    {
        column.push(this.getSlot(x, i));
    }

    return column;
};

/**
 * Algorithm which finds the correct quadrant of a given
 * coordinate and gets all the numbers which are contained
 * inside it. This operation relies on the fact that there
 * are three quadrants and once you make it so the first
 * index of quadrant one is considered as (3,3) you can
 * divide all X and Y values by 3 and yield their quadrant #.
 * @param x coordinate.
 * @param y coordinate.
 * @returns {Array}
 */
SudokuBoard.prototype.getQuadrant = function(x, y)
{
    // Determine what quadrant this coordinate is in.
    var horizQuad = Math.floor((x + 2) / 3); // 1 2 or 3
    var vertQuad = Math.floor((y + 2) / 3); // 1 2 or 3

    var quadrant = [];

    for (var i = 1; i <= 3; i++)
    {
        for (var h = 1; h <= 3; h++)
        {
            // Add the number to the array.
            quadrant.push(this.getSlot((horizQuad - 1) * 3 + i, (vertQuad - 1) * 3 + h));
        }
    }

    return quadrant;
};

/**
 * Gets a given slot on the board.
 * The X,Y coordinates work on the typical number
 * scale, meaning indexes start from 1, not 0.
 * X corresponds to the horizontal axis while Y
 * corresponds to the vertical axis. The bottom
 * left of the board is at 1,1. The bottom right
 * of the board is at 9,1.
 * @param x coordinate.
 * @param y coordinate.
 */
SudokuBoard.prototype.getSlot = function(x, y)
{
    return this.getBoard()[this.getBoard().length - y][x - 1];
};

/**
 * Sets a given slot on the board to a value.
 * The X,Y coordinates work on the typical number
 * scale, meaning indexes start from 1, not 0.
 * X corresponds to the horizontal axis while Y
 * corresponds to the vertical axis. The bottom
 * left of the board is at 1,1. The bottom right
 * of the board is at 9,1.
 * @param x coordinate.
 * @param y coordinate.
 * @param value to be placed.
 */
SudokuBoard.prototype.setSlot = function(x, y, value)
{
    this.getBoard()[this.getBoard().length - y][x - 1] = value;
};

SudokuBoard.prototype.clone = function()
{
    var numbers = [];

    for (var i = 0; i < this.getBoard().length; i++)
    {
        for (var h = 0; h < this.getBoard()[i].length; h++)
        {
            numbers.push(this.getBoard()[i][h]);
        }
    }

    return new SudokuBoard(numbers);
};

/**
 * ToString() method for SudokuBoard.
 * @returns {string}
 */
SudokuBoard.prototype.toString = function()
{
    const border = "+-----+-----+-----+";
    const nextline = "<br>";

    var temp = border + nextline;

    for (var i = 0; i < this.getBoard().length; i++)
    {
        temp += "|";

        for (var h = 0; h < this.getBoard()[i].length; h++)
        {
            // Every third character is proceeded by a |
            //\u00A0 for empty space.
            temp += ((this.getBoard()[i][h] == "0") ? "-" : this.getBoard()[i][h]) + ((h % 3 == 2) ? "|" : " ");
        }

        // Add a new line.
        temp += nextline;
    }

    // Return and add the bottom border.
    return temp + border;
};


Tester.js

var nums = [0, 0, 0, 0, 0, 0, 1, 4, 6,
            4, 0, 8, 7, 0, 0, 0, 0, 0,
            0, 6, 0, 0, 5, 0, 8, 9, 0,
            0, 0, 0, 1, 0, 0, 0, 0, 3,
            0, 8, 0, 0, 7, 4, 0, 0, 0,
            7, 0, 0, 0, 0, 0, 9, 0, 0,
            0, 0, 1, 8, 0, 9, 2, 0, 0,
            0, 0, 0, 5, 0, 0, 0, 0, 0,
            8, 0, 3, 0, 1, 7, 0, 0, 0];

var myBoard = new SudokuBoard(nums);
println("ORIGINAL:");
println(myBoard);

var clone = myBoard.clone();
println("CLONING:");
println(clone);

myBoard.setSlot(1, 1, 3);
println("CHANGED ORIGINAL:");
println(myBoard);

println("CLONE:");
println(clone);




/**
 * Used for debugging.
 * @param line
 */
function println(line)
{
    document.write(line + "<br>");
}


Runner.html

    <!DOCTYPE html>
<!--
  Project: SudokuSolver
  Name: Kevin
  Date: 2/12/2016
 -->

<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <font face="monospace"><font size="12">
    <!--Load from JavaScript file. -->
    <script type="text/javascript" src="SudokuBoard.js"></script>
    <script type="text/javascript" src="Tester.js"></script>
    </font></font>
</head>
<body>

</body>
</html>

最佳答案

我没有发现您的.clone()方法有什么问题。

问题出在您的构造函数中,它如何设置.getBoard()方法。每次调用构造函数时,都会覆盖原型.getBoard()方法,该方法引用闭包捕获的局部变量,而不是实例变量。因此,为SudokuBoard的任何实例调用.getBoard(),您将获得原型方法,该方法将从最新实例的关闭处引用局部变量,从而仅返回最近创建的板。

更改此行:

SudokuBoard.prototype.getBoard = function()


创建实例方法而不是原型方法:

this.getBoard = function()


如果每个实例都有自己的.getBoard(),它们都将引用自己的闭包。

10-01 18:43