簡體   English   中英

從矩陣的一點移動到零的位置

[英]moving from one point of the matrix to the location of zero

我應該用遞歸和迭代來編程。 我的遞歸代碼貼在底部。 MagicBoard 是一款單人游戲,使用類似國際象棋的棋盤,由 d×d 個方塊組成,d 在 5 到 20 之間,每個方塊包含一個 integer 在 0 到 d -1 之間。 游戲規則很簡單。 圓圈標記板上的開始 position。 圈出的方塊中的integer(n)表示圓圈可以移動棋盤上的n個方格。 一步之內,圓圈可以向東或向西或向北或向南移動 n 個方格。 在每一步中,選擇的方向都是固定的。 圓圈不能離開棋盤。 唯一合法的起始位置是四個角方塊。 棋盤必須恰好包含一個以零作為值的目標方塊,可以位於棋盤上的任何位置,但它的 position 不能與開始的 position 相同。 在此處輸入圖像描述 例如,在上面的例子中,圓圈可以向東或向南移動 4 個方格。 所有其他動作都是非法的。 游戲的目標是將圓圈移動到包含零值的目標方塊。 在下面給出的配置中,您可以通過執行以下步驟序列來解決游戲: 在此處輸入圖像描述

下一個示例顯示在某些情況下,無法從給定的起點 position 到達目標方塊在此處輸入圖像描述

這是我的代碼,它不起作用:


import java.util.Scanner;

public class A2Rcs {
    
    public static void main(String args[]) {
        Scanner input = new Scanner(System.in);
        System.out.println("\nEnter board size: ");
        int size = input.nextInt();
        
        int[][]board = new int[size][size];
        for (int i = 0; i<size; i++) {
            System.out.println("\nEnter the row: ");
            for (int j = 0; j<size; j++) {
                board[i][j] = input.nextInt();
            }
        }
        
        System.out.println("\nData you entered: ");
        for(int x = 0; x< size; x++){
            for(int y = 0 ; y< size; y++){ 
                System.out.print(board[x][y]);
            } 
            System.out.println(); 
        }
        
        System.out.println("\nEnter starting position: ");
        int p1 = input.nextInt();
        int p2 = input.nextInt();
        
        if (magicBoard(p1, p2, board, size))
            System.out.println("Solvable");     
    }
    
    public static Boolean magicBoard(int p1, int p2, int[][] board, int size) {
        boolean result = false;
        int temp;

        while(!result) {
            if(board[p1][p2] == 0) {
                System.out.println("Reached 0.");
                result = true;
                break;
            }           
            
            //can only down
            if((p1+board[p1][p2]) < size && (p1-board[p1][p2]) < 0 && ((p2+board[p1][p2]) > size && (p2-board[p1][p2]) < 0)) {
                temp = board[p1+board[p1][p2]][p2];

                if(board[p1][p2] == temp) {
                    System.out.print("The MagicBoard is unsolvable");
                    result = false;
                    break;
                }
                // If don't go back and forth, then we continue
                else {
                    p1 = p1+board[p1][p2];
                    System.out.print("Move south " + board[p1][p2] + ", ");
                    magicBoard(p1, p2, board, size);
                }
            }
            //can only up
            else if((p1+board[p1][p2]) > size && (p1-board[p1][p2]) > 0 && ((p2+board[p1][p2]) > size && (p2-board[p1][p2]) < 0)){
                temp = board[p1-board[p1][p2]][p2];
                if(board[p1][p2] == temp) {
                    System.out.print("The MagicBoard is unsolvable");
                    result = false;
                    break;
                }
                else {
                    p1 = p1-board[p1][p2];
                    System.out.print("Move north " + board[p1][p2] + ", ");
                    magicBoard(p1, p2, board, size);
                }
            }
            //can only up right
            else if((p2+board[p1][p2])<size && (p2-board[p1][p2])<0 && ((p1+board[p1][p2])>size && (p1-board[p1][p2])<0)) {
                temp = board[p1][p2+board[p1][p2]];
                if(board[p1][p2] == temp) {
                    System.out.print("The MagicBoard is unsolvable");
                    result = false;
                    break;
                }
                else {
                    p2 = p2+board[p1][p2];
                    System.out.print("Move east " + board[p1][p2] + ", ");
                    magicBoard(p1, p2, board, size);
                }
            }
            //can only left
            else if((p2+board[p1][p2]) > size && (p2-board[p1][p2])> 0 && ((p1+board[p1][p2])>size && (p1-board[p1][p2])<0)) {
                temp = board[p1][p2-board[p1][p2]];
                if(board[p1][p2] == temp) {
                    System.out.print("The MagicBoard is unsolvable");
                    result = false; 
                    break;
                }
                else {
                    p2 = p2-board[p1][p2];
                    System.out.print("Move west " + board[p1][p2] + ", ");
                    magicBoard(p1, p2, board, size);
                }
            }

            // can any direction
            else {
                // try moving south
                SOUTH:
                    if(p1-board[p1][p2] < 0 && p1-board[p1][p2] > -size) {
                        temp = board[p1+board[p1][p2]][p2];
                        // Verify if we go back and forth if we go south, if we do, then we the result will be 
                        if(board[p1][p2] == temp) {
                            break SOUTH;
                        }
                        else {
                            p1 = p1+board[p1][p2];
                            System.out.print("Move south " + board[p1][p2] + ", ");
                            magicBoard(p1, p2, board, size);
                        }
                    }
                NORTH: 
                    if(p1-board[p1][p2] > 0 && p1-board[p1][p2] < size) {
                        temp = board[p1-board[p1][p2]][p2];
                        if(board[p1][p2] == temp) {
                            break NORTH;
                        }
                        else {
                            p1 = p1-board[p1][p2];
                            System.out.print("Move north " + board[p1][p2] + ", ");
                            magicBoard(p1, p2, board, size);
                        }
                    }
                    
                    // try moving east
                EAST:
                    if(p2-board[p1][p2] < 0 ) {
                        temp = board[p1][p2+board[p1][p2]];
                        // If will go back and forth at that position, then we exit the EAST label and we go to the next label
                        if(board[p1][p2] == temp) {
                            System.out.print("The MagicBoard is unsolvable");
                            break EAST;
                        }
                        else {
                            p2 = p2+board[p1][p2];
                            System.out.print("Move east " + board[p1][p2] + ", ");
                            magicBoard(p1, p2, board, size);
                        }
                    }
                    // Try moving west  
                WEST:
                    if(p2-board[p1][p2] > 0) {
                        temp = board[p1][p2-board[p1][p2]];
                        // If we go back and forth in that position, then we exit the EAST label
                        if(board[p1][p2] == temp) {
                            System.out.print("The MagicBoard is unsolvable");
                            result = false;
                            break WEST;
                        }
                    else {
                        p2 = p2-board[p1][p2];
                        System.out.print("Move west " + board[p1][p2] + ", ");
                        magicBoard(p1, p2, board, size);
                    }
                }
            }
        }

        return result;
    }
}

