Java 骑士';s巡回算法帮助
好了,各位,我知道骑士之旅的问题对所有cs学生来说都很普遍,我的问题很难解决。我使用这种递归算法来进行移动,但是,一旦我移动到大约50步,我就必须回溯,因为没有可用的移动,我最终永远无法完成整个过程。我传递一个棋子节点(保存节点是否已被访问、移动它已被访问等内容)、下一行、下一列和上一个节点的移动计数Java 骑士';s巡回算法帮助,java,recursion,Java,Recursion,好了,各位,我知道骑士之旅的问题对所有cs学生来说都很普遍,我的问题很难解决。我使用这种递归算法来进行移动,但是,一旦我移动到大约50步,我就必须回溯,因为没有可用的移动,我最终永远无法完成整个过程。我传递一个棋子节点(保存节点是否已被访问、移动它已被访问等内容)、下一行、下一列和上一个节点的移动计数 private int moveRecur(ChessNode current, int row, int column, int moveV){ current.moveVisited
private int moveRecur(ChessNode current, int row, int column, int moveV){
current.moveVisited = moveV+1;
if(current.moveVisited > 63){
return 0;
}
if(current.position==13 && aboard[row-1][column+2].visited != 1){
current.visited = 1;
moveRecur(aboard[row-1][column+2], row-1, column+2, current.moveVisited);
}
else if(current.position==22 && aboard[row-2][column+1].visited != 1){
current.visited = 1;
moveRecur(aboard[row-2][column+1], row-2, column+1, current.moveVisited);
}
else if(current.position == 50 && aboard[row+1][column-2].visited != 1){
current.visited = 1;
moveRecur(aboard[row+1][column-2], row+1, column-2, current.moveVisited);
}
else if(current.position == 41 && aboard[row+2][column-1].visited != 1){
current.visited =1;
moveRecur(aboard[row+2][column-1], row+2, column-1, current.moveVisited);
}
else if(current.position == 46 && aboard[row+2][column+1].visited != 1){
current.visited = 1;
moveRecur(aboard[row+2][column+1], row+2, column+1, current.moveVisited);
}
else if(current.position == 53 && aboard[row+1][column+2].visited != 1){
current.visited = 1;
moveRecur(aboard[row+1][column+2], row+1, column+2, current.moveVisited);
}
else if(current.position == 10 && aboard[row-1][column-2].visited != 1){
current.visited = 1;
moveRecur(aboard[row-1][column-2], row-1, column-2, current.moveVisited);
}
else if (current.position == 17 && aboard[row-2][column-1].visited != 1){
current.visited =1;
moveRecur(aboard[row-2][column-1], row-2, column-2, current.moveVisited);
}
if(row+1>=0 && row+1<8 && column+2>=0 && column+2<8){
if(aboard[row+1][column+2].visited != 1){
current.visited = 1;
moveRecur(aboard[row+1][column+2], row+1, column+2, current.moveVisited);
}
}
if(row+2>=0 && row+2<8 && column+1>=0 && column+1<8){
if(aboard[row+2][column+1].visited != 1){
current.visited = 1;
moveRecur(aboard[row+2][column+1], row+2, column+1, current.moveVisited);
}
}
if(row-1>=0 && row-1<8 && column-2>=0 && column-2<8){
if(aboard[row-1][column-2].visited != 1){
current.visited = 1;
moveRecur(aboard[row-1][column-2], row-1, column-2, current.moveVisited);
}
}
if(row-2>=0 && row-2<8 && column-1>=0 && column-1<8){
if(aboard[row-2][column-1].visited != 1){
current.visited = 1;
moveRecur(aboard[row-2][column-1], row-2, column-1, current.moveVisited);
}
}
if(row+1>=0 && row+1<8 && column-2>=0 && column-2<8){
if(aboard[row+1][column-2].visited != 1){
current.visited = 1;
moveRecur(aboard[row+1][column-2], row+1, column-2, current.moveVisited);
}
}
if(row+2>=0 && row+2<8 && column-1>=0 && column-1<8){
if(aboard[row+2][column-1].visited != 1){
current.visited = 1;
moveRecur(aboard[row+2][column-1], row+2, column-1, current.moveVisited);
}
}
if(row-1>=0 && row-1<8 && column+2>=0 && column+2<8){
if(aboard[row-1][column+2].visited != 1){
current.visited = 1;
moveRecur(aboard[row-1][column+2], row-1, column+2, current.moveVisited);
}
}
if(row-2>=0 && row-2<8 && column+1>=0 && column+1<8){
if(aboard[row-2][column+1].visited != 1){
current.visited = 1;
moveRecur(aboard[row-2][column+1], row-2, column+1, current.moveVisited);
}
}
//System.out.println(current.position + " "+current.moveVisited);
current.visited = 0;
return 0;
}
private int-moveRecur(当前棋盘节点、int行、int列、int-moveV){
current.moveV=moveV+1;
如果(current.moveVisited>63){
返回0;
}
如果(当前位置==13&&在[row-1][column+2]上访问过!=1){
当前访问量=1;
moveRecur(在[第1行][第2列]上,第1行,第2列,当前.moveRecur);
}
else if(当前位置==22&&在[row-2][column+1]上。已访问!=1){
当前访问量=1;
moveRecur(在[第2行][第1列]上,第2行,第1列,当前.moveRecur);
}
else if(current.position==50&&on[row+1][column-2]。已访问!=1){
当前访问量=1;
moveRecur(在[行+1][列-2]上,行+1,列-2,当前.moveRecur);
}
else if(current.position==41&&on[row+2][column-1]。已访问!=1){
当前访问量=1;
moveRecur(船上[第2行][第1列],第2行,第1列,当前.moveRecur);
}
else if(current.position==46&&on[row+2][column+1]。已访问!=1){
当前访问量=1;
moveRecur(船上[第2行][第1列],第2行,第1列,当前.moveVisited);
}
else if(current.position==53&&on[row+1][column+2]。已访问!=1){
当前访问量=1;
moveRecur(在[行+1][列+2]上,行+1,列+2,当前.moveVisited);
}
else if(current.position==10&&on[row-1][column-2]。已访问!=1){
当前访问量=1;
moveRecur(船上[第1行][第2列],第1行,第2列,当前移动访问);
}
else if(current.position==17&&on[row-2][column-1]。已访问!=1){
当前访问量=1;
moveRecur(船上[第2行][第1列],第2行,第2列,当前移动访问);
}
如果(行+1>=0&&row+1=0&&column+2=0&&row+2=0&&column+1=0&&column-2=0&&column-2=0&&column-1=0&&row+1=0&&column-1=0&&row-1=0&&column+2=0&&column+1我有一个C#中的程序实现。您可以在这里找到它:
不过,它只能找到第一个解决方案。我不是说要复制它,但你可以看看它是否有用。这是java中的骑士之旅代码,布局非常出色。我使用递归回溯实现了这一点。这是我的课堂作业。如果理解或运行此代码有任何问题,请与我联系。
package knights.tour;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.*;
import javax.swing.*;
public class KnightsTour extends JFrame implements ActionListener{
//All the static variables used between action listeners and functions.
public static String path;
public static int btnPressed = 0;
public static int rowSelected;
public static String[] pathArray;
public static int[][] coordinatesArray;
public static int columnSelected;
public static int flag =0;
public static int increment = 0;
public static JPanel panel1 = new JPanel();
public static JPanel panel3 ;
public static JButton btnStart = new JButton("Start Animation");
public static JButton btnClear = new JButton("Clear");
public static JTextArea lblPath = new JTextArea();
public static JLabel lblStartRow = new JLabel();
public static JLabel lblStartColumn = new JLabel();
public static JButton[][] button;
public static int variableForIncrement=0;
static int row ;
static int column ;
static int[][] array = new int[row][column];
public static int count = 1;
KnightsTour(){
//Setting layout of the frame in the constructor and adding buttons to the panel and the frame.
getContentPane().setLayout(new GridLayout(2,1));
lblPath.setLineWrap(true);
lblPath.setColumns(10);
lblPath.setSize(700, 100);
lblPath.setEditable(false);
panel1.add(btnStart);
panel1.add(btnClear);
panel1.add(lblStartRow);
panel1.add(lblStartColumn);
panel1.add(lblPath);
panel3 = new JPanel(new GridLayout(row,column));
// Initializing Array of buttons for the user to click on the chess board.
button= new JButton[row][column];
array = new int[row][column];
coordinatesArray = new int[row*column][2]; // This array stores the coordinates as the Knight
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
button[i][j] = new JButton();
}
}
//Setting background of the buttons to black and white for chessboard layout.
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(i%2 ==j%2){
button[i][j].setBackground(Color.BLACK);
button[i][j].setForeground(Color.WHITE);
}
else{
button[i][j].setBackground(Color.WHITE);
}
panel3.add(button[i][j]);
button[i][j].addActionListener(this);
}
}
btnClear.addActionListener(this);
btnStart.addActionListener(this);
add(panel3);
add(panel1);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
// TODO code application logic here
String input =JOptionPane.showInputDialog("Enter the rows and columns in the format (row,column)");
String[] ar = input.split(",");
row = Integer.parseInt(ar[0]); // Finding out row and column from the user input.
column = Integer.parseInt(ar[1]);
pathArray = new String[row*column]; // This array is kept to store the path of the knight.
JFrame frame = new KnightsTour();
frame.setVisible(true);
frame.setSize(700,700);
}
//All the computation takes place in this function. It checks the neighbour and recursively calls itself.
public static void neighbourRecursion(int a,int b){
pathArray[increment] = Integer.toString(a) + "," + Integer.toString(b); // Storing the path of the Knight
increment++;
array[a][b] = count; //Stroing value of count.
button[a][b].setText(String.valueOf(count));
coordinatesArray[variableForIncrement][0] = button[a][b].getX(); //Finding coordinates of buttons to show animation
coordinatesArray[variableForIncrement][1] = button[a][b].getY();
count++;
variableForIncrement++;
//Checking for valid neighbours and calling itself recursively.
if(a <= row-3 && b<=column-2){
if(alreadyVisited(a+2,b+1)){
neighbourRecursion(a+2,b+1);
}
}
if(a<=row-3 && b>=1){
if(alreadyVisited(a+2,b-1)){
neighbourRecursion(a+2,b-1);
}
}
if(a>=2 && b<=column-2){
if(alreadyVisited(a-2,b+1)){
neighbourRecursion(a-2,b+1);
}
}
if(a>=2 && b>=1){
if(alreadyVisited(a-2,b-1)){
neighbourRecursion(a-2,b-1);
}
}
if(a<=row-2 && b>=2){
if(alreadyVisited(a+1,b-2)){
neighbourRecursion(a+1,b-2);
}
}
if(a<=row-2 && b<=column-3){
if(alreadyVisited(a+1,b+2)){
neighbourRecursion(a+1,b+2);
}
}
if(a>=1 && b>=2){
if(alreadyVisited(a-1,b-2)){
neighbourRecursion(a-1,b-2);
}
}
if(a>=1 && b <=column-3){
if(alreadyVisited(a-1,b+2)){
neighbourRecursion(a-1,b+2);
}
}
//Breaking condition of the function.
if(count == (row*column)+1){
}
// Backtracking condition if there is no neighbour.
else{
button[a][b].setText("");
array[a][b]=0;
count--;
variableForIncrement--;
if(increment >0){
increment--;
}
return ;
}
}
//This function checks if the neighbour is already visited.
public static boolean alreadyVisited(int a,int b){
if(array[a][b] != 0){
return false;
}
else{
return true;
}
}
@Override
public void actionPerformed(ActionEvent e) {
//when clear is pressed all arrays and global variables are set to initial conditon.
if(e.getSource() == btnClear){
for(int i =0;i<row;i++){
for(int j=0;j<column;j++){
array[i][j] = 0;
button[i][j].setText("");
count = 1;
lblPath.setText("");
lblStartRow.setText("");
lblStartColumn.setText("");
flag =0;
variableForIncrement=0;
increment =0;
path =" ";
}
}
}
//If start animation button is pressed animation is started.
else if(e.getSource() == btnStart){
animate();
}
// When the button is pressed.
else{
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(e.getSource() == button[i][j]){
if(flag == 1){
lblPath.setText(" Please press clear before clicking again"); // Button pressed twice without reset.
}
else{
rowSelected = i;
columnSelected =j;
// If odd * odd board and selected postion is odd then No path is possible.
if(row%2 ==1 && column%2 == 1 && rowSelected%2 ==0 && columnSelected%2 == 1 || row%2 ==1 && column%2 == 1 && rowSelected%2 ==1 && columnSelected%2 == 0){
lblPath.setText(" Path not possible from this point");
}
else{
int count;
lblStartRow.setText("Starting Row : "+String.valueOf(rowSelected + 1));
lblStartColumn.setText("Starting Column : "+String.valueOf(columnSelected + 1));
count = 1;
flag = 1;
startTour(); //Start tour function called.
for(int q=0;q<row;q++){
for(int w=0;w<column;w++){
if(array[i][j] == 0){
count++;
}
}
}
if(count > 2){
lblPath.setText(" No Path found");
}
//Printing path of the knight here.
else{
for(int k=0;k<pathArray.length;k++){
path = path+"->"+ pathArray[k];
}
lblPath.setText(" Path : \n"+ path.substring(5));
}
btnPressed = 1;
break;
}
}
}
}
}
} }
//Function for the animation.
void animate(){
if(btnPressed == 1){
btnPressed =0;
Graphics g = getGraphics();
for(int i=0;i<(row*column)-1;i++){
try {
Thread.sleep(600); // this function slows down drawing of lines.
} catch (InterruptedException ex) {
}
g.setColor(Color.RED); // setting colour or line to red.
g.drawLine((coordinatesArray[i][0]+65),(coordinatesArray[i][1]+50),(coordinatesArray[i+1] [0]+65),(coordinatesArray[i+1][1]+50));
}
}
else{
lblPath.setText(" Please clear, select a button to see the animation again"); //Animate button pressed twice without clear.
}
}
//This function calls the neighbour function with the selected row and column by the user.
static void startTour(){
neighbourRecursion(rowSelected,columnSelected);
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
System.out.print(array[i][j]+" ");
}
System.out.println();
}
}
}
package knights.tour;
导入java.awt.*;
导入java.awt.event.*;
导入java.util.logging.*;
导入javax.swing.*;
公共类KnightsTour扩展JFrame实现ActionListener{
//操作侦听器和函数之间使用的所有静态变量。
公共静态字符串路径;
公共静态int btnPressed=0;
选择公共静态整数;
公共静态字符串[]路径数组;
公共静态int[][]坐标阵列;
选择公共静态属性;
公共静态int标志=0;
公共静态整数增量=0;
publicstaticjpanelpanel1=newjpanel();
公共静态JPanel panel3;
公共静态JButton btnStart=新JButton(“开始动画”);
公共静态JButton btnClear=新JButton(“清除”);
公共静态JTextArea lblPath=新JTextArea();
公共静态JLabel lblStartRow=新JLabel();
public static JLabel lblStartColumn=new JLabel();
公共静态JButton[][]按钮;
公共静态int变量forincrement=0;
静态int行;
静态int列;
静态int[][]数组=新int[行][列];
公共静态整数计数=1;
骑士(){
//在构造器中设置框架布局,并向面板和框架添加按钮。
getContentPane().setLayout(新的GridLayout(2,1));
lblPath.setLineWrap(true);
lblPath.setColumns(10);
lblPath.setSize(700100);
lblPath.setEditable(false);
面板1.添加(btnStart);
面板1.添加(btnClear);
面板1.添加(lblStartRow);
面板1.添加(lblStartColumn);
面板1.添加(lblPath);
panel3=新的JPanel(新的网格布局(行、列));
//初始化按钮数组,以便用户单击棋盘。
按钮=新的JButton[行][列];
数组=新整数[行][列];
CoordinateArray=newint[row*column][2];//此数组将坐标存储为数组
对于(int i=0;i)您的代码有点难以阅读和重复(可能也容易出错)。关于这个问题以及回溯问题,有很多资源。请后退一步,重新思考您的算法,然后再次实现它(可能首先从较小的字段开始)。