Getting values of Grid's individual nodes (JAVA) - java

I want to create a program that can simulate the influence of a social structure of a matrix / grid. It's like an Erdos Renyi structure, but an nxn matrix where each node initially has a random value of +1 or -1. Each node has 4 neighbors (top, bottom, left, right) which also has values of +1 or -1. Thus, I can find the neighborhood of each node, which should be just a list / vector of the 4 values of those neighbors. The value of each node is then influenced by the neighbors' values, and the grid's values keep simulating and changing until an equilibrium is reached.
So far, I have a code which can create a grid with random -1 or +1 variables. Now, I am not sure how to get the values of each node (and its neighbors) inside the main method. I am a little confused as to how to go about this project so far, as in how to get the values.
In the main method, I cannot do like... int x = grid[0][1] etc. Sorry that I'm rusty in Java, but what topics can I look up in finding out the procedure to do this? I can't remember what it's called.
Also, is there a way that I can edit what each button (or node) on the grid says in the main method? Like, I can change it while it's looping, and I can also write what the values of its neighbors are? Thanks!
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.GridLayout;
public class Grid {
JFrame frame = new JFrame(); // create frame
static JButton[][] grid;
// constructor
public Grid (int w, int l) {
frame.setLayout(new GridLayout(w, l));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
// create grid
grid = new JButton[w][l];
for (int y = 0; y < l; y++) {
int value = 0;
for (int x = 0; x < w; x++) {
// probability p
double p = 0.5;
// randomly allocate opinion
double random = Math.random();
if (random <= p)
value = -1;
else if (random > p)
value = 1;
grid[x][y] = new JButton("" + value);
frame.add(grid[x][y]);
}
}
}
public static void main (String[] args) {
// DIMENSION
// int d = 2;
// LENGTH
int l = 2;
// WIDTH
int w = 2;
new Grid(l,w); // create new Grid with parameters
}
}

I changed your approach a little bit, so it is more object-oriented. I hope this example makes clear, what you have to do. To get an basic understanding, google keywords like "encapsulation" or "object-orientation". There are many tutorials out there.
public class Grid {
private JFrame frame = new JFrame();
private JButton[][] grid; // Has to be a field of the object. static would make it to an field of the class
public Grid (int w, int l) {
frame.setLayout(new GridLayout(w, l));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
createGrid (w, l);
}
private void createGrid (int w, int l) {
// Your above implementation
}
public void stepInSimulation () {
// Your algorithm, you want to implement
}
public JButton[][] getGrid () {
return grid;
}
public static void main (String[] args) {
Grid grid = new Grid(2,2);
grid.getGrid ()[0][1]; // Access a value
grid.stepInSimulation (); // Do a step, call it in while loop, to do multiple steps
}
}
I hope this helps.

Related

How can I completely fill new drawn shapes over old shapes

