Search code examples
javarandomchess

How to make a knight randomly move in a chessboard?


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

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


Solution

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