I have this binary array:
int[] bitArray = {
0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,
0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,1,0,0,1,1,
0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,0,
0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,0,1,0,1,1,
0,1,1,1,1,0,0,1,};
It makes the phrase: The sun is in the sky
How would you convert the int binary array to a char?
Every eight bits make up a char. You could just loop over the bits and accumulate every eight together:
int[] bitArray = {0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1,};
char[] chars = new char[bitArray.length / 8];
for (int i = 0; i < chars.length; ++i) {
int c = 0;
for (int j = i * 8; j < (i + 1) * 8; ++j) {
c = c << 1;
c += bitArray[j];
}
chars[i] = (char)c;
}
String s = new String(chars);
System.out.println(s);
Loop over every byte (8 bits) of the array, create a string of those bits, and then convert those bits to an integer using Integer.parseInt(x,2) and then cast that to a character and added to the result.
public static void main (String[] args) throws java.lang.Exception
{
int[] bitArray = {0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,0,1,0,1,1,0,1,1,1,1,0,0,1,};
int CHAR_SIZE = 8;
String T = "";
String result ="";
for (int i=0; i<bitArray.length; i+= CHAR_SIZE)
{
for (int j=0; j<CHAR_SIZE; j++)
T += Integer.toString(bitArray[i+j]);
result += Character.toString((char)Integer.parseInt(T, 2));
T="";
}
System.out.println(result);
}
output
The sun is in the sky
ASCII chars are one byte. One byte is eight bits. Separate the array elements in segments of 8 (0-7), (8-15), ...
Store these segments in another array. Use the following constructor to finish.
public String(byte[] bytes,
Charset charset)
Remember to specify utf8 as your charset. This causes the chars to be treated as one-byte ASCII chars.
Related
I have a following 2 dimensional array:
int[][] array = new int[][]{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 1, 1, 0, 1, 1, 0, 0, 0},
{0, 0, 1, 1, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0}
};
and I would like to trim all the surrounding zeroes, so my output would be like this (removing "zeros" outside and preserving the zeroes that are surrounded by "ones"):
{0, 1, 1, 1, 0},
{0, 1, 1, 1, 1},
{1, 1, 0, 1, 1},
{1, 1, 0, 1, 0},
{0, 1, 1, 1, 1},
{0, 1, 1, 1, 1},
{0, 0, 0, 1, 0}
I'm looking for an efficient way of doing this.
Possible solution (dunno if it is the most efficient way):
public static int[][] trim(int[][] mtx, int rmin, int rmax, int cmin, int cmax) {
int[][] result = new int[rmax-rmin+1][];
for (int r = rmin, i = 0; r <= rmax; r++, i++) {
result[i] = Arrays.copyOfRange(mtx[r], cmin, cmax+1);
}
return result;
}
public static int[][] trim(int[][] mtx, int trimmed) {
int cmin = mtx[0].length;
int rmin = mtx.length;
int cmax = -1;
int rmax = -1;
for (int r = 0; r < mtx.length; r++)
for (int c = 0; c < mtx[0].length; c++)
if (mtx[r][c] != trimmed) {
if (cmin > c) cmin = c;
if (cmax < c) cmax = c;
if (rmin > r) rmin = r;
if (rmax < r) rmax = r;
}
return trim(mtx, rmin, rmax, cmin, cmax);
}
public static void main (String[] args) {
int[][] array = new int[][]{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 1, 1, 0, 1, 1, 0, 0, 0},
{0, 0, 1, 1, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0}
};
int[][] trim = trim(array, 0);
System.out.println(Arrays.deepToString(trim));
}
I'll readily admit that this code is weird and a pretty unorthodox way of creating anything 2.5D, however if anyone can see what's going on I would appreciate help.
The result of my code is as shown:
I do of course want a totally flat plane, however I'm unsure as to why it curves like so. The code is shown below if anyone has any answers:
public static int width = 640;
public static int height = 480;
private Image image;
private Graphics imageG;
private int mapWidth = 20, mapHeight = 15;
private int[] map;
private float x, y;
public Game(String title)
{
super(title);
}
#Override
public void render(GameContainer gc, Graphics g) throws SlickException
{
imageG.setBackground(Color.black);
imageG.clear();
for (int y = 0; y < mapHeight; y++)
for (int x = 0; x < mapWidth; x++)
{
switch (map[x + y * (mapWidth)])
{
case 0:
imageG.setColor(Color.green);
break;
case 1:
imageG.setColor(Color.yellow);
break;
}
imageG.fillRect(x * 32, y * 32, 32, 32);
}
imageG.flush();
Image frustrum;
for (int i = 0; i < 240; i++)
{
frustrum = image.getSubImage((int) (x - i), (int) (y - i), 32 + 2 * i, 1);
frustrum.draw(0, height - 1 - i, width, 1);
//g.drawImage(frustrum, x - i, y - i);
}
//g.setColor(Color.blue);
//g.fillRect(x, y, 32, 32);
}
#Override
public void init(GameContainer gc) throws SlickException
{
try
{
image = new Image(width, height);
imageG = image.getGraphics();
} catch (SlickException e)
{
e.printStackTrace();
}
/*map = new int[]
{
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
};*/
map = new int[mapWidth * mapHeight];
Random random = new Random();
for (int i = 0; i < map.length; i++)
{
map[i] = random.nextInt(2);
}
x = 10 * 32;
y = 7 * 32;
}
#Override
public void update(GameContainer gc, int delta) throws SlickException
{
if (gc.getInput().isKeyDown(Input.KEY_W)) y--;
if (gc.getInput().isKeyDown(Input.KEY_S)) y++;
if (gc.getInput().isKeyDown(Input.KEY_A)) x--;
if (gc.getInput().isKeyDown(Input.KEY_D)) x++;
}
public static void main(String[] args)
{
try
{
AppGameContainer appgc = new AppGameContainer(new Game("2.5D Game"));
appgc.setDisplayMode(width, height, false);
appgc.start();
} catch (SlickException e)
{
e.printStackTrace();
}
}
This is my first post, so sorry if things look a bit messy. I'm sure I'll get used to it eventually...
I'm looking for extracting image pixel data into a list of integers (or any number representation). E.g., having a 2 x 2 white image, the result will be [255,255,255,255]. The Mat.dump() method prints the image pixel values accurately if the image was code generated and not read form the disk:
Mat m = new Mat(5, 10, CvType.CV_8UC1, new Scalar(0));
System.out.println("OpenCV Mat: " + m);
Mat mr1 = m.row(1);
mr1.setTo(new Scalar(1));
Mat mc5 = m.col(5);
mc5.setTo(new Scalar(5));
System.out.println("OpenCV Mat data, "+m.total()+" elements:\n" +
m.dump());
prints accurately=>
OpenCV Mat: Mat [ 5*10*CV_8UC1, isCont=true, isSubmat=false,
nativeObj=0x1415d50, dataAddr=0x13a6880 ]
OpenCV Mat data, 50 elements:
[ 0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
1, 1, 1, 1, 1, 5, 1, 1, 1, 1;
0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
0, 0, 0, 0, 0, 5, 0, 0, 0, 0]
but if I write the Mat "m" contents on the disk and afterwards I read it again, the dump() method spits out strange output:
Imgcodecs.imwrite(TRAIN_PATH_PROC+"m.jpg",m);
m = null;
m = Imgcodecs.imread(TRAIN_PATH_PROC+"m.jpg");
System.out.println("Fresly read m, "+m.total()+" elements:\n"+m.dump());
prints
Fresly read m, 50 elements:
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
5, 5, 5, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0;
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1;
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 5,
5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,
4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
5, 5, 5, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Due to the fact i need to extract the int values from read images, and relying on dump() for the string representation, this causes me trouble.
EDIT:
I have managed to extract the data simply using
List<Integer> values = new ArrayList<>();
for (int i = 0; i < m.rows(); i++) {
for (int j = 0; j < m.cols(); j++) {
values.add((int)m.get(i,j)[0]);
}
}
Mat.dump() is our friend as is printing the mat name to reveal its properties. (The question title should be changed not to disparage dump().) imread automatically assumes conversion to BGR thus the 3 channels of data instead of the expected 1 channel. imwrite JPEG automatically compresses somewhat. You can control the imread conversion and lessen the compression but it's still a little lossy.
MatOfInt imwrite_flags = new MatOfInt();
imwrite_flags.fromArray(Imgcodecs.IMWRITE_JPEG_QUALITY , 100);
Imgcodecs.imwrite(TRAIN_PATH_PROC+"m.jpg",m, imwrite_flags);
m = Imgcodecs.imread(TRAIN_PATH_PROC+"m.jpg", Imgcodecs.IMREAD_UNCHANGED);
What you need is no or lossless compression so use TIFF format - example of both below with TIFF. (See Is there a way to set specific compression scheme when saving tiff file in opencv?)
String TRAIN_PATH_PROC = "";
Mat m = new Mat(5, 10, CvType.CV_8UC1, new Scalar(0));
System.out.println("OpenCV Mat: " + m);
Mat mr1 = m.row(1);
mr1.setTo(new Scalar(1));
Mat mc5 = m.col(5);
mc5.setTo(new Scalar(5));
System.out.println("OpenCV Mat data, "+m.total()+" elements:\n" +
m.dump());
MatOfInt imwrite_flags = new MatOfInt();
imwrite_flags.fromArray(Imgcodecs.IMWRITE_TIFF_COMPRESSION , 1); // no compression
Imgcodecs.imwrite(TRAIN_PATH_PROC+"m2.tif",m, imwrite_flags);// note name change so both examples can run
// OR
Imgcodecs.imwrite(TRAIN_PATH_PROC+"m.tif",m); // default compression LZW grayscale but lossless, I think
m = null;
m = Imgcodecs.imread(TRAIN_PATH_PROC+"m.tif", Imgcodecs.IMREAD_UNCHANGED);
System.out.println("OpenCV Mat: " + m);
System.out.println("Fresly read m, "+m.total()+" elements:\n"+m.dump());
I have the following
ArrayList<ArrayList<Integer>> row = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> column = new ArrayList<Integer>();
for(int i = 0; i < 12; i++) {
column.add(0);
}
for(int j=0; j < 12 ; j++) {
row.add(column);
}
which it gave me
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
what I want is to replace a specific index in the arrayList. let's say 2nd arrayList of 3rd index with a 9.
row.get(2).set(3, 9);
but above replaces entire column with 9 instead. how should I set the arrayList to be specific without affecting other rows.
You currently add the same exact column 12 times, but you should add 12 different ones, all shaped in the same way initially:
ArrayList<ArrayList<Integer>> row = new ArrayList<ArrayList<Integer>>();
for(int j=0; j < 12 ; j++) {
ArrayList<Integer> column = new ArrayList<Integer>();
for(int i = 0; i < 12; i++) {
column.add(0);
}
row.add(column);
}
This is because you add the same instance of ArrayList as many times as you have columns, you need to create a copy first as next otherwise indeed all your columns will be affected by a modification:
for(int j=0; j < 12 ; j++) {
row.add(new ArrayList<>(column));
}
It doesn't replace all the values, it only replaces the one value. Your problem is that all 12 elements of the row list is referencing the same column list.
You need to create a new column list for each row.
Also, indexes are zero-based, so to set the 2nd arrayList of 3rd index, you need to specify indexes 1 and 2, not 2 and 3.
If you know the exact size of the matrix, you should use regular arrays, not ArrayList.
I've been following a tutorial about creating a basic tile-based tower defense game in Java and have encountered a piece of code I cannot wrap my brain around and would like some help. (My main question is at the bottom after the code)
At this point we are iterating through a multidimensional array of 0's and 1's that we pass to a constructor which has a method that assigns a grass tile for 0's and stone tile for 1's and then another method to draw them to the screen creating our game screen. Simple enough, right?
Here is the class:
package data;
import static helpers.Artist.*;
public class TileGrid {
public Tile[][] map;
public TileGrid(int[][] newMap){
map = new Tile[20][15];
for(int i = 0; i < map.length; i++){
for(int j = 0; j <map[i].length; j++){
switch(newMap[j][i]){
case 0:
map[i][j] = new Tile(row * 64, col * 64, 64, 64, TileType.GRASS);
break;
case 1:
map[i][j] = new Tile(row * 64, col * 64, 64, 64, TileType.STONE);
break;
case 2:
map[i][j] = new Tile(row * 64, col * 64, 64, 64, TileType.WATER);
break;
}
}
}
}
public void Draw(){
for(int i = 0; i < map.length; i++){
for(int j = 0; j < map[i].length; j++){
Tile t = map[i][j];
DrawQuadTex(t.getTexture(), t.getX(), t.getY(), t.getWidth(), t.getHeight());
}
}
}
}
And here is the array we are passing in:
int[][] map = { //20 tiles wide, 15 tiles high
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0},
};
So my main question has to do with the switch statement in the constructor for the TileGrid.
Why do the i and the j get switched newMap[j][i] when checking what it equals? I get that this code works, well, because it does and I understand nested for loops to iterate through a multidimensional array.
But why wouldn't newMap[i][j] work?
As well at the very beginning of that same constructor why do we create an array (of type Tile) with the dimension of map = new Tile[20][15] when we are passing in an array with the dimensions of map[15][20]?
I have tried to figure this out and study this on my own and will continue to do so until I understand it but any help would be soooo appreciated!
You are passing to the TileGrid constructor a 2D array of 15 rows and 20 columns, but inside the constructor you create a 2D array of 20 rows and 15 columns. That's why map[i][j] corresponds with newMap[j][i].
If the input int[][] map was also of 20 rows and 15 columns, you wouldn't have to switch the order of the indices inside the constructor.
This would give an index out of bounds error if it was really switched. However, there is a col variable in the second for loop that is not defined anywhere so it's hard to tell what's going on. This code will not compile.
If it is some code pulled off a a tutorial on some web page, I would just assume that it was a typo and continue on with that in mind. OR better yet, contact the author.