Convert map image to 2d-array. Algorithm dfs,bfs, astar - java

I have problem how to start with this program.
I want to get 2d-array of pixel localization.
Then work on this array with bfs, dfs to get path from orange dot to green dot.
Draw grey pixel if visited.
Draw the path and save it to other image.
When i will handle with this i would like to change cost on each pixel (by drawing in paint something similar to walls but it could go throught by them with higher cost)
public int [][] gRGB(BufferedImage image)
{
int width = image.getWidth();
int height = image.getHeight();
int[][] result = new int[width][height];
for (int row = 0; row < width; row++) {
for (int col = 0; col < height; col++) {
result[row][col] = image.getRGB(row, col);
}
}
return result;
}
}
From this code i get 2d-array full of -1 value. Is there option to get color information as value (not rgb i would like to have it as one number not 4)
EDIT:
protected static int [][] convert(BufferedImage image)
{
int width = image.getWidth();
int height = image.getHeight();
int[][] result = new int [width][height];
for(int row = 0; row < height; row++)
for(int col = 0; col < width; col++)
{
Color c = new Color(image.getRGB(col, row));
String h = String.format("%02x%02x%02x", c.getRed(),c.getGreen(),c.getBlue());
if(h.equals("000000")) // black
{
result[col][row] = 0;
}
else if(h.equals("fe0000")) // red
{
result[col][row] = 5;
}
else if(h.equals("ffffff")) // white
{
result[col][row] = 1;
}
else if(h.equals("ff7d41")) // orange - start
{
result[col][row] = 10;
}
else if (h.equals("ff0078")) // pink - end
{
result[col][row] = 9;
}
else
{
result[col][row] = 3;
}
}
for(int row = 0; row < height; row++)
{
System.out.println();
for(int col = 0; col < width; col++)
System.out.print("\t" + result[col][row]);
}
return result;
}
So i have now the array of pixel value. Can someone explain me how to write DFS or BFS algorithm?? Where the cost is the value of pixel?
Black - walls, Orange dot - start, Green dot - end

For finding the path with minimum cost it is better to use algorithms such as UCS,A* or IDA* (It is very inefficient to use BFS or DFS to find shortest path on a weighted graph). My suggestion is to first implement UCS , then improve it with a simple heuristic such as manhattan distance to A*. For full explanation about UCS and A* please refer to these links:
Wikipedia A*
Wikipedia UCS
As for using these algorithms on your 2D-Array, you should consider every point a node and connect that node to every neighbor nodes. So every node is connected to its 4 non-wall neighbors ( or 8 non-wall neighbors if you can move diagonally ).

Related

Compute the range of column height

The key of the below code is to find the tallest and shortest block in a column. I created a method that gets the tallest block. I need help with getting the range of the highest and lowest block and returning that range. I get that I'm getting the max height but I feel very lost with what I need to do. Any help would be appreciated.
Helper Code
--get the tallest height of a block
public int getColumnHeight(Board board, int col){
int highestPiece = 0;
for (int row = 0; row < Board.HEIGHT; row++){
if (board.isBlockAt(col, row)){
highestPiece = row + 1;
}
}
return highestPiece;
}
-- get the range of column heights (need help with this portion)
public int getColumnHeightRange(Board board){
int columnHeightRange = 0;
for (int col = 0; col < Board.WIDTH; col++){
int columnHeight = getColumnHeight(board, col);
if (columnHeight > colHeightRange){
colHeightRange = columnHeight;
}
}
return colHeightRange;
}

Creating a dynamic checkerboard, even numbers causing problems

My homework challenge is to make a checkerboard using JavaFX based on the size the user inputs from a JOptionPane. I've done this and works perfectly only with odd numbers, how can I fix this so it works for both odd and evens correctly?
I'm assuming it's an issue with how I'm polling the color to use since with even numbers each row would be identical.
Color[] colors = {Color.BLACK, Color.WHITE};
int nextColor = 0;
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
nextColor = (nextColor == 0) ? 1 : 0;
Rectangle rec = new Rectangle();
rec.setWidth(50);
rec.setHeight(50);
rec.setFill(colors[nextColor]);
GridPane.setRowIndex(rec, row);
GridPane.setColumnIndex(rec, col);
grid.getChildren().addAll(rec);
}
}
odd numbers
even numbers
If you're going through the board filling the fields with alternating colors, a even number of columns will result in the last field being colored with a different color than the first field in the row and thus the first field in the next row will have the same color than the field directly above.
To fix this you can simply add the column and row numbers and take the remainder of the division by 2 to determine the color:
Color[] colors = {Color.WHITE, Color.BLACK};
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
int nextColor = (row + col) % 2;
Rectangle rec = new Rectangle();
rec.setWidth(50);
rec.setHeight(50);
rec.setFill(colors[nextColor]);
GridPane.setRowIndex(rec, row);
GridPane.setColumnIndex(rec, col);
grid.getChildren().addAll(rec);
}
}
Another variant than what muzzlator proposes would be to set color by position alone, without storing some current alternate color. This is error-prone as you see.
Simply go with int color = (row + col) % 2;.

Dropping characters when printing from 2D array