I am trying to write a program in Java that draws trees filling the screen. I have variables set to randomly place a tree on the x-axis and move down 10 steps each time. The problem I am encountering is when the new trees are drawn they overlap the old trees so the fill does not fill the tree. So my question is how can I fully fill a drawn shape filling over what is underneath. I have tried messing with the color I'm using but I just don't know what to do. I am brand new to Java but I have a fair bit of experience in Javascript.
Here is my code so far:
public class Turtle extends TurtleGraphicsWindow
{
public Turtle()
{
super(650, 550);
}
static void PrintTree() {
Turtle t = new Turtle();
t.speed(100);
for (int i = 0; i < 30; i++) { //to move the trees down
//randomizer
int min = -300;
int max = 300;
int random_int = (int)Math.floor(Math.random()*(max-min+1)+min);
var tWx = random_int;
int tWy = -10*i+150;
//trunk
t.pu();
t.setpensize(3);
t.setxy( (tWx-25) , (tWy-100) );
t.setpc(8); //brown
t.pd();
t.fd(50);
t.setx(t.xcor()+50);
t.bk(50);
t.setx(t.xcor()-50);
t.pu();
t.setxy(t.xcor()+5,t.ycor()+5);
t.setpc(9); //tan
t.fill();
//tree
t.setxy((tWx+100),(tWy-50));
t.setpencolor(31);
t.pd();
var tx = 50;
t.setx(t.xcor()-200);
t.setxy(t.xcor()+tx,t.ycor()+(tx+10));
t.setx(t.xcor()-(tx-15));
t.setxy(t.xcor()+(tx-5),t.ycor()+(tx+5));
t.setx(t.xcor()-(tx-20));
t.setxy(t.xcor()+(tx-10),t.ycor()+(tx));
t.setx(t.xcor()-(tx-30));
t.setxy(t.xcor()+(tx-15),t.ycor()+(tx-5));
t.setx(t.xcor()-(tx-35));
t.setxy(t.xcor()+(tx-20),t.ycor()+(tx-10));
//right side of tree
t.setxy(t.xcor()+(tx-20),t.ycor()-(tx-10));
t.setx(t.xcor()-(tx-35));
t.setxy(t.xcor()+(tx-15),t.ycor()-(tx-5));
t.setx(t.xcor()-(tx-30));
t.setxy(t.xcor()+(tx-10),t.ycor()-(tx));
t.setx(t.xcor()-(tx-20));
t.setxy(t.xcor()+(tx-5),t.ycor()-(tx+5));
t.setx(t.xcor()-(tx-15));
t.setxy(t.xcor()+tx,t.ycor()-(tx+10));
t.pu();
t.setpc(FOREST);
t.setxy(t.xcor()-10,t.ycor()+5);
t.fill();
}
}
public static void main(String[] args)
{
PrintTree();
}
}
This is what it has been looking like now:
https://i.stack.imgur.com/ipwhN.png

How to Randomize Placement of a JLabel on a GridLayout of JButtons?