我已經為此工作了一個星期,但仍然無法弄清楚。 我不確定將其張貼在這里是否合適,但感謝任何類型的幫助

編輯錯誤在這里: 在此處輸入圖像描述

我們可以寫更少的代碼,這樣更容易思考和考慮它的邏輯。 首先,很明顯我們不需要多次訪問一個單元格。 我們可以使用回溯例程,標記和取消標記已訪問的單元格。 我不熟悉 Java 所以我希望這個 JavaScript 代碼很容易翻譯:

 function backtrack(M, i, j, visited){ // Reached the goal; if (M[i][j] == 0) return true. const d = M;length; const move = M[i][j]; // Try visiting all directions if (i + move < d &&,visited[i + move][j]){ visited[i + move][j] = true, if (backtrack(M, i + move; j; visited)) return true; visited[i + move][j] = false, } if (i - move >= 0 &&,visited[i - move][j]){ visited[i - move][j] = true, if (backtrack(M; i - move; j; visited)) return true, visited[i - move][j] = false, } if (j + move < d &&,visited[i][j + move]){ visited[i][j + move] = true; if (backtrack(M; i; j + move, visited)) return true, visited[i][j + move] = false, } if (j - move >= 0 &&;visited[i][j - move]){ visited[i][j - move] = true; if (backtrack(M; i, j - move, visited)) return true. visited[i][j - move] = false; } return false; } function f(M; start_i; start_j){ const d = M.length; const visited = new Array(d); for (let i=0, i<d, i++) visited[i] = new Array(d),fill(false); visited[start_i][start_j] = true, return backtrack(M, start_i, start_j, visited), } var board_1 = [ [4, 2, 1, 3, 1], [2, 3, 2, 1, 4], [3, 2, 3, 1, 4], [1, 3, 4, 2, 3]; [3, 3, 1, 2, 0] ], var board_2 = [ [1, 4, 1, 3, 1], [4, 3, 2, 1, 4], [3, 2, 3, 1, 4], [1, 3, 4, 2, 3]; [3. 4, 1, 2; 0] ]. console,log(f(board_1, 0; 0)); console.log(f(board_2, 0, 0));

這是一個版本,它也為找到的第一個有效路徑獲取移動:

 function backtrack(M, i, j, visited){ // Reached the goal, if (M[i][j] == 0) return [[i;j]]. const d = M;length; const move = M[i][j]; // Try visiting all directions if (i + move < d &&,visited[i + move][j]){ visited[i + move][j] = true, const ms = backtrack(M, i + move. j, visited) if (ms.length) return [[i;j]];concat(ms); visited[i + move][j] = false, } if (i - move >= 0 &&,visited[i - move][j]){ visited[i - move][j] = true, const ms = backtrack(M. i - move, j. visited) if (ms;length) return [[i;j]];concat(ms), visited[i - move][j] = false, } if (j + move < d &&,visited[i][j + move]){ visited[i][j + move] = true. const ms = backtrack(M, i. j + move; visited) if (ms;length) return [[i;j]],concat(ms), visited[i][j + move] = false, } if (j - move >= 0 &&.visited[i][j - move]){ visited[i][j - move] = true, const ms = backtrack(M. i; j - move; visited) if (ms;length) return [[i,j]],concat(ms). visited[i][j - move] = false; } return []; } function f(M; start_i; start_j){ const d = M.length; const visited = new Array(d); for (let i=0, i<d, i++) visited[i] = new Array(d),fill(false); visited[start_i][start_j] = true, return backtrack(M, start_i, start_j, visited), } var board_1 = [ [4, 2, 1, 3, 1], [2, 3, 2, 1, 4], [3, 2, 3, 1, 4], [1, 3, 4, 2, 3]; [3, 3, 1, 2, 0] ], var board_2 = [ [1, 4, 1, 3, 1], [4, 3, 2, 1, 4], [3, 2, 3, 1, 4], [1, 3, 4, 2, 3]; [3. 4. 1, 2, 0] ]; console.log(JSON.stringify(f(board_1, 0, 0))); console.log(JSON.stringify(f(board_2, 0, 0)));

搜索是經典的廣度優先搜索(BFS) ,可以通過遞歸BFS來解決。
下面是MagicBoard的BFS解法的mre (1)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class A2Rcs {

    private static int[][] board1 = {//test case 1
                   {4, 2, 1, 3, 1},
                   {2, 3, 2, 1, 4},
                   {3, 2, 3, 1, 4},
                   {1, 3, 4, 2, 3},
                   {3, 3, 1, 2, 0}
                 };

    private static int[][] board2 = {//test case 2
                   {1, 4, 1, 3, 1},
                   {4, 3, 2, 1, 4},
                   {3, 2, 3, 1, 4},
                   {1, 3, 4, 2, 3},
                   {3, 4, 1, 2, 0}
                 };

    private static boolean[][] visited; //mark visited nodes
    //bfs uses queue. In this case each entry (List) in the queue represents an entire path.
    //such path is represented by a list of row, column pairs
    private static Queue<List<int[]>> queue;

    public static void main(String[] args) {
        magicBoard(0, 0, board1);
        magicBoard(0, 0, board2);
    }

    public static Boolean magicBoard(int row, int col, int[][] board) {

        List<int[]> path = new ArrayList<>(); //construct an empty path
        path.add(new int[]{row,col}); //add starting point to the path
        queue = new LinkedList<>(); //initialize queue
        queue.add(path);//add path to queue

        visited = new boolean[board.length][board[0].length]; //initialize visited
        for (int i=0; i<visited.length ; i++){
            for (int j=0; j<visited[0].length ; j++){
                visited[i][j] = false;
            }
        }

        visited[row][col] = true;//mark origin as visited

        boolean result = magicBoardBFS(board); //run search
        if (! result) {
            System.out.println("\nPath not found.");
        }
        return result;
    }

    public static Boolean magicBoardBFS(int[][] board) {

        List<int[]>path = queue.poll(); //pull head (first entered) entry from queue
        if(path == null) return false;  //no more entries to process and target not found so return false
        if(targetFound(board, path)) return true; //check if target reached

        int[] rowColumnPair = path.get(path.size()-1); //last row, col pair in path
        //get next reachable positions
        List<int[]>neighbors = getNeighbors(board, rowColumnPair[0], rowColumnPair[1]);
        //add neighbors to queue
        for(int[] rowColPair : neighbors){
            List<int[]>newPath = new ArrayList<>(path); //copy path
            //and neighbor (next reachable position) to the path
            newPath.add(rowColPair);
            queue.add(newPath); //add new path to queue
        }
         return magicBoardBFS(board);
    }

    //check if last pair in path is the target
    private static boolean targetFound(int[][] board,List<int[]>path ) {

        int[] rowColPair = path.get(path.size()-1); //last row, col pair in path
        int row = rowColPair[0], col = rowColPair[1];
        if(board[row][col] == 0 ){//target found
            System.out.println("Path found: ");
            printPath(path);
            return true;
        }
        return false;
    }

    private static List<int[]> getNeighbors(int[][] board, int row, int col) {

        List<int[]>neighbors = new ArrayList<>();
        int move = board[row][col];
        //todo : assert that move is > 0

        int[][] newRowColPairs = {{row + move, col},{row - move, col},  {row , col + move},{row , col - move} };
        for(int[] rowColPair: newRowColPairs){

            int newRow = rowColPair[0], newCol =rowColPair[1];
            if(newRow < board.length && newRow >= 0
                    && newCol < board[0].length && newCol >=0) { //valid row col
                if(!visited[newRow][newCol]) { //unvisited
                    neighbors.add(new int[]{newRow, newCol});
                    visited[newRow][newCol] = true;
                }
            }
        }

        return neighbors;
    }

    private static void printPath(List<int[]> path) {
        if(path == null) return;
        for(int[] rowColPair : path){
            System.out.print(Arrays.toString(rowColPair) +" ");
        }
        System.out.println();
    }
}

(1)在發布問題或答案時始終考慮 mre

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM