Outline to blocks in XY Block renderer jfreechart - java

I am drawing a kind of heatmap using XYZ dataset and XY block renderer. The block's color is a function of the Z value and color is assigned using grayscale. i.e. the block with 0 Z value is assigned white color and one with maximum is assigned black color.
My grayscale goes from 0 to 100 (or more lets say). If the scale is this big, the blocks with count as 0 and 10 will have very little difference in color values. To understand, lets say the whole grid is divided in blocks. One block hasZ value of 100, one has 2 and all others are 0. Then, this block with 2 as Z value is not much visible because of very light shade.
I want to give outline to blocks of some color so that they are distinguishable. I tried with setBaseItemOutline() etc functions but none does this.
Any help on this?
Edit: Below
One of my classes is this:
public class BlockRenderer extends ApplicationFrame {
/**
* Constructs the demo application.
*
* #param title the frame title.
*/
public BlockRenderer(String title) {
super(title);
JPanel chartPanel = createDemoPanel();
//chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
/**
* Creates a chart for the specified dataset.
*
* #param dataset the dataset.
*
* #return A chart instance.
*/
private static JFreeChart createChart(XYZDataset dataset) {
NumberAxis xAxis = new NumberAxis("X");
xAxis.setLowerMargin(0.0);
xAxis.setUpperMargin(0.0);
NumberAxis yAxis = new NumberAxis("Y");
yAxis.setAutoRangeIncludesZero(false);
yAxis.setInverted(true);
yAxis.setLowerMargin(0.0);
yAxis.setUpperMargin(0.0);
yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
XYBlockRenderer renderer = new XYBlockRenderer();
CustomGrayPaintScale paintScale = new CustomGrayPaintScale(0,1000);
renderer.setPaintScale(paintScale);
XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
plot.setBackgroundPaint(Color.lightGray);
plot.setAxisOffset(new RectangleInsets(5, 5, 5, 5));
JFreeChart chart = new JFreeChart("XYBlockChartDemo3", plot);
chart.removeLegend();
chart.setBackgroundPaint(Color.white);
SymbolAxis scaleAxis = new SymbolAxis(null, new String[] {"", "OK",
"Uncertain", "Bad"});
scaleAxis.setRange(0.5, 3.5);
scaleAxis.setPlot(new PiePlot());
scaleAxis.setGridBandsVisible(false);
PaintScaleLegend psl = new PaintScaleLegend(paintScale, scaleAxis);
psl.setAxisOffset(5.0);
psl.setPosition(RectangleEdge.BOTTOM);
psl.setMargin(new RectangleInsets(5, 5, 5, 5));
chart.addSubtitle(psl);
renderer.setBaseToolTipGenerator(new XYToolTipGenerator() {
#Override
public String generateToolTip(XYDataset dataset, int arg1, int arg2) {
// TODO Auto-generated method stub
XYZDataset xyzDataset = (XYZDataset)dataset;
return String.valueOf(xyzDataset.getZValue(arg1, arg2));
}
});
return chart;
}
/**
* Utility method called by createDataset().
*
* #param data the data array.
* #param c the column.
* #param r the row.
* #param value the value.
*/
private static void setValue(double[][] data,
int c, int r, double value) {
data[0][(r) * 10 + c] = c;
data[1][(r) * 10 + c] = r;
data[2][(r) * 10 + c] = value;
}
/**
* Creates a sample dataset.
*/
private static XYZDataset createDataset() {
double[] xvalues = new double[10*10];
double[] yvalues = new double[10*10];
double[] zvalues = new double[10*10];
double[][] data = new double[][] {xvalues, yvalues, zvalues};
// set the default z-value to zero throughout the data array.
int count [][] = new int[10][10];
for ( int i=0; i<10; i++ ) {
for ( int j=0; j<10; j++ ) {
count[i][j] = i*j;
if ( i==0 && j== 5 )
count[i][j] = 3;
}
}
for ( int i=0; i<10; i++ ) {
for ( int j=0; j<10; j++ ) {
setValue(data,j,i,count[i][j]);
}
}
DefaultXYZDataset dataset = new DefaultXYZDataset();
dataset.addSeries("Series 1", data);
System.out.println(dataset.getZValue(0, 1));
return dataset;
}
/**
* Creates a panel for the demo.
*
* #return A panel.
*/
public static JPanel createDemoPanel() {
return new ChartPanel(createChart(createDataset()));
}
/**
* Starting point for the demonstration application.
*
* #param args ignored.
*/
public static void main(String[] args) {
BlockRenderer demo = new BlockRenderer("Block Chart Demo 3");
//demo.pack();
demo.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
I have made CustomGrayPaintScale class to get white color for 0 Z values by over riding its getPaint(). If above class is run, we'll notice that the blocks are not much distinguishable. There is cell in the top row with value as 3 and all others in that row are 0. Because of my large range, its color value is not much different from its adjacent. So, I wanted something which can draw outline to these blocks. Also, I want to assign lets say blue color to some block items and others should have the paintscale on the basis of Z value only (Better if paint scale is designed which assigns different intensity levels of any color ex green to all the items, not the spectrum paint scale which gives all the different colors to the block).
How can I achieve this?

XYBlockRenderer ignores the outline properties inherited from the parent, AbstractRenderer. The drawItem() method simply sets the paint returned from the PaintScale, using the same color for both fill() and draw(). Some possible approaches would include these:
Override drawItem() and set a different paint after fill() but before draw(), perhaps using a brighter() or darker() color.
Use a PaintScale other than GrayPaintScale, such as LookupPaintScale or your own implementation. You can specify more distinctive colors at the problem end, perhaps using Color.getHSBColor() to vary the hue, saturation and/or brightness.
This example implements the PaintScale interface.
This example varies the hue in an XYLineAndShapeRenderer.
This example varies the saturation in a GanttRenderer.

Related

How to draw image below boxes on a Vaadin canvas?

I currently have a canvas where I will first draw an image before all the other canvas mouse-draw functions come in (to draw the boxes). I also have an undo function which will remove the last drawn box, clear the entire canvas and redraw all the remaining boxes back onto the canvas. However, after undoing, the image will somehow appear on top of the boxes and covering them, instead of below as it should be. I was able to fix this using z-index in HTML5 previously, but do not know how to do so using the Java way.
This is my Canvas.java (undo method is towards the end):
package com.vaadin.starter.beveragebuddy.ui.components;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasSize;
import com.vaadin.flow.component.HasStyle;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.ElementFactory;
import com.vaadin.flow.shared.Registration;
import com.vaadin.starter.beveragebuddy.backend.MainLayout;
import elemental.json.JsonObject;
import java.util.ArrayList;
import java.util.List;
/**
* Canvas component that you can draw shapes and images on. It's a Java wrapper
* for the
* <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">HTML5
* canvas</a>.
* <p>
* Use {#link #getContext()} to get API for rendering shapes and images on the
* canvas.
* <p>
*/
#Tag("canvas")
#SuppressWarnings("serial")
public class Canvas extends Component implements HasStyle, HasSize {
private static CanvasRenderingContext2D context;
private Element element;
private boolean mouseSelect = false;
private boolean mouseIsDown = false;
private double endX;
private double endY;
public static int boxCount = 0;
public static boolean undoCalled = false;
public static ArrayList <BoundingBox> arrayBoxes = new ArrayList<BoundingBox>();
public static ArrayList <MousePosition> mousePosArray = new ArrayList<MousePosition>();
public static ArrayList <SelectBox> selectBoxes = new ArrayList<SelectBox>();
private List<Runnable> mouseMoveListeners = new ArrayList<>(0);
public static ArrayList<BoundingBox> getArrayBoxes() {
return arrayBoxes;
}
public static ArrayList<MousePosition> getMousePosArray() {
return mousePosArray;
}
public static void setMousePosArray(ArrayList<MousePosition> mousePosArray) {
Canvas.mousePosArray = mousePosArray;
}
/**
* Creates a new canvas component with the given size.
* <p>
* Use the API provided by {#link #getContext()} to render graphics on the
* canvas.
* <p>
* The width and height parameters will be used for the canvas' coordinate
* system. They will determine the size of the component in pixels, unless
* you explicitly set the component's size with {#link #setWidth(String)} or
* {#link #setHeight(String)}.
*
// * #param width
// * the width of the canvas
// * #param height
// * the height of the canvas
// */
public Registration addMouseMoveListener(Runnable listener) {
mouseMoveListeners.add(listener);
return () -> mouseMoveListeners.remove(listener);
}
public Canvas(int width, int height) {
context = new CanvasRenderingContext2D(this);
context.drawImage("https://freedesignfile.com/upload/2016/10/Red-Clouds-and-Prairie-Background.jpg", 0, 0);
element = getElement();
element.getStyle().set("border", "1px solid");
getElement().setAttribute("width", String.valueOf(width));
getElement().setAttribute("height", String.valueOf(height));
element.addEventListener("mousedown", event -> { // Retrieve Starting Position on MouseDown
Element boundingBoxResult = ElementFactory.createDiv();
element.appendChild(boundingBoxResult);
JsonObject evtData = event.getEventData();
double xBox = evtData.getNumber("event.x");
double yBox = evtData.getNumber("event.y");
boundingBoxResult.setAttribute("data-x", String.format("%f", xBox));
boundingBoxResult.setAttribute("data-y", String.format("%f", yBox));
BoundingBox newBox = new BoundingBox("","", xBox, yBox, 0.0, 0.0);
arrayBoxes.add(newBox);
SelectBox select = new SelectBox(xBox, 0.0, yBox, 0.0);
selectBoxes.add(0, select);
mouseIsDown=true;
mouseMoveListeners.forEach(Runnable::run);
}).addEventData("event.x").addEventData("event.y");
element.addEventListener("mouseup", event -> { // Draw Box on MouseUp
Element boundingBoxResult2 = ElementFactory.createDiv();
element.appendChild(boundingBoxResult2);
JsonObject evtData2 = event.getEventData();
endX = evtData2.getNumber("event.x");
endY = evtData2.getNumber("event.y");
boundingBoxResult2.setAttribute("end-x", String.format("%f", endX));
boundingBoxResult2.setAttribute("end-y", String.format("%f", endY));
// System.out.println(endX);
// System.out.println(endY);
double xcoordi = 0;
double ycoordi = 0;
double boxWidth = 0;
double boxHeight = 0;
// for (int i = 0; i < arrayBoxes.size(); i++) {
System.out.println(endX);
System.out.println(endY);
arrayBoxes.get(boxCount).setWidth(endX, arrayBoxes.get(boxCount).xcoordi);
arrayBoxes.get(boxCount).setHeight(endY, arrayBoxes.get(boxCount).ycoordi);
xcoordi = arrayBoxes.get(boxCount).getXcoordi();
ycoordi = arrayBoxes.get(boxCount).getYcoordi();
boxWidth = arrayBoxes.get(boxCount).getWidth();
boxHeight = arrayBoxes.get(boxCount).getHeight();
boxCount++;
mouseIsDown=false;
context.beginPath();
context.setStrokeStyle("green");
context.setLineWidth(2);
context.strokeRect(xcoordi, ycoordi, boxWidth, boxHeight);
context.stroke();
context.fill();
SelectBox select = new SelectBox(endX, 0.0, endY, 0.0);
selectBoxes.add(1, select);
// if (selectBoxes.get(1).getSelectEndX() == selectBoxes.get(0).getSelectStartX()){
// mouseSelect = true;
// context.beginPath();
// context.setStrokeStyle("yellow");
// context.setLineWidth(2);
// context.strokeRect(arrayBoxes.get(i).xcoordi, arrayBoxes.get(i).ycoordi, arrayBoxes.get(i).boxWidth, arrayBoxes.get(i).boxHeight);
// context.fill();
// }
System.out.println(arrayBoxes.toString());
//
// for (int i = 0; i < arrayBoxes.size(); i++){
// if(arrayBoxes.get(i).xcoordi)
// if (endX > arrayBoxes.get(i).xcoordi){
// if (endX < arrayBoxes.get(i).endY)
// }
// }
mouseMoveListeners.forEach(Runnable::run);
}).addEventData("event.x").addEventData("event.y");
element.addEventListener("mousemove", event -> { // Retrieve Mouse Position when Moving
JsonObject mousePos = event.getEventData();
double mouseX = mousePos.getNumber("event.x");
double mouseY = mousePos.getNumber("event.y");
MousePosition currentPos = new MousePosition(mouseX, mouseY);
mousePosArray.add(0, currentPos);
setMousePosArray(mousePosArray);
mouseMoveListeners.forEach(Runnable::run);
}).addEventData("event.x").addEventData("event.y");
}
public static void undoLast() {
undoCalled = true;
if (arrayBoxes.size() > 0) {
arrayBoxes.remove(arrayBoxes.size() - 1);
}
System.out.println(arrayBoxes.toString());
System.out.println(arrayBoxes.size());
context.clearRect(0, 0, 1580, 700);
context.drawImage("https://freedesignfile.com/upload/2016/10/Red-Clouds-and-Prairie-Background.jpg", 0, 0);
for (int i = 0; i < arrayBoxes.size(); i++){
context.beginPath();
context.setStrokeStyle("green");
context.setLineWidth(2);
context.strokeRect(arrayBoxes.get(i).xcoordi, arrayBoxes.get(i).ycoordi, arrayBoxes.get(i).boxWidth, arrayBoxes.get(i).boxHeight);
context.fill();
}
boxCount--;
System.out.println("Box Count: " + boxCount);
}
/**
* Gets the context for rendering shapes and images in the canvas.
* <p>
* It is a Java wrapper for the <a href=
* "https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D">same
* client-side API</a>.
*
* #return the 2D rendering context of this canvas
*/
public CanvasRenderingContext2D getContext() {
return context;
}
/**
* {#inheritDoc}
* <p>
* <b>NOTE:</b> Canvas has an internal coordinate system that it uses for
* drawing, and it uses the width and height provided in the constructor.
* This coordinate system is independent of the component's size. Changing
* the component's size with this method may scale/stretch the rendered
* graphics.
*/
#Override
public void setWidth(String width) {
HasSize.super.setWidth(width);
}
/**
* {#inheritDoc}
* <p>
* <b>NOTE:</b> Canvas has an internal coordinate system that it uses for
* drawing, and it uses the width and height provided in the constructor.
* This coordinate system is independent of the component's size. Changing
* the component's size with this method may scale/stretch the rendered
* graphics.
*/
#Override
public void setHeight(String height) {
HasSize.super.setHeight(height);
}
/**
* {#inheritDoc}
* <p>
* <b>NOTE:</b> Canvas has an internal coordinate system that it uses for
* drawing, and it uses the width and height provided in the constructor.
* This coordinate system is independent of the component's size. Changing
* the component's size with this method may scale/stretch the rendered
* graphics.
*/
#Override
public void setSizeFull() {
HasSize.super.setSizeFull();
}
public void addComponent(Label label) {
}
}
Any help is much appreciated, thank you!
I believe your issue is due to one or both of these issues
When drawing the image, you correctly wait for it to load before actually drawing it to the canvas (image.onload = ...). This means that your code might start loading the image, then it draws all the boxes, and then the image loads so that it is drawn on top.
You run the image drawing script on beforeClientResponse, which means it might get called after all the code for drawing the boxes is called.
The simplest solution, if you always want to have an image as the background, is to use two canvases on top of each other (with absolute positioning, for example). This way, you can always draw the images to the background canvas, and all boxes to the foreground canvas. A bonus of this is that you don't have to redraw the background even if you clear the foreground canvas.

How do i iterate through my ArrayList of objects to create a condition?

I am trying to have my last IF loop to iterate through the three objects within
the PinballTypeOne list, only these three objects inside the ArrayList should change their former color to orange once they've hit the left wall. Collision does work, but objects keep bouncing off without being changed to orange so i think i might have a problem with either how the ArrayList was made or how i'm attempting to iterate through the ArrayList. No compilation errors.
public class PinballObject
{
private int currentXLocation;
private int currentYLocation;
private int speedXTravel;
private int speedYTravel;
private Color colour;
private int radius;
private Machine machine;
private final int leftWallPosition;
private final int bottomWallPosition;
private final int topWallPosition;
private final int rightWallPosition;
private ArrayList<PinballObject> PinballTypeOneList = new ArrayList<PinballObject>();
/**
* Constructor for objects of class Pinball_Obj
*
* #param xPos the horizontal coordinate of the object
* #param yPos the vertical coordinate of the object
* #param xVel the horizontal speed of the object
* #param yVel the vertical speed of the object
* #param objectRadius the radius (in pixels) of the object
* #param objectColor the color of the object
* #param theMachine the machine this object is in
*/
public PinballObject(int xPos, int yPos, int xVel, int yVel, Color objectColor, int objectRadius, Machine theMachine)
{
currentXLocation = xPos;
currentYLocation = yPos;
speedXTravel = xVel;
speedYTravel = yVel;
colour = objectColor;
radius = objectRadius;
machine = theMachine;
leftWallPosition = machine.getLeftWall();
bottomWallPosition = machine.getBottomWall();
topWallPosition = machine.getTopWall();
rightWallPosition = machine.getRightWall();
}
public void makeType1()
{
PinballObject firstTypeOne = new PinballObject(50, 200, -5, 3, Color.RED, 10, machine);
PinballTypeOneList.add(firstTypeOne);
PinballObject secondTypeOne = new PinballObject(100, 300, 1, 2, Color.BLUE, 55, machine);
PinballTypeOneList.add(secondTypeOne);
PinballObject thirdTypeOne = new PinballObject(450, 125, -1, -1, Color.YELLOW, 40, machine);
PinballTypeOneList.add(thirdTypeOne);
}
/**
* Move this object according to its position and speed and redraw.
**/
public void move()
{
// remove from universe at the current position
machine.erase(this);
// compute new position
currentYLocation += speedYTravel;
currentXLocation += speedXTravel;
// check if it has hit the leftwall + change color to orange only for the objects IN the arraylist
if(currentXLocation <= (leftWallPosition + radius))
{
currentXLocation = leftWallPosition + radius;
speedXTravel = -speedXTravel;
if(this.equals(PinballTypeOneList)){
colour = Color.ORANGE;
}
// draw again at new position
machine.draw(this);
}
}
For your function move you should do so:
public void move()
{
machine.erase(this);
currentYLocation += speedYTravel;
currentXLocation += speedXTravel;
if(currentXLocation <= (leftWallPosition + radius))
{
currentXLocation = leftWallPosition + radius;
speedXTravel = -speedXTravel;
for(PinballObject po : PinballTypeOneList) { //Iterating through list of PinballObject's
if(this.equals(po)) { // If this PinballObject is in list
colour = Color.ORANGE; // Or use po.colour
}
}
machine.draw(this);
}
}
and you need to override equals and hashCode methods because you using your own defined class(PinballObject), see this question.
And i have question about your PinballTypeOneList why it is in PinballObject class? This means every PinballObject has it, this sounds bad... You need to make PinballTypeOneList global and then store in it your PinballObjects, or you have particular reason for doing so?
After this I believe your code should work.(though i didn't see most code).

Flat line instead wave

I want to plot a sine wave, but instead my application generates a flat line. When I use series with random from jchartfree example everything works fine. I also use debugger to check if values are good. Values are different than zero
public void createDataset() {
XYSeriesCollection dataset = new XYSeriesCollection();
XYSeries series1 = new XYSeries("Object 1");
double A = 1;
double T = 1;
double Fs = 10;
double f = 200;
int rozmiar = (int) (T*Fs);
double[] x = new double[rozmiar];
for (int i = 0; i < rozmiar; i++)
{
x[i] = A * Math.sin(2 * Math.PI * f * i / Fs);
series1.add(i, x[i]);
}
dataset.addSeries(series1);
data = dataset;
}
//...
public void createChartPanel() {
//pWykres = new JPanel();
//if(java.util.Arrays.asList(getComponents()).contains(pWykres)){
//getContentPane().remove(pWykres);
//}
if(pWykres != null){
pWykres.removeAll();
pWykres.revalidate();
}
String chartTitle = "Objects Movement Chart";
String xAxisLabel = "X";
String yAxisLabel = "Y";
JFreeChart chart = ChartFactory.createXYLineChart(chartTitle,
xAxisLabel, yAxisLabel, dataset);
customizeChart(chart);
pWykres = new ChartPanel(chart);
getContentPane().add(pWykres, BorderLayout.CENTER);
setSize(620, 460);
//validate();
pWykres.repaint();
}
//endregion
//...
//region
private void customizeChart(JFreeChart chart) {
XYPlot plot = chart.getXYPlot();
XYSplineRenderer renderer;
renderer = new XYSplineRenderer();
renderer.setSeriesShapesVisible(0, false);
// sets paint color for each series
renderer.setSeriesPaint(0, Color.RED);
// sets thickness for series (using strokes)
renderer.setSeriesStroke(0, new BasicStroke(1.0f));
// sets paint color for plot outlines
//plot.setOutlinePaint(Color.BLUE);
//plot.setOutlineStroke(new BasicStroke(2.0f));
// sets renderer for lines
plot.setRenderer(renderer);
// sets plot background
plot.setBackgroundPaint(Color.WHITE);
// sets paint color for the grid lines
plot.setRangeGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.BLACK);
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.BLACK);
}
You are taking the sine of values that are always whole multiples of 2 * PI, so all of these values will be (approximately) zero, hence your graph will end up appearing flat unless it is scaled to show up these tiny values (which are just floating point errors).
x[i] = A * Math.sin(2 * Math.PI * f * i / Fs);
where A = 1 and f/Fs = 20 and i is integer
For example:
Math.sin(0) // 0.0
Math.sin(2 * Math.PI) // -2.4492935982947064E-16 (approximately zero)
Math.sin(4 * Math.PI) // -4.898587196589413E-16 (approximately zero)
To see the characteristic shape of a sine wave, you need to vary the input to the sin function by much smaller increments, e.g. pi/10 or less.

Tic Tac Toe Java Program - CPU not responding

I've been working on this program for a couple weeks now, adding components to an applet in order to output a simple tic tac toe game. I've gotten some of it to work, but as of now, when you run, all it does is that you click it once, the CPU projects its mark in the upper left corner, and then you can click anywhere else and it automatically says you win. I can't get the CPU to keep playing. I don't expect anyone to tell me what to do, but I'm just confused as to which method I need to work on in order to get the CPU to respond. My professor has left some very helpful pseudocode, but I still don't quite understand. I've been working with the method "gameEnd," checking for winners horizontally, vertically and diagonally to see if that's the source to getting the game to continue beyond just two marks, but it's not working. Anyone got any suggestions? Thanks.
import java.awt.Color;
import java.awt.Event;
import java.awt.Font;
import java.awt.Graphics;
import java.util.Random;
public class TicTacToe extends java.applet.Applet {
// Ignore this constant
private static final long serialVersionUID = 1942709821640345256L;
// You can change this boolean constant to control debugging log output
private static final boolean DEBUGGING = false;
// Constants
// Size of one side of the board in pixels
private static final int BOARD_SIZE_PIXELS = 600;
// Number of squares on one side of the board
private static final int SQUARES = 3;
// Diameter of the circle drawn in each square
private static final int CIRCLE_WIDTH = 90;
// Colors to be used in the game
private static final Color BACKGROUND_COLOR = Color.WHITE;
private static final Color SQUARE_BORDER_COLOR = Color.BLACK;
private static final Color GAME_OVER_MESSAGE_COLOR = Color.BLACK;
private static final Color HUMAN_COLOR = Color.RED;
private static final Color HUMAN_WINNING_COLOR = Color.MAGENTA;
private static final Color CPU_COLOR = Color.BLUE;
private static final Color CPU_WINNING_COLOR = Color.CYAN;
// Status constant values for the game board
private static final int EMPTY = 0;
private static final int HUMAN = 1;
private static final int HUMAN_WINNING = 2;
private static final int CPU = -1;
private static final int CPU_WINNING = -2;
// String displayed when the game ends
private static final String GAME_WIN_MESSAGE = "You win! Click to play again.";
private static final String GAME_LOSE_MESSAGE = "You lose......Click to play again.";
private static final String GAME_DRAW_MESSAGE = "No one wins? Click to play again...";
// Instance variables that control the game
// Whether or not the user just clicked the mouse
private boolean mouseClicked = false;
// Whether or not to start the game again
private boolean restart = false;
// Whether or not the CPU should start playing a move.
// USED ONLY WHEN THE CPU PLAYS FIRST!
private boolean onFirstMove = false;
// The column and row of the SQUARE the user clicked on
private int xMouseSquare; // column
private int yMouseSquare; // row
// The width (and height) of a single game square
private int squareWidth = BOARD_SIZE_PIXELS / SQUARES;
// An array to hold square status values on the board.
// The status values can be EMPTY, HUMAN, CPU or other values
private int[][] gameBoard;
// The column and row of the SQUARE the CPU player will move on
private int xCPUMove;
private int yCPUMove;
// Add the rest of your instance variables here, if you need any. (You won't
// need to, but you may if you want to.)
// Ignore these instance variables
// CPUinMove represents if the CPU is thinking (generating the CPU move).
// If it is true, it means the CPUMove() method is running and no new move
// should be added
private boolean CPUinMove;
// Methods that you need to write:
/*
* Pre: x and y are x-coordinate and y-coordinate where the user just
* clicks. squareWidth is the width (and height) of a single game square.
*
* Post: xMouseSquare and yMouseSquare are set to be the column and row
* where the user just clicked on (depending on x and y).
*
* Hint: You need only two statements in this method.
*/
// Setting MouseSquare equal to x and y divided by the Square Width to create a location for
// the user after clicking
private void setMouseSquare(int x, int y) {
//
xMouseSquare = x/squareWidth;
yMouseSquare = y/squareWidth;
}
/*
* Pre: SQUARES is an int that holds the number of game squares along one
* side of the game board. xSquare is an int such that 0 <= xSquare <
* SQUARES. CIRCLE_WIDTH is an int that holds the diameter of the circle to
* be drawn in the center of a square. squareWidth is an int that holds the
* width and height in pixels of a single game square.
*
* Post: Return the correct x-coordinate (in pixels) of the left side of the
* circle centered in a square in the column xSquare.
*
* Hint: This method should be very simple. What you need to do is to find
* the right equation.
*/
private int getIconDisplayXLocation(int xSquare) {
// This line is an example of using DEBUGGING variable
if (DEBUGGING) {
System.out.println("The input that getIconDisplayXLocation() receives is: " + xSquare);
}
// equation that returns the correct variable in the column xSquare
return squareWidth * xSquare + (squareWidth - CIRCLE_WIDTH)/2;
}
/*
* Pre: SQUARES is an int that holds the number of game squares along one
* side of the game board. ySquare is an int such that 0 <= ySquare <
* SQUARES. CIRCLE_WIDTH is an int that holds the diameter of the circle to
* be drawn in the center of a square. squareWidth is an int that holds the
* width and height in pixels of a single game square.
*
* Post: Return the correct y-coordinate (in pixels) of the top of the
* circle centered in a square in the row ySquare.
*
* Hint: This method should be very simple. What you need to do is to find
* the right equation.
*/
private int getIconDisplayYLocation(int ySquare) {
// This line is an example of using DEBUGGING variable
if (DEBUGGING) {
System.out.println("The input that getIconDisplayYLocation() receives is: " + ySquare);
}
// equation that returns the correct variable in the column ySquare
return squareWidth * ySquare + (squareWidth - CIRCLE_WIDTH)/2;
}
/*
* The instance variable gameBoard will be created and initialized
*
* Pre: SQUARES is set to an int. gameBoard is a 2-dimensional array type
* variable that holds the status of current game board. Each value in the
* array represents a square on the board
*
* Post: gameBoard must be assigned a new 2-dimensional array. Every square
* of gameBoard should be initialized to EMPTY.
*
* Hint: A loop.
*/
private void buildBoard() {
// Setting the two methods equal to local variables, x and y
int x = xMouseSquare;
int y = yMouseSquare;
// This line creates the gameBoard array. You must write several more
// lines to initialize all its values to EMPTY
// Write game board using the equation of three across and down for each column
// Constructs a 3 by 3 array of integers for the board
gameBoard = new int[3][3];
// Initialize variables i and j, set equal to 0; this establishes a connection for loop
for (x = 0; x < 3; x++) {
for (y = 0; y < 3; y++) {
gameBoard[x][y] = EMPTY;
}
}
}
/*
* Returns whether the most recently clicked square is a legal choice in the
* game.
*
* Pre: gameBoard is a 2-dimensional array type variable that holds the
* status of current game board. xSquare and ySquare represent the column
* and row of the most recently clicked square.
*
* Post: Returns true if and only if the square is a legal choice. If the
* square is empty on current game board, it is legal and the method shall
* return true; if it is taken by either human or CPU or it is not a square
* on current board, it is illegal and the method shall return false.
*
* Hint: Should be simple but think carefully to cover all cases.
*/
private boolean legalSquare(int xSquare, int ySquare) {
if (gameBoard[xSquare][ySquare] == EMPTY)
return true;
else return false;
}
/*
* Pre: gameBoard is an array that holds the current status of the game
* board. xSquare and ySquare represent the column and row of the most
* recently clicked square. player represent the current player (HUMAN or
* CPU). This method is always called after checking legalSquare().
*
* Post: Set the square as taken by current player on the game board if the
* square is empty.
*
* Hint: Very simple.
*/
private void setMovePosition(int xSquare, int ySquare, int player) {
player = HUMAN;
player = CPU;
this.xMouseSquare = xSquare;
this.yMouseSquare = ySquare;
}
/*
* Check if HUMAN or CPU wins the game.
*
* Pre: gameBoard is an array to hold square status values on the board. The
* status values can be EMPTY, HUMAN, CPU or other values.
*
* Post: The method will return true if and only if a player wins the game.
* Winning a game means there is at least one row, one column, or one
* diagonal that is taken by the same player. The method does not need to
* indicate who wins because if it is implemented correctly, the winner must
* be the one who just made a move.
*
* Hint: Complicated method. Use loops to shorten your code. Think about how
* to represent "a player takes 3 squares in a row/column/diagonal".
*/
private boolean gameEnd() {
// Setting local variables
int i = 0;
int x = xMouseSquare;
int y = yMouseSquare;
int sw = squareWidth;
int[][] g = gameBoard;
// Checking for a winner
// Checking columns
for (y = 0; y < 3; y++) {
for (x = 0; x < 3; x++) {
i = g[x][y] + i;
}
}
{
// Checking rows
for (x = 0; x < 3; x++) {
for (y = 0; y < 3; y++) {
i = g[x][y] + i;
}
}
}
// Checking first diagonal
{
for (x = 0; x < 3; x++) {
g[x][x] = 3;
}
}
for (x = 1; x < 3; x++) {
g[x][x] = 3;
}
for (x = 2; x < 3; x++) {
g[x][x] = 3;
}
// Checking second diagonal
for (y = 0; y < 3; y++) {
g[y][2 - y] = 3;
}
for (y = 1; y < 3; y++) {
g[y][2 - y] = 3;
}
for (y = 2; y < 3; y++) {
g[y][2 - y] = 3;
}
return true;
}
/*
* Check if the game ends as a draw.
*
* Pre: gameBoard is an array to hold square status values on the board. The
* status values can be EMPTY, HUMAN, CPU or other values. This method is
* always called after gameEnd().
*
* Post: The method will return true if and only if all squares on the game
* board are taken by HUMAN or CPU players (no EMPTY squares left).
*
* Hint: Should be simple. Use loops.
*/
// Value of...
private boolean gameDraw() {
if (squareWidth == (3^2 - 1)) {
}
return true;
}
/*
* Marks circles on the line on which a player wins.
*
* Pre: g is Graphics object that is ready to draw on. HUMAN_WINNING_COLOR
* and CPU_WINNING_COLOR are both Color objects that represent the color to
* show when HUMAN/CPU wins. gameBoard is gameBoard is an array to hold
* square status values on the board. The status values can be EMPTY, HUMAN,
* CPU or other values.
*
* Post: ALL the row(s)/column(s)/diagonal(s) on which a player wins will be
* marked as the special color.
*
* Hint: You must draw a new circle with the special color (to replace the
* old circle) on the square if the square belongs to a winning
* row/column/diagonal. You can change gameBoard because the board will be
* reset after displaying the winning line. You can use helper methods
* (existing ones or your own) to finish this method. Pay attention that
* many functions in this method is similar to gameEnd(). You should think
* about reusing code.
*
* Hint2: This method is not necessary for the game logic. You don't have to
* start it early. Start when you know everything else is correct.
*/
private void markWinningLine(Graphics g) {
// TODO
}
/*
* Generates the next square where the CPU plays a move.
*
* Pre: gameBoard is an array to hold square status values on
* the board. The status values can be EMPTY, HUMAN, CPU or other values.
*
* Post: Set xCPUMove and yCPUMove to represent the column and the row which
* CPU plans to play a move on. The respective square MUST BE EMPTY! It will
* cause a logical error if this method returns a square that is already
* taken!
*
* Hint: Don't start too early -- currently this method works (though
* naively). Make sure that everything else works before touching this
* method!
*/
private void CPUMove() {
// TODO
// The following block gives a naive solution -- it finds the first
// empty square and play a move on it. You can use this method to test
// other methods in the beginning. However, you must replace this block
// with your own algorithms eventually.
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (gameBoard[i][j] == 0) {
xCPUMove = i;
yCPUMove = j;
return;
}
}
}
}
/* Put any helper methods you wish to add here. */
/* You will not need to change anything below this line. */
/*
* DO NOT change this method.
*
* Set the game board to show a new, blank game.
*/
private void wipeBoard(Graphics g) {
g.setColor(BACKGROUND_COLOR);
g.fillRect(0, 0, BOARD_SIZE_PIXELS, BOARD_SIZE_PIXELS);
}
/*
* DO NOT change this method.
*
* Displays a circle on g, of the given color, in the center of the given
* square.
*/
private void displayHit(Graphics g, Color color, int xSquare, int ySquare) {
g.setColor(color);
g.fillOval(getIconDisplayXLocation(xSquare),
getIconDisplayYLocation(ySquare), CIRCLE_WIDTH, CIRCLE_WIDTH);
}
/*
* DO NOT change this method.
*
* This method handles mouse clicks. You will not need to call it.
*/
#Override
public boolean mouseDown(Event e, int xMouse, int yMouse) {
if (isClickable()) {
mouseClicked = true;
setMouseSquare(xMouse, yMouse);
}
repaint();
return true;
}
/*
* DO NOT change this method.
*
* This method handles drawing the board. You will not need to call it.
*/
#Override
public void update(Graphics g) {
paint(g);
}
/*
* DO NOT change this method.
*
* Draws the border between game squares onto canvas. Also, draws the moves
* that are already made.
*/
private void displayGame(Graphics canvas) {
canvas.setColor(SQUARE_BORDER_COLOR);
for (int i = 0; i < BOARD_SIZE_PIXELS; i += squareWidth) {
for (int j = 0; j < BOARD_SIZE_PIXELS; j += squareWidth) {
canvas.drawRect(i, j, squareWidth, squareWidth);
}
}
for (int i = 0; i < SQUARES; i++) {
for (int j = 0; j < SQUARES; j++) {
switch (gameBoard[i][j]) {
case HUMAN:
case HUMAN_WINNING:
displayHit(canvas, HUMAN_COLOR, i, j);
break;
case CPU:
case CPU_WINNING:
displayHit(canvas, CPU_COLOR, i, j);
break;
default:
break;
}
}
}
}
/*
* DO NOT change this method.
*
* This method relays information about the availability of mouse clicking
* in the game. You will not need to call it.
*/
private boolean isClickable() {
return !CPUinMove;
}
/*
* DO NOT change the contents this method.
*
* If this method is changed to public void paint(Graphics canvas), it will
* execute the program with the CPU-first order.
*
* This method is like the "main" method (but for applets). You will not
* need to call it. It contains most of the game logic.
*/
// #Override
public void paint(Graphics canvas) {
displayGame(canvas);
if (mouseClicked) {
if (onFirstMove) {
CPUMove();
setMovePosition(xCPUMove, yCPUMove, CPU);
displayHit(canvas, CPU_COLOR, xCPUMove, yCPUMove);
onFirstMove = false;
} else {
if (restart) {
wipeBoard(canvas);
setUpGame();
repaint();
} else if (legalSquare(xMouseSquare, yMouseSquare)) {
setMovePosition(xMouseSquare, yMouseSquare, HUMAN);
displayHit(canvas, HUMAN_COLOR, xMouseSquare, yMouseSquare);
if (gameEnd()) {
markWinningLine(canvas);
canvas.setFont(new Font("SansSerif", Font.PLAIN, 30));
canvas.setColor(GAME_OVER_MESSAGE_COLOR);
canvas.drawString(GAME_WIN_MESSAGE, squareWidth / 2,
squareWidth);
restart = true;
} else {
CPUinMove = true;
CPUMove();
setMovePosition(xCPUMove, yCPUMove, CPU);
displayHit(canvas, CPU_COLOR, xCPUMove, yCPUMove);
CPUinMove = false;
if (gameEnd()) {
markWinningLine(canvas);
canvas
.setFont(new Font("SansSerif", Font.PLAIN,
30));
canvas.setColor(GAME_OVER_MESSAGE_COLOR);
canvas.drawString(GAME_LOSE_MESSAGE,
squareWidth / 2, squareWidth);
restart = true;
} else if (gameDraw()) {
canvas
.setFont(new Font("SansSerif", Font.PLAIN,
30));
canvas.setColor(GAME_OVER_MESSAGE_COLOR);
canvas.drawString(GAME_DRAW_MESSAGE,
squareWidth / 2, squareWidth);
restart = true;
}
}
}
}
mouseClicked = false;
}
}
/*
* DO NOT change this method.
*
* This method is like the "main" method (but for applets). You will not
* need to call it. It contains most of the game logic.
*/
public void paint_game(Graphics canvas) {
// display the current game board
displayGame(canvas);
// the following block will run every time the user clicks the mouse
if (mouseClicked) { // when the user clicks the mouse
// if the game is ready to start or to be restarted
if (restart) {
// clear the window and set up the game again
wipeBoard(canvas);
setUpGame();
repaint();
}
// else, if the game is in play, check if the click is on a legal
// square
else if (legalSquare(xMouseSquare, yMouseSquare)) {
// if the square is legal, mark the corresponding position as
// taken by HUMAN
setMovePosition(xMouseSquare, yMouseSquare, HUMAN);
// display the new position with a HUMAN_COLOR circle
displayHit(canvas, HUMAN_COLOR, xMouseSquare, yMouseSquare);
// check if the game ends (if it is, HUMAN wins)
if (gameEnd()) {
// if HUMAN wins, mark the winning line as a special color.
markWinningLine(canvas);
// display the human winning message
canvas.setFont(new Font("SansSerif", Font.PLAIN, 30));
canvas.setColor(GAME_OVER_MESSAGE_COLOR);
canvas.drawString(GAME_WIN_MESSAGE, squareWidth / 2,
squareWidth);
// mark the game as ready to restart
restart = true;
} else if (gameDraw()) {
// if HUMAN doesn't win but the board is full, it is a draw
// display the draw message
canvas.setFont(new Font("SansSerif", Font.PLAIN, 30));
canvas.setColor(GAME_OVER_MESSAGE_COLOR);
canvas.drawString(GAME_DRAW_MESSAGE, squareWidth / 2,
squareWidth);
// mark the game as ready to restart
restart = true;
} else {
// if HUMAN doesn't win and the board is not full, the CPU
// is ready to move
CPUinMove = true;
// calculates the next CPU move
CPUMove();
// mark the corresponding position as taken by CPU
setMovePosition(xCPUMove, yCPUMove, CPU);
// display the new position with a CPU_COLOR circle
displayHit(canvas, CPU_COLOR, xCPUMove, yCPUMove);
CPUinMove = false;
if (gameEnd()) {
// if CPU wins, mark the winning line as a special
// color.
markWinningLine(canvas);
// display the human losing message
canvas.setFont(new Font("SansSerif", Font.PLAIN, 30));
canvas.setColor(GAME_OVER_MESSAGE_COLOR);
canvas.drawString(GAME_LOSE_MESSAGE, squareWidth / 2,
squareWidth);
// mark the game as ready to restart
restart = true;
}
// else (if the game is not ended after the CPU move), the
// game is ready to get the next HUMAN move
}
}
mouseClicked = false;
}
}
/*
* DO NOT change this method.
*
* This method initializes the applet. You will not need to call it.
*/
#Override
public void init() {
setSize(BOARD_SIZE_PIXELS, BOARD_SIZE_PIXELS);
setBackground(BACKGROUND_COLOR);
setUpGame();
}
/*
* DO NOT change this method.
*
* Creates a fresh game board and sets up the game state to get ready for a
* new game.
*/
private void setUpGame() {
buildBoard();
CPUinMove = false;
restart = false;
onFirstMove = true;
}
}

How can I plot points on a graph from function in another class which returns an array filled with values to plot

I have my first class
public class GetResults{
public double[] tableOfresults() {
double[] outputArray = new double[100];
double time;
double results
for(time = 0; time<outputArray.length; i++) {
//Some values are calculated and then stored in an array as below
outputArray[(int)Time] = Results
}
return outputarray;
This class just calculates some values I want to plot on a graph and stores them in the array.
This next class is what actually plots the points on my graph. I am unsure of a simple way to get points to plot on my X axis which are the Values of time(Time being the array index 0,1,2,3 ect) and my Y axis which are my Results. I am currently having to put all the positions in myself.
public class graph{
GetResults gr = new GetResuts();
public XYSeries inputOutputGraph() {
XYSeries graph = new XYSeries("My graph");
XYDataset xyDataset = new XYSeriesCollection(graph);
graph.add(1, gr.tableOfResults()[1]);
graph.add(2, gr.tableOfResults()[2]);
graph.add(3, gr.tableOfResults()[3]);
graph.add(4, gr.tableOfResults()[4]);
Here I am having to add the values myself(I have 1000 to do). I need something that looks like this graph.add(gr.tableOfResults()[gr.Time], gr.tableOfResults()[gr.Results]);
So that as my time goes up 0,1,2,3 it will plot my Results which is stored at index 0,1,2,3 at that position. How could I do this?? I have tried that code^^ and I got an array index out of bounds with the vaue my array size was set to
JFreeChart chart = ChartFactory.createXYLineChart(
"Graph", "Time", "results",
xyDataset, PlotOrientation.VERTICAL, true, true, false);
ChartFrame graphFrame = new ChartFrame("XYLine Chart", chart);
graphFrame.setVisible(true);
graphFrame.setSize(300, 300);
return graph;
}
}
You could just put your calculated values directly in an XYSeries and then let GetResults have a method that returns that series.
class GetResults {
public XYSeries getSeries() {
XYSeries series = new XYSeries("Series");
for (int i = 0; i < 10; i++) {
series.add(i, Math.pow(2, i));
}
return series;
}
}
Here's how you would use getSeries() in this example.
dataset.addSeries(new GetResults().getSeries());

Categories