java - 从矩阵的一点移动到零的位置
问题描述
我应该用递归和迭代来编程。我的递归代码贴在底部。MagicBoard 是一款单人游戏,使用类似于国际象棋的棋盘,由 d×d 方格组成,d 介于 5 和 20 之间,每个方格包含一个介于 0 和 d -1 之间的整数。游戏规则很简单。圆圈标记板上的开始位置。圆圈中的整数 (n) 表示圆圈可以在棋盘上移动 n 个方格。在一个步骤中,圆可以向东或向西或向北或向南移动 n 个方格。在每一步,选择的方向都是固定的。圆圈不能移出棋盘。唯一合法的起始位置是四个角方块。棋盘必须恰好包含一个以零为值的目标方格,该方格可以位于棋盘上的任何位置,但其位置不能与起始位置相同。 例如,在上面的例子中,圆可以向东或向南移动 4 个方格。所有其他动作都是非法的。游戏的目标是将圆圈移动到包含零值的目标方格。在下面给出的配置中,您可以通过以下步骤来解决游戏:
下一个示例显示在某些情况下,无法从给定的起始位置到达目标方格
这是我的代码不起作用:
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)));
推荐阅读
- javascript - 代码停止执行而不抛出错误
- javascript - 如何使我的图片在我的 ejs 文件中可见?
- c++ - 扩展 std::vector 的功能
- 命名空间、组合或继承? - sql - 如何使用两个表中的数据创建视图
- php - CURL 仅更改一个值并保留其余的意外字符('='(代码 61)
- c++ - 如何在函数中使用默认参数?
- java - 无法解决:E/RecyclerView:未连接适配器;跳过布局并且不能在 child() 中为参数“pathString”传递 null
- python - 如何从以前的迭代中访问 TF 变量?
- visual-studio - 没有cmd的visual studio 2019输出
- postgresql - 在 Manjaro 中更新后 PostGIS 不起作用