I am working on the following problem:
Write a method that, given a chessboard with one knight, rocks on some of the squares, and a target position, indicates whether or not the knight can reach the target without landing on any rocks, and if so, the smallest number of moves needed by the knight to reach the target. The method should return the minimum number of moves needed to do so; otherwise, the method should return the value -1. (If the initial position has a rock on it, the method should return -1; likewise, if the target position has a rock on it, the method should return -1.)
You can see the code I've implemented so far below. My approach to rocks is to change the "coordinates" on the chessboard that have rocks as visited, so the knight can't revisit them, hence blocking his path(?).
My program compiles but doesn't return either minimum moves or -1. Any tips/different approaches to the problem are much appreciated. Thanks!!
PS: I'm ridiculously new to Java so apologies in advance for the messy code :)
import java.util.*;
public class Knight {
public static int numMoves( int dim, int xstart, int ystart, int xtarget,
int ytarget, int[] xrock, int[] yrock )
{
int result = -1;
List<Integer> knightPos = new ArrayList<>(Arrays.asList(xstart, ystart));
int [] targetPos = {xtarget, ytarget};
int dis = 0;
// x and y direction, where a knight can move
int[] dx = { -2, -1, 1, 2, -2, -1, 1, 2 };
int[] dy = { -1, -2, -2, -1, 1, 2, 2, 1 };
// queue for storing states of knight in board
Vector<cell> q = new Vector<>();
// push starting position of knight with 0 distance
q.add(new cell(knightPos.get(xstart), knightPos.get(ystart), dis));
cell t;
int x, y;
boolean[][] visit = new boolean[dim + 1][dim + 1];
// make all cell unvisited
for (int i = 1; i <= dim; i++) {
for (int j = 1; j <= dim; j++) {
visit[i][j] = false;
}
}
// visit starting state
visit[knightPos.set(0,xstart)][knightPos.set(1,ystart)] = true;
// visit rock squares
for (int i = 0; i < xrock.length;) {
for (int j = 0; j < yrock.length; ++i, ++j) {
visit[knightPos.get(i)][knightPos.get(j)] = true;
}
}
// loop until we have one element in queue
while (!q.isEmpty()) {
t = q.firstElement();
q.remove(0);
// if current cell is equal to target cell,
// return its distance
if (t.x == targetPos[0] && t.y == targetPos[1])
return t.dis;
// loop for all reachable states
for (int i = 0; i < 8; i++) {
x = t.x + dx[i];
y = t.y + dy[i];
// If reachable state is not yet visited and
// inside board, push that state into queue
if (isInside(x, y, dim) && !visit[x][y]) {
visit[x][y] = true;
q.add(new cell(x, y,dis + 1));
}
}
}
return result;
}
public static boolean isInside (int x, int y, int dim)
{
return x >= 0 && x <= dim && y >= 0 && y <= dim;
}
static class cell {
int x, y;
int dis;
public cell(int x, int y, int dis) {
this.x = x;
this.y = y;
this.dis = dis;
}
}
public static void main( String[] args )
{
}
}
Related
I'm trying to solve this challenge which is to get the min cost of Knight's moves from a source to a destination in a (8*8) chess board and I'm getting a case that not working … I guess I messed up somewhere and I cant figure that out.
see image here
the full code
import java.util.ArrayList;
import java.util.List;
public class Solution {
static class Position{
public int x;
public int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
}
public static int solution(int src, int dest) {
int min = 100000000;
int depth = 0;
Position source = new Position(0, 0), destination = new Position(0, 0);
int [][] board = getBoard(src, dest, source, destination);
if(arrived(source, destination)) return 0;
return solve(board, source, destination, (depth), min);
}
public static int[][] getBoard(int src, int dest, Position source, Position destination) {
int c = 0;
int [][] board = new int[8][8];
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board.length; j++){
if(c == src) {
board[i][j] = 1;
source.x = i;
source.y = j;
}else if(c == dest) {
board[i][j] = -1;
destination.x = i;
destination.y = j;
}else {
board[i][j] = 0;
}
c++;
}
}
return board;
}
public static int solve(int[][] board, Position position, Position destination, int depth, int min){
if(depth > min) {
return depth;
}
for(Position p: sort(getPossibleMoves(board, position), destination)){
if(arrived(p,destination)) {
return depth + 1;
}
board[p.x][p.y] = depth +2;
int cost = solve(board, p, destination, (depth + 1), min);
board[p.x][p.y] = 0;
if(cost < min){
min = cost;
}
}
return min;
}
public static List<Position> sort(List<Position> positions, Position dest) {
Position temp;
boolean sorted = false;
while(!sorted) {
sorted = true;
for(int i = 0; i < positions.size() - 1; i++) {
if(distance(positions.get(i), dest) > distance(positions.get(i+1), dest)) {
temp = positions.get(i);
positions.set(i, positions.get(i+1));
positions.set(i+1, temp);
sorted = false;
}
}
}
return positions;
}
public static double distance(Position a, Position b) {
if(a.x == b.x && a.y == b.y) return 0;
return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}
public static boolean arrived(Position src, Position dest) {
return src.x == dest.x && src.y == dest.y;
}
public static List<Position> getPossibleMoves(int [][] board, Position current){
int [][] moves = {{1,2}, {2,1}, {-1,2}, {1,-2}, {-2,1}, {2,-1}, {-1,-2}, {-2,-1}};
List<Position> positions = new ArrayList();
for(int i = 0; i < moves.length; i++) {
int x = current.x + moves[i][0];
int y = current.y + moves[i][1];
if(x >= 0 && y >= 0 && x < board.length && y < board.length && board[x][y] <= 0)
positions.add(new Position(x, y));
}
return positions;
}
public static void main(String [] args) {
System.out.println(solution(0, 1));
}
}
so here is my approach :
we start from a position and we try all the possible moves (sorted by the nearest) till we find the destination and then do some kind of backtracking to see if there's a better way to get there at a low cost and return the minimum.
some rules I've set :
the board is represented by a matrix of integers ( full of zeros if empty)
the source is represented by 1
the destination is represented by -1
wherever the knight goes its going to be marked by an integer representing the cost (the start is 1 the second move will be 2 , third 3 and so on …)
let me break the code a little bit down to make it easier
we start from the function solution public static int solution(int src, int dest) which will initialize the board, set the source and destinatin positions, and return the cost using the solve(board, source, destination, (depth), min) function
the function public static int[][] getBoard(int src, int dest, Position source, Position destination) take the board, position … look trough all possible moves ( unmarked positions and sorted by the nearest) for that position and call recursively with a new position until it found the destination or the depth (witch is the cost) is bigger then the minimum that we already have
the function public static List<Position> getPossibleMoves(int [][] board, Position current) will return the 8 possible moves for knight from a position but only those who are not out of the board and are also unvisited ( unvisited will be 0 or -1 for the destination )
the function public static List<Position> sort(List<Position> positions, Position dest) will sort the possible moves by the nearest to the destination ( let's prioritize the nearest one)
please if you can help me figure out what's wrong or if you have another approach I'd really appreciate !
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.
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();
}
}
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<Integer> 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<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);
}
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.
I have to do a method that will go through the matrix.I give the coordinates from the keyboard of the position [L, C], from where the extension will start.It will pass to the next value only if the next value is smaller than this.On the diagonals do not go!
PS: Sorry for my english
Like in image:
enter image description here
Three steps need to be done here:
// prepare output matrix and fill it with -1
int[][] outMatrix = prepareOut(inputArray.length, inputArray[0].length);
// call recursively method to mark cells starting from the initial coordinates
outMatrix = markCell(inputArray, outMatrix, line, column, 1);
// print output matrix
printOutput(outMatrix);
The most relevant method implementation may be like this:
static int[][] markCell(int[][] arr, int[][] out, int y, int x, int move) {
int val = arr[y][x];
if (out[y][x] == 0) {
return out;
} else if (out[y][x] < 0) {
out[y][x] = move;
}
// checking a cell above the current one (north)
if (y > 0 && out[y - 1][x] < 0) {
if (cellMarked(arr, out, y - 1, x, val, move)) {
out = markCell(arr, out, y -1, x, move + 1);
}
}
// checking a cell under the current one (south)
if (y < arr.length - 1 && out[y + 1][x] < 0) {
if (cellMarked(arr, out, y + 1, x, val, move)) {
out = markCell(arr, out, y +1, x, move + 1);
}
}
// checking a cell to the left of the current one (west)
if (x > 0 && out[y][x - 1] < 0) {
if (cellMarked(arr, out, y, x - 1, val, move)) {
out = markCell(arr, out, y, x - 1, move + 1);
}
}
// checking a cell to the right of the current one (east)
if (x < arr[0].length - 1 && out[y][x + 1] < 0) {
if (cellMarked(arr, out, y, x +1, val, move)) {
out = markCell(arr, out, y, x + 1, move + 1);
}
}
return out;
}
static boolean cellMarked(int[][] arr, int[][] out, int y, int x, int val, int move) {
final boolean marked = arr[y][x] <= val;
out[y][x] = marked ? move : 0;
return marked;
}
When printing the output matrix, you replace remaining -1 with 0:
static void printOutput(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
char c = arr[i][j] <= 0 ? '0' : '*';
System.out.print(c);
System.out.print('\t');
}
System.out.print('\n');
}
}
prepareOut may be implemented like this:
private static int[][] prepareOut(int rows, int cols) {
int [][] out = new int[rows][cols];
for(int[] row: out) {
Arrays.fill(row, -1);
}
return out;
}
I am new to this website so correct me if there is anything wrong with my question. I keep receiving this error and I am not entirely sure what is wrong with my program:
Exception in thread "main" java.lang.IllegalArgumentException: Parameter N must be positive
at StdRandom.uniform(StdRandom.java:119)
at Maze.chooseRandomlyFrom(Maze.java:52)
at Maze.expandMaze(Maze.java:136)
at Maze.main(Maze.java:193)**
I ran the JUnit test in my IDE (eclipse) however I could not trace where the error is coming from. Any help or guidance is greatly appreciated and thank you for taking the time to check out the code. Here is what I am working with. I included comments for each method as clearly as I could.
public class Maze {
public static final int EAST = 1;
public static final int NORTH = 0;
public static final int[][] OFFSETS = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
public static final int SOUTH = 2;
public static final int WEST = 3;
//Purpose: Modifies passage to contain a one-way passage from location a to location
//b. Assumes these two locations (arrays of two numbers) are adjacent.
//Parameters: boolean[][][] passages, int[] a, int[] b
//Return: N/A
public static void addPassage(boolean[][][] passages, int[] a, int[] b)
{
int ax = a[0];
int ay = a[1];
int bx = b[0];
int by = b[1];
if (by == ay + 1) {
passages[ax][ay][0] = true;
} else if (bx == ax + 1) {
passages[ax][ay][1] = true;
} else if (by == ay - 1) {
passages[ax][ay][2] = true;
} else {
passages[ax][ay][3] = true;
}
}
//Purpose: Gets array of pairs containing start and all locations in the list.
//Parameters: int[] start, int[][] list
//Return: Returns a new array of pairs containing start followed by all of the locations in list.
public static int[][] addToFront(int[] start, int[][] list)
{
int[][] path = new int[list.length + 1][];
path[0] = start;
for (int i = 1; i < path.length; i++) {
path[i] = list[(i - 1)];
}
return path;
}
//Purpose: Gets random one from the first element of the list
//Parameters: int[][] list, int n
//Return: Returns a random one of the first n elements of list.
public static int[] chooseRandomlyFrom(int[][] list, int n)
{
return list[StdRandom.uniform(n)];
}
//Purpose: Gets pair and compares to first number as one of the first n element
//Parameters: int[] pair, int[][] list, int n
//Return: Returns true if pair, assumed to be an array of two numbers, has the same
//numbers as one of the first n elements of list.
public static boolean contains(int[] pair, int[][] list, int n)
{
for (int i = 0; i < n; i++) {
if ((pair[0] == list[i][0]) && (pair[1] == list[i][1])) {
return true;
}
}
return false;
}
//Purpose: Will draw the maze
//Parameters: boolean[][][] passages
//Return: N/A
public static void drawMaze(boolean[][][] passages)
{
StdDraw.clear(StdDraw.PINK);
StdDraw.setPenColor(StdDraw.WHITE);
int width = passages.length;
StdDraw.setPenRadius(0.75 / width);
// Draw passages
for (int x = 0; x < width; x++) {
for (int y = 0; y < width; y++) {
if (passages[x][y][NORTH] || (y + 1 < width && passages[x][y + 1][SOUTH])) {
StdDraw.line(x, y, x, y + 1);
}
if (passages[x][y][EAST] || (x + 1 < width && passages[x + 1][y][WEST])) {
StdDraw.line(x, y, x + 1, y);
}
}
}
// Draw entrance and exit
StdDraw.line(0, 0, -1, 0);
StdDraw.line(width - 1, width - 1, width, width - 1);
StdDraw.show(0);
}
//Purpose: Will draw the maze solution
//Parameters: int[][] path, int width
//Return: N/A
public static void drawSolution(int[][] path, int width)
{
StdDraw.setPenColor(); // Black by default
StdDraw.setPenRadius();
StdDraw.line(0, 0, -1, 0);
StdDraw.line(width - 1, width - 1, width, width - 1);
for (int i = 0; i < path.length - 1; i++) {
StdDraw.line(path[i][0], path[i][1], path[i + 1][0], path[i + 1][1]);
}
StdDraw.show(0);
}
//Purpose: Checks if here's neighbor in direction (called there) is in unexplored. If so, adds a passage from here
//to there and returns there. If not,returns null.
//Parameters: boolean[][][] passages, int[][] unexplored, int n, int[] here, int direction otherwise.
public static int[] expandLocation(boolean[][][] passages, int[][] unexplored, int n, int[] here, int direction)
{
int[] there = new int[2];
here[0] += OFFSETS[direction][0];
here[1] += OFFSETS[direction][1];
if (contains(there, unexplored, n))
{
addPassage(passages, here, there);
return there;
}
return null;
}
//Purpose: Chooses "here" to be either lastExploredLocation (if it is not null) or a random location in
//frontier. If possible, adds a passage from "here" to a location "there" in unexplored, then moves "there" from unexplored to
//frontier. If not, moves "here" from frontier to done.
//Parameters: boolean[][][] passages, int[][] done, int[][] frontier, int[][] unexplored, int[] counts, int[] lastExploredLocation
//Return: N/A
public static int[] expandMaze(boolean[][][] passages, int[][] done, int[][] frontier, int[][] unexplored, int[] counts, int[] lastExploredLocation)
{
int[] here;
if (lastExploredLocation == null) {
here = chooseRandomlyFrom(frontier, counts[1]);
} else {
here = lastExploredLocation;
}
int direction = StdRandom.uniform(4);
for (int i = 0; i < 4; i++)
{
int[] there = expandLocation(passages, unexplored, counts[2], here, direction);
if (there != null)
{
frontier[counts[1]] = there;
counts[1] += 1;
remove(there, unexplored, counts[2]);
counts[2] -= 1;
return there;
}
direction = (direction + 1) % 4;
}
done[counts[0]] = here;
counts[0] += 1;
remove(here, frontier, counts[1]);
counts[1] -= 1;
return null;
}
//Purpose: Draws then solves maze
//Parameters: String[] args
//Return: N/A
public static void main(String[] args)
{
int width = 20;
StdDraw.setXscale(-0.5, width - 0.5);
StdDraw.setYscale(-0.5, width - 0.5);
StdDraw.show(0);
boolean[][][] passages = new boolean[width][width][4];
// Initially, no locations are done
int[][] done = new int[width * width][];
// The frontier only contains {0, 0}
int[][] frontier = new int[width * width][];
frontier[0] = new int[] { 0, 0 };
// All other locations are in unexplored
int[][] unexplored = new int[width * width][];
// Number of nodes done, on the frontier, and unexplored
int[] counts = { 0, 1, width * width - 1 };
int i = 0;
for (int x = 0; x < width; x++) {
for (int y = 0; y < width; y++) {
if (x != 0 || y != 0) {
unexplored[i] = new int[] { x, y };
i++;
}
}
}
// As long as there are unexplored locations, expand the maze
int[] lastExploredLocation = null;
while (counts[2] > 0) {
lastExploredLocation = expandMaze(passages, done, frontier, unexplored, counts, lastExploredLocation);
drawMaze(passages);
StdDraw.show(25);
}
// Solve the maze
int[][] solution = solve(passages, new int[] { 0, 0 }, new int[] { width - 1, width - 1 });
drawSolution(solution, width);
}
//Purpose: Modifies list so that pair is replaced with the (n - 1)th element of list. Assumes pair is an
//array of two numbers that appears somewhere in list. Thus, when this method is done, the first n - 1 element of list are
//the same as the first n elements of the old version, but with pair removed and with the order of elements potentially different.
//Parameters: int[] pair, int[][] list, int n
//Return: N/A
public static void remove(int[] pair, int[][] list, int n)
{
for (int i = 0; i < n; i++) {
if ((pair[0] == list[i][0]) && (pair[1] == list[i][1]))
{
list[i] = list[(n - 1)];
return;
}
}
}
//Purpose: Gets a return path from start to finish
//Parameters: boolean[][][] passages, int[] start, int[] goal
//Return: Returns a path (sequence of locations) leading from start to goal in passages or null if there is no such path.
public static int[][] solve(boolean[][][] passages, int[] start, int[] goal) {
if ((start[0] == goal[0]) && (start[1] == goal[1])) {
return new int[][] { goal };
}
for (int d = 0; d < 4; d++) {
if (passages[start[0]][start[1]][d] != false)
{
int[] next = { start[0] + OFFSETS[d][0], start[1] + OFFSETS[d][1] };
int[][] restOfPath = solve(passages, next, goal);
if (restOfPath != null) {
return addToFront(start, restOfPath);
}
}
}
return null;
}
}
When you pass the argument 'n' to
StdRandom.uniform() at Maze.chooseRandomlyFrom(Maze.java:52) the argument you are passing is negative. According to the error message, the parameter must be positive. This could be because during expandMaze, you are assigning counts[1] to be one less than its current value (counts[1] -= 1;), which will eventually result in a negative number. It would appear that the method is called over and over as long as counts[2] > 0, which in some cases must be the case for enough iterations such as counts[1] becomes a negative number.
Perhaps before calling this StdRandom.uniform() method, you should take the absolute value of counts[1] to ensure it is always positive. Math.abs(counts[1]) should do the trick.
So for a match 3 type game, like candy crush I need to search a 2D array and if the same number is repeated create a match.
For Example, if my 2d array is something like
212031201
012102312
101223200
012131013
010321022
201210101
102023202 <--
012102312 <--
012321022 <--
You notice there are three twos in a line on the bottom right side (arrows pointing). How would I search the array to return the values and create a match. Here is what I am thinking but I'm not sure if even my logic is correct:
public class matchAI
{
Game game = new Game();
public void search() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (game.board[i][j] == game.Emerald) //game.Board is the Array which is 9x9 filled with numbers 0,1,2. game.Emerald =0
{
//Store value
//Check Around current position for similar numbers
//Add to Score, indicating match, and remove current matched numbers and shift the rest down, like gravity sucks others down.
//Fill top row which would be empty from others shifting
}
}
}
}
}
I think it might be better to keep a 2D array of Tile objects. A Tile class could look like this:
public class Tile {
private int x, y;
private int type;
private int[][] neighbors;
public Tile(int x, int y, int type){
this.x = x;
this.y = y;
this.type = type;
findNeighbors();
}
private void findNeighbors(){
int[] top = new int[] {x, y+1};
int[] right = new int[] {x+1, y};
int[] bottom = new int[] {x, y-1};
int[] left = new int[] {x-1, y};
neighbors = new int[][] {top, right, bottom, left};
}
public int getType() {
return type;
}
public int[] getNeigbor(int side) {
if(side == 0) {
return neighbors[0];
}
//etc
return null;
}
}
Then you can just ask each tile for the position of its neighbors and then check their types. Some checking would be necessary for edge tiles, but I think this should work fairly well.
The elegant way would be to design an iterator that delivers each element around a supplied point.
public static class Around<T> implements Iterable<T> {
// Steps in x to walk around a point.
private static final int[] xInc = {-1, 1, 1, 0, 0, -1, -1, 0};
// Ditto in y.
private static final int[] yInc = {-1, 0, 0, 1, 1, 0, 0, -1};
// The actual array.
final T[][] a;
// The center.
final int cx;
final int cy;
public Around(T[][] a, int cx, int cy) {
// Grab my parameters - the array.
this.a = a;
// And the center we must walk around.
this.cx = cx;
this.cy = cy;
}
#Override
public Iterator<T> iterator() {
// The Iterator.
return new Iterator<T>() {
// Starts at cx,cy
int x = cx;
int y = cy;
// Steps along the inc arrays.
int i = 0;
#Override
public boolean hasNext() {
// Stop when we reach the end of the sequence.
return i < xInc.length;
}
#Override
public T next() {
// Which is next.
T it = null;
do {
// Take the step.
x += xInc[i];
y += yInc[i];
i += 1;
// Is it a good spot? - Not too far down.
if (y >= 0 && y < a.length) {
// There is a row here
if (a[y] != null) {
// Not too far across.
if (x >= 0 && x < a[y].length) {
// Yes! Use that one.
it = a[y][x];
}
}
}
// Keep lookng 'till we find a good one.
} while (hasNext() && it == null);
return it;
}
};
}
}
public void test() {
Integer[][] a = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
for (Integer i : new Around<>(a, 1, 1)) {
System.out.print(i + ",");
}
System.out.println();
for (Integer i : new Around<>(a, 2, 2)) {
System.out.print(i + ",");
}
}