I am trying to make a chessboard, that will randomize the place of its pieces throughout the board.
Below is what I have so far
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class ChessBoard extends JFrame {
JLayeredPane layeredpane;
JPanel chessboard;
JButton[][] chessboardButtons;
Color black;
JLabel [][] chessboardLabels;
UIManager Ui;
ChessBoard() {
Dimension Size = new Dimension(600, 600);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
pack();
setResizable(true);
setLocationRelativeTo(null);
setVisible(true);
setSize(600, 600);
setTitle("Chess Board");
layeredpane = new JLayeredPane();
getContentPane().add(layeredpane);
layeredpane.setPreferredSize(Size);
chessboard = new JPanel();
layeredpane.add(chessboard, JLayeredPane.DEFAULT_LAYER);
chessboard.setLayout(new GridLayout(8, 8));
chessboard.setPreferredSize(Size);
chessboard.setBounds(0, 0, Size.width, Size.height);
Ui = new UIManager();
chessboardButtons = new JButton[8][8];
black = Color.black;
ButtonHandler handler = new ButtonHandler();
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
chessboardButtons[i][j] = new JButton();
chessboardButtons[i][j].setBorderPainted(false);
if ((i + j) % 2 != 0) {
chessboardButtons[i][j].setBackground(black);
chessboardButtons[i][j].setOpaque(true);
}
chessboard.add(chessboardButtons[i][j]);
chessboardButtons[i][j].addActionListener(handler);
}
}
chessboardLabels = new JLabel[8][8];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
chessboardLabels[i][j] = new JLabel();
chessboardLabels[i][j].setFont(new Font("Ariel", Font.BOLD, 20));
chessboardLabels[i][j].setText("H");
chessboardLabels[i][j].setHorizontalAlignment(JLabel.CENTER);
chessboardLabels[i][j].setVerticalAlignment(JLabel.CENTER);
chessboardLabels[i][j].setOpaque(true);
chessboardButtons[i][j].add(chessboardLabels[i][j]);
if(chessboardButtons[i][j].getBackground() == Color.black) {
chessboardLabels[i][j].setBackground(Color.black);
chessboardLabels[i][j].setForeground(Color.white);
}
}
}
}
private class ButtonHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == chessboardButtons[0][0]) {
System.out.println("Button 0,0");
}
if (e.getSource() == chessboardButtons[0][1]) {
System.out.println("Button 0,1");
}
}
}
}
Right now I have the letter H filling all my buttons. What I need it to do is to:
limit the number of "H"'s there are on the board to be 32, 16 "White" and 16 "black" and
randomize the placement throughout the board.
Any ideas will be helpful!
I tried exactly this years ago, and I ran into several problems. One of the biggest is that dragging a piece from one square (JComponent) to another hard to do, because each JComponent has its bounds, and its Graphics clipping prevents you from drawing outside of these bounds. There are workarounds, like adding an Image to a higher level in the JLayeredPane, but this is still very hard to get right.
You really want to make you GUI a custom JComponent/JPanel that draws the whole board and can get mouse events across the whole board.
But before that, the right place to start is by creating a ChessModel that encapsulates the logic of the game. If you do that first and test it thoroughly, adding a GUI on top of that is easier than the other way around.
public class ChessModel {
char[][] board = new char[8][8];
...
public Point[] getPossibleMoves(Point pieceLocation) {
...
}
}
Create an ArrayList with 64 Integers numbered from 0 - 63
Use Collections.shuffle(...) to shuffle the numbers randomly
Take the first 16 values from the ArrayList and add white pieces to the board based on the integer value.
Take the next 16 values from the ArrayList and add the black pieces to the board.
First, I would start by decoupling parts of the system, this will provide you with a lot more flexibility.
For example, you want to decouple the "visual" from the "virtual". Components aren't managed in a "grid", instead, they are maintained in a list, so, you want some way you can quickly and easily ascertain the location of various components on the screen and how the relate to the "virtual" concept of the game or grid.
This is at the core concept of "model-view-controller", where the model represents a "grid" of "pieces" and the view is used to visually represent the model to the user. So you end up with a little bit of translation going on.
Now, you can do something like...
int row = (value / 8);
int col = (value % 8);
which, given a component index, will give you the row/col that they represent, but I'm also lazy 😉, so, I'm going to isolate the concept of a Piece...
public class Piece extends JPanel {
private JLabel label;
private Point cell;
public Piece(int index) {
setLayout(new GridBagLayout());
label = new JLabel(Integer.toString(index));
label.setForeground(Color.RED);
add(label);
setOpaque(false);
}
public void setCell(Point cell) {
this.cell = cell;
}
public Point getCell() {
return cell;
}
}
This does several things for me, first, it gives me a simple building block which can be used to represent a piece of data as well as maintain the "virtual" position of the piece, so I can easily look it up, independently.
It also divorces the piece from the board, which will make it easier to maintain (IMHO).
Next, I build the board...
setLayout(new GridLayout(8, 8));
int index = 0;
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
JPanel panel = new JPanel(new GridBagLayout()) {
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
};
// Indexed via x/y
cells[col][row] = panel;
if (index % 2 == 0) {
panel.setBackground(Color.WHITE);
} else {
panel.setBackground(Color.BLACK);
}
add(panel);
index++;
}
index++;
}
There's nothing really fancy here, it's just GridLayout with a bunch of color panels laid out on it.
The "fancy" part is the idea that, instead of using something complicated, like JLayeredPane, I'm simply going to add the Pieces directly to each cell.
Which leads us to the heart of the problem, how to randomise the position of the cells. Essentially, I'm going to create a list of numbers from 0 to 63 inclusive, randomise the list and then pop each number of off the list till I'm done.
Now, you could use an array, but filling an array with random numbers is not a simple task (especially if you want to guarantee uniqueness 😉)
// Fill a list of numbers
int totalCells = 8 * 8;
List<Integer> locations = new ArrayList<>(totalCells);
for (int value = 0; value < totalCells; value++) {
locations.add(value);
}
// Randomise the list
Collections.shuffle(locations);
// For al the white pieces, randomise their positions
for (index = 0; index < 16; index++) {
int value = locations.remove(0);
// Virtual coordinates
int row = (value / 8);
int col = (value % 8);
Point cell = new Point(col, row);
Piece piece = new Piece(index);
whitePieces[index] = piece;
piece.setCell(cell);
// Get the component offset by the value (physical)
JPanel cellPane = (JPanel) getComponent(value);
cellPane.add(piece);
}
// Now you can continue with the black pieces, just like above
// and because you've removed the "used" cell indexes from the
// list, you won't end up with duplicate positions
Now you're probably scratching your head over all this. But simply put, when you want to move a "piece", you simply remove it from it's current parent container, calculate the position ((row * 8) + col), get the new parent component (like above) and add it, simple.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Test extends JFrame {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JPanel[][] cells = new JPanel[8][8];
private Piece[] whitePieces = new Piece[16];
public TestPane() {
setLayout(new GridLayout(8, 8));
int index = 0;
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
JPanel panel = new JPanel(new GridBagLayout()) {
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
};
// Indexed via x/y
cells[col][row] = panel;
if (index % 2 == 0) {
panel.setBackground(Color.WHITE);
} else {
panel.setBackground(Color.BLACK);
}
add(panel);
index++;
}
index++;
}
int totalCells = 8 * 8;
List<Integer> locations = new ArrayList<>(totalCells);
for (int value = 0; value < totalCells; value++) {
locations.add(value);
}
Collections.shuffle(locations);
for (index = 0; index < 16; index++) {
int value = locations.remove(0);
int row = (value / 8);
int col = (value % 8);
Point cell = new Point(col, row);
Piece piece = new Piece(index);
whitePieces[index] = piece;
piece.setCell(cell);
JPanel cellPane = (JPanel) getComponent(value);
cellPane.add(piece);
}
}
}
public class Piece extends JPanel {
private JLabel label;
private Point cell;
public Piece(int index) {
setLayout(new GridBagLayout());
label = new JLabel(Integer.toString(index));
label.setForeground(Color.RED);
add(label);
setOpaque(false);
}
public void setCell(Point cell) {
this.cell = cell;
}
public Point getCell() {
return cell;
}
}
}
Oh, and just in case it's important, you can make use of component based drag-n-drop as well
How to make draggable components with ImageIcon
JLayeredPanel layout manager free moving objects
But, needs drives wants 😉

Java drawing to JPanel Graphics, using byte array, blinking white

So I am trying to update a JPanel using a byte array with a specified byte/color
This is a very simple version.
When I start the program it's white for half a second, then becomes the right color, and then after 1 second it's going back to being white, I tried to print out the current color, and sometimes it's changing to '0'.
What am I doing wrong?
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static Random ran = new Random();
public static byte[] buffer;
public static int num = 0;
public static JFrame frame = new JFrame();
public static JPanel panel = new JPanel() {
private static final long serialVersionUID = 1L;
#Override
public void paint(Graphics g) {
num = 0;
byte[] current_buffer = buffer.clone();
for (int y = 0; y < panel.getHeight(); y++) {
for (int x = 0; x < panel.getWidth(); x++) {
g.setColor(new Color(current_buffer[num], current_buffer[num], current_buffer[num]));
g.fillRect(x, y, 1, 1);
num++;
}
}
}
};
public static void main(String[] args) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1200, 800);
frame.setLocationRelativeTo(null);
frame.setContentPane(panel);
frame.setResizable(false);
frame.setVisible(true);
engine.run();
}
public static boolean running = true;
public static Thread engine = new Thread() {
#Override
public void run() {
buffer = new byte[panel.getWidth() * panel.getHeight()];
for (int i = 0; i < buffer.length; i++) {
buffer[i] = (byte) 34;
}
while (running) {
panel.repaint(10L);
}
}
};
}
Not really understanding your logic:
for (int i = 0; i < buffer.length; i++) {
buffer[i] = (byte) 34;
}
You assign the same value to the buffer.
Then you create a Color object using the same value.
g.setColor(new Color(current_buffer[num], current_buffer[num], current_buffer[num]));
So every pixel will be the same Color.
And since the buffer is always built with the same values, the color won't change.
Also, why would you use
byte[] current_buffer = buffer.clone();
You are just using the values in the buffer, not updating the values in the buffer so I see no reason for the clone.
Don't use a Thread with a while loop. For animation you should be using a Swing Timer. When the Timer fires you update the values in the buffer and then invoke repaint().
When I start the program it's white for half a second, then becomes the right color, and then after 1 second it's going back to being white,
I don't see that behaviour.
it blinks a light color
it stays painted at a darker color
The above makes sense because:
Your paintCompnent() method does not invoke super.paintComponent(...) to make sure the background is cleared
The array is not initialized to any values when it is created so the default value will be 0.
After the Thread takes over the array will alway contain the same value so the same color will be painted.
What do you expect it to do?

Why doesn't my GUI show squares after repaint()? [duplicate]

I posted this question a bit earlier and was told to make it SSCCE so here goes (if I can make any improvements feel free to let me know):
I'm wondering why when my button "confirm" is clicked the old squares disappear and the redrawn squares do not appear on my GUI (made with swing). The Squares class draws 200 spaced out squares with an ID (0, 1, 2, or 3 as String) inside obtained from a different class (for the purpose of this question, let's assume it is always 0 and not include that class). For clarification: Squares draws everything perfectly the first time (also retrieves the correct IDs), but I want it to redraw everything once the button is clicked with new IDs.
Code for Squares:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
public class Squares extends JPanel{
private ArrayList<Rectangle> squares = new ArrayList<Rectangle>();
private String stringID = "0";
public void addSquare(int x, int y, int width, int height, int ID) {
Rectangle rect = new Rectangle(x, y, width, height);
squares.add(rect);
stringID = Integer.toString(ID);
if(ID == 0){
stringID = "";
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontMetrics fm = g2.getFontMetrics();
int fontAscent = fm.getAscent();
g2.setClip(new Rectangle(0,0,Integer.MAX_VALUE,Integer.MAX_VALUE));
for (Rectangle rect : squares) {
g2.drawString(stringID, rect.x + 7, rect.y + 2 + fontAscent);
g2.draw(rect);
}
}
}
Code for GUI:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUIReserver extends JFrame implements Runnable{
private int myID;
private JButton confirm = new JButton("Check Availability and Confirm Reservation");
private JFrame GUI = new JFrame();
private Squares square;
public GUIReserver(int i) {
this.myID = i;
}
#Override
public void run() {
int rows = 50;
int seatsInRow = 4;
confirm.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
GUI.getContentPane().remove(square);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this does not show up at all (could be that it wasn't drawn, could be that it is out of view etc...)
GUI.repaint(); //the line in question
}
});
GUI.setLayout(new FlowLayout());
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setLocation(0,0);
GUI.setExtendedState(JFrame.MAXIMIZED_BOTH);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this shows up the way I wish
GUI.add(confirm);
GUI.pack();
GUI.setVisible(true);
}
}
Code for main:
public class AircraftSeatReservation {
static AircraftSeatReservation me = new AircraftSeatReservation();
private final int rows = 50;
private final int seatsInRow = 4;
private int seatsAvailable = rows * seatsInRow;
private Thread t3;
public static void main(String[] args) {
GUIReserver GR1 = new GUIReserver(3);
me.t3 = new Thread(GR1);
me.t3.start();
}
}
One major problem: Your Squares JPanels preferred size is only 20 by 20, and will likely actually be that size since it seems to be added to a FlowLayout-using container. Next you seem to be drawing at locations that are well beyond the bounds of this component, and so the drawings likely will never be seen. Consider allowing your Squares objects to be larger, and make sure to only draw within the bounds of this component.
Note also there is code that doesn't make sense, including:
private int myID;
private JTextField row, column, instru draft saved // ???
package question2;ction1, instruction2, seatLabel, rowLabel; // ???
I'm guessing that it's
private int myID;
private JTextField row, column, instruction1, instruction2, seatLabel, rowLabel;
And this won't compile for us:
int rows = AircraftSeatReservation.getRows();
int seatsInRow = AircraftSeatReservation.getSeatsInRow(); // and shouldn't this take an int row parameter?
since we don't have your AircraftSeatReservation class (hopefully you don't really have static methods in that class).
And we can't compile or run your current code. We don't want to see your whole program, but rather you should condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem. So as Andrew Thompson recommends, for better help, please create and post your Minimal, Complete, and Verifiable example or Short, Self Contained, Correct Example.
I would try to OOP-ify your problem as much as possible, to allow you to divide and conquer. This could involve:
Creating a SeatClass enum, one with possibly two elements, FIRST and COACH.
Creating a non-GUI Seat class, one with several fields including possibly: int row, char seat ( such as A, B, C, D, E, F), a SeatClass field to see if it is a first class seat or coach, and a boolean reserved field that is only true if the seat is reserved.
This class would also have a getId() method that returns a String concatenation of the row number and the seat char.
Creating a non-GUI Airplane class, one that holds two arrays of Seats, one for SeatClass.FIRST or first-class seats, and one for SeatClass.COACH.
It would also have a row count field and a seat count (column count) field.
After creating all these, then work on your GUI classes.
I'd create a GUI class for Seats, perhaps GuiSeat, have it contain a Seat object, perhaps have it extend JPanel, allow it to display its own id String that it gets from its contained Seat object, have it override getBackground(...) so that it's color will depend on whether the seat is reserved or not.
etc.....

