我试图用java编写一个Knights Walk Algorithm(蛮力)。我可以创建一个程序来通过5x5网格移动,但是程序总是在板上遗漏06个单元格。我的骑士也不能从这些方格移动到任何地方。
例如,我有以下网格:
----------------
a1,b1,c1,d1,e1
a2,b2,c2,d2,e2
a3,b3,c3,d3,e3
a4,b4,c4,d4,e4
a5,b5,c5,d5,e5
----------------
我的算法打印出下面的路径和访问的单元格
a1 -> b3
b3 -> c5
c5 -> a4
a4 -> c3
c3 -> d5
d5 -> b4
b4 -> a2
a2 -> c1
c1 -> d3
d3 -> e5
e5 -> c4
c4 -> a3
a3 -> b5
b5 -> d4
d4 -> c2
c2 -> e3
e3 -> d1
d1 -> b2
Cells Visited : [a1, b3, c5, a4, c3, d5, b4, a2, c1, d3, e5, c4, a3, b5, d4, c2, e3, d1, b2, b2, b2, b2, b2, b2, b2]
如您所见,网格仍然有以下6个单元格未被触及(访问了x个标记)。
----------------
x,b1,x,x,e1
x,x,x,d2,e2
x,x,x,x,x
x,x,x,x,e4
a5,x,x,x,x
这将生成以下6个单元格:
b1,e1,d2,e2,e4,a5
保持原样,我似乎也不能从这些牢房转移到其他牢房。
有人能指出我可能做错了什么吗?。我的代码如下:
import java.util.ArrayList;
import java.util.List;
public class KnightsWalk {
String[] colnames = {"a", "b", "c", "d", "e","f","g","h"};
String[] rownumbers = {"1", "2", "3", "4", "5","6","7","8"};
static final int gridSize = 5; //Specify the grid size here
static String grid[][] = new String[gridSize][gridSize];
static int[][] moves = {{2, 1},{1, 2},{-1,-2},{-2,-1},{2,-1},{-2,1},{-1,2},{1,-2}};//All Possible Moves
//Visited Cells
static List<String> visitedCells = new ArrayList<>();
private void initGrid() {
if (gridSize>=3 || gridSize<=8) {
for (int col = 0; col < grid.length; col++) {
for (int row = 0; row < grid.length; row++) {
grid[row][col] = colnames[col] + rownumbers[row];
}
}
} else {
System.out.println("Grid Size of "+gridSize+" is Not Supported ");
System.exit(0);
}
}
private boolean canMoveToCell(int[] cellvisiting) {
try{
//check if the cell visiting has been visited before
String cell = grid[cellvisiting[0]][cellvisiting[1]];
boolean canmove = !visitedCells.contains(cell);
return canmove;
}
catch(ArrayIndexOutOfBoundsException ex){
return false;
}
}
private void walk(int cell[]) {
String start = grid[cell[0]][cell[1]];
visitedCells.add(start); //Add the starting cell to already visited
if(visitedCells.size() == (gridSize*gridSize)){
return;
}
int[] nextCellToMoveto = null;
for(int[] move:moves){
int[] nc1 = { cell[0]+move[0], cell[1]+move[1] };
if (canMoveToCell(nc1)) {
printMove(cell, nc1);
nextCellToMoveto=nc1;
break;
}
else{
int[] nc2 = { cell[0]+move[1], cell[1]+move[0] };
if(canMoveToCell(nc2)){
printMove(cell, nc2);
nextCellToMoveto=nc2;
break;
}
else{
nextCellToMoveto=cell;
}
}
}
walk(nextCellToMoveto);
}
public static void main(String[] args) {
KnightsWalk gw = new KnightsWalk();
gw.initGrid();
gw.printGrid();
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid.length; col++) {
int startingcell [] = {row,col};
System.out.println("Cells Visited : "+visitedCells);
visitedCells.clear();//Clearing the Previous cells visited when hit a dead end
gw.walk(startingcell);
System.out.println("Trying with Starting Cell : "+grid[startingcell[0]][startingcell[1]]);
}
}
System.out.println("Cells Visited : "+visitedCells);
}
/**
* Auxiliary Support Methods for user output support
*/
private void printMove(int[] start, int[] end) {
System.out.println(grid[start[0]][start[1]] + " -> " + grid[end[0]][end[1]]);
}
private void printGrid() {
System.out.println("----------------");
for (String[] row : grid) {
for (int col = 0; col < grid.length; col++) {
String sep = (col < grid.length - 1) ? "," : "";
System.out.print(row[col] + sep);
}
System.out.println("\n");
}
System.out.println("----------------");
}
}
更新3现在,代码将按如下方式打印解决方案:
----------------
a1,a2,a3,a4,a5
b1,b2,b3,b4,b5
c1,c2,c3,c4,c5
d1,d2,d3,d4,d5
e1,e2,e3,e4,e5
----------------
25 of out 25 Cells Visited in the order [a1, c2, a3, b1, d2, e4, c3, b5, d4, e2, c1, a2, b4, d5, e3, d1, b2, a4, c5, b3, a5, c4, e5, d3, e1]
BUILD SUCCESSFUL (total time: 0 seconds)
更新后的代码如下:
import java.util.ArrayList;
import java.util.List;
public class KnightsWalk {
String[] rownames = {"a", "b", "c", "d", "e", "f", "g", "h"};
String[] colnames = {"1", "2", "3", "4", "5", "6", "7", "8"};
static final int gridSize = 5; //Specify the grid size here
static String grid[][];
static int[][] moves = {{-2, -1}, {-2, 1}, {2, -1}, {2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}};//All Possible Moves
static List<String> visitedCells = new ArrayList<>(); //Visited Cells
int numberOfMoves = 0;
private void initGrid() {
if (gridSize >= 3 && gridSize <= 8) {
grid = new String[gridSize][gridSize];
int rownum = 0;
for (String[] gridrow : grid) {
for (int cell = 0; cell < gridrow.length; cell++) {
gridrow[cell] = rownames[rownum] + colnames[cell];
}
rownum += 1;
}
} else {
System.out.println("Grid Size of " + gridSize + " is Not Supported ");
System.exit(0);
}
}
private boolean canWalkToCell(int[] cellvisiting) {
//check if the cell visiting has been visited before
try {
//Method chained to return if the cell is in the list
String cell = grid[cellvisiting[0]][cellvisiting[1]];
if(visitedCells.contains(cell)){
return false;
}
else{
return true;
}
} catch (ArrayIndexOutOfBoundsException ex) {
//This is the lazy way to check if the coordinates are in the grid
return false;
}
}
private boolean walk(int cell[]) {
String nextCell = grid[cell[0]][cell[1]];
visitedCells.add(nextCell); //Add the starting cell to already visited
numberOfMoves += 1;
if (numberOfMoves == (gridSize * gridSize)) {
return true;
}
for (int[] move : moves) {
int[] nc = {cell[0] + move[0], cell[1] + move[1]};
if (canWalkToCell(nc)) {
if(walk(nc)){
return true;
}
}
}
//Backtracking
numberOfMoves -= 1;
visitedCells.remove(nextCell);
return false;
}
public static void main(String[] args) {
KnightsWalk gw = new KnightsWalk();
gw.initGrid();
gw.printGrid();
int startingcell[] = {0, 0};
gw.walk(startingcell);
System.out.println("" + visitedCells.size() + " of out " + (gridSize * gridSize) + " Cells Visited in the order " + visitedCells);
}
/**
* Auxiliary Support Methods for user output support
*/
private void printAtteptedMove(int[] start, int[] end) {
System.out.println(grid[start[0]][start[1]] + " -> " + grid[end[0]][end[1]]);
}
private void printGrid() {
System.out.println("----------------");
for (String[] gridrow : grid) {
for (int cell = 0; cell < gridrow.length; cell++) {
String sep = (cell < gridrow.length - 1) ? "," : "";
System.out.print(gridrow[cell] + sep);
}
System.out.println("\n");
}
System.out.println("----------------");
}
}
最佳答案
问题是它不是一个真正的蛮力算法。你只要开始跑步直到一切都不可能对于一个蛮力算法,你也必须尝试所有其他的移动可能性,而不仅仅是那些从a1->b3->c5开始的移动。
尝试使用递归函数实现暴力
我也不明白为什么你需要以下代码,当你的移动列表(单次移动)完成。
else{
int[] nc2 = { cell[0]+move[1], cell[1]+move[0] };
if(canMoveToCell(nc2)){
printMove(cell, nc2);
nextCellToMoveto=nc2;
break;
}
else{
nextCellToMoveto=cell;
}
更新:
更新后的操作版本仍然存在错误。如果尝试新路径,它应该会忘记“visitedcell”中的旧路径。因此,您需要做的是:在函数“walk”中的for循环之后,从列表“visitedCells”中移除元素。
在输出中可以看到您的错误:
[...]
h2 -> f1
b6 -> a8
f2 -> h1
我想不是这样的