I have a string of characters for which I want to encrypt by loading into a 2D array by rows and then printing the array by column. Such that:
|A|B|
|C|D|
|E|
encrypts to "ACEBD".
However I cant seem to be able to avoid dropping characters in the last row in my output getting "ACBD". Any idea how to solve this?
public static void main(String[] args) throws FileNotFoundException {
if (handleArguments(args))
System.out.println("encrypt");
// get input
Scanner input = new Scanner(inputFile);
String line = input.nextLine();
// calculate height of the array
int height = line.length() / width;
// Add one to height if there's a partial last row
if (line.length() % width != 0)
height += 1;
loadUnloadGrid(line, width, height);
}
static void loadUnloadGrid(String line, int width, int height) {
// make an empty array
char grid[][] = new char[height][width];
// fill the array row by row with character from line
int charCount = 0;
for (int r = 0; r < height - 1; r++) {
for (int c = 0; c < width; c++) {
// check to make sure accessing past end of the line
if (charCount < line.length()) {
grid[r][c] = line.charAt(charCount);
charCount++;
}
}
}
// print to standard output the characters in array
System.out.printf("Grid width %d: \"", width);
for (int r = 0; r < width; r++) {
for (int c = 0; c < height; c++) {
System.out.print(grid[c][r]);
}
}
// !!Special handling for last row!!
int longColumn = line.length() % width;
if (longColumn == 0)
longColumn = width;
for (int c = 0; c < longColumn; c++) {
System.out.print(grid[height - 1][c]);
}
System.out.println();
}
You need to loop the rows before you loop the columns, i.e., just the way you usually don't do it.
for (int i = 0; i < array[0].length; i++) {
for (int j = 0; j < array.length; j++) {
// prints columns before rows
}
}
However, be aware that you cannot check whether one row has less columns than another within the loop. Usually array[i].length avoids any NPEs. In this case you might want to define a check whether the array at row j even has column i. This could be done within the second loop by checking:
if (array[j].length > i)
// System.out.println(...);
else
break;
Edit: I see your loop should be working correctly. Most likely height is only 1 instead of 2 and thus, the last row gets cut off. My code as it is works for your input and your loop should be working the same way. Try to print height and check if it is correct or debug your program and go through it step by step.

Rotating image 90 degree counter clockwise in Java

public static int[][] rotate(int[][] array){
int height = array.length;
int width = array[0].length;
int[][] rotatedArray = array;
for(int col = 0; col < width; col++){
for(int row = 0; row < height; row++){
rotatedArray[row][col] = array[col][row];
}
}
return rotatedArray;
}
This is my code as method to rotate image 90 degree counter-wise, but it doesn't work. I have no idea how to arrange new rows and columns and rotate it properly, how can I fix it? Thanks!
Try rotatedArray[row][col] = array[col][height - row - 1];.
Also, you need to define rotatedarray as a new array. Right now, you're assigning it array, which means they are both referencing the same data.
Here's how you can do it:
public static int[][] rotate(int[][] array) {
int height = array[0].length;
int width = array.length;
int[][] rotatedArray = new int[height][];
for(int row = 0; row < height; row++) {
rotatedArray[row] = new int[width];
for(int col = 0; col < width; col++) {
rotatedArray[row][col] = array[col][height - row - 1];
}
}
return rotatedArray;
}
Note that the height of the original array becomes the width of the new array and vice versa.
By transposing the row & column indices with rotatedArray[row][col] = array[col][row], you are mirroring the image along the diagonal, instead of rotating it. Think about it - any entry where both indices are matching such as array[0][0] or array[1][1] is unchanged. That's not what you want!
I would recommend drawing a picture to see what pattern you see. You can start with very small examples, 2-by-2 or 3-by-3.

Creating a QImage from QBytearray

I'm trying to construct QImages from data saved as 16-bit integers in a binary file. I'm able to load the data in fine, but my program fails when I use the QImage::loadFromData(QBytearray ba) function (returning false) as follows:
QBytearray frame;
QImage pic = QImage(256, 256, QImage::Format_RGB888);
for(int i = 0; i < height; i++) {
for(int j = 0; j < width; j++) {
// Access value of pixel at each location
datum = store[i][j];
for(int c = 0; c < 3; c++) {
// Calculate colour at given pixel
col = (255.0f * ((float)datum - (float)min) / ((float)(max - min)));
// Assign colour value to the pixel
frame[c+3*j+3*i*width] = ((unsigned char)col);
}
}
}
pic.loadFromData(frame);
I repurposed this from Java code I had previously written which worked perfectly as intended (from the exact same data):
BufferedImage image = = new BufferedImage(256, 256, BufferedImage.TYPE_3BYTE_BGR);
byte[] data = image.getRaster().getDataBuffer();
for (j=0; j<height; j++) {
for (i=0; i<width; i++) {
//Find value of the pixels at the location
datum=data[j][i];
for (c=0; c<3; c++) {
//Calculate the colour at the given pixel
col=(255.0f*((float)datum-(float)min)/((float)(max-min)));
//Assign the colour value to the pixel
data[c+3*i+3*j*width] = (byte)col;
}
}
}
Can anybody help me to see where I'm getting this wrong? I've been stumped for days and am all out of ideas.
Ok, assuming that you are in fact trying to set RGB values for individual pixels, after reading the QImage details, I see you can do it using the following:
value = qRgb(189, 149, 39); // 0xffbd9527
image.setPixel(1, 1, value);
So, something like:
QImage pic = QImage(256, 256, QImage::Format_RGB888);
QRgb value;
int r,b,g;
for(int i = 0; i < height; i++) {
for(int j = 0; j < width; j++) {
// Access value of pixel at each location
datum = store[i][j];
//I get really confused what is going on here... you don't seem to be actually using `c` for the calculation?
for(int c = 0; c < 3; c++) { //let's just pretend you set the ints r,b,g in here somewhere
// Calculate colour at given pixel
col = (255.0f * ((float)datum - (float)min) / ((float)(max - min)));
}
// Assign colour value to the pixel
value = qRgb(r, g, b);
pic.setPixel(i, j, value);
}
}

Categories

Resources