Google Answers Logo
View Question
 
Q: Java program code ( Answered 5 out of 5 stars,   7 Comments )
Question  
Subject: Java program code
Category: Computers > Programming
Asked by: wcryder-ga
List Price: $80.00
Posted: 14 Nov 2002 19:59 PST
Expires: 14 Dec 2002 19:59 PST
Question ID: 108084
Write a java program that implements a general "Game of Life", a
"cellular automaton" world consisting of a rectangular array of cells,
each of which is either Alive or Dead. It is important that these
guidelines for the question are followed. The world starts in an
initial state (i.e. a pattern of Alive and Dead cells), and then moves
through a series of successive states. Each state is called a
generation. State-transition rules determine the way the pattern of
Alive/Dead cells change from one generation to the next. There are 4
transition possibilities for a cell:

Dead -> Dead:   "stasis"
Dead -> Alive:  "birth"
Alive -> Alive: "survival"
Alive -> Dead:  "death"

The fate of a cell in going from one generation to the next depends on
whether it is Alive or Dead in the current generation, and on the
number of Alive neighbors it has in the current generation. Different
state-transition rules lead to different "Games of Life" with worlds
that evolve in different ways. A particularly interesting state
transition rule discovered by the mathematician John Horton Conway is
this: A "birth" happens only with 3 Alive neighbors, "survival"
happens only with 2 or 3 Alive neighbors, and "stasis" or "death"
happens otherwise. This Conway Rule leads to many interesting patterns
developing in the game.

A neighbor of a cell is defined as one of its 8 adjacent cells (upper
left, above, upper right, left, right, lower left, below, lower
right), so a cell can have at most 8 Alive neighbors. The world is a
finite rectangle with a certain number of rows and columns, and there
are no Alive cells outside the world. The program shall be run as
follows:

java Life <FILENAME>

The initial state of the world is read from the file whose name is
given as the first command line argument (format specified below) A
window is created, which contains these components:
1.	A central panel, which displays the initial state of the world, and
subsequent generations, in a form described below. The user can change
the state of the world by clicking the mouse in a displayed cell.
Doing so changes the state of that cell (to Alive it was Dead, or to
Dead if it was Alive). The result of such a change is displayed.
2.	A text field, initialized to "10", in which the user can enter a
nonnegative integer which is the number of successive generations to
compute and display. This text field should have a label associated
with it, that indicates to the user that it represents the number of
generations.
3.	A button labeled "Start", which when pushed computes and displays
as many subsequent generations as are indicated by the number in the
text field, at a rate of approximately two per second.
4.	An output label that displays a running count of the number of
generations displayed, and error messages as appropriate.

File format: The initial state of the world will be read from a file.
This file is a binary file, with format as follows:
The first 4 bytes of the file are an int, indicating the number of
rows in the world, R. The next 4 bytes in the file are another int,
indicating the number of columns in the world, C. Then there follow
R*C bytes. The first C bytes specify the states of the cells in the
top row of the world, left to right; and so on. A byte that is equal
to 0 indicates a Dead cell; a nonzero byte indicates a Alive cell. If
there are more bytes in the file than required by the world size, the
extra ones are to be ignored. If there are fewer bytes in the file
than required by the world size, the unspecified cells are assumed to
be Dead.

Display format: When run, the Life program first reads a world state
specification file, as described above. It displays this world in a
central panel in the application window, and permits the user to
change the state of some cells by clicking on them. Each cell in the
world should be displayed on the central panel as a filled circle 10
pixels in diameter, and the central panel should be the exact size
required to display all cells in the world. The panel background,
Alive cells, and Dead cells should be displayed in contrasting colors
so they can be distinguished from each other.
When the user clicks the start button, new generations are computed
and displayed. The application pauses after the required generations
have been displayed, permitting the user to continue if they want to,
or to exit the application by clicking on the "close window" button
provided by the window system.

