如何让马在棋盘中随机移动?

How to make a knight randomly move in a chessboard?

我有一个名为 knight tour 的程序,其中骑士在棋盘上移动。我一直在想办法让骑士随机移动,而不是遵循某种模式。

我想知道怎么随机移动骑士

这是我的代码:

package assignment3;

import java.util.Random;

/*
 * knows its current position (row and column) 
 * knows the eight types of moves it can make
 * can tell you it’s current row and column
 * can determine whether a move of a given type is legal or not
 * can move
 */
public class Knight {
    private int boardSize = 8;
    private int[] rowMoves = {-1, -2, -2, -1, 1, 2, 2, 1};
    private int[] colMoves = {2, 1, -1, -2, -2, -1, 1, 2};

    public Knight() {
        //ignore this constructor
    }

    public void InitializeBoard() {
        //initialize board
        for (int i = 0; i < boardSize; i++)
            Arrays.fill(chessboard2[i], Integer.MIN_VALUE); //setting array to negative value
    }

    /**
     * calls method canMove to check if knight can move
     * moves knight
     */
    public boolean move(int moveNum, int x, int y, int[][] chessboard2) {
        Random rand = new Random(); 
        //if moveNum == 64 all squares have been visited 
        if (moveNum == 64) {
            System.out.println("\ntrue board is 64\n");
            return true;
        }
        
        //int nextRow = rand.nextInt(boardSize);
        //int nextCol = rand.nextInt(boardSize);
        
        //for loop to try 8 possibe moves
        for (int i = 0; i < rowMoves.length; i++) {
            int nextRow =  x + rowMoves[i];
            int nextCol =  y + colMoves[i];
       
            //check if postion is valid and not visited yet
            if (canMove(nextRow, nextCol) && chessboard2[nextRow][nextCol] == Integer.MIN_VALUE) {
                //if move is valid knight moves
                chessboard2[nextRow][nextCol] = moveNum + 1;
                
                //make next move
                if(move(moveNum + 1, nextRow, nextCol, chessboard2))
                   return true;

                //move(moveNum + 1, nextRow, nextCol);
           
                //if cant find next move: backtrack
                chessboard2[nextRow][nextCol] = Integer.MIN_VALUE;
            }
        }
        
        return false;
    }     

    /**
     * calls method moveLegal from class Chessboard to see if move is legal
     * @return true if move is legal, else return false
     */
    public boolean canMove(int x, int y) {
        //if statement to check if currentRow and currentCol is whithin 
        //boundaries
        return(x >= 0 && x < boardSize && y >= 0 && y < boardSize);
    }

    public void print() {
        for (int i = 0; i < boardSize; i++)
            System.out.println(String.join(" ", chessboard2[i]));
    }
 
    public void solve() {
        //setting array location [0][0] to 0
        chessboard2[0][0] = 1;
    
        //check move
        if (move(1, 0, 0)) // if true, it will print chess board
            print();
        else //if false, there is no solution
            System.out.print("no solution");
    }
}

public class TesterMain {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Knight test = new Knight();
        test.solve();
    }
}

对不起,如果我的代码有点乱,我还在写程序。

您可以使用枚举(我们称它为 Move)来表示每一个动作,然后使用 Move.values() 列出这些动作。 然后你可以在每次你想移动并采取第一个合法移动时用 Collections.shuffle 洗牌列表。

使您的移动随机化的最简单方法是为骑士的给定位置创建一个有效移动列表,然后 select 随机创建一个。 ListRandom API 齐头并进:

//List<Integer> moves = ...
int move = moves.get(new Random().nextInt(moves.size()));

将您的 move 方法重组为类似这样的方法应该可以完成工作:

