如何让一个骑士在棋盘上随机移动?

huangapple go评论73阅读模式
英文:

How to make a knight randomly move in a chessboard?

问题

我有一个名为**骑士之旅(knight tour)**的程序,在这个程序中,骑士会在棋盘上移动。我一直在努力找出如何使骑士随机移动,而不是按照固定的模式移动。

我想知道如何让骑士随机移动。

以下是我的代码:

package assignment3;

import java.util.Random;

/*
 * 知道当前位置(行和列)
 * 知道八种可能的移动方式
 * 能告诉你它当前的行和列
 * 能确定给定类型的移动是否合法
 * 能够移动
 */
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() {
        // 忽略这个构造函数
    }

    public void InitializeBoard() {
        // 初始化棋盘
        for (int i = 0; i < boardSize; i++)
            Arrays.fill(chessboard2[i], Integer.MIN_VALUE); // 将数组设置为负值
    }

    /**
     * 调用 canMove 方法检查骑士是否可以移动
     * 移动骑士
     */
    public boolean move(int moveNum, int x, int y, int[][] chessboard2) {
        Random rand = new Random(); 
        // 如果 moveNum == 64,所有的方格都已经访问过
        if (moveNum == 64) {
            System.out.println("\ntrue board is 64\n");
            return true;
        }
        
        //int nextRow = rand.nextInt(boardSize);
        //int nextCol = rand.nextInt(boardSize);
        
        // 循环尝试8种可能的移动方式
        for (int i = 0; i < rowMoves.length; i++) {
            int nextRow =  x + rowMoves[i];
            int nextCol =  y + colMoves[i];
       
            // 检查位置是否合法且尚未访问过
            if (canMove(nextRow, nextCol) && chessboard2[nextRow][nextCol] == Integer.MIN_VALUE) {
                // 如果移动合法,骑士移动
                chessboard2[nextRow][nextCol] = moveNum + 1;
                
                // 进行下一步移动
                if(move(moveNum + 1, nextRow, nextCol, chessboard2))
                   return true;

                //move(moveNum + 1, nextRow, nextCol);
           
                // 如果找不到下一步移动:回溯
                chessboard2[nextRow][nextCol] = Integer.MIN_VALUE;
            }
        }
        
        return false;
    }     

    /**
     * 调用 Chessboard 类的 moveLegal 方法来检查移动是否合法
     * @return 如果移动合法则返回 true,否则返回 false
     */
    public boolean canMove(int x, int y) {
        // 使用 if 语句检查当前行和列是否在边界内
        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() {
        // 将数组位置 [0][0] 设置为 0
        chessboard2[0][0] = 1;
    
        // 检查移动
        if (move(1, 0, 0)) // 如果为真,将打印棋盘
            print();
        else // 如果为假,表示没有解决方案
            System.out.print("no solution");
    }
}

public class TesterMain {
    /**
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        Knight test = new Knight();
        test.solve();
    }
}

抱歉如果我的代码有点混乱,我还在继续努力完善这个程序。

英文:

I have this program called knight tour where the knight moves around a chess board. I have been trying to figure out how to make the knight move randomly, instead of following a pattern.

I would like to know how to randomly move the knight.

Here's my code:

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 &lt; 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(&quot;\ntrue board is 64\n&quot;);
return true;
}
//int nextRow = rand.nextInt(boardSize);
//int nextCol = rand.nextInt(boardSize);
//for loop to try 8 possibe moves
for (int i = 0; i &lt; 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) &amp;&amp; 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 &gt;= 0 &amp;&amp; x &lt; boardSize &amp;&amp; y &gt;= 0 &amp;&amp; y &lt; boardSize);
}
public void print() {
for (int i = 0; i &lt; boardSize; i++)
System.out.println(String.join(&quot; &quot;, 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(&quot;no solution&quot;);
}
}
public class TesterMain {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Knight test = new Knight();
test.solve();
}
}

Sorry if my code is a bit messy, I am still working on the program.

答案1

得分: 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<Integer> validMoves = new ArrayList<Integer>();
    // 使用循环尝试8种可能的移动
    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. 尝试进行移动(如果有可用的移动)
    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] = moveNum + 1;
    return move(moveNum + 1, nextRow, nextCol, chessboard2);
}
英文:

The easiest way to randomise your move is to create a list of valid moves for a given position of the knight and then select one at random. List and Random APIs go hand in hand:

//List&lt;Integer&gt; moves = ...
int move = moves.get(new Random().nextInt(moves.size()));

Restructuring your move method to something like this should do the job:

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

答案2

得分: 2

这里有一个解决方案,但需要进行一些重构:

  • 创建一个名为ChessMove的类,用于存储行和列的移动(整数)。
  • 添加一个ChessMove[]数组,用于存储所有可能的骑士可以执行的移动。
  • 重构move方法:
    • 创建一个ArrayList<ChessMove>,用于存储骑士在当前位置可以执行的所有可能移动。
    • 使用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); //将数组设置为负值
    }

    public boolean move(int moveNum, int x, int y) {
        // 如果 moveNum == 64,所有方格都已经访问过
        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;
       
            // 检查位置是否有效且尚未访问过
            if (canMove(nextRow, nextCol) && chessboard2[nextRow][nextCol] == Integer.MIN_VALUE)
                possibleMoves.add(move);
        }
        
        if (!possibleMoves.isEmpty()) {
            Random rand = new Random();
            // 在这里进行移动选择
            ChessMove chosenMove = possibleMoves.get(rand.nextInt(possibleMoves.size()));

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

            // 如果移动有效,骑士移动
            chessboard2[nextRow][nextCol] = moveNum + 1;
                
            // 进行下一步移动
            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)) // 如果为 true,将打印棋盘
            print();
        else // 如果为 false,表示没有解决方案
            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();
    }
}
英文:

There is a solution but it would require some refactoring:

  • Create a ChessMove class that stores a row and a column move (integers)
  • Add a ChessMove[] to store all possible moves that your knight can possibly do
  • Refactor the move method:
    • Create an ArrayList&lt;ChessMove&gt; that stores all possible moves that your knight can do in its current position
    • Randomly select a move in this list using rand.nextInt(possibleMoves.size());

Here is the complete code:

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 &lt; 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(&quot;\ntrue board is 64\n&quot;);
return true;
}
ArrayList&lt;ChessMove&gt; possibleMoves = new ArrayList&lt;ChessMove&gt;();
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) &amp;&amp; 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 &gt;= 0 &amp;&amp; x &lt; boardSize &amp;&amp; y &gt;= 0 &amp;&amp; y &lt; boardSize);
}
public void print() {
for (int i = 0; i &lt; boardSize; i++) {
for (int cell : chessboard2[i])
if (cell == Integer.MIN_VALUE)
System.out.print(&quot;*** &quot;);
else
System.out.print(String.format(&quot;%3d&quot;, cell) + &quot; &quot;);
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(&quot;no solution&quot;);
}
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();
}
}

答案3

得分: 0

你可以使用枚举(enum)来表示每个单独的移动,我们称其为“Move”,然后使用Move.values()创建一个包含这些移动的列表。
然后,每当你想要移动并且需要获取第一个合法移动时,你可以使用Collections.shuffle对列表进行随机排序。

英文:

You can use an enum, let's call it Move, to represent every single move, and then make a list of these moves using Move.values().
Then you can shuffle the list with Collections.shuffle every time you want to move and take the first legal move.

huangapple
  • 本文由 发表于 2020年10月9日 20:02:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/64279680.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定