These are the Class interface specifications.  The Life class should
be defined to extend JFrame. An instance of the Life class will
correspond to the top-level application window.

Define this protected instance variable in the class: 
 protected boolean[][] world;  

The elements of the world array represent the states of cells in an
instance of the game of Life. Each cell is in one of two states (Alive
or Dead), so a boolean array is appropriate. The number of rows and
columns of this two-dimensional array must be exactly the same as the
number of rows and columns in this instance of Life. (And note that it
must have protected visibility, so subclasses can access it as
needed.)
 
Define at least these public methods in the Life class: 
/** Constructor:  initialize a new Life object to represent
 *  a world with the given number of rows and columns of cells.
 *  All cells are initially Dead.  This constructor also creates
 *  appropriate components and containers and adds them to the
 *  application container, and creates and registers appropriate
 *  listener objects.  It does not make any GUI objects visible.
 */
public Life(int rows, int cols) 
/** Read a world initial state specification file (format described
 *  in the P7 README) with name given by its argument.  
 *  Create and return a Life object whose world is in the state
specified
 *  by the file.
 *  @throws java.io.IOException containing an appropriate message if
 *  the file is badly formatted or unreadable, or if an I/O error
occurs.
 */
public static Life fromFile(String filename)
		throws IOException
/** Update the state of the protected boolean[][] world array of
 * this Life object (i.e., compute the next generation) according
 * to the Conway state-transition rule.
 * This method does not do any displaying.
 */
public void next() 
/** The entry point for the Life program.  
 *  Creates a Life object initialized from the file given as
 *  the first command line argument, and makes it visible.
 */
public static void main(String args[])

You may define any other private static or instance methods or
variables, or inner classes that you wish.

Here are some suggestions just to help you out 
1.  The hard part is supposed to be implementing the next() method. It
is quite hard to compute the state of the next generation using only
the world array that is representing the current generation; so it is
suggested you create another array to hold the new generation while
you are computing it, and then make the world array pointer point to
it when done. In any case, when next() returns, the protected world
variable must point to the new generation.
2. To compute a new generation, apply the rule of the game to each
cell. Be sure to take into account that the world "ends" at its edges,
as mentioned above. In thinking about how to decompose the problem
into manageable pieces, you may find that methods with suggestive
names like countLiveNeighbors(int row, int col) and isAlive(int row,
int col) might be useful.
4. Each cell takes up a circle 10 pixels in diameter when displayed.
Therefore, if your world has R rows and C columns, your central panel
must have width 10*C and height 10*R pixels to display the world. The
application JFrame needs to be large enough to hold such a central
panel, the start button, the text field, the two required labels, plus
any default borders and decorations belonging to the JFrame. A trick
of JFC/AWT programming to accomplish this is to use a JPanel for the
central panel, call the setPreferredSize() method of the JPanel to set
its size, and after adding it and all other needed components to the
JFrame's content pane, to "pack" the JFrame. Note that
setPreferredSize() takes one argument, of type Dimension. Some code in
your Life constructor can look something like this:
	Container c = this.getContentPane();
	JPanel p = new JPanel();
	p.setPreferredSize(new Dimension(10*C,10*R));
	c.add(p);
	this.pack();