Java: Writing a program that calculates midpoints based on randomly picking 2 out of 3 verticies

What I want to do is start with three points that make an equilateral triangle. My code should pick two of the three points at random, calculate a midpoint (m), and plot it. Then from the midpoint m it generated, the code will pick another one of the three original points at random and compute a new midpoint (m2). The last step should be repeated 10,000 times.
I'm just starting out with Java and am really lost. My biggest problem is that I don't know how to pick a point at random, and I also don't know how to go from taking the midpoint of two of the original points to taking the midpoint of the old midpoint and an original point. This is the code I have so far (please feel free to point out any mistakes I made in the code I have!):
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Dimension;
public class Game
{
static final int HEIGHT = 500;
static final int WIDTH = 500;
public static void main(String[] args)
{
JFrame frame = new JFrame("The Game");
Board board = new Board(WIDTH, HEIGHT);
Point p1 = new Point(0,0);
Point p2 = new Point(500, 0);
Point p3 = new Point(0, 250);
frame.setSize(WIDTH, HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(board);
board.addPoint(p1);
board.addPoint(p2);
board.addPoint(p3);
frame.pack();
frame.setVisible(true);
}
}
class Board extends JPanel
{
public Board(int h, int w)
{
setPreferredSize(new Dimension(w, h));
}
public void addPoint(Point p)
{
points.add(p);
}
public void paint(Graphics g)
{
super.paint(g);
int i = 0;
while (i < 10000)
{
board.add();
i++;
}
}
}
class Point
{
int x;
int y;
public Point(int x, int y)
{
x = this.x;
y = this.y;
}
private static Point midPoint(Point p1, Point p2)
{
return new Point((p1.x + p2.x)/2, (p1.y + p2.y)/2);
}
public double getX()
{
return x;
}
public double getY()
{
return y;
}
}
Split the problem. First, generate the 100000 points using your algorithm and add them to a list.
If you have a list of 3 points, and you want to pick two at random,
then Collections.shuffle() the list and pick the two first.
In the paint method, simply iterate the list and plot the points. No need to rebuild the list.
(Yes, you can do everything in the paint method and save some memory, but I think it's good for you to sort out your thoughts a little :-)
Edit:
Btw, the triangle in your example isn't equilateral.
To pick one of three points, first pick a random number from 0 to 1 (using Math.random()). If the number is smaller than 1/3 take the first point, if it is between 1/3 and 2/3 take the second one, otherwise take the third point. Example:
double r = Math.random();
if ( r < 1.0/3) {
// Chose first point
} else if (r < 2.0/3) {
// Choose second point
} else {
// Choose third point
}

Categories