I need some help with creating a grid in java AWT. You get a certain number of columns, for now let's say 13.
for(int i = 0; i < 13; i++)
{
Graphics.fillRect((i * 15), 10, 10, 10);
}
Graphics takes in x, y, width, height.
This results in;
XXXXXXXXXXXXX
This will put all cubes next to each other. This is not what I want. I need the y position to go down by 15 pixels every time 4 cubes have been drawn.
The result would be
XXXX
XXXX
XXXX
X
Thanks for your time!
Basically, you have to increment the x, and every time you reach the limit, you bring the x back to zero, and increase the y:
// These should be constants, defined at the class level
public static final int NUM_RECTANGLES = 13;
public static final int NUM_COLUMNS = 4;
// And your loop
int col = 0;
int row = 0;
for(int i = 0; i < NUM_RECTANGLES; i++)
{
Graphics.fillRect((col * 15), 10 + (row * 15), 10, 10);
col++;
if( col == NUM_COLUMNS ) {
col = 0;
row++;
}
}
As you see, after each rectangle, you increase the column. If you get to the limit for the column (remember you started from 0), you move to the next line. This means the column is again 0, and the row is increased.
Of course, if your 13 and 4 are actually parameters, ignore my remark about constants.
Just use a double for() loop
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++) {
Graphics.fillRect(i * 15, j * 15, 10, 10);
}
}
This will create a 4x4 grid of rectangles. If you want to limit it to a 4x4-like grid that only has 1 rectangle in the last row, which it seems like you want, use j < ((i == 3) ? 1 : 4) as your termination condition in the second for loop, or use a simple if condition like so:
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++) {
Graphics.fillRect(i * 15, j * 15, 10, 10);
if(i == 3) break;
}
}
edit: Generic Solution
int nRow, nCol, nLastCol;
//Initialize values
for(int i = 0; i < cRow; i++){
for(int j = 0; j < ((i == nRow - 1) ? nLastCol : nCol); j++) {
Graphics.fillRect(i * 15, j * 15, 10, 10);
}
}
You need to set how many columns and keep track of which column you're drawing so that you can increment the row. On a side note, I also wouldn't put a magic number in the loop, instead make that a variable (just good programming practice). Something like this:
int numRectangles = 13;
int numColumns = 4;//set this to however many columns you need
int currentRow = 1;//start at one, not zero
int tempRow = 1;
for(int i = 0; i < numRectangles; i++)
{
Graphics.fillRect((i * 15), (tempRow * 10), 10, 10);
currentRow++;
if(currentRow > numColumns) {
currentRow = 1;
tempRow++;
}
}
Related
Im trying to run a two for loops that iterate over something like colored large square (for example 300x300) and replacing it with the colors(or pixels) of a smaller square (say 100x100) which is what k and l represent.
Essentially, I was wondering how to keep k and l running between 0-100 and restarting once it hits 100, but also keep i and j running the whole time. I tried used 4 nested for loops but it did not work properly, although I'm starting to think that may be a solution, but that would be very inefficient.
Please let me know if this sounds a little confusing I will try my best to explain more clearly, thanks.
excuse the psuedocode
for (i=0; i < width; i++)
for (j=0; i< height; j++)
set(i, j , pixel(k,l));
The problem seems to be to tile an image onto another image. You have width and height for the target image's dimensions, so let's say sourceWidth and sourceHeight are the source image's dimensions (100 by 100, in your example).
To tile an image, you want k == i % sourceWidth and l == j % sourceHeight, so that the pixel you read from the source image "wraps around" the boundaries. These should be invariant conditions. The simplest way to satisfy them is to declare them that way directly:
for(int i = 0; i < width; ++i) {
int k = i % sourceWidth;
for(int j = 0; j < height; ++j) {
int l = j % sourceHeight;
set(i, j, pixel(k, l));
}
}
This does a lot of % operations, which could be quite inefficient, but it gives us a correct piece of code to transform. If we are incrementing k and l, then there are two properties needed to maintain the invariants:
k and i are incremented in unison; and l and j are incremented in unison.
When k reaches sourceWidth it must wrap back to 0, likewise for l and sourceHeight.
for(int i = 0, k = 0; i < width; ++i, ++k) {
if(k == sourceWidth) { k = 0; }
for(int j = 0, l = 0; j < height; ++j, ++l) {
if(l == sourceHeight) { l = 0; }
set(i, j, pixel(k, l));
}
}
Note that the for loop initialiser and stepper now declare and update two variables, for both loops. This is allowed in Java.
This is likely to be faster than doing a lot of % operations, but note that branching with if statements can also slow down an algorithm, so you may want to benchmark it to be sure.
In the special case where source image's dimensions are powers of two, we can achieve the same result with a fast bitwise operation: i % sourceWidth will be equivalent to i & (sourceWidth - 1):
// special case: sourceWidth and sourceHeight are powers of 2
int wMask = sourceWidth - 1, hMask = sourceHeight - 1;
for(int i = 0, k = 0; i < width; ++i, ++k) {
for(int j = 0, l = 0; j < height; ++j, ++l) {
set(i, j, pixel(i & wMask, j & hMask));
}
}
It could be done by something like this:
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
if(k > 100) {
k = 0;
}
if(l > 100) {
l = 0;
}
k++;
l++;
set(i, j , pixel(k,l));
}
}
I've taken this piece of code out of my bigger project, basically I want to pick a random point within the array and remember that it's been picked (by setting its value to 1) and repeat it till the whole array is filled.
What's wrong with this code? Why doesn't it fill every single field?
//initialize
int arraysizex = 5;
int arraysizey = 5;
int x = 0, y = 0;
int filledcount = 0;
int[][] array = new int[arraysizex][arraysizey];
//fill
for (int i = 0; i < arraysizex * arraysizey; i++) {
do {
x = (int) (Math.random() * arraysizex);
y = (int) (Math.random() * arraysizey);
if (array[x][y] == 0) {
array[x][y] = 1;
//do something
}
} while (array[x][y] == 0);
}
//display
for (int i = 0; i < arraysizey; i++) {
System.out.println();
for (int j = 0; j < arraysizex; j++) {
System.out.print(array[j][i]);
if (array[j][i] == 1) {
filledcount++;
}
}
}
System.out.print("\n" + filledcount+"\n");
In the 'worst case', if it picked x = 0, y = 0 every time, your code would apply the operation to only that pixel. It'd then try arraysizex * arraysizey times but skip due to the check for being zero.
Try
int i = 0;
while(i < arraysizex * arraysizey) {
x = (int) (Math.random() * arraysizex);
y = (int) (Math.random() * arraysizey);
if (array[x][y] == 0) {
array[x][y] = 1;
i++;
//do something
}
}
This guarantees that you did the operation arraysizex * arraysizey times, as it only increments when you do the operation
I need a simple java program that can generate me the custom sets for a set,say for {'1','2','3','4'}. The result should be:
{'1','2'},{'2','3'},{'3','4'},{'1','2','3'},{'2','3','4'}.
I have tried codes for powerset,but the output isn't desirable. It would be appreciable if the code could be something like:
for(j=2;j<set.size()-1;j++)
{
for(i=0;i<set.size()-1;i++)
{
//a[i],a[i+1] when j=2
//a[i],a[i+1],a[i+2] when j=3
}
}
I know .size() is for ArrayList and a[i] is for simple array and i've written both as any approach will do!! Thanks In Advance!! :)
This code should print the values you want:
final int[] values = {1, 2, 3, 4};
for (int size = 2; size < values.length; size++) {
for (int i = 0; i + size <= values.length; i++) {
for (int j = 0; j <= size - 1; j++) {
System.out.print(values[i + j]);
}
System.out.println();
}
}
From the example, we see that you want to print sets of values whose length is greater than 1 and smaller than the total set, so that 's what the following line does:
for (int size = 2; size < values.length; size++) {
After that we compute the starting index of the subset, watching not to run into a IndexArrayOutOfBounds exception (see the line below)
for (int i = 0; i + size <= values.length; i++) {
From there we just print the values starting at i index and with the subset length of size
for (int j = 0; j <= size - 1; j++)
This is the sample code which is generating the desired result:
int[] array = { 1, 2, 3, 4 };
int size = 2;
for (int j = 0; j < array.length; j++) {
for (int i = 0; i <= array.length - size; i++) {
int[] temp = Arrays.copyOfRange(array, i, i + size);
for (int x : temp) {
System.out.print(x + ",");
}
System.out.println();
}
size++;
if (size == array.length) {
break;
}
}
Output:
1,2,
2,3,
3,4,
1,2,3,
2,3,4,
I need to try and duplicate and image, created by array(a), both vertically and horizontally to make a square full of the repeating image. So starting with 1 square image and I want to duplicate it 2 times horizontally and 2 times vertically it will create another image with 4 of the initial image, 2x2.
public static int[][] replicate(int[][] a) {
int[][] replicated = new int[a.length * 2][a[0].length * 2];
for (int r = 0; r < 2; r++) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
replicated[i][j + r * a[i].length] = a[i][j];
}
}
}
for (int r = 0; r < 2; r++) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
replicated[i + r * a.length][j] = a[i][j];
}
}
}
return replicated;
}
This gets them across the horizontal for 1 line, and vertical for 1 line but does not fully fill in. So if I ran this I would be missing the bottom right of the 4 images. I'm having trouble putting them together.
public static int[][] replicate(int[][] image) {
int[][] replicated = new int[a.length * 2][];
for (int y=0; y<image.length; y++) {
int[] column = image[y];
replicated[y] = new int[column.length * 2];
replicated[y + image.length] = new int[column.length * 2];
System.arraycopy(column, 0, replicated[y], 0, column.length);
System.arraycopy(column, 0, replicated[y], column.length, column.length);
System.arraycopy(column, 0, replicated[y + image.length], 0, column.length);
System.arraycopy(column, 0, replicated[y + image.length], column.length, column.length);
}
return replicated;
}
There might be some problems with this code since I wrote it not in front of a compiler, but I think it gets the point across.
Also, if this is for painting the image, you should consider using a TexturePaint instead.
I am trying to create a nested loop which will allow me to display something a particular amount of times, but the problem is that it is only placing one element and not the others. How do I set the coordinates for that?
int rows, cols;
rows = 7;
cols = 6;
for (int i=0; i <rows; i++); {
for (int j=0; j< cols; j++);
}
Maybe because you hardcoded the circle position and it is therefore the same for all circles?
canvas.drawCircle(80, 155, 40, white);
what about calculating the position?
int x = i * radius + 10; // or whatever you wanna calculate here...
int y = j * radius + 10;
canvas.drawCircle(x, y, 40, white);
Make sure you're updating the circle coordinates on each loop cycle! Right now they are hardcoded. This may help:
int rows, cols;
rows = 7;
cols = 6;
for (int i=0; i <rows; i++); {
for (int j=0; j< cols; j++) {
canvas.drawCircle(80 + (80*i), 155 + (155*j), 40, white);
}
}
I just used the same values for x and y as the offsets, although you may want to play around with them(80 and 155) to find the look you're going for.
Your for loop doesen't change the position of the circle since you only say to draw it on 80 and 155
try something like this
int rows, cols;
rows = 7;
cols = 6;
//initial x and y positions
float initialX =80;
float initialY =155;
int radius = 40;
for (int i=0; i <rows; i++); {
//you need to reset it for each circle
float drawX = initialX;
for (int j=0; j< cols; j++){
canvas.drawCircle(initialX, initialY, radius, white);
//where 10 will be the little space you want between circles
drawX+=radius*2+10;
}
initialY+=radius*2+10;
}