The pack() method computes the right size for the JFrame to be able to
contain its Components, so you don't have to.
Inner classes will be necessary, and in particular anonymous inner
classes will be appropriate.  When useful, include these:
a. An anonymous inner class that extends JPanel and that overrides the
paintComponent(Graphics g) method to display the current world state
in the JPanel. This method should first call super.paintComponent(g)
to clear the background and produce a better-looking animation. An
instance of this class will be the central panel in the application
window.
b. An anonymous inner class that extends MouseAdapter and that
overrides mouseClicked() to handle the mouse click events fired by the
central JPanel. An instance of this class will be registered as a
MouseEvent listener with the central JPanel. The handler method needs
to determine the x,y coordinates of the mouse click, to change the
state of the clicked cell appropriately, and to display the new state.
To display the new state, you can just call the repaint() method of
the JPanel, which takes care of calling its paintComponent() method.
c. An anonymous inner class that implements ActionListener and that
overrides actionPerformed() to handle the start button being clicked.
An instance of this class will be registered as an ActionEvent
listener with the start button. The handler method needs to get the
text in the text field, convert it to an int, and run the game of life
for that many generations (not counting the current generation),
causing each generation to be displayed in the central JPanel. If the
contents of the text field are not parseable as a positive int, an
error should be displayed in the output label. As each generation is
displayed, the number of that generation should be displayed in the
output label.
d. An anonymous inner class that extends WindowAdapter and that
overrides windowClosing() to exit the application. An instance of this
class will be registered as a WindowEvent listener with the overall
JFrame. Alternatively, you could just setDefaultCloseOperation to
JFrame.EXIT_ON_CLOSE.
6. To cause a container to display all of its components, you normally
call the container's repaint() method. However, for animations such as
the Life program, that may not work as you would hope; in an attempt
to be efficient, the runtime system can "coalesce" multiple calls to
paint() into one call, and you won't see anything but the last frame
in the animation. Instead, it is better in animations to call the
paintImmediately() method of the container, which does not do this
coalescing. Note that paintImmediately() takes 4 int arguments which
specify the rectangular area in the container to paint immediately:
paintImmediately(int x, int y, int width, int height)
You should think about calling paintImmediately for two purposes: 
a. In the event handler for the start button, after a new generation
has been computed, call the paintImmediately() method of the central
JPanel. (This leads to its overrided paintComponent() method being
called.) If the JPanel is p, painting the entire JPanel immediately
can be done with a call like
p.paintImmediately(0,0,p.getWidth(),p.getHeight());
b. In the event handler for the start button, after a new generation
has been computed, you will update the text in the output label. To
make this new text appear immediately, call the paintImmediately()
method for that label's container. For convenience, you may want to
place that label in a JPanel container, and place that JPanel in a
region of the top-level JFrame.
7. You might want to create files to test the class.

Clarification of Question by wcryder-ga on 14 Nov 2002 21:15 PST
Please include javadoc comments.
Answer  
Subject: Re: Java program code
Answered By: rbnn-ga on 18 Nov 2002 18:26 PST
Rated:5 out of 5 stars
 
Thank you for your question.

Remember please: if you have any questions or need additional features
or functionality, use the "Request Clarification" to solicit these
*before* rating the question. I am happy to modify the code in
response to requests.

I have placed these files on 

http://www.rbnn.com/google/life 

http://www.rbnn.com/google/life/Life.java
http://www.rbnn.com/google/life/LifePanel.java
http://www.rbnn.com/google/life/LifeTest.java
http://www.rbnn.com/google/life/script.txt
http://www.rbnn.com/google/life/file1.dat
http://www.rbnn.com/google/life/file2.dat
http://www.rbnn.com/google/life/file3.dat
http://www.rbnn.com/google/life/file4.dat
http://www.rbnn.com/google/life/answer.txt
http://www.rbnn.com/google/life/index.html [not for download; for
viewing]

Here is the description of each file:

Life.java is the main JFrame that runs the simulation and is written
according to the specification in your question. It's main purpose is
to create a bunch of JPanels, JButtons, and other things like that,
and to render the main frame.

LifePanel.java handles the "Life-specific" logic and rendering. It is
responsible for displaying and rendering a particular Life grid, and
for computing the next generation from a given generation.

LifeTest.java creates 4 files, file1.dat, file2.dat, file3.dat and
file4.dat. These files are described in the LifeTest.java
documentation, and are designed to test edge cases of the file format.
You can read that documentation from the JavaDoc generated HTML here:

http://www.rbnn.com/google/life/LifeTest.html , or just go to

http://www.rbnn.com/google/life/index.html 

and click on "LifeTest" .

file1.dat is a valid file; file2.dat has missing data; file3.dat has
an invalid ncolumns; and file4.dat has extra data .

script.txt is a sample script that shows how the files are compiled
and run. As it is short, here it is:
# This script demonstrates compiling and running the system

%  ls *.java
Life.java  # the JFrame
LifePanel.java # the JPanel
LifeTest.java # creating the test files
%  javac *.java  # compile everything
%  javadoc -private *.java # lots of output deleted here....
%  java LifeTest # create the .dat files
%  ls *.dat # list the .dat files
file1.dat # normal
file2.dat # missing rows
file3.dat # bad format
file4.dat # extra data

%  java Life file1.dat # this displays a 20x30 life picture
%  java Life file2.dat # displays same, with all but first two rows
dead
%  java Life file3.dat # gives error
Unable to read from file: file3.dat. Got error: java.io.IOException:
bad format
%  java Life file4.dat # same as file1.dat

answer.txt is this answer .

index.html is the root of the javadoc generated tree that holds HTML
documentation of the classes and methods.

all.zip is the zipped version of all the files in the directory.

TO DOWNLOAD
----------
The simplest way is:
 1.  download the java files
 2. javac *.java # to compile the java files
 3. java LifeTest # to generate the dat files
 4. java Life file1.dat # to run a Life simulation
 5. javadoc -private *.java to generate the .html files from javadoc

The script.txt files shows how to generate the .dat and the javadoc
.html files.

SEARCH STRATEGY/DESIGN DECISIONS
-------------------------------

Although I enjoy Life very much, and have even met John Conway in
person (in fact I have a paper in a book in which he also has a
paper), I had some difficulty with the problem here. One of my friends
spent so much time designing Life patterns he delayed his graduation
in fact.

First, generally I think GUI design should be done by GUI designers.
I'm not a GUI designer, and I don't have one available for this
project. That means that things like color schemes and button
placements, although they work, are not aesthetic.

Of course, if you would like to have a different GUI design, just say
so and I can implement it. But making a pretty GUI is something that
is more for artists than programmers.

I tried out many different GUI designs, using BorderLayout first and
then finally the BoxLayout.

One of the big problems that tended to happen is that a layout would
look fine for 50 x 50 grids, but look really bad for 5 x 5 grids. So
the current layout solution I have should at least look OK for fairly
small to reasonably large grids.

Second, some aspects of the specification were a little bit difficult
to do. For instance, I might not have put the boolean[][]world
instance variable in the main GUI class. I would have just delegated
all the Life logic and representation to another class. Having the
world be a boolean[][] in the main class forces the main class to have
too much information on the details of the representation, perhaps. In
general, there were some specific method signatures required that were
fairly tricky to do well.

I considered three designs for the program: 

o Everything in one big class

o The GUI logic in one class and the Life logic in another

o The container logic in one class and the Life logic in another .

I coded everything as the first, but the resulting class became huge
and hard to read. So I split it up.

I also coded a solution using the second, but then I realized that the
world[][] requirement made this tricky.

So instead I used the third solution. 

I tried to re-use code and logic from the CreatureWorld class in an
earlier question.

I also considered using a Swing Timer instead of a Thread.sleep().
This would be a bit cleaner, but did not seem to be required by the
spec.

A good book on design decisions is 

Applying UML and Patterns. by Craig Larman. Prentice-Hall 1997. It has
a lot of excellent design advice.


OTHER LINKS
------------
 
See: http://www.cse.sc.edu/~bays/Life_4D/objects.html for some simple
life objects. These can be input to the program to check that it is
correctly generating Life patterns.

Clarification of Answer by rbnn-ga on 18 Nov 2002 20:01 PST
I forgot to mention here - one important design consideration that I
wanted the code to be as easy as understand as possible subject to the
program specifications. Therefore, I did not add additional features
that would have cluttered up the program (for example - user-settable
frame rate, or an option to use wraparound at the edges).

