I'm really sorry on advance that the codes are little long - but they're very simple to read and understand because I'm a beginner.
The problem is that I'm trying to get this output:
Black Image Constructor:
(0,0,0) (0,0,0) (0,0,0) (0,0,0)
(0,0,0) (0,0,0) (0,0,0) (0,0,0)
(0,0,0) (0,0,0) (0,0,0) (0,0,0)
Constructor with RGBColor[][] Array Parameter:
(0,0,0) (0,0,0) (0,0,0) (0,0,0)
(1,1,1) (1,1,1) (1,1,1) (1,1,1)
(2,2,2) (2,2,2) (2,2,2) (2,2,2)
and instead of that, I'm just getting errors.
Here are my 3 codes:
RGBColor Class:
/**
* This program is used to represent 3 Colors: Red, Green, Blue. (RGB)
* These colors hold values between 0 and 255.
*
*
* #Author Ilan Aizelman.
*/
public class RGBColor {
/**
* attributes: red, green and blue component of a color.
*/
private int _red,_green,_blue;
/**
* final variables.
*/
private final int MAX_VALUE = 255,MIN_VALUE = 0;
private final double THIRTY_PERCENT = 0.3,FIFTY_NINE_PERCENT = 0.59,ELEVEN_PERCENT = 0.11;
/**
* Consctructor which gets 3 colors (RGB), we check here if their range is valid (0 - 255), if not we assign black to it.
*
* #param red - The red color component value.
* #param green - The green color component value.
* #param blue - The blue color component value
*/
public RGBColor(int red, int green, int blue)
{
if(isValid(red,green,blue))
{
_red = red;
_green = green;
_blue = blue;
}
else
doBlack();
}
/**
* Construct a black RGBColor. i.e. red = green = blue = 0
*/
public RGBColor()
{
doBlack();
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* #param nums - a component value, should be the number between 1-4
* #param return - return true if the number is between 1-4, false otherwise.
*/
private boolean isValid(int nums)
{
return ((nums >= MIN_VALUE) && (nums <= MAX_VALUE));
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* #param red - the red component
* #param green - the green component
* #param blue - the red component
* #param return true if values are correct, false otherwise.
*/
private boolean isValid(int red, int green, int blue)
{
return ((red <= MAX_VALUE && red >= MIN_VALUE &&
green <= MAX_VALUE && green >= MIN_VALUE &&
blue <= MAX_VALUE && blue >= MIN_VALUE));
}
/**
* Returns RGB color string triplet with numbers between 0-255, i.e. (0,127,127)
*/
public String toString()
{
return ("(" + _red + "," + _green + "," + _blue + ")");
}
/**
* RGBColor will become the color Black. (0,0,0)
*/
private void doBlack()
{
_red = _green = _blue = 0;
}
}
RGBImage class:
public class RGBImage
{
private int _rows, _cols;
final int ZERO_VALUE = 0;
private RGBColor[][] _pixels;
/**
* Constructor for objects of class RGBImage
*/
public RGBImage(int rows, int cols)
{
_rows = rows;
_cols = cols;
_pixels = new RGBColor[_rows][_cols];
for(int i = 0; i < _rows; i++)
{
for(int j = 0; j < _cols; j++)
{
_pixels[i][j] = new RGBColor();
}
//System.out.println();
}
}
public RGBImage(RGBColor[][] pixels)
{
_pixels = new RGBColor[pixels.length][pixels[0].length];
for(int i = 0; i < pixels.length; i++)
{
for(int j 0; j < pixels[0].length; j++)
{
_pixels[i][j] = new RGBColor(pixels[i][j]);
}
}
}
}
and my StudentTester class which has to print the output I wrote in the beginning:
public class StudentTester {
public static void main(String[] args) {
System.out.println("Black Image Constructor:");
RGBImage rgbImg0 = new RGBImage(3,4);
System.out.println(rgbImg0);
System.out.println("Constructor with RGBColor[][] Array Parameter:");
RGBColor[][] rgbArray1 = new RGBColor[3][4];
for (int i=0; i<rgbArray1.length;i++)
for (int j=0; j<rgbArray1[0].length;j++)
rgbArray1[i][j] = new RGBColor(i,i,i);
RGBImage rgbImg1 = new RGBImage(rgbArray1);
System.out.println(rgbImg1);
System.out.println("Have a Nice Work!");
}
}
The error is:
Black Image Constructor:
RGBImage#47520d
Constructor with RGBColor[][] Array Parameter:
RGBImage#1aa4b35
Have a Nice Work!
EDIT:
I've added this now,
I've added this:
public String toString() {
String pixelSet="";
for(int i=0; i<_rows;i++){
for(int j=0 ;j<_cols;j++){
pixelSet+=this._pixels[i][j].toString();
}
pixelSet +="\n";
}
return pixelSet;
}
and I'm not getting the "Constructor with RGBColor[][] Array Parameter:" output yet. still working on it, thanks guys!
solution: (edit2)
public RGBImage(RGBColor[][] pixels)
{
_rows = pixels.length;
_cols = pixels[0].length;
_pixels = new RGBColor[_rows][_cols];
for(int i = 0; i < _rows; i++)
{
for(int j = 0; j < _cols; j++)
{
_pixels[i][j] = new RGBColor(pixels[i][j]);
}
}
}
Here you are printing an object.
System.out.println(rgbImg0);
But you have not defined what you want to happen when you print a RGBImage object. When you pass an object reference to a print statement, the objects toString(); method is called and the result is printed out. By default Object subclasses print out a reference, something like RGBImage#47520d which is ClassName + # + Hashcode.
You can override the toString() method of RGBColor to print what you need.
#Override
public String toString() {
return "("+_red+","+_green+","+_blue+")";
}
Then you can override the toString() method of RGBImage class to print your array of RBGColor objects.
public String toString() {
// If your not too bothered about formatting, you can do it in a single line.
// return Arrays.deepToString(_pixels);
String pixelSet="";
for(int i=0; i<_pixels.length;i++){
for(int j=0 ;j<_pixels[i].length;j++){
pixelSet+=this._pixels[i][j].toString();
}
pixelSet +="\n";
}
return pixelSet;
}
I hope this helps.
Hi #Illan Aizelman WS,
I don't see any compilation error in your code, but looking at the output I could see that what you are getting is the toString representation of the object you are trying to print. If you want to get the output as indicated in your question, simply override toString method of java.lang.Object class in RGBImage. If you directly try to print the object using System.out.printXX you will not get the desired output. Refer to the following steps.
Override toString method in RGBImage class.
Iterate through the array in the toString method.
While iterating through the array, print every element you encounter and apply the formatting you wish.
You have to implement toString in your RgbImage class as well (similar to your RgbColor class). The standard implementation simply prints the objectId of your RgbImage instance. Think about what should happen if you print a RgbImage instance. You could for instance call toString of all individual pixels of that image, you could apply some extra formatting, etc.
Related
Just to be clear, I have looked at problems somewhat similar to this on Stack Overflow and other websites before asking for help. I also included all of the code below just in case it could help anyone understand the problem.
In the game Othello, also known as Reversi, there are two players who use tiles of opposite colors. The player needs to place a tile so it is adjacent to a tile of the opposite color and the opposite color must be surrounded by a tile on either side in the same direction. For example, if there is a white tile to the left of a black tile, then another black tile needs to be placed on the left of the white tile so it is surrounded. If a tile is surrounded it flips.
(Black - White - Black) --> (Black - Black - Black)
Surrounding can happen either horizontally, diagonally or vertically.
The problem I'm having is I do not know how to check all of the indices and see if they work at once. I have tried checking for the values adjacent to a tile of the opposite color, by checking all possible values next to it. This doesn't work properly as it can't make sure that a tile is surrounded on both sides or apply to a line of more than one tile in a row.
/**
* Checks to see if a valid move can be made at the indicated OthelloCell,
* for the given player.
* #param xt The horizontal coordinate value in the board.
* #param yt The vertical coordinate value in the board.
* #param bTurn Indicates the current player, true for black, false for white
* #return Returns true if a valid move can be made for this player at
* this position, false otherwise.
*/
public boolean isValidMove(int xt, int yt, boolean bTurn)
{
int length = board[0].length;
// checks if the tile has already been picked, meaning it can no longer be selected
if(board[xt][yt].hasBeenPlayed())
{
return false;
}
else
{
/* For BLACK (Working) */
if(bTurn)
{
// checks tiles one row above
if(xt + 1 < length && board[xt + 1][yt].getBlackStatus() == false)
{
System.out.println("the one 1 row up and in the same column doesn't work");
return true;
}
if(xt + 1 < length && board[xt + 1][yt + 1].getBlackStatus() == false)
{
System.out.println("the one 1 row up and in the right column doesn't work");
return true;
}
if(xt + 1 < length && board[xt + 1][yt - 1].getBlackStatus() == false)
{
System.out.println("the one 1 row up and in the left column doesn't work");
return true;
}
// checks tiles left and right
if(yt + 1 < length && board[xt][yt + 1].getBlackStatus() == false)
{
System.out.println("the one in the same row and in the right column doesn't work");
return true;
}
if(yt > 1 && board[xt][yt - 1].getBlackStatus() == false)
{
System.out.println("the one in the same row and in the left column doesn't work");
return true;
}
// checks tiles one row below
if(xt > 1 && board[xt - 1][yt].getBlackStatus() == false)
{
System.out.println("The one 1 row down and in the same column doesn't work");
return true;
}
if(xt > 1 && board[xt - 1][yt + 1].getBlackStatus() == false)
{
System.out.println("The one 1 row down and in the right column doesn't work");
return true;
}
if(xt > 1 && board[xt - 1][yt - 1].getBlackStatus() == false)
{
System.out.println("The one 1 row down and in the left column doesn't work");
return true;
}
}
}
return false;
}
/**
* Checks to see if a valid move can be made at the indicated OthelloCell, in a
* particular direction (there are 8 possible directions). These are indicated by:
* (1,1) is up and right
* (1,0) is right
* (1,-1) is down and right
* (0,-1) is down
* (-1,-1) is down and left
* (-1,0) is left
* (-1,1) is left and up
* (0,1) is up
* #param xt The horizontal coordinate value in the board.
* #param yt The vertical coordinate value in the board.
* #param i -1 is left, 0 is neutral, 1 is right,
* #param j -1 is down, - is neutral, 1 is up.
* #param bTurn Indicates the current player, true for black, false for white.
* #return Returns true if this direction has pieces to be flipped, false otherwise.
*/
public boolean directionValid(int xt, int yt, int i, int j, boolean bTurn)
{
return true;
}
Above are the two methods I'm having trouble with.
public class Othello
{
/** The board object. This board will be 8 x 8, and filled with OthelloCells.
* The cell may be empty, hold a white game piece, or a black game piece. */
private OthelloCell [][] board;
/** The coordinates of the active piece on the board. */
private int x, y;
/** Booleans indicating that the mouse is ready to be pressed, that it is
* black's turn to move (false if white's turn), and that the game is over. */
private boolean mousePressReady, blackTurn, gameOver;
/**
* Creates an Othello object, with a sized graphics canvas, and a 2D (8 x 8) array
* of OthelloCell, setting up initial values.
*/
/* COMPLETE */
public Othello ( )
{
StdDraw.setCanvasSize(500,650);
StdDraw.setXscale(0,1);
StdDraw.setYscale(0,1.3);
StdDraw.enableDoubleBuffering();
Font font = new Font("Arial", Font.BOLD, 30);
StdDraw.setFont(font);
startBoard();
}
/**
* Called by the constructor, or when the player hits the "RESET" button,
* initializing the game board (an 8 x 8 array of OthelloCell).
*/
/* COMPLETE */
public void startBoard ( )
{
mousePressReady = blackTurn = true;
gameOver = false;
board = new OthelloCell[8][8];
for ( int i = 0; i < board.length; i++ )
{
for ( int j = 0; j < board[i].length; j++ )
{
board[i][j] = new OthelloCell(i,j);
}
}
board[3][3].playIt();
board[3][3].setBlack(true);
board[4][4].playIt();
board[4][4].setBlack(true);
board[4][3].playIt();
board[4][3].setBlack(false);
board[3][4].playIt();
board[3][4].setBlack(false);
}
/**
* Sets up and runs the game of Othello.
*/
/* COMPLETE */
public static void main(String [] args)
{
Othello game = new Othello();
game.run();
}
/**
* Runs an endless loop to play the game. Even if the game is over, the
* loop is still ready for the user to press "RESET" to play again.
*/
/* COMPLETE */
public void run ( )
{
do
{
drawBoard();
countScoreAnddrawScoreBoard();
StdDraw.show();
StdDraw.pause(30);
makeChoice();
gameOver = checkTurnAndGameOver();
}
while(true);
}
/**
* Draws the board, in its current state, to the GUI.
*/
/* COMPLETE */
public void drawBoard ( )
{
StdDraw.setPenColor(new Color(150,150,150));
StdDraw.filledRectangle(0.5,0.75,0.5,0.75);
StdDraw.setPenColor(new Color(0,110,0));
StdDraw.filledSquare(0.5,0.5,0.45);
StdDraw.setPenColor(new Color(0,0,0));
StdDraw.filledSquare(0.5,0.5,0.42);
for ( int i = 0; i < board.length; i++ )
{
for ( int j = 0; j < board[i].length; j++ )
{
board[i][j].drawCell();
}
}
}
/**
* Waits for the user to make a choice. The user can make a move
* placing a black piece or the white piece (depending on whose turn
* it is), or click on the "RESET" button to reset the game.
*/
/* COMPLETE */
public void makeChoice ( )
{
boolean moveChosen = false;
while(!moveChosen)
{
if(mousePressReady && StdDraw.isMousePressed())
{
mousePressReady = false;
double xval = StdDraw.mouseX();
double yval = StdDraw.mouseY();
if(xval > 0.655 && xval < 0.865 && yval > 1.15 && yval < 1.23) // This if checks for a reset.
{
startBoard();
return;
}
if(xval < 0.1 || xval > 0.9 || yval < 0.1 || yval > 0.9) // This if checks for a press off the board.
{
return;
}
int tempx = (int)(10 * (xval - 0.1));
int tempy = (int)(10 * (yval - 0.1));
if(isValidMove(tempx,tempy,blackTurn)) // This if checks to see if the move is valid.
{
x = tempx;
y = tempy;
playAndFlipTiles();
blackTurn = !blackTurn;
System.out.println(x + " " + y);
}
}
if(!StdDraw.isMousePressed() && !mousePressReady) // This if gives back control when the mouse is released.
{
mousePressReady = true;
return;
}
StdDraw.pause(20);
}
}
/**
* Checks to see if a valid move can be made at the indicated OthelloCell,
* for the given player.
* #param xt The horizontal coordinate value in the board.
* #param yt The vertical coordinate value in the board.
* #param bTurn Indicates the current player, true for black, false for white
* #return Returns true if a valid move can be made for this player at
* this position, false otherwise.
*/
public boolean isValidMove(int xt, int yt, boolean bTurn)
{
int length = board[0].length;
// checks if the tile has already been picked, meaning it can no longer be selected
if(board[xt][yt].hasBeenPlayed())
{
return false;
}
else
{
}
return false;
}
/**
* Checks to see if a valid move can be made at the indicated OthelloCell, in a
* particular direction (there are 8 possible directions). These are indicated by:
* (1,1) is up and right
* (1,0) is right
* (1,-1) is down and right
* (0,-1) is down
* (-1,-1) is down and left
* (-1,0) is left
* (-1,1) is left and up
* (0,1) is up
* #param xt The horizontal coordinate value in the board.
* #param yt The vertical coordinate value in the board.
* #param i -1 is left, 0 is neutral, 1 is right,
* #param j -1 is down, - is neutral, 1 is up.
* #param bTurn Indicates the current player, true for black, false for white.
* #return Returns true if this direction has pieces to be flipped, false otherwise.
*/
public boolean directionValid(int xt, int yt, int i, int j, boolean bTurn)
{
return true;
}
/**
* Places a game piece on the current cell for the current player. Also flips the
* appropriate neighboring game pieces, checking the 8 possible directions from the
* current cell.
*/
public void playAndFlipTiles ( )
{
board[x][y].setBlack(blackTurn);
board[x][y].playIt();
// To be completed by you.
}
/**
* A helper method for playAndFlipTiles. Flips pieces in a given direction. The
* directions are as follows:
* (1,1) is up and right
* (1,0) is right
* (1,-1) is down and right
* (0,-1) is down
* (-1,-1) is down and left
* (-1,0) is left
* (-1,1) is left and up
* (0,1) is up
* #param xt The horizontal coordinate value in the board.
* #param yt The vertical coordinate value in the board.
* #param i -1 is left, 0 is neutral, 1 is right,
* #param j -1 is down, - is neutral, 1 is up.
*/
public void flipAllInThatDirection(int xt, int yt, int i, int j)
{
}
/**
* Counts the white pieces on the board, and the black pieces on the board.
* Displays these numbers toward the top of the board, for the current state
* of the board. Also prints whether it is "BLACK'S TURN" or "WHITE'S TURN"
* or "GAME OVER".
*/
/* COMPLETE */
public void countScoreAnddrawScoreBoard ( )
{
int whiteCount = 0, blackCount = 0;
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[i].length; j++)
{
if(board[i][j].hasBeenPlayed())
{
if(board[i][j].getBlackStatus())
{
blackCount++;
}
else
{
whiteCount++;
}
}
}
}
drawScoresAndMessages(whiteCount,blackCount);
}
/**
* A helper method for countScoreAnddrawScoreBoard. Draws the scores
* and messages.
* #param whiteCount The current count of the white pieces on the board.
* #param blackCount The current count of the black pieces on the board.
*/
/* COMPLETE */
public void drawScoresAndMessages(int whiteCount, int blackCount)
{
StdDraw.setPenColor(new Color(0,0,0));
StdDraw.filledRectangle(0.41,1.05,0.055,0.045);
StdDraw.filledRectangle(0.80,1.05,0.055,0.045);
StdDraw.filledRectangle(0.76,1.19,0.11,0.045);
StdDraw.setPenColor(new Color(255,255,255));
StdDraw.filledRectangle(0.41,1.05,0.05,0.04);
StdDraw.filledRectangle(0.80,1.05,0.05,0.04);
StdDraw.filledRectangle(0.76,1.19,0.105,0.04);
StdDraw.setPenColor(new Color(0,0,0));
StdDraw.text(0.24,1.04,"BLACK");
StdDraw.text(0.41,1.04,"" + blackCount);
StdDraw.text(0.63,1.04,"WHITE");
StdDraw.text(0.80,1.04,"" + whiteCount);
StdDraw.text(0.76,1.18,"RESET");
if(gameOver)
{
StdDraw.text(0.34,1.18,"GAME OVER");
}
else if(blackTurn)
{
StdDraw.text(0.34,1.18,"BLACK'S TURN");
}
else
{
StdDraw.text(0.34,1.18,"WHITE'S TURN");
}
}
/**
* Checks to see if black can play. Checks to see if white can play.
* If neither can play, the game is over. If black can't go, then set
* blackTurn to false. If white can't go, set blackTurn to true.
* #return Returns true if the game is over, false otherwise.
*/
/* COMPLETE */
public boolean checkTurnAndGameOver ( )
{
boolean whiteCanGo = false, blackCanGo = false;
// To be completed by you.
return false;
}
}
/**
* Represents a single cell in the game of Othello. By default, a cell is black, and
* has not been played. When a game piece is "placed" on the board, the boolean played
* is set to true. If the game piece is black, then the boolean black is true, and if
* the game piece is white, then the boolean black is false. The ints x and y
* represent the coordinate values of the cell within the game board, with the lower
* left at (0,0) and the upper right at (7,7).
*/
class OthelloCell
{
/** The coordinates of the active piece on the board. */
private int x, y;
/** Booleans indicating if a piece has been played (or is empty), and indicating
* if the piece is black (or white) */
private boolean played, black;
/**
* Creates an OthelloCell object, at the given coordinate pair.
* #param i The horizontal coordinate value for the cell on the board.
* #param j The vertical coordinate value for the cell on the board.
*/
/* COMPLETE */
public OthelloCell(int i, int j)
{
played = false;
x = i;
y = j;
black = true;
}
/**
* Draws the cell on the board, in its current state.
*/
/* COMPLETE */
public void drawCell ( )
{
StdDraw.setPenColor(new Color(0,0,0));
StdDraw.filledSquare(0.15 + 0.1 * x, 0.15 + 0.1 * y, 0.05);
StdDraw.setPenColor(new Color(0,110,0));
StdDraw.filledSquare(0.15 + 0.1 * x, 0.15 + 0.1 * y, 0.048);
if(played)
{
for(int i = 0; i <= 20; i++)
{
if(black)
{
StdDraw.setPenColor(new Color(5+8*i,5+8*i,5+8*i));
}
else
{
StdDraw.setPenColor(new Color(255-8*i,255-8*i,255-8*i));
}
StdDraw.filledCircle(0.15 + 0.1 * x - i*0.001, 0.15 + 0.1 * y + i*0.001, 0.043-i*0.002);
}
}
}
/**
* Sets the piece to black (black true) or white (black false).
* #param bool The value to be assigned to the game piece.
*/
/* COMPLETE */
public void setBlack(boolean bool)
{
if(bool)
{
black = true;
}
else
{
black = false;
}
}
/**
* Return the status of black; true for a black piece, false for a white piece.
* #return Returns true for a black piece, false for a white piece.
*/
/* COMPLETE */
public boolean getBlackStatus ( )
{
return black;
}
/**
* Sets the value of played to true, to indicate that a piece has been placed on this cell.
*/
/* COMPLETE */
public void playIt ( )
{
played = true;
}
/**
* Return the status of played, indicating whether or not there is a game piece on this cell.
* #return Returns true if a game piece is on this cell, false otherwise.
*/
/* COMPLETE */
public boolean hasBeenPlayed ( )
{
return played;
}
}
You can get the 8 adjacent cells using two different arrays. These arrays are used to get row and column numbers of 8 neighbors of a given cell
int rowNbr[] = new int[] {-1, -1, -1, 0, 0, 1, 1, 1};
int colNbr[] = new int[] {-1, 0, 1, -1, 1, -1, 0, 1};
And iterate the given matrix by adding the current row/col to above arrays like :
for (int k = 0; k < 8; ++k) {
sop(matrix[row + rowNbr[k], col + colNbr[k]])
}
Also,you might want to check https://www.geeksforgeeks.org/find-number-of-islands/
Hope this will get you the further thought process. Thnx
This is my approach, although its in C# I am sure its of some use.
Also uses part of the solution from Ashutosh.
My Board is the two dimensional array "pieces", lowercase "length" is just the size of the board and num is an indicator for a color: Empty is 0, num is whats currently being played, 1 for White and 2 for Black.
All its doing is looking for the closest matching color in either direction without empty spaces inbetween and then placing the current playing color in all the array spaces inbetween.
This can probably be done way smarter, I dont even like my approach of always checking for the full size of the field in every direction and just ignoring index out of range exceptions, but it was the simplest
int[] rowNbr = { -1, -1, -1, 0, 0, 1, 1, 1 };
int[] colNbr = { -1, 0, 1, -1, 1, -1, 0, 1 };
for (int x = 0; x < 8; x++)
{
int facX = rowNbr[x];
int facY = colNbr[x];
try
{
for (int i = 1; i < length; i++)
{
if (pieces[click.X + i * facX, click.Y + i * facY] == 0) break;
if (pieces[click.X + i * facX, click.Y + i * facY] == (byte)num)
{
for (int j = i - 1; j > 0; j--)
{
pieces[click.X + j * facX, click.Y + j * facY] = (byte)num;
}
break;
}
}
}
catch { }
}
I'm getting wrong output. I'll put the 3 codes here, they are pretty basic as I've just started to study. (The third code is the tester)
The problem: in the tester I'm getting that input (0,0,0), but I need to get (50,40,30)
I think the main problem is here:
public void setColor (RGBColor color)
{
}
I tried playing with it, and I don't have a better solution than:
_color = new RGBColor(color);
_color.setRed(color.getRed());
_color.setGreen(color.getGreen());
_color.setBlue(color.getBlue());
RGBColor class.
/**
* This program is used to represent 3 Colors: Red, Green, Blue. (RGB)
* These colors hold values between 0 and 255.
*
*
* #Author doesn't matter ;)
*/
public class RGBColor
{
/**
* attributes: red, green and blue component of a color.
*/
private int _red,_green,_blue;
/**
* final variables.
*/
private final int MAX_VALUE = 255,MIN_VALUE = 0;
private final double THIRTY_PERCENT = 0.3,FIFTY_NINE_PERCENT = 0.59,ELEVEN_PERCENT = 0.11;
/**
* Consctructor which gets 3 colors (RGB), we check here if their range is valid (0 - 255), if not we assign black to it.
*
* #param red - The red color component value.
* #param green - The green color component value.
* #param blue - The blue color component value
*/
public RGBColor(int red, int green, int blue)
{
if(isValid(red,green,blue))
{
_red = red;
_green = green;
_blue = blue;
}
else
doBlack();
}
/**
* Construct a black RGBColor. i.e. red = green = blue = 0
*/
public RGBColor()
{
doBlack();
}
/**
* Construct a new RGBColor which is a copy of the given color.
*
* #param other - The RGBColor to copy.
*/
public RGBColor(RGBColor other)
{
_red = other._red;
_green = other._green;
_blue = other._blue;
}
/**
* Returns the Red component of RGBColor.
*
* #return The red color component value of this RGBColor.
*/
public int getRed()
{
return _red;
}
/**
* Returns the Green component of RGBColor.
*
* #return The green color component value of this RGBColor.
*/
public int getGreen()
{
return _green;
}
/**
* Returns the blue component of RGBColor.
*
* #return The blue color component value of this RGBColor.
*/
public int getBlue()
{
return _blue;
}
/**
* Sets the red color component value of this RGBColor, only if the color range is valid (0-255).
*
* #param num - The red color component value to set.
*/
public void setRed(int num)
{
if(isValid(num))
_red = num;
}
/**
* Sets the green color component value of this RGBColor, only if the color range is valid (0-255).
*
* #param num - The green color component value to set.
*/
public void setGreen(int num)
{
if(isValid(num))
_green = num;
}
/**
* Sets the blue color component value of this RGBColor, only if the color range is valid (0-255).
*
* #param num - The blue color component value to set.
*/
public void setBlue(int num)
{
if(isValid(num))
_blue = num;
}
/**
* Compares the 3 RGB colors, returns true if all are equal.
*
* #return true if the RGBColors are equal; false otherwise.
*/
public boolean equals(RGBColor other)
{
return ((_red == other._red) &&
(_green == other._green) &&
(_blue == other._blue));
}
/**
* Changes this color to be a mix of this and other RGBColors, It simply takes this color and other RGBColor and makes and average of them.
* For example (255,0,0) and (0,0,255) becomes: (127,0,127). Note that it returns integer numbers and not fraction numbers.
*
* #param other is the other color.
*/
public void mix(RGBColor other)
{
_red = (_red + other._red) / 2;
_green = (_green + other._green) / 2;
_blue = (_blue + other._blue) / 2;
}
/**
* Returns the grayscale value of this RGBColor.
* Grayscale is defined by taking Red multipled by 30% plus green multiplied by 59% plus blue multipled by 11%.
*
* #return The grayscale value of this RGBColor, a double number.
*/
public double convertToGrayscale()
{
return ((THIRTY_PERCENT * _red) + (FIFTY_NINE_PERCENT * _green) + (ELEVEN_PERCENT * _blue));
}
/**
* Inverts the color of RGBColor, every spot is reduced relative to 255. For example: (10,20,30) becomes (245,235,225).
*/
public void invert()
{
_red = (MAX_VALUE - _red);
_green = (MAX_VALUE - _green);
_blue = (MAX_VALUE - _blue);
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* #param nums - a component value, should be the number between 1-4
* #param return - return true if the number is between 1-4, false otherwise.
*/
private boolean isValid(int nums)
{
return ((nums >= MIN_VALUE) && (nums <= MAX_VALUE));
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* #param red - the red component
* #param green - the green component
* #param blue - the red component
* #param return true if values are correct, false otherwise.
*/
private boolean isValid(int red, int green, int blue)
{
return ((red <= MAX_VALUE && red >= MIN_VALUE &&
green <= MAX_VALUE && green >= MIN_VALUE &&
blue <= MAX_VALUE && blue >= MIN_VALUE));
}
/**
* Returns RGB color string triplet with numbers between 0-255, i.e. (0,127,127)
*/
public String toString()
{
return ("(" + _red + "," + _green + "," + _blue + ")");
}
/**
* RGBColor will become the color Black. (0,0,0)
*/
private void doBlack()
{
_red = _green = _blue = 0;
}
}
LightBulb Class.
/**
* In this program we use _color to represent the color of the bulb
* And we use _switchedOn to represent whether the bulb is turned on or off.
*
* #author
* #date 20/11/2014.
*/
public class LightBulb
{
/**
instance private variables of the lightbulb's color and the switch state.
*/
private static RGBColor _color;
private boolean _switchedOn;
private int ZERO = 0;
private int MAX = 255;
/**
* Construct a new LightBulb with the given color component values.
* Check if atleast one of the color isn't in the given value range (0-255)
* if not in the range, the default color is black (0,0,0).
*/
public LightBulb(int red, int green, int blue)
{
if(isTrue(red,green,blue))
_color = new RGBColor(red,green,blue);
else
_color = new RGBColor(ZERO,ZERO,ZERO);
_switchedOn = false;
}
/**
* Construct a new LightBulb which is a copy of the given bulb, and turn switch off.
*/
public LightBulb(RGBColor color)
{
_color = new RGBColor(color);
_switchedOn = false;
}
/**
* Construct a new LightBulb which is a copy of the given LightBulb
*/
public LightBulb (LightBulb other)
{
_color = new RGBColor(other._color);
_switchedOn = other._switchedOn;
}
//Return the current color of the bulb.
public RGBColor getColor()
{
return new RGBColor(_color);
}
//Sets the color of the bulb.
public void setColor (RGBColor color)
{
_color = new RGBColor(color);
}
//Checks if the bulb is on, if it is - returns true. else, returns false.
public boolean isSwitchedOn()
{
if(_switchedOn)
return true;
else
return false;
}
//If the lightbulb is turned on, it turns it off. else,if it is off - it turns it on.
public void switchLight()
{
if(_switchedOn)
_switchedOn = false;
else
_switchedOn = true;
}
//Returns a string which prints a triplet of the color in numbers of range (0-255), and the switch state of the bulb.
// e.g. (255,255,0) On , e.g. (255,127,0) Off
public String toString()
{
_color = new RGBColor();
return ("(" +_color.getRed()+ "," +_color.getGreen()+ "," + _color.getBlue() + ")" + " " + switchState());
}
//If the switch is on - returns a string "On". else, if it is off returns a string "Off".
public String switchState()
{
if(_switchedOn)
return ("On");
else
return ("Off");
}
public boolean isTrue(int red, int green, int blue)
{
if( red >= ZERO && red <= MAX &&
green >= ZERO && green <= MAX &&
blue >= ZERO && blue <= MAX )
return true;
else
return false;
}
}
LightBulb tester class.
/**
* Write a description of class Tester here.
*
* #author
* #version (a version number or a date)
*/
public class LightBulbTester
{
/**
*
*/
public static void main(String[] args)
{
// Create two light bulb objects
LightBulb l1 = new LightBulb(127,0,127);
LightBulb l2 = new LightBulb(new RGBColor(127,0,127));
LightBulb l3 = new LightBulb(l2);
// Print (test the get method)
System.out.println("Welcome to Light Bulb tester");
System.out.println("1) color of light object is " + l1.getColor());
// Test the set method
l1.setColor(new RGBColor(50,40,30));
System.out.println("2) The new color of light is :" + l1);
// Test isSwitchedOn
System.out.println("3) Light object is switched on? " + l1.isSwitchedOn());
// Now switch on
l1.switchLight();
System.out.println("4) Light after switchLight():" + l1);
System.out.println("Good luck!");
}
}
In this code -
public String toString()
{
_color = new RGBColor();
return ("(" +_color.getRed()+ "," +_color.getGreen()+ "," + _color.getBlue() + ")" + " " + switchState());
}
you're always outputting the value of a new RGBColor object, which will always give you black. You probably don't want to set _color's value here; just remove that line (or replace it with a null check).
Also, remove the static qualifier from the _color property. You don't want to share the value between all bulbs!
I am at wits end with this problem.
Please note I am a really novice coder (although I'm sure you will see by my code).
The basics:
I have an image that I would like to count the number of objects in. Objects in this instance are just joined up pixels (the image has been threshold-ed and undergone binarization and binary erosion to get to this stage, code not included).
My problem:
I am trying to write some code to count how many objects there are left in this image, and within that method I call another method which is meant to remove any objects that have already been included by searching for neighbouring pixels to which they are attached. However, my current implementation of this removal method is throwing up an error: "coordinates out of bounds". I'm asking for any help solving this issue.
Code for overall object counting:
/**
* countObjects in image
*
* #param binary image to count objects in
* #param original image to put labels on
*
* #return labelled original image for graphics overlay
*/
public static BufferedImage countObjects(BufferedImage image, BufferedImage original){
BufferedImage target = copyImage(image);
int rgbBand = 0;
boolean finished = false;
Graphics labelColour = original.getGraphics();
labelColour.setColor(Color.RED);
while(!finished){
finished = false;
for ( int i=0; i<= target.getRaster().getWidth() - 1; i++ ) {
for( int j=0; j< target.getRaster().getHeight() - 1; j++ ) {
int clrz = target.getRaster().getSample(i, j, rgbBand);
if (clrz == 1) {
System.out.println(clrz);
removeObject(i, j, target);
labelColour.drawString( ""+count, i, j);
finished=true;
}
}
}
}
return original;
Code for object removal:
/**
*
* #param x
* #param y
* #param newImage
*
*/
private static void removeObject( int x, int y, BufferedImage newImage ){
int rgbBand = 0;
int[] zero = new int[] { 0 };
newImage.getRaster().setPixel(x, y, zero);
for (int a = Math.max(0, x - 1); a <= Math.min(x + 1, newImage.getRaster().getWidth()); a++) {
for (int b = Math.max(0, y - 1); b <= Math.min(y + 1, newImage.getRaster().getHeight()); b++) {
int na = a;
int nb = b;
if (newImage.getRaster().getSample(na, nb, rgbBand) == 1) {
removeObject( nc, nd, newImage );
}
}
}
}
In the above removeObject method, I am trying to use a recursive technique to remove pixel coordinates from the image being counted once either they or neighbouring pixels have been labelled.
If any of this is unclear (and I know there are probably more than a few confusing parts of my code, please ask and I will explain further).
Thanks for any help.
I dont have enough reputation to comment hence writing my comment as answer .
Are u sure u dint messed up with the x and y coordinates ?I had faced a similar problem some time ago ,but I had messed up with height and width of the image.
I'm having a little difficulty doing an assignment. I'll post the class and explain.
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.text.*;
/**
* A class that represents a picture. This class inherits from
* SimplePicture and allows the student to add functionality to
* the Picture class.
*
* Copyright Georgia Institute of Technology 2004-2005
* #author Barbara Ericson ericson#cc.gatech.edu
*/
public class Picture extends SimplePicture
{
///////////////////// constructors //////////////////////////////////
/**
* Constructor that takes no arguments
*/
public Picture ()
{
/* not needed but use it to show students the implicit call to super()
* child constructors always call a parent constructor
*/
super();
}
/**
* Constructor that takes a file name and creates the picture
* #param fileName the name of the file to create the picture from
*/
public Picture(String fileName)
{
// let the parent class handle this fileName
super(fileName);
}
/**
* Constructor that takes the width and height
* #param width the width of the desired picture
* #param height the height of the desired picture
*/
public Picture(int width, int height)
{
// let the parent class handle this width and height
super(width,height);
}
/**
* Constructor that takes a picture and creates a
* copy of that picture
*/
public Picture(Picture copyPicture)
{
// let the parent class do the copy
super(copyPicture);
}
////////////////////// methods ///////////////////////////////////////
/**
* Method to return a string with information about this picture.
* #return a string with information about the picture such as fileName,
* height and width.
*/
public String toString()
{
String output = "Picture, filename " + getFileName() +
" height " + getHeight()
+ " width " + getWidth();
return output;
}
/**
* Modified version of method from page 154 of the textbook for copying pictures
*/
public void copyPictureTo(Picture sourcePicture, int xStart, int yStart)
{
Pixel sourcePixel = null;
Pixel targetPixel = null;
//loop through the columns
try{
for (int sourceX = 0, targetX = xStart;
sourceX < sourcePicture.getWidth();
sourceX++, targetX++)
{
//loop through the rows
for (int sourceY = 0,
targetY = yStart;
sourceY < sourcePicture.getHeight();
sourceY++, targetY++)
{
sourcePixel = sourcePicture.getPixel(sourceX,sourceY);
targetPixel = this.getPixel(targetX,targetY);
targetPixel.setColor(sourcePixel.getColor());
}
}
}catch(IndexOutOfBoundsException ex){System.out.println("Either xStart or yStart is out of bounds");System.exit(0);}
}
//morphStage() method is located here.
public void morphStage(Picture startPicture, Picture endPicture, int numStages, int k)
{
Pixel[] pixelArrayStart = startPicture.getPixels();
Pixel[] pixelArrayEnd = endPicture.getPixels();
Pixel pixelObjEnd = null;
Pixel pixelObjStart = null;
Pixel pixelObjNew = null;
//Colour values for starting picture.
int startingRedValue = 0;
int startingGreenValue = 0;
int startingBlueValue = 0;
//Colour values for ending picture.
int endRedValue = 0;
int endGreenValue = 0;
int endBlueValue = 0;
//Colour values for intermediate pictures.
int redValue = 0;
int greenValue = 0;
int blueValue = 0;
//Loops through each entry int he first array, getting the RGB values
for (int i = 0; i < pixelArrayStart.length; i++)
{
//Loops through each entry in the second array, getting the RGB values
{
for (int j = 0; j < pixelArrayEnd.length; j++)
{
pixelObjEnd = pixelArrayEnd[j];
endRedValue = pixelObjEnd.getRed();
endGreenValue = pixelObjEnd.getGreen();
endBlueValue = pixelObjEnd.getBlue();
pixelObjStart = pixelArrayStart[i];
startingRedValue = pixelObjStart.getRed();
startingGreenValue = pixelObjStart.getGreen();
startingBlueValue = pixelObjStart.getBlue();
redValue = startingRedValue +((endRedValue - startingRedValue)/(numStages + 1))*k;
greenValue = startingGreenValue +((endGreenValue - startingGreenValue)/(numStages + 1))*k;
blueValue = startingBlueValue +((endBlueValue - startingBlueValue)/(numStages + 1))*k;
pixelObjNew.setRed(redValue);
pixelObjNew.setGreen(greenValue);
pixelObjNew.setBlue(blueValue);
}
}
}
}
}
// end of class Picture, put all new methods before this
The idea is to create a series of intermediate pictures using the equation, redValue = startingRedValue +((endRedValue - startingRedValue)/(numStages + 1))*k.
I'm not sure if I'm writing the code properly, but the idea was to create an array of pixels for the first picture, get the RGB values, create an array of pixels for the second picture, get the RGB values, and then create the a new pixel, pixelObjNew by setting each RGB value using the equation.
The code compiles fine, but when I try to run it with two pictures, there's an error. (NB: TestMorphing is the class I wrote for the test)
java.lang.NullPointerException
at Picture.morphStage(Picture.java:149)
at TestMorphing.main(TestMorphing.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
This is an introduction to computer science class, btw.
Much appreciated!
EDIT: Here's the pixel class.
import java.awt.Color;
/**
* Class that references a pixel in a picture. A pixel has an x and y
* location in a picture. A pixel knows how to get and set the red,
* green, blue, and alpha values in the picture. A pixel also knows
* how to get and set the color using a Color object.
*
* Copyright Georgia Institute of Technology 2004
* #author Barb Ericson ericson#cc.gatech.edu
*/
public class Pixel
{
////////////////////////// fields ///////////////////////////////////
/** the digital picture this pixel belongs to */
private DigitalPicture picture;
/** the x location of this pixel in the picture (0,0) is top left */
private int x;
/** the y location of this pixel in the picture (0,0) is top left */
private int y;
////////////////////// constructors /////////////////////////////////
/**
* A constructor that take the x and y location for the pixel and
* the picture the pixel is coming from
* #param picture the picture that the pixel is in
* #param x the x location of the pixel in the picture
* #param y the y location of the pixel in the picture
*/
public Pixel(DigitalPicture picture, int x, int y)
{
// set the picture
this.picture = picture;
// set the x location
this.x = x;
// set the y location
this.y = y;
}
///////////////////////// methods //////////////////////////////
/**
* Method to get the x location of this pixel.
* #return the x location of the pixel in the picture
*/
public int getX() { return x; }
/**
* Method to get the y location of this pixel.
* #return the y location of the pixel in the picture
*/
public int getY() { return y; }
/**
* Method to get the amount of alpha (transparency) at this pixel.
* It will be from 0-255.
* #return the amount of alpha (transparency)
*/
public int getAlpha() {
/* get the value at the location from the picture as a 32 bit int
* with alpha, red, green, blue each taking 8 bits from left to right
*/
int value = picture.getBasicPixel(x,y);
// get the alpha value (starts at 25 so shift right 24)
// then and it with all 1's for the first 8 bits to keep
// end up with from 0 to 255
int alpha = (value >> 24) & 0xff;
return alpha;
}
/**
* Method to get the amount of red at this pixel. It will be
* from 0-255 with 0 being no red and 255 being as much red as
* you can have.
* #return the amount of red from 0 for none to 255 for max
*/
public int getRed() {
/* get the value at the location from the picture as a 32 bit int
* with alpha, red, green, blue each taking 8 bits from left to right
*/
int value = picture.getBasicPixel(x,y);
// get the red value (starts at 17 so shift right 16)
// then and it with all 1's for the first 8 bits to keep
// end up with from 0 to 255
int red = (value >> 16) & 0xff;
return red;
}
/**
* Method to get the red value from a pixel represented as an int
* #param value the color value as an int
* #return the amount of red
*/
public static int getRed(int value)
{
int red = (value >> 16) & 0xff;
return red;
}
/**
* Method to get the amount of green at this pixel. It will be
* from 0-255 with 0 being no green and 255 being as much green as
* you can have.
* #return the amount of green from 0 for none to 255 for max
*/
public int getGreen() {
/* get the value at the location from the picture as a 32 bit int
* with alpha, red, green, blue each taking 8 bits from left to right
*/
int value = picture.getBasicPixel(x,y);
// get the green value (starts at 9 so shift right 8)
int green = (value >> 8) & 0xff;
return green;
}
/**
* Method to get the green value from a pixel represented as an int
* #param value the color value as an int
* #return the amount of green
*/
public static int getGreen(int value)
{
int green = (value >> 8) & 0xff;
return green;
}
/**
* Method to get the amount of blue at this pixel. It will be
* from 0-255 with 0 being no blue and 255 being as much blue as
* you can have.
* #return the amount of blue from 0 for none to 255 for max
*/
public int getBlue() {
/* get the value at the location from the picture as a 32 bit int
* with alpha, red, green, blue each taking 8 bits from left to right
*/
int value = picture.getBasicPixel(x,y);
// get the blue value (starts at 0 so no shift required)
int blue = value & 0xff;
return blue;
}
/**
* Method to get the blue value from a pixel represented as an int
* #param value the color value as an int
* #return the amount of blue
*/
public static int getBlue(int value)
{
int blue = value & 0xff;
return blue;
}
/**
* Method to get a color object that represents the color at this pixel.
* #return a color object that represents the pixel color
*/
public Color getColor()
{
/* get the value at the location from the picture as a 32 bit int
* with alpha, red, green, blue each taking 8 bits from left to right
*/
int value = picture.getBasicPixel(x,y);
// get the red value (starts at 17 so shift right 16)
// then and it with all 1's for the first 8 bits to keep
// end up with from 0 to 255
int red = (value >> 16) & 0xff;
// get the green value (starts at 9 so shift right 8)
int green = (value >> 8) & 0xff;
// get the blue value (starts at 0 so no shift required)
int blue = value & 0xff;
return new Color(red,green,blue);
}
/**
* Method to set the pixel color to the passed in color object.
* #param newColor the new color to use
*/
public void setColor(Color newColor)
{
// set the red, green, and blue values
int red = newColor.getRed();
int green = newColor.getGreen();
int blue = newColor.getBlue();
// update the associated picture
updatePicture(this.getAlpha(),red,green,blue);
}
/**
* Method to update the picture based on the passed color
* values for this pixel
* #param alpha the alpha (transparency) at this pixel
* #param red the red value for the color at this pixel
* #param green the green value for the color at this pixel
* #param blue the blue value for the color at this pixel
*/
public void updatePicture(int alpha, int red, int green, int blue)
{
// create a 32 bit int with alpha, red, green blue from left to right
int value = (alpha << 24) + (red << 16) + (green << 8) + blue;
// update the picture with the int value
picture.setBasicPixel(x,y,value);
}
/**
* Method to correct a color value to be within 0 and 255
* #param the value to use
* #return a value within 0 and 255
*/
private static int correctValue(int value)
{
if (value < 0)
value = 0;
if (value > 255)
value = 255;
return value;
}
/**
* Method to set the red to a new red value
* #param value the new value to use
*/
public void setRed(int value)
{
// set the red value to the corrected value
int red = correctValue(value);
// update the pixel value in the picture
updatePicture(getAlpha(), red, getGreen(), getBlue());
}
/**
* Method to set the green to a new green value
* #param value the value to use
*/
public void setGreen(int value)
{
// set the green value to the corrected value
int green = correctValue(value);
// update the pixel value in the picture
updatePicture(getAlpha(), getRed(), green, getBlue());
}
/**
* Method to set the blue to a new blue value
* #param value the new value to use
*/
public void setBlue(int value)
{
// set the blue value to the corrected value
int blue = correctValue(value);
// update the pixel value in the picture
updatePicture(getAlpha(), getRed(), getGreen(), blue);
}
/**
* Method to set the alpha (transparency) to a new alpha value
* #param value the new value to use
*/
public void setAlpha(int value)
{
// make sure that the alpha is from 0 to 255
int alpha = correctValue(value);
// update the associated picture
updatePicture(alpha, getRed(), getGreen(), getBlue());
}
/**
* Method to get the distance between this pixel's color and the passed color
* #param testColor the color to compare to
* #return the distance between this pixel's color and the passed color
*/
public double colorDistance(Color testColor)
{
double redDistance = this.getRed() - testColor.getRed();
double greenDistance = this.getGreen() - testColor.getGreen();
double blueDistance = this.getBlue() - testColor.getBlue();
double distance = Math.sqrt(redDistance * redDistance +
greenDistance * greenDistance +
blueDistance * blueDistance);
return distance;
}
/**
* Method to compute the color distances between two color objects
* #param color1 a color object
* #param color2 a color object
* #return the distance between the two colors
*/
public static double colorDistance(Color color1,Color color2)
{
double redDistance = color1.getRed() - color2.getRed();
double greenDistance = color1.getGreen() - color2.getGreen();
double blueDistance = color1.getBlue() - color2.getBlue();
double distance = Math.sqrt(redDistance * redDistance +
greenDistance * greenDistance +
blueDistance * blueDistance);
return distance;
}
/**
* Method to get the average of the colors of this pixel
* #return the average of the red, green, and blue values
*/
public double getAverage()
{
double average = (getRed() + getGreen() + getBlue()) / 3.0;
return average;
}
/**
* Method to return a string with information about this pixel
* #return a string with information about this pixel
*/
public String toString()
{
return "Pixel red=" + getRed() + " green=" + getGreen() +
" blue=" + getBlue();
}
}
Your problem seems to stem from your trying to use the Pixel type variable, pixelObjNew, while it is still null. You appear to be using a 3rd party library, likely part of your Ga Tech class code, and our not being privy to this code will necessary limit our ability help, but having said that, the bottom line is that you should first assign a valid instantiated object to this variable prior to trying to use it. This might be as simple as calling,
pixelObjNew = new Pixel();
Or it might be a whole lot more complex. Check your library's API, your class notes, your sample code, to find out what you should do.
Key points for solving NPE:
Finding and inspecting the line that throws the NPE is critical to solving it.
A variable that you are trying to use on that line is null, and your trying to dereference it is causing your problem.
Often it's obvious by looking at the line to see which variable is at fault.
At other times you'll need a debugger or System.out.println(...)` statements (the so-called "poor man's debugger") to help you.
Edit
On looking at your Pixel class, it appears that 1) using a default constructor won't do, and that 2) a Pixel by itself appears to be meaningless, that it only makes sense in context with the Picture from which it is a component. This would also suggest to me that your current approach to morphing might be (accent on the might) be off.
My guess, and please understand that this is a huge guess, is that you might want to create several Picture objects, one for each intermediate stage, and one for the end picture. And then you can extract Pixel arrays from each Picture and adjust them (linearly?). Again this is a silly wild arsed guess. Use this advice with caution.
Also, I think that I would not nest for loops to do my morphing if it is to be a linear morph.
pixelObjNew is initialized as null and that never changes. So pixelObjNew.setRed(redValue); is going to throw an NPE.
I am writing a small game where 20 balloons are created on screen and mouse released on them expands them. They are supposed to 'pop' when one balloon touches another, but at present when I click a balloon it pops a random one and throws an 'Array index out of bounds' exception. I've racked my brain to figure out why my code isn't working but just can't get it. Here's some of the code causing the problem:
import comp102.*;
import java.util.*;
import java.awt.Color;
public class BalloonGame implements UIButtonListener, UIMouseListener{
// Fields
private final int numBalloons = 20;
private int currentScore; // the score for the current game
private int highScore = 0; // highest score in all games so far.
private int totalPopped = 0;
Balloon balloons[] = new Balloon[numBalloons];
// Constructor
/** Set up the GUI, start a new game.
*/
public BalloonGame(){
UI.setMouseListener(this);
UI.addButton("New Game", this);
UI.addButton("Lock Score", this);
this.newGame();
}
// GUI Methods to respond to buttons and mouse
/** Respond to button presses, to start a new game and to end the current game */
public void buttonPerformed(String cmd){
if (cmd.equals("New Game")) { this.newGame(); }
else if (cmd.equals("Lock Score")) { this.endGame(); }
}
/** Respond to mouse released with the main action of the game*/
public void mousePerformed(String action, double x, double y) {
if (action.equals("released")) {
this.doAction(x, y);
}
}
/** Start the game:
Clear the graphics pane
Initialise the score information
Make a new set of Balloons at random positions
*/
public void newGame(){
UI.clearGraphics();
this.currentScore = 0;
this.totalPopped = 0;
for (int i = 0; i < this.balloons.length; i++) {
this.balloons[i] = new Balloon(50 + Math.random()*400, 50 + Math.random()*400);
this.balloons[i].draw();
}
UI.printMessage("New game: click on a balloon. High score = "+this.highScore);
}
/** Main game action.
Find the balloon at (x,y) if any,
Expand it
Check whether it is touching another balloon,
If so, update totalPopped, pop both balloons, and remove them from the list
Recalculate the score.
If there are no balloons left, end the game.
*/
public void doAction(double x, double y) {
for (int i = 0; i < this.balloons.length; i++) {
if (this.balloons[i].on(x, y) && !this.balloons[i].isPopped()) {
this.balloons[i].expand();
}
for (int j = 1; j <this.balloons.length; j++) {
if (this.balloons[i].isTouching(this.balloons[j]) && this.balloons[j] != null)
{
this.totalPopped +=2;
this.balloons[i].pop();
this.balloons[j].pop();
this.balloons[i] = null;
this.balloons[j] = null;
}
}
}
this.calculateScore();
if (totalPopped == numBalloons) {
this.endGame();
}
}
/** Find a balloon that the point (x, y) is on.
* Returns null if point is not on any balloon*/
public Balloon findBalloon(double x, double y){
return null;
}
/** Find and return another balloon that is touching this balloon
* Returns null if no such Balloon. */
public Balloon findTouching(Balloon balloon){
return null;
}
/** Calculate the score: sum of the sizes of current ballons, minus
the total of the popped balloons (totalPopped).
Report the score as a message */
public void calculateScore(){
for (Balloon b: balloons) {
this.currentScore += b.size();
}
if (currentScore >= highScore) {
this.highScore = this.currentScore;
}
UI.printMessage("Score = "+this.currentScore+" High score = "+this.highScore);
}
/** Returns true if all the balloons have been popped,
* Returns false if any of the balloons is not popped */
public boolean allPopped(){
for (Balloon b : this.balloons){
if (!b.isPopped()){
return false;
}
}
return true;
}
/** End the current game.
Record the the score as the new high score if it is better
Print a message
Clear the list of balloons (so the player can't keep playing)
*/
public void endGame(){
this.highScore = this.currentScore;
UI.println("High score = " + this.highScore);
Arrays.fill(balloons, null);
}
// Main
public static void main(String[] arguments){
BalloonGame ob = new BalloonGame();
}
}
uses the balloon class also:
import comp102.*;
import java.util.*;
import java.awt.Color;
import java.io.*;
/** Represents a balloon that can grow until it pops.
A Balloon can say whether a particular point is on it, and
whether it is touching another balloon.
It can also return its size.
Once it has popped, no point is on it, and it can't touch another balloon.
Also, its size is reported as a negative value.
*/
public class Balloon{
// Fields
private double radius = 10;
private double centerX, centerY;
private Color color;
private boolean popped = false;
// Constructors
/** Construct a new Balloon object.
Parameters are the coordinates of the center of the balloon
Does NOT draw the balloon yet.
*/
public Balloon(double x, double y){
this.centerX = x;
this.centerY = y;
this.color = Color.getHSBColor((float)Math.random(), 1.0f, 1.0f);
}
public void draw(){
UI.setColor(color);
UI.fillOval(centerX-radius, centerY-radius, radius*2, radius*2);
if (!this.popped){
UI.setColor(Color.black);
UI.drawOval(centerX-radius, centerY-radius, radius*2, radius*2);
}
}
/** Make the balloon larger by a random amount between 4 and 10*/
public void expand(){
if (! this.popped){
this.radius = this.radius + (Math.random()*6 + 4);
this.draw();
}
}
/** pop the balloon (changes colour to gray, draws, and pauses briefly)*/
public void pop(){
this.color = Color.lightGray;
this.popped = true;
this.draw();
UI.sleep(20);
}
/** Returns true if the balloon has been popped */
public boolean isPopped(){
return this.popped;
}
/** Returns true if the point (x,y) is on the balloon, and false otherwise */
public boolean on(double x, double y){
if (popped) return false;
double dx = this.centerX - x;
double dy = this.centerY - y;
return ((dx*dx + dy*dy) < (this.radius * this.radius));
}
/** Returns true if this Balloon is touching the other balloon, and false otherwise
* Returns false if either balloon is popped. */
public boolean isTouching(Balloon other){
if (this.popped || other.popped) return false;
double dx = other.centerX - this.centerX;
double dy = other.centerY - this.centerY;
double dist = other.radius + this.radius;
return (Math.hypot(dx,dy) < dist);
}
/** Calculates and returns the area of the balloon
* Returns it in "centi-pixels" (ie, number of pixels/100)
* to keep them in a reasonable range.
* Returns a negative size if it is popped.*/
public int size(){
int s = (int) ((this.radius * this.radius * Math.PI)/100);
if (popped) { s = 0 - s; }
return s;
}
}
is this right?
for (int j = 1; j <this.balloons.length; j++) {
doesn't it allow i and j to be equal, so you end up asking whether a balloon is touching itself? Do you mean j = i + 1 ?
If you are now getting null pointer exceptions, get into a debugger and step through until you see where. My guess is that you are visiting array items that have been popped, and hence are null.
if (this.balloons[i].isTouching(this.balloons[j]) && this.balloons[j] != null)
You are testing this.balloons[j] for null after you are using it. I'd put some null checks before trying to work with each item.