SkyHog
Touchdown! Greaser!
- Joined
- Feb 23, 2005
- Messages
- 18,431
- Location
- Castle Rock, CO
- Display Name
Display name:
Everything Offends Me
This was a real PITA. It was the first program I had to write in which literally no information was given on how the GUI worked, and we had to write a class that interacted with the GUI without modifying it at all. With the sudoku game, the GUI was well documented so I could figure it out ok. This was not like that.
This is "The Game of Life" the cell birthing game (and I use game lightly). I have officially turned the project in, so I can post it here. Anyone wanna tell me what I did wrong, or could have done better?
I wrote GameOfLife.java and the teacher provided GameOfLifeGUI.java and society.dat (I modified the .dat file to test a few things and everything works fine as long as the rules of the contruct are unchanged. We weren't supposed to test for legit data).
****Turns out I can't attach java or dat files, so here y'all go:
GameOfLife.java
GameOfLifeGUI.java, not written by me, but required for the program to work:
edit: Oh, and the .dat file too, must be located in a folder called societies, in a file called society.dat :
This is "The Game of Life" the cell birthing game (and I use game lightly). I have officially turned the project in, so I can post it here. Anyone wanna tell me what I did wrong, or could have done better?
I wrote GameOfLife.java and the teacher provided GameOfLifeGUI.java and society.dat (I modified the .dat file to test a few things and everything works fine as long as the rules of the contruct are unchanged. We weren't supposed to test for legit data).
****Turns out I can't attach java or dat files, so here y'all go:
GameOfLife.java
Code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
/*This class created by Nick Brennan for CS152.
* A Few notes. I used Global Variables because I make reference to them throughout the program
* I know we haven't covered that yet, but its the best way I could think to use it without passing massive
* amounts of variables between methods. I created a copy of the BoardPlace array to make modifications without
* them taking effect right away. The update method is a bit clunky, but with only a week to work on this with other
* classes having stuff due also, I was unable to think of a better way to check the surrounding cells. I hope this is
* acceptable
*
*/
public class GameOfLife {
/* These are public variables, and I don't think we've done this yet, I hope its ok
*
* outputText is a String to hold the data from the board that checks for the presence of an "O"
* BoardPlace is a character array that holds the data for the board itself
* numCols holds the number of columns in BoardPlace
* numRows holds the number of rows in BoardPlace
*/
public String outputText = "";
public char[][] BoardPlace;
public int numCols, numRows;
public GameOfLife (String fileName){
/* This Method creates the construct for the main GUI to use
*
* inputtedFile is only used to store the file name
* inputText is the Scanner object
*/
File inputtedFile = new File (fileName);
Scanner inputText = null;
try {
inputText = new Scanner (inputtedFile);
} catch (FileNotFoundException e) {
System.err.println("" + fileName + " does not exist");
System.exit(1);
}
//Determine the number of columns
numCols = Integer.parseInt(inputText.next());
//Determine the number of Rows
numRows = Integer.parseInt(inputText.next());
BoardPlace = new char[numCols][numRows];
//Read the rest of the file
inputText.nextLine(); //This throws away the carrage return we don't need
int x = 0; // x here will be the line number we are on
do{
String inputLine = inputText.nextLine();
outputText += inputLine + "\n";
//split inputLine into chunks for the array
for (int y = 0; y < numRows; y++){ //y here will be the column we are in
BoardPlace[x][y] = inputLine.charAt(y);
}
x++;
} while (inputText.hasNext());
}
public String toString (){
/* This method takes the data we use in the board and returns it as a string
* We could at a later time write this to disk, but for now, it is important
* as it helps us test for the presense of "O" on the board, and it gives the
* GUI the ability to parse through the data and separate is as necessary
*/
outputText = "";
for (int x = 0; x < numCols; x++){ //x is the row we are on
for (int y = 0; y < numRows; y++){ //y is the column we are on
outputText += BoardPlace[x][y];
}
outputText += "\n";
}
return outputText;
}
public boolean hasMore(){
/* This method returns a boolean value to determine whether or not
* the letter "O" appears in the board. Without it, it means the board is
* dead
*
* tempOutput is a string that holds the data from the board as its sifted through
*/
String tempOutput = "";
for (int x = 0; x < numCols; x++){
for (int y = 0; y < numRows; y++){
tempOutput += BoardPlace[x][y];
}
tempOutput += "\n";
}
if (tempOutput.contains("O")) return true;
return false;
}
public boolean update() {
/* The meat of the class. This method moves the board to next generation.
* We create a temporary board to store the data temporary, and then after
* checking all of the rules, we overwrite the main board data.
*
* The rules:
* If a cell is dead, and 3 of its neighbors are alive, it becomes alive
* If a cell is alive, and 2 or 3 of its neighbors are alive, it stays alive
* if a cell is alive, and less than 2 or more than 3 of its neighbors are alive, it dies
*
*
* tempBoard is a character array used to hold the Board data while we check it
* alive is a boolean variable used to determine the life status of each cell
* numOfAlive is an integer variable that keeps count of the number of living neighbors
*
*/
//create a temporary board to hold the new data before we rewrite it
char[][] tempBoard = new char[numCols][numRows];
if (hasMore()){ //determines if there are any cells to check
boolean alive;
for (int x = 0; x < numCols; x++){ //x is the column we are on
for (int y = 0; y < numRows; y++){ //y is the row we are on
if (BoardPlace[x][y] == "O".charAt(0)){
alive = true;
}else {
alive = false;
}
if (!alive){
//the cell is dead, are 3 neighbors alive? REMEMBER TO USE tempBoard
//also remember to check if it is a border cell
int numOfAlive = 0;
//check cell directly left
if (y > 0 && BoardPlace[x][y-1] == "O".charAt(0)) {
numOfAlive++;
}
//check the cell directly right
if (y < (numRows - 1) && BoardPlace[x][y+1] == "O".charAt(0)){
numOfAlive++;
}
//check the cell above and to the left
if (x > 0 && y > 0 && BoardPlace[x-1][y-1] == "O".charAt(0)){
numOfAlive++;
}
//check the cell directly above
if (x > 0 && BoardPlace[x-1][y] == "O".charAt(0)){
numOfAlive++;
}
//check the cell above and to the right
if (x > 0 && y < (numRows -1) && BoardPlace[x-1][y+1]== "O".charAt(0)){
numOfAlive++;
}
//check the cell below and to the left
if (x < (numCols - 1) && y > 0 && BoardPlace[x+1][y-1] == "O".charAt(0)){
numOfAlive++;
}
//check the cell directly below
if (x < (numCols - 1) && BoardPlace[x+1][y] == "O".charAt(0)){
numOfAlive++;
}
//check the cell below and to the right
if (x < (numCols - 1) && y < (numRows- 1) && BoardPlace[x+1][y+1] == "O".charAt(0)){
numOfAlive++;
}
// if numOfAlive is exactly 3, then we make the cell alive
if (numOfAlive == 3){
tempBoard[x][y] = "O".charAt(0);
}else {
tempBoard[x][y] = ".".charAt(0);
}
} else {
//the cell is alive, if 2 or 3 neighbors are alive, we leave it alone
//CHECK FOR BORDER CELL
int numOfAlive = 0;
//check the cell directly to the left
if (y > 0 && BoardPlace[x][y-1] == "O".charAt(0)){
numOfAlive++;
}
//check the cell directly to the right
if (y < (numRows - 1) && BoardPlace[x][y+1] == "O".charAt(0)){
numOfAlive++;
}
//check the cell above and left
if (x > 0 && y > 0 && BoardPlace[x-1][y-1] == "O".charAt(0)){
numOfAlive++;
}
//check the cell directly above
if (x > 0 && BoardPlace[x-1][y] == "O".charAt(0)){
numOfAlive++;
}
//check the cell above and right
if (x > 0 && y < (numRows -1 ) && BoardPlace[x-1][y+1] == "O".charAt(0)){
numOfAlive++;
}
//check the cell below and left
if (x < (numCols - 1) && y > 0 && BoardPlace[x+1][y-1] =="O".charAt(0)){
numOfAlive++;
}
//check the cell directly below
if (x < (numCols - 1) && BoardPlace[x+1][y]=="O".charAt(0)){
numOfAlive++;
}
//check the cell below and right
if (x < (numCols - 1) && y < (numRows - 1) && BoardPlace[x+1][y+1] == "O".charAt(0)){
numOfAlive++;
}
//now we check to see if there are exactly 2 or 3 neighbors, and if so, don't change
if (numOfAlive == 2 || numOfAlive == 3) {
tempBoard[x][y]= "O".charAt(0);
}
//the cell is alive, if less than 2 or more than 3 neighbors are alive, kill it
if (numOfAlive < 2 || numOfAlive > 3){
tempBoard[x][y] = ".".charAt(0);
}
}
}
}
//Determine if there is a change to the board
if (tempBoard == BoardPlace) return false;
else {
BoardPlace = tempBoard;
return true;
}
}
//There are no living cells, so there are no updates available
return false;
}
public void changeCell (int row, int col){
/* This method changes the status of a cell. If it is dead, we make it alive.
* If it is alive, we make it dead. This is only called when the user
* clicks on a box manually to change it
*
* There are no local variables.
*/
if (BoardPlace[row][col] == "O".charAt(0)){
BoardPlace[row][col] = ".".charAt(0);
} else if (BoardPlace[row][col] == ".".charAt(0)){
BoardPlace[row][col] = "O".charAt(0);
}
}
}
GameOfLifeGUI.java, not written by me, but required for the program to work:
Code:
/**
* Original version by Tom Slattery.
* Augmented by Andree Jacobson (andree@cs.unm.edu), 12/07/2005
*/
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class GameOfLifeGUI extends JFrame implements ActionListener {
// To avoid Xlint problems in Java 5.0
public static final long serialVersionUID = 1;
public static final int maxDelay = 1000; // By Andree
private GameOfLifePanel myWorld;
private JButton myRunButton, myStopButton;
private JSlider mySpeedSlider; // By Andree
private javax.swing.Timer myTimer;
public GameOfLifeGUI ( String filename ) {
setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
setTitle ( "CS 251 Fall 2006 -- Game of Life" ); //Updated by Nick
setLayout ( new BoxLayout ( getContentPane ( ), BoxLayout.Y_AXIS ) );
myWorld = new GameOfLifePanel ( filename );
add ( myWorld );
myTimer = new javax.swing.Timer ( maxDelay / 2, myWorld );
JPanel controlPanel = new JPanel ( );
myRunButton = new JButton ( "Run" );
myStopButton = new JButton ( "Stop" );
mySpeedSlider = new JSlider ( JSlider.HORIZONTAL, 0, maxDelay, maxDelay / 2 );
JButton stepButton = new JButton ( "Step" );
mySpeedSlider.addChangeListener ( new ChangeListener ( ) {
public void stateChanged ( ChangeEvent e ) {
JSlider source = (JSlider) e.getSource ( );
myTimer.setDelay ( maxDelay - source.getValue ( ) );
}
} );
myRunButton.addActionListener ( this );
myStopButton.addActionListener ( this );
stepButton.addActionListener ( myWorld );
controlPanel.setLayout ( new BoxLayout ( controlPanel, BoxLayout.Y_AXIS ) );
controlPanel.add ( mySpeedSlider );
JPanel buttonCtrl = new JPanel ( new FlowLayout ( ) );
buttonCtrl.add ( stepButton );
buttonCtrl.add ( myRunButton );
buttonCtrl.add ( myStopButton );
controlPanel.add ( buttonCtrl );
add ( controlPanel );
pack ( );
setResizable ( false );
}
public void actionPerformed ( ActionEvent e ) {
if ( e.getSource ( ) == myRunButton )
myTimer.start ( );
else if ( e.getSource ( ) == myStopButton )
myTimer.stop ( );
}
public static void main ( String[] args ) {
new GameOfLifeGUI ( ( args.length == 0 ) ? "./societies/society.dat" : args[0] )
.setVisible ( true );
}
private class GameOfLifePanel extends JPanel implements ActionListener {
// To avoid Xlint problems in Java 5.0
public static final long serialVersionUID = 1;
private GameOfLife mySociety;
private static final int TILE_SIZE = 12;
private int myRows, myCols, myGen;
public GameOfLifePanel ( String filename ) {
mySociety = new GameOfLife ( filename );
myGen = 0;
StringTokenizer sizer = new StringTokenizer ( mySociety.toString ( ) );
myRows = sizer.countTokens ( );
myCols = sizer.nextToken ( ).length ( );
setPreferredSize ( new Dimension ( TILE_SIZE * myCols + myCols - 1,
TILE_SIZE * myRows + myRows + 2 ) );
setBackground ( Color.white );
addMouseListener ( new ClickListener ( ) );
}
private class ClickListener extends MouseAdapter {
public void mouseReleased ( MouseEvent e ) {
int row = e.getY ( ) / ( 1 + TILE_SIZE );
int col = e.getX ( ) / ( 1 + TILE_SIZE );
mySociety.changeCell ( row, col );
repaint ( );
}
}
public void actionPerformed ( ActionEvent e ) {
myGen++;
boolean ret = mySociety.update ( );
if ( !ret )
myTimer.stop ( );
repaint ( );
}
public void paintComponent ( Graphics g ) {
super.paintComponent ( g );
g.setColor ( Color.lightGray );
for ( int r = 1; r <= myRows; r++ )
g.drawLine ( 0, TILE_SIZE * r + r, getWidth ( ), TILE_SIZE * r + r );
for ( int c = 1; c <= myCols; c++ )
g.drawLine ( TILE_SIZE * c + c, 0, TILE_SIZE * c + c, getHeight ( ) );
StringTokenizer st = new StringTokenizer ( mySociety.toString ( ), " \n" );
int r = 0;
while ( st.hasMoreTokens ( ) ) {
String row = st.nextToken ( );
for ( int c = 0; c < myCols; c++ )
if ( row.charAt ( c ) == 'O' ) {
g.setColor ( Color.pink );
g.fillRoundRect ( TILE_SIZE * c + c + 1, TILE_SIZE * r + r + 1,
TILE_SIZE, TILE_SIZE, TILE_SIZE / 2, TILE_SIZE / 2 );
g.setColor ( Color.darkGray );
g.drawRoundRect ( TILE_SIZE * c + c + 1, TILE_SIZE * r + r + 1,
TILE_SIZE, TILE_SIZE, TILE_SIZE / 2, TILE_SIZE / 2 );
}
r++;
}
g.setColor ( Color.darkGray );
g.drawString ( "T = " + myGen, (int) ( TILE_SIZE * .5 ), TILE_SIZE - 1 );
}
}
}
edit: Oh, and the .dat file too, must be located in a folder called societies, in a file called society.dat :
Code:
12 18
..................
..................
...O......O.O.....
..O..O.......O....
..................
..................
....OO.OO.........
....OO........O...
......O.......O...
.............OOO..
..................
..................
Last edited: