I am trying to make a simple version of Conway's Game of Life where the computer generates a grid of rectangles and fills in the rectangles that represent "live" cells. The problem I am having is that I cannot get the grid to clear after the first pattern, so all the patterns are generated on the same grid and it looks like a big blob of colored rectangles.
Here is my code:
public class GameofLife {
static JPanel panel;
static JFrame frame;
public static void main(String[] args) throws InterruptedException{
int [][] array = new int [17][17];
/*
* Set the pattern for Conway's Game of Life by manipulating the array below.
*/
array[2][4]=1;
array[2][5]=1;
array[2][6]=1;
panel = new JPanel();
Dimension dim = new Dimension(400,400);
panel.setPreferredSize(dim);
frame = new JFrame();
frame.setSize(1000, 500);
Container contentPane = frame.getContentPane();
contentPane.add(panel);
frame.setVisible(true);
/*
* Runs the Game of Life simulation "a" number of times.
*/
int [][] end = new int [array.length][array[0].length];
int a=0;
while(a<4){
for(int i=1; i<=array.length-2; i++)
{
for(int j=1; j<=array[0].length-2; j++)
{
int counter = surround(array,i,j);
if(array[i][j]==1 && counter<=2)
{
end[i][j]=0;
}
if(array[i][j]==1 && counter==3)
{
end[i][j]=1;
}
if(array[i][j]==1 && counter>4)
{
end[i][j]=0;
}
if(array[i][j]==0 && counter==3)
{
end[i][j]=1;
}
if(array[i][j]==1 && counter==4)
{
end[i][j]=1;
}
}
}
Graphics g = panel.getGraphics();
Graphics(array,g);
a++;
for(int i=0; i<array.length; i++)
{
for(int j=0; j<array[0].length; j++)
{
array[i][j]=end[i][j];
end[i][j]=0;
}
}
Thread.sleep(1000);
g.dispose();
}
}
public static int surround(int[][] initial, int i, int j){
int[][] surrounding = {{initial[i-1][j-1],initial[i-1][j],initial[i-1][j+1]},
{initial[i][j-1],initial[i][j],initial[i][j+1]},
{initial[i+1][j-1],initial[i+1][j],initial[i+1][j+1]}};
int counter = 0;
for(int a=0; a<=2; a++)
{
for(int b=0; b<=2; b++)
{
if(surrounding[a][b]==1)
{
counter ++;
}
}
}
return counter;
}
public static void Graphics(int[][] array, Graphics g)
{
int BOX_DIM=10;
for(int i=0; i<array.length; i++)
{
for(int j=0; j<array[0].length; j++)
{
g.drawRect(i*BOX_DIM, j*BOX_DIM, 10,10);
g.setColor(Color.BLACK);
if(array[i][j]==1)
{
g.fillRect(i*BOX_DIM, j*BOX_DIM, 10, 10);
}
}
}
}
}
Any help is much appreciated!
You need to draw rectangles for both "alive" and "dead" cells but color them differently. Live cells could be black and dead cells white but if you don't redraw every cell during every iteration you'll run into the issue you've described. That being said...you seem to have answered your own question.
You COULD fix this immediate concern by clearing grid at the top of the Graphics() function:
g.setColor(Color.??); // Choose desired background color here
g.fillRect( 0, 0, array.length * BOX_DIM, array[0].length * BOX_DIM);
BUT, consider that your approach is fighting against the natural way of handling graphics in Java. Any time your window gets clipped, it may not repaint in a timely manner.
You might want to consider sub-classing JPanel and overriding its onPaint() method, then invalidating the panel whenever the data model changes.
Related
I have to randomly generate a cityscape with 3 layered functions in processing. I'm doing so by drawing each floor in a loop that runs until a random integer, and doing the same thing with floors per building. Currently, the floors are initially randomly generated, but then they eventually fill out to the maximum of the random function. How do I get it so they stay random? Thanks, code is below.
int boxX = 0;
int boxY = 479;
void setup() {
size(1000, 500);
background(255);
frameRate(10);
}
void draw() {
for (int i = 0; i < 8; i++) {
building(boxX, boxY);
translate(150, 0);
}
}
void room(int boxX, int boxY) {
rect(boxX, boxY, 20, 20);
}
void floor(int boxX, int boxY) {
int randomNum = (int)random(3, 5);
for (int i=0; i<= randomNum; i++) {
room(boxX, boxY);
boxX += 20;
}
}
void building(int boxX, int boxY) {
int randomNum = int(random(10, 20));
for (int i = 0; i < randomNum; i++) {
floor(boxX, boxY);
boxY -= 20;
}
}
The problem is that you're generating a random cityscape every single frame, but you're never clearing out old frames. That means that your new frames are just drawn right on top of your old frames.
To better see what I'm talking about, clear out the old frames by adding a call to background() as the first line in your draw() function:
void draw() {
background(200);
for (int i = 0; i < 8; i++) {
building(boxX, boxY);
translate(150, 0);
}
}
You need to take a step back and ask yourself exactly what you want to happen. Do you want to generate a new cityscape every frame? If so leave the call to background() in. Do you just want to generate a single cityscape? If so then call noLoop() to prevent the draw() function from being called more than once, or store your cityscape in a data structure that you redraw every frame instead of regenerating.
I've been doing a CrossWord puzzle in java for a project. However I haven't been able to fix one problem I'm having with drawing the CrossWord into a JPanel
The program takes the data from a 2D array of chars and generates a grid of a custom type of JLabels with it. This is the code:
public void update(Observable o, Object o1) {
if(model.getMatrix() != null){
configurePanel(model.getRows(), model.getCols());
this.add(panel);
this.pack();
this.revalidate();
this.repaint();
}
}
private void configurePanel(int w, int h) {
if (panel!=null){
this.remove(panel);
}
panel = new JPanel();
panel.setBounds(40, 40, w*50, h*50);
panel.setLayout(new GridLayout(w, h));
labels = createLabels(model.getMatrix());
for (int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
panel.add(labels[i][j]);
}
}
}
private CWlabel[][] createLabels(char[][] matrix) {
int w = matrix.length;
int h = matrix[0].length;
labels = new CWlabel[w][h];
for (int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
char c = matrix[i][j];
labels[i][j] = new CWlabel();
labels[i][j].setBorder(BorderFactory.createLineBorder(Color.black));
labels[i][j].setOpaque(true);
if (c != ' '){
labels[i][j].setBackground(Color.white);
} else {
labels[i][j].setBackground(Color.black);
}
}
}
return labels;
}
My main problem is in configurePanel(), where the size of the panel are set proportional to the crossword dimensions, which should ensure every component inside it is perfectly square, however this is not the case as seen here
In the example shown the difference is subtle but still notizable. The strange part its that if I manually replace,
panel.setBounds(40, 40, w*50, h*50);
with,
panel.setBounds(40, 40, 400, 450);
the result appears to be proportional to the amount of rows and columns as shown here
By my count you have 9 rows and 8 columns so calling configurePanel like the following:
configurePanel(model.getRows(), model.getCols());
Is going to result in a width of 450 and a height of 400, but you want a width of 400 and a height of 450. Thus switch around the first and second parameters, like the following:
configurePanel(model.getCols(), model.getRows());
Note: You shouldn't use absolute positioning, it causes many formatting problems down the road (resizing components, adding components, etc.). You should instead use a layout manager with more customization like GridBagLayout or MigLayout.
I'm not really keen on Java GUI, but am learning as I go. I am in the process of making a very simple and basic Sudoku puzzle. Right now I am just on the basic layout of it.
I wanted to see if there was a simple way of adding a text field to each little rectangle that I have drawn out (81 total rectangles - 9x9 puzzle). So that a user can type something in there.
I am delving into it, but wanted to get the code up here to see if anyone had any tips, cause truth be told, I am mega lost with this.
Here is what I have so far...
import java.awt.*;
import javax.swing.*;
class MyCanvas extends JComponent {
public void paint(Graphics g) {
int coordinateX = 0;
int coordinateY = 0;
// maximum 9 rows
int rows = 9;
int columns = 1;
// make a 9x9 puzzle
while (columns <= rows) {
//for loop to increment the boxes
for (int j = 1; j <= rows; j++) {
// add and assign coordinte x... equivalent to x = x + 30
coordinateX += 30;
// where x and y determine start of the box and 30 determines the size
g.drawRect(coordinateX, coordinateY, 30, 30);
} //end of for loop
//reset the value of x to start a new row
coordinateX = 0;
coordinateY += 30;
columns++;
} //end of while loop
} //end of void paint
} //end of class
public class DrawRect {
public static void main(String[] a) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(100, 100, 500, 500);
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
} // end of void main
} // end of class
Hopefully someone has some pointers that could help me out, cause boy oh boy do I need it. Was kinda thrown into the lion's den without prior knowledge or practice, but I'm trying hard.
Thanks guys!!
You could use a GridLayout(9,9) and an array of arrays of JTextField's
This is, of course, just an example of how I would do it. There are other ways to do this.
Find below a generic example.
Solution
public static void main(String[] args) {
JTextField[][] boxes = new JTextField[9][9];
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(9,9));
frame.setSize(500, 500);
for (int i = 0 ; i < 9 ; i++){
for (int j = 0 ; j < 9 ; j++){
boxes[i][j] = new JTextField("0");
frame.add(boxes[i][j]);
}
}
frame.setVisible(true);
}
Output
So am working on a School Project, and I want to draw a game board made out of Rectangles which are saved in an array. I managed to do that, but only the last drawn Rectangle Stays on the Panel. I'm really desperate and i don't know where my mistake is.
The Field is a 4x5 field. The Coordinates saved in the Tile Class:
the first two represent the upper left Corner
the last two represent the bottom right corner of it
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class quoVadis{
public static void main(String[] args) {
new Frame();
}
}
class Tile {
Random rGen = new Random();
int sX,sY,eX,eY;
Color farbe;
public Tile(int sX, int sY,int eX,int eY){
this.sX = sX;
this.sY = sY;
this.eX = eX;
this.eY = eY;
farbe = new Color(rGen.nextInt(156)+100,rGen.nextInt(156)+100,rGen.nextInt(156)+100);
}
}
class Frame extends JFrame{
private Game game;
final int GAMESIZE = 400;
final int PANELSIZE = GAMESIZE/5;
public Frame() {
super("Quo Vadis");
this.setSize(GAMESIZE, GAMESIZE*5/4);
this.setLocation(50, 50);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game = new Game(GAMESIZE, PANELSIZE);
game.setLayout(null);
game.setBackground(Color.WHITE);
this.getContentPane().add(game);
this.setVisible(true);
}
}
class Game extends JPanel{
int GAMESIZE;
int PANELSIZE;
private Tile field[][]=new Tile[4][5];
Random rGen = new Random(4711);
Tile stein;
public Game(int g, int p) {
GAMESIZE = g;
PANELSIZE = p;
// The Mistake has to be in this following Part:
int idx=0;
for(Tile i:levels){
for(int j = i.sX; j <= i.eX; j++){
for(int k = i.sY; k <= i.eY; k++){
field[j][k] = levels[idx];
}
}
idx++;
}
for(int k = 0; k <= 4; k++){
for(int j = 0; j <= 3; j++){
if(field[j][k]==null)continue;
stein=field[j][k];
draw((field[j][k].sX * PANELSIZE) , (field[j][k].sY * PANELSIZE) , ((((field[j][k].eX-field[j][k].sX) + 1) * PANELSIZE) -1), ((((field[j][k].eY-field[j][k].sY)+ 1) * PANELSIZE) -1));
}
}
this.setVisible(true);
}
int rx, ry,rdx,rdy;
private void draw(int a, int b, int c, int d){
rx=a;
ry=b;
rdx=c;
rdy=d;
repaint(rx,ry,rdx,rdy);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(stein.farbe);
g.fillRect(rx, ry, rdx, rdy);
}
Tile[] levels = {
new Tile(1,0,2,1),
new Tile(0,0,0,1),
new Tile(3,0,3,1),
new Tile(0,2,0,3),
new Tile(1,2,2,2),
new Tile(3,2,3,3),
new Tile(0,4,0,4),
new Tile(1,3,1,3),
new Tile(2,3,2,3),
new Tile(3,4,3,4),
};
}
I already checked the Position of the Rectangles in numbers and they are correct in every way so they do not overlap or something like that.
Sorry for my bad english, it's not my primary language.
You need to draw each rectangle inside of your paintComponent method every time.
Currently you are calling your draw method for one rectangle then you call repaint and draw that single rectangle. paintComponent will redraw the entire panel each time it is called. This means that it will on preserve the last rectangle (the rest were "repainted over".
You want to loop through all of your tiles and use the drawRect method to draw them inside of your paintComponent method so they will be drawn every time.
public void paintComponent(Graphics g) {
super.paintComponent(g)
for(int k = 0; k <= 4; k++){
for(int j = 0; j <= 3; j++){
if(field[j][k]==null)continue;
stein=field[j][k];
g.setColor(stein.farbe);
g.fillRect((field[j][k].sX * PANELSIZE) , (field[j][k].sY * PANELSIZE) , ((((field[j][k].eX-field[j][k].sX) + 1) * PANELSIZE) -1), ((((field[j][k].eY-field[j][k].sY)+ 1) * PANELSIZE) -1));
}
}
}
This question already has answers here:
How to draw a filled circle in Java?
(2 answers)
Closed 9 years ago.
public static void board(){ //Create's my board
{
JFrame board = new JFrame();
board.setSize(400, 200 );
board.setTitle("Quiz Board Game");
Container pane = board.getContentPane();
pane.setLayout(new GridLayout(rows, columns));
Color temp;
for (int i = 0; i < rows; i++)
{
if (i%2 == 0)
{
temp = col1;
}
else
{
temp = col2;
}
for (int j = 0; j < columns; j++)
{
JPanel panel = new JPanel();
panel.setBackground(temp);
if (temp.equals(col1))
{
temp = col2;
}
else
{
temp = col1;
}
pane.add(panel);
}
}
board.setVisible(true);
I have this code written in java, I was wondering how i would add two circles so it would create a board with two pieces? Thanks.
P.S I'm new at java
override the paintComponent(Graphics g) method.
// create Image
Image i = new ImageIcon("//filepath").getImage();
int pointXForFirstPiece = 0; // update for the x position of where your piece will be
int pointYForFirstPiece = 0; // update for the y position
public void paintComponent(Graphics g) {
// do the painting for the two objects here
// paint image
// create another image object as done above, and then
// rewrite the line below for the second piece
g.drawImage(i, pointXForFirstPiece, pointYForFirstPiece, null);
}
hope this helps