Request for Answer Clarification by wcryder-ga on 18 Nov 2002 20:35 PST
just a minor note. can you put all of the code in one file and make
whatever needs to be inner classes.

Request for Answer Clarification by wcryder-ga on 18 Nov 2002 20:47 PST
ok just to clarify...i understand that you originally put the code in
one file but it is kind of necessary that Life.java and LifePanel.java
are one file.  THank you.

Clarification of Answer by rbnn-ga on 18 Nov 2002 22:21 PST
Sure, I'd be happy to. 

One quick check - do you mean "all the Java code in one file" or "all
the Java code in one class (which is in one file)"?

It is possible to have two top-level classes in one Java file, I think
anyway.

Anyway, for now I will rewrite the code to put everything in one big
class...

Clarification of Answer by rbnn-ga on 18 Nov 2002 22:57 PST
I have placed the revised files in http://www.rbnn.com/google/life2 .

Please feel free to continue to use the "request clarification"
feature if you have any other questions or would like additional
changes.

If I might make a suggestion, when dealing with multiple versions of
programs, as is the case here, when there is no version control system
(such as CVS) in use, it is a good idea to delet all previous versions
of the software before downloading the new software. Otherwise, subtle
and difficult-to-catch bugs can arise if files from different software
versions are coalesced.

The files to download are now:

http://www.rbnn.com/google/life2 

http://www.rbnn.com/google/life2/Life.java
http://www.rbnn.com/google/life2/LifeTest.java
http://www.rbnn.com/google/life2/script.txt [unchanged, actually,
except for removal of a comment about LifePanel]
http://www.rbnn.com/google/life2/file1.dat
http://www.rbnn.com/google/life2/file2.dat
http://www.rbnn.com/google/life2/file3.dat
http://www.rbnn.com/google/life2/file4.dat
http://www.rbnn.com/google/life2/answer2.txt [this file]
http://www.rbnn.com/google/life2/index.html [not for download; for
viewing]


As requested, I have coalesced Life.java and LifePanel.java into a
single file. However, when this is done there is no particular benefit
from having a separate LifePanel class, so I moved most of the logic
of LifePanel into Life.

The only vestige of LifePanel is now it is an anonymous inner class
used to create a new JPanel, which overrides JPanel.paintComponent:

	grid = new JPanel(){ // anonymous inner class
		public void paintComponent(Graphics g){
		    super.paintComponent(g);
		    paintGrid(g);
		}
	    };

Request for Answer Clarification by wcryder-ga on 19 Nov 2002 00:07 PST
hello again, thanks for the second version.  i don't exactly know if i
did everything right but when after compiling i ran the program using
"java Life explode" where explode is a sample file given to me to test
the class.  when run i get the following error...and i dont know what
it is referring to.  could you help me out?

Exception in thread "main" java.lang.InternalError: Can't connect to
X11 window server using ':0.0' as the value of the DISPLAY variable.
        at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
        at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:126)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:130)
        at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:62)
        at java.awt.Window.init(Window.java:208)
        at java.awt.Window.<init>(Window.java:252)
        at java.awt.Frame.<init>(Frame.java:398)
        at javax.swing.JFrame.<init>(JFrame.java:198)
        at Life.<init>(Life.java:86)
        at Life.fromFile(Life.java:197)
        at Life.main(Life.java:349)

Clarification of Answer by rbnn-ga on 19 Nov 2002 08:47 PST
Hi there,

Sure - this kind of error message is not uncommon. It probably doesn't
have anything to do with the java program; it sounds like a system
configuration issue.

For example, can you check that you can still run Creature? Or if you
have X, can you run X? Try running *any* java program that displays
graphics (not just text), none of them should work.

Typically, one sees an error like this in a situation where you are
running an X program (for example, running a program on a Sun) that
displays its windows on a different terminal (say a local terminal).

