因为
frame.setVisible(false);
给出了以下异常,
Exception in thread "main" java.lang.NullPointerException
at Simulation.drawOcean(Simulation.java:72)
at Simulation.main(Simulation.java:191)
应用程序有2个以下的java文件。
模拟类启动GUI。
使用默认命令行参数运行Simulation.java后,尽管有限的while循环,Frame仍未关闭。 在模拟完成后,我无法通过单击关闭按钮(右上角 - 红色)来关闭框架。
我是否需要为Frame设置一些属性?
请帮帮我!!!
/* Simulation.java */
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.util.Random;
/* DO NOT CHANGE THIS FILE (except as noted). */
/* (You may wish to make temporary changes or insert println() statements) */
/* while testing your code. When you're finished testing and debugging, */
/* though, make sure your code works with the original version of this file */
/**
* The Simulation class is a program that runs and animates a simulation of
* Sharks and Fish.
*
* The Simulation program takes up to four parameters. The first two specify
* the width and height of the ocean. The third parameter specifies the value
* of starveTIme. For example, if you run
*
* java Simulation 25 25 1
*
* then Simulation will animate a 25x25 ocean with a starveTime of 1. If you
* run "java Simulation" with no parameters, by default Simulation will animate
* a 50x25 ocean with a starveTime of 3. With some choices of parameters,
* the ocean quickly dies out; with others;, it teems forever.
*
* @author mohet01
*
*/
public class Simulation {
/**
* The constant cellSize determines the size of each cell on the screen
* during animation. (You may change this if you wish).
*/
private static final int cellSize = 4;
/**
* Default parameters. (You may change this of you wish).
*/
private static int i = 50; //Default ocean width
private static int j = 25; //Default ocean height
private static int starveTime = 3; //Default shark starvation time
/**
* drawOcean() adds cell contents as part of graphics
*/
private static void drawOcean(Graphics graphics, Ocean ocean){
if(ocean != null){
int width = ocean.width();
int height = ocean.height();
for(int row = 0; row < height; row++){
for(int col = 0; col < width; col++){
int contents = ocean.cellContents(row, col);
if(contents == Ocean.SHARK){
//Draw a red Shark
graphics.setColor(Color.red);
graphics.fillRect(row*cellSize, col*cellSize, cellSize, cellSize);
}else if(contents == Ocean.FISH){
// Draw a green fish
graphics.setColor(Color.green);
graphics.fillRect(row * cellSize, col * cellSize, cellSize, cellSize);
}else{
//Clear the rectangle
graphics.clearRect(row, col, cellSize, cellSize);
}
}
}
}
}
/**
* main() reads the parameters and performs the simulation and animation.
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
Ocean sea;
/**
* Read the input parameters
*/
if(args.length >0){
try{
i = Integer.parseInt(args[0]);
}catch(NumberFormatException e){
System.out.println("First argument to Simulation is not a number.");
}
}
if(args.length > 1){
try{
j = Integer.parseInt(args[1]);
}catch(NumberFormatException e){
System.out.println("Second argument to Simulation is not a number");
}
}
if(args.length > 2){
try{
starveTime = Integer.parseInt(args[2]);
}catch(NumberFormatException e){
System.out.println("Third argument to Simulation is not a number");
}
}
/**
* Create a window on your screen
*/
Frame frame = new Frame("Sharks and Fish");
frame.setSize(i*cellSize + 10, j*cellSize + 30);
frame.setVisible(true);
/**
* Create a "Canvas" we can draw upon; attach it to the window
*/
Canvas canvas = new Canvas();
canvas.setBackground(Color.white);
canvas.setSize(i*cellSize, j*cellSize);
frame.add(canvas);
Graphics graphics = canvas.getGraphics();
/**
* Create the initial ocean.
*/
sea = new Ocean(i, j, starveTime);
/**
* Visit each cell (in a roundabout order); randomnly place a fish, shark,
* or nothing in each.
*/
Random random = new Random(0);
int x = 0;
int y = 0;
for(int row = 0;row < j; row++){
//This will visit every x-coordinate once.
x = (x + 78887) %j;
if((x & 8) == 0){
for(int col = 0; col < i; col++){
//This will visit every y coordinate once.
y = (y+78887)%i;
if((y & 8) == 0){
int r = random.nextInt();
if(r < 0){
//50% of cells start with fish
//x - width, y - height
sea.addFish(x, y);
}else if(r > 1500000000){
//~15% of cells start with sharks
sea.addShark(x, y);
}
}
}
}
}
/**
* Perform timesteps forever
*/
int timeLeft = 20;
while (timeLeft > 0) {
// Wait one second (1000 milliseconds)
Thread.sleep(1000);
// Draw the current ocean
drawOcean(graphics, sea);
// For fun, you might wish to change the delay in the next line.
// If you make it too short, though, the graphics won't work properly.
// Simulate a timestep
sea = sea.timeStep();
timeLeft--;
}
}
}
/* Ocean.java */
/**
* The Ocean class defines an object that models an ocean full of sharks and
* fish. Descriptions of the methods you must implements appear below. They
* include a constructor of the form
*
* public Ocean(int i, int j, int starveTime);
*
* that creates an empty ocean having width i and height j, in which sharks
* starve after starveTime timesteps.
*
* See the README file accompanying this project for additional details.
*
* @author mohet01
*
*/
public class Ocean {
/**
* Do not rename these constants. WARNING: if you change the numbers, you
* will need to recompile Test4.java. Failure to do so will give you a very
* hard-to-find bug.
*/
public final static int EMPTY = 1;
public final static int SHARK = 2;
public final static int FISH = 3;
/**
* Define any variables associated with an Ocean object here. These
* variables MUST be private.
*
*/
private final static int UNKNOWN = -1; // for unknown return type
private int width;
private int height;
private int[][] oceanMatrix;
//TODO space optimization on below matrix
private int[][] sharkHungerLevelMatrix;
private int starveTime;
/**
* The following methods are required for Part I.
*
*/
/**
* Constructor that creates an empty ocean having width i and
* height j, in which sharks starve until after starveTime timesteps.
*
* @param width(i)
* is the width of the ocean.
* @param height(j)
* is the height of the ocean.
* @param starveTime
* is the number of timeSteps sharks survive without food.
*/
public Ocean(int i, int j, int starveTime) {
this.width = i;
this.height = j;
this.oceanMatrix = new int[j][i];
this.sharkHungerLevelMatrix = new int[j][i];
this.starveTime = starveTime;
for (int row = 0; row < j; row++) {
for (int col = 0; col < i; col++) {
oceanMatrix[row][col] = EMPTY;
}
}
for (int row = 0; row < j; row++) {
for (int col = 0; col < i; col++) {
sharkHungerLevelMatrix[row][col] = EMPTY;
}
}
}
/**
* width() returns the width of an ocean Object.
*
* @return the width of the ocean.
*
*/
public int width() {
return this.width;
}
/**
* height() returns the height of an Ocean object.
*
* @return the height of the Ocean.
*/
public int height() {
return this.height;
}
/**
* starveTime() returns the number of timesteps sharks survive without food.
*
* @return the number of timesteps sharks survive without food.
*/
public int starveTime() {
return starveTime;
}
/**
* addFish() places a fish in cell (x,y) if the cell is empty. If the cell
* is already occupied, leave the cell as it is.
*
* @param x
* is the x-coordinate of the cell to place a fish in.
* @param y
* is the y-coordinate of the cell to place a fish in.
*/
public void addFish(int x, int y) {
if (oceanMatrix[x][y] == EMPTY) {
oceanMatrix[x][y] = FISH;
}
}
/**
* addShark() (with two parameters) places a newborn shark in cell (x, y) if
* the cell is empty. A "newborn" shark is equivalent to a shark that has
* just eaten. If the cell is already occupied, leave the cell as it is.
*
* @param x
* is the x-coordinate of the cell to place a shark in.
* @param y
* is the y-coordinate of the cell to place a shark in.
*/
public void addShark(int x, int y) {
if (oceanMatrix[x][y] == EMPTY) {
oceanMatrix[x][y] = SHARK;
}
}
/**
* cellContents() returns EMPTY is cell (x,y) is empty, FISH if it contains
* a fish, and SHARK if it contains a shark.
*
* @param x
* is the x-coordinate of the cell whose contents are queried.
* @param y
* is the y-coordinate of the cell whose contents are queried.
*/
public int cellContents(int x, int y) {
return oceanMatrix[x][y];
}
/**
* isFish() checks for the existence of fish in that cell.
* @param x
* is the x-coordinate of the cell whose contents are queried.
* @param y
* is the y-coordinate of the cell whose contents are queried.
* @return the boolean value
*/
private boolean isFish(int x, int y){
return (this.oceanMatrix[x][y] == Ocean.FISH);
}
/**
* isShark() checks for the existence of shark in that cell.
* @param x
* is the x-coordinate of the cell whose contents are queried.
* @param y
* is the y-coordinate of the cell whose contents are queried.
* @return the boolean value
*/
private boolean isShark(int x, int y){
return (this.oceanMatrix[x][y] == Ocean.SHARK);
}
/**
* isSharkStarving() checks the hunger level of shark, if reached to starveTime level
* @param x
* is the x-coordinate of the cell whose contents are queried.
* @param y
* is the y-coordinate of the cell whose contents are queried.
* @return the boolean value
*/
private boolean isSharkStarving(int x, int y){
return (this.sharkHungerLevelMatrix[x][y] == (this.starveTime+1));
}
/**
* checkFish() checks the existence of atleast one fish
* surrounding shark cell
* @param x
* is the x-coordinate of the cell whose contents are queried.
* @param y
* is the y-coordinate of the cell whose contents are queried.
* @return returns true on atleast one fish exist otherwise false
*
*/
private boolean checkFish(int x, int y){
for(int i = x-1;i <= x+1; i++){
for(int j = y-1; j <= y+1; j++){
if(this.isFish(mod(i,this.height), mod(j,this.width))){
return true;
}
}
}
return false;
}
/**
* countShark() counts the number of sharks surrounding queried cell
* @param x
* is the x-coordinate of the cell whose contents are queried.
* @param y
* is the y-coordinate of the cell whose contents are queried.
* @return returns number of sharks surrounding fish cell
*/
private int countShark(int x, int y){
int neighbourSharkCount = 0;
for(int i = x-1;i <= x+1; i++){
for(int j = y-1; j <= y+1; j++){
if(this.isShark(mod(i,this.height), mod(j,this.width))){
neighbourSharkCount++;
}
} // end inner for loop
}//end outer for loop
return neighbourSharkCount;
}
/**
* countFish() counts the number of fish surrounding queried cell
* @param x
* is the x-coordinate of the cell whose contents are queried.
* @param y
* is the y-coordinate of the cell whose contents are queried.
* @return returns number of sharks surrounding queried cell
*/
private int countFish(int x, int y){
int neighbourFishCount = 0;
for(int i = x-1;i <= x+1; i++){
for(int j = y-1; j <= y+1; j++){
if(this.isFish(mod(i,this.height), mod(j,this.width))){
neighbourFishCount++;
}
} // end inner for loop
}//end outer for loop
return neighbourFishCount;
}
/**
* mod() performs the modulo operation using euclidean divison
*
* @param n
* is the numerator
* @param d
* is the denominator
* @return the remainder
*/
private int mod(int n, int d) {
if (n >= 0)
return n % d;
else
return d + ~(~n % d);
}
/**
* timeStep() performs a simulation timestep as described in README.
*
* @return an ocean representing the elapse of one timestep.
*/
public Ocean timeStep() {
Ocean sea = new Ocean(width, height, starveTime);
for (int row = 0; row < this.height; row++) {
for (int col = 0; col < this.width; col++) {
switch(this.oceanMatrix[row][col]){
case Ocean.SHARK:
boolean gotTheFish = false;
//Check all the 8 neighbors of a Shark Cell for fish
if(this.checkFish(row,col)){
gotTheFish = true;
}
//Updating Shark Cell
if(gotTheFish){
/*
* 1) If a cell contains a shark, and any of its neighbors is a fish, then the
* shark eats during the time step, and it remains in the cell at the end of the
* time step. (We may have multiple sharks sharing the same fish. This is fine;
* they all get enough to eat.)
*/
sea.oceanMatrix[row][col] = Ocean.SHARK; // for next time step
}else{
/*
* 2) If a cell contains a shark, and none of its neighbors is a fish, it gets
* hungrier during the time step. If this time step is the (starveTime + 1)th
* time step the shark has gone through without eating, then the shark dies
* (disappears). Otherwise, it remains in the cell.
*/
this.sharkHungerLevelMatrix[row][col]++;
if(this.isSharkStarving(row,col)){
this.oceanMatrix[row][col] = Ocean.EMPTY; // for this time step
this.sharkHungerLevelMatrix[row][col] = Ocean.EMPTY; // for this time step
}
sea.sharkHungerLevelMatrix[row][col] = this.sharkHungerLevelMatrix[row][col]; // for next time step
sea.oceanMatrix[row][col] = this.oceanMatrix[row][col]; // for next time step
}
break;
case Ocean.FISH:
int neighbourSharkCount=0;
//Check all the 8 neighbors of a Fish cell to count for sharks
neighbourSharkCount=countShark(row,col);
//Updating fish cell for current & next time step
if(neighbourSharkCount ==1){
/*
* 4) If a cell contains a fish, and one of its neighbors is a shark, then the
* fish is eaten by a shark, and therefore disappears.
*/
this.oceanMatrix[row][col] = Ocean.EMPTY; //fish disappears this time step
}
else if(neighbourSharkCount > 1){
/*
* 5) If a cell contains a fish, and two or more of its neighbors are sharks, then
* a new shark is born in that cell. Sharks are well-fed at birth; _after_ they
* are born, they can survive an additional starveTime time steps without eating.
*/
sea.oceanMatrix[row][col] = Ocean.SHARK; // new shark for next time step
}
else if(neighbourSharkCount < 1){
/*
* 3) If a cell contains a fish, and all of its neighbors are either empty or are
* other fish, then the fish stays where it is.
*/
sea.oceanMatrix[row][col] = FISH; //for next time step
}
break;
case Ocean.EMPTY:
int fishCount=0;
int sharkCount=0;
//Check all the 8 neighbors of an Empty cell to count sharks and Fish
fishCount = this.countFish(row,col);
sharkCount = this.countShark(row, col);
//Update Empty Cell for current & next time step.
/* (no need to handle this case)
* 6) If a cell is empty, and fewer than two of its neighbors are fish, then the
* cell remains empty.
*/
if((fishCount >= 2) && (sharkCount <=1)){
/*
* 7) If a cell is empty, at least two of its neighbors are fish, and at most one
* of its neighbors is a shark, then a new fish is born in that cell.
*/
this.oceanMatrix[row][col] = FISH;// for current time step
sea.oceanMatrix[row][col] = FISH; //for next time step
}else if((fishCount >= 2) && (sharkCount >= 2)){
/*
* 8) If a cell is empty, at least two of its neighbors are fish, and at least two
* of its neighbors are sharks, then a new shark is born in that cell. (The new
* shark is well-fed at birth, even though it hasn’t eaten a fish yet.)
*/
sea.oceanMatrix[row][col] = Ocean.SHARK; // for next time step
}
break;
}
}//end inner for loop
}//end outer for loop
return sea;
}
/**
* The following method is required for Part II.
*
*
*/
/**
* addShark() (with three parameters) places a shark in cell (x, y) if the
* cell is empty. The shark's hunger is represented by the third parameter.
* If the cell is already occupied, leave the cell as it is, You will need
* this method to help convert run-length encodings to Oceans.
*
* @param x
* is the x-coordinate of the cell to place a shark in.
* @param y
* is the y-coordinate of the cell to place a shark in.
* @param feeding
* is an integer that indicates the shark's hunger. You may
* encode it any way you want; for instance, "feeding" may be the
* last timestep the shark was fed, or the amount of time that
* has passed since the shark was last fed, or the amount of time
* left before the shark will starve. It's upto you, but be
* consistent.
*/
public void addShark(int x, int y, int feeding) {
this.oceanMatrix[x][y] = Ocean.SHARK;
this.sharkHungerLevelMatrix[x][y] = feeding;
}
/**
* The following method is required for Part III.
*/
/**
* sharkFeeding() returns an integer that indicates the hunger of the shark
* in cell (x, y), using the same "feeding" representation as the parameter
* to addShark() described above. If cell (x, y) does not contain a shark,
* then its return value is undefined--that is, anything you want. Normally,
* this method should not be called if cell (x, y) does not contain a shark.
* You will need this method to help convert Oceans to run-length encodings.
*
* @param x
* is the x-coordinate of the cell whose contents are queried.
* @param y
* is the y-coordinate of the cell whose contents are queried.
*
*/
public int sharkFeeding(int x, int y) {
if(this.isShark(x, y)){
return this.sharkHungerLevelMatrix[x][y];
}
return Ocean.UNKNOWN;
}
}
答案 0 :(得分:6)
虽然这不是不是 Swing程序,但您可以将JFrame
替换为Frame
以利用EXIT_ON_CLOSE
。
JFrame frame = new JFrame("Sharks and Fish");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
AWT方法是添加WindowListener
。
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
答案 1 :(得分:1)
你试过吗?
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);