我的项目object
有一个核心SudokuBoard
。 SudokuBoard
唯一的字段是2D array
。 SudokuBoard
的所有原型功能都包含2D array
,并且始终需要其可见性。
问题:
在即将出现的算法中,我需要某种方式来制作SudokuBoard的副本。这是强制性功能。每当我尝试制作副本时,它的2D数组只是对旧数组的引用。我不知道为什么。
我了解到clone
在Javascript
中绝对是一场噩梦,所以我有点担心。我是一个初学者,所以我要做的最后一件事是安装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(),它们都将引用自己的闭包。