【问题标题】:How to make a knight randomly move in a chessboard?如何让骑士在棋盘中随机移动?
【发布时间】:2020-10-09 12:02:51
【问题描述】:

我有一个名为 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();
    }
}

对不起,如果我的代码有点乱,我仍在处理程序。

【问题讨论】:

  • chessboard2 被定义为move 方法的参数,但我在print 方法中也看到了chessboard2。这是非常模棱两可的;你在哪里声明第二个?一定是班级成员,但我没看到
  • 是的,chessboard2 来自另一个班级。它不应该在那里。我忘记评论了。

标签: java random chess


【解决方案1】:

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

  • 创建一个ChessMove 类来存储行和列的移动(整数)
  • 添加一个ChessMove[] 来存储你的骑士可以做的所有可能的动作
  • 重构move 方法:
    • 创建一个ArrayList&lt;ChessMove&gt;,存储您的骑士在当前位置可以执行的所有可能动作
    • 使用rand.nextInt(possibleMoves.size());在此列表中随机选择一个移动

完整代码如下:

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();
    }
}

【讨论】:

  • 这是我得到的:
  • ------骑士巡回赛----------- 1 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -214748368 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648
  • 修复了它。但现在我没有解决办法
  • 我已经编写了这段代码,但没有在 Eclipse 中对其进行测试。今天下午我会试试的
  • @Straightup0 我已经更新了我的答案,对你有用吗?
【解决方案2】:

让你的移动随机化的最简单方法是为骑士的给定位置创建一个有效移动列表,然后随机选择一个。 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);
}

【讨论】:

  • 你能给我解释一下吗:List validMoves = new ArrayList();。我是 ArrayList 的新手。请。
  • @Straightup0 这是一个创建空列表的标准习语。解释列表和泛型如何工作超出了这个问题的范围。您是否正在寻找没有列表的解决方案?
  • 不,任何类型的解决方案都有效,只要我理解它。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多