public boolean move(int moveNum, int x, int y, int [][] chessboard2) {
    // 1. List all valid moves
    List<Integer> validMoves = new ArrayList<Integer>();
    //for loop to try 8 possibe moves
    for(int i = 0; i < rowMoves.length; i++) {
        if (
            canMove(x + rowMoves[i], y + colMoves[i])
         && chessboard2[x + rowMoves[i]][y + colMoves[i]] == Integer.MIN_VALUE
        ) {
            validMoves.add(i);
        }
    }

    // 2. Try to make the move if any available
    if (validMoves.isEmpty()) {
        return false;
    }
    Random rand = new Random();
    int move = validMoves.get(rand.nextInt(validMoves.size()));
    int nextRow = x + rowMoves[move];
    int nextCol = y + colMoves[move]:
    chessboard2[nextRow][nextCol] = moveNumb + 1;
    return move(moveNum + 1, nextRow, nextCol, chessboard2);
}

有一个解决方案,但它需要一些重构:

  • 创建一个 ChessMove class 来存储一行和一列移动(整数)
  • 添加一个ChessMove[]来存储你的骑士可能做的所有可能动作
  • 重构move方法:
    • 创建一个 ArrayList<ChessMove> 来存储您的骑士在其当前位置可以进行的所有可能移动
    • 使用rand.nextInt(possibleMoves.size());
    • 在此列表中随机select一步

完整代码如下:

package assignment3;

import java.lang.*;
import java.util.*;

public class Knight {
    private int boardSize = 8;
    private int[][] chessboard2 = new int[boardSize][boardSize];

    private final ChessMove[] moves = {
                                          new ChessMove(-1, 2), 
                                          new ChessMove(-2, 1), 
                                          new ChessMove(-2, -1), 
                                          new ChessMove(-1, -2), 
                                          new ChessMove(1, -2), 
                                          new ChessMove(2, -1), 
                                          new ChessMove(2, 1), 
                                          new ChessMove(1, 2)
                                      };

    public Knight() {
        initializeBoard();
    }

    public void initializeBoard() {
        for (int i = 0; i < boardSize; i++)
            Arrays.fill(chessboard2[i], Integer.MIN_VALUE); //setting array to negative value
    }

    public boolean move(int moveNum, int x, int y) {
        //if moveNum == 64 all squares have been visited 
        if (moveNum == 64) {
            System.out.println("\ntrue board is 64\n");
            return true;
        }
        
        ArrayList<ChessMove> possibleMoves = new ArrayList<ChessMove>();
        for (ChessMove move : moves) {
            int nextRow =  x + move.row;
            int nextCol =  y + move.col;
       
            //check if postion is valid and not visited yet
            if (canMove(nextRow, nextCol) && chessboard2[nextRow][nextCol] == Integer.MIN_VALUE)
                possibleMoves.add(move);
        }
        
        if (!possibleMoves.isEmpty()) {
            Random rand = new Random();
            // Move choice is done here
            ChessMove chosenMove = possibleMoves.get(rand.nextInt(possibleMoves.size()));

            int nextRow =  x + chosenMove.row;
            int nextCol =  y + chosenMove.col;

            //if move is valid knight moves
            chessboard2[nextRow][nextCol] = moveNum + 1;
                
            //make next move
            move(moveNum + 1, nextRow, nextCol);
            return true;
        } else
            return false;
    }     

    public boolean canMove(int x, int y) {
        return (x >= 0 && x < boardSize && y >= 0 && y < boardSize);
    }

    public void print() {
        for (int i = 0; i < boardSize; i++) {
            for (int cell : chessboard2[i])
                if (cell == Integer.MIN_VALUE)
                    System.out.print("*** ");
                else
                    System.out.print(String.format("%3d", cell) + " ");

            System.out.println();
        }
    }
 
    public void solve() {
        chessboard2[0][0] = 1;
    
        if (move(1, 0, 0)) // if true, it will print chess board
            print();
        else //if false, there is no solution
            System.out.print("no solution");
    }

    class ChessMove {
        int row = 0, col = 0;

        ChessMove(int r, int c) {
            this.row = r;
            this.col = c;
        }
    }
}

public class TesterMain {
    public static void main(String[] args) {
        Knight test = new Knight();
        test.solve();
    }
}