The cause of the problem in this case is typically that the local
terminal did not do an "xhosts +" command; or that the DISPLAY
envirnment variable is not set in the remote shell where you are
running java.

Actually it's often a little bit risky to run complex Java programs
over *some* X windowing systems - once in a while X can get confused
(that is not the problem here though).

Anyway, to help you debug this issue, can you please:

1. See if you can still run other java programs?

2. I need to know the exact system configuration you are using:
     A. What kind of computer (operating system) are you sitting down
to run on?
     B. What kind of computer (operating system) is the "java Life"
executing on? The same computer or a different one?
     C. Assuming A and B are different, how exactly are you connecting
to the computer in B?
     D. If A and B are different, can you try running with everything
on the same computer?

Anyway let me know please - I have many years of painful experience
dealing with X problems, it's a tricky protocol.

Request for Answer Clarification by wcryder-ga on 19 Nov 2002 19:09 PST
OK, yes i ran the program from another appropriate terminal and indeed
that was my problem.  everything look excellent!  thank you very much.

Clarification of Answer by rbnn-ga on 19 Nov 2002 19:40 PST
You are welcome and thanks for the comments.
wcryder-ga rated this answer:5 out of 5 stars
very helpful...

Comments  
Subject: Re: Java program code
From: rbnn-ga on 14 Nov 2002 20:21 PST
 
This seems like considerably more work than
https://answers.google.com/answers/main?cmd=threadview&id=106592 
(which attracted an answer at 40) since none of the GUI code is
written. I suspect that you'll be more likely to attract an answer if
either the price for this question were significantly increased over
the 106592 question, or if the GUI code is provided. I cannot speak
for other researchers (some of whom may be quicker Java programmers
than I, of course, so it might be easier for them) but this would take
me a lot of time and I probably wouldn't do it for less than $80 .


Also do you want JavaDoc style comments?
Subject: Re: Java program code
From: wcryder-ga on 14 Nov 2002 21:17 PST
 
At this time, this is the most I can offer for this question.
Subject: Re: Java program code
From: funkywizard-ga on 14 Nov 2002 23:43 PST
 
Best of luck on getting an answer to your question. It is an
interesting question and I look forward to seeing the result.
Subject: Re: Java program code
From: haversian-ga on 15 Nov 2002 00:01 PST
 
Is there any framework you are attaching your code to?  This sounds
like an intro programming assignment, and when I took the intro class,
we were given some GUI code and specifications for how our code must
be written to accomodate it (a list of methods to give the GUI the
information it needed, and some ways for the GUI to request certain
work to be done).

I suspect that you could get someone to do the conceptually hard part
and give you fairly detailed pseudocode, perhaps with real code
snippets for the central loops and such.  Actually writing, testing,
and debugging the code will take quite a bit of time though.  Some
bored Researcher may take on your project, but if you need an answer
sooner than later, the more work you can do yourself, the more likely
you are to succeed.

I might even have helped you myself if I were qualified - I don't know
anything about GUI programming in Java though.

Best of luck!

Haversian
Subject: Re: Java program code
From: mathtalk-ga on 15 Nov 2002 07:04 PST
 
Hi, wcryder and others:

Some ideas for this might be gleaned from this implementation:

[Java applet (with source) by Edwin Martin]

http://www.bitstorm.org/gameoflife/

or a number of others that can be found with Google's keyword search:

"Game of Life" "Java applet" source

://www.google.com/search?hl=en&ie=UTF-8&oe=UTF-8&q=%22Game+of+Life%22+%22Java+applet%22+source&btnG=Google+Search

regards, mathtalk
Subject: Re: Java program code
From: studboy-ga on 19 Nov 2002 13:28 PST
 
Another WOW answer from rbnn-ga!  You're the man!
Can I hire you?  I think you're underpaid :)
Subject: Re: Java program code
From: studboy-ga on 19 Nov 2002 13:38 PST
 
Oh, BTW, GO Bears!  rbnn-ga!  If I'm not wrong...

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy