Game of Life Assignment - java

My board correctly detects groups with less than 3 neighbors and kills them off, but doesn't seem to detect and give birth to cells with 3 neighbors.
Any thoughts?
If I haven't provided enough information let me know, and I can paste more of the code, but I think this is all of the relevant parts.
Thank you in advance for any advice offered.
public boolean getCell(int row, int col) {
boolean state = board[row][col];
int neighbors = 0;
for (int x = row-1; x <= row+1; x++) {
for (int y = col-1; y <= col+1; y++) {
// don't include this
if ((x != row || y != col) && x != -1 && y != -1
&& x != NROWSCOLS && y != NROWSCOLS) {
if (board[x][y] == ALIVE){
neighbors ++;
}
}
}
}
if (neighbors > 3 || neighbors < 2)
state = DEAD;
else if(neighbors == 3)
state = ALIVE;
return state;
}
Here is the lifeCycle method requested.
/** Process one life cycle of the cellular automaton
*
*/
public void lifeCycle() {
for (int x = 0; x < NROWSCOLS ; x++) {
for (int y = 0; y < NROWSCOLS; y++) {
getCell(x,y);
}
}
generations ++;
}
I've attached the LifeGUI for reference, but this code is provided and not intended for me to change.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LifeGUI extends JPanel {
// game instance variables
private Life board; // game board
// GUI components
private JLabel generationsLived;
private JButton resetButton, cycleButton; // reset control and cycle control
private Cell[][] cells; // board cells for display
/** Construct new Life game with a graphical user interface */
public LifeGUI() {
// create and initialize game board and display representation
board = new Life();
cells = new Cell[Life.NROWSCOLS][Life.NROWSCOLS];
// set layout for game display
setLayout(new BorderLayout());
// Create board cells and add to display
JPanel boardPanel = new JPanel();
boardPanel.setLayout(new GridLayout(Life.NROWSCOLS, Life.NROWSCOLS));
for (int row = 0; row < Life.NROWSCOLS; row++) {
for (int col = 0; col < Life.NROWSCOLS; col++) {
cells[row][col] = new Cell(Life.DEAD, row, col);
boardPanel.add(cells[row][col]);
}
}
add(boardPanel, BorderLayout.CENTER);
// Set up 2 buttons
// a reset button so it starts a new game when clicked
// a cycle button to tell the Life automaton to live one cycle
resetButton = new JButton("New Game");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
board.newGame();
updateDisplay();
}
});
cycleButton = new JButton("Live One Cycle");
cycleButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
board.lifeCycle();
updateDisplay();
}
});
// Put the buttons and the generation count display on the screen
JPanel buttonPanel = new JPanel();
buttonPanel.add(resetButton);
buttonPanel.add(cycleButton);
generationsLived = new JLabel(" Generations Lived: " , JLabel.RIGHT);
buttonPanel.add(generationsLived);
add(buttonPanel, BorderLayout.SOUTH);
// show initial display
updateDisplay();
}
/** Update display to match game state. */
public void updateDisplay() {
// update count display
generationsLived.setText(" Generations Lived: " + board.getGenerationCount());
// update board display
for (int row = 0; row < Life.NROWSCOLS; row++) {
for (int col = 0; col < Life.NROWSCOLS; col++) {
cells[row][col].setState(board.getCell(row,col));
}
}
repaint();
}
/** Create new game and a window to display it */
private static void test() {
JFrame f = new JFrame("The Game of Life"); // top-level window
LifeGUI l = new LifeGUI();
f.getContentPane().add(l);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600,600);
f.validate();
f.setVisible(true);
f.toFront();
}
public static void main(String[] args) {
// To support stand-alone application
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
LifeGUI.test();
}
});
}
}

public boolean getCell(int row, int col) {
boolean state = board[row][col];
int neighbors = 0;//you are summing the alive neighbours
//keep var declaration outside the iteration over them
for (int x = Math.max(0,row-1); x < Math.min(row+2,NROWSCOLS); x++) {
for (int y = Math.max(0,col-1); y < Math.min(col+2,NROWSCOLS); y++) {
//using min and max to ensure x and y remain between 0 and NROWSCOLS
//so no IOBException
if (board[x][y] == ALIVE){
neighbors ++;
}
}
}
}
if (neighbors > 3 || neighbors < 2)//only do the check when you are finished counting the alive neighbours
state = DEAD;
else if(neighbors == 3)
state = ALIVE;
return state;
}

check your loop is not correct.
for (int x = row-1; x <= row; x++)
it will always go to board[row] index. which is out of bound . same thing for other loop

Please check this
at Life.getCell(Life.java:63)
The problem is in the line 63 of Life.java
I don't know if the problem is there but check this line:
if (x != row || y != col && x != -1 && y != -1
&& x != NROWSCOLS && y != NROWSCOLS) {
because is not doing what you think it's doing beacuse of the operator precedence,
please, add some parentheses.
Like this
if ((x != row || y != col) && x != -1 && y != -1
&& x != NROWSCOLS && y != NROWSCOLS) {

The || will not work as intended without adding perenthisis.
Current code will do this:
if (x != row || (y != col && x != -1 && y != -1 && x != NROWSCOLS && y != NROWSCOLS))
You prob want this
if ((x != row || y != col) && x != -1 && y != -1 && x != NROWSCOLS && y != NROWSCOLS)
or this
if (x != row && y != col && x != -1 && y != -1 && x != NROWSCOLS && y != NROWSCOLS)

Related

Calculating next frame in conways game of life using java

trying to create a Conways Game of life, but apparently the shapes are not like they have to be. Perhaps someone can help me find the issue.
For example the glider :
- X - - - -
- - X X - -
- X X - - -
- - - - - -
becomes this
- - X X - -
- X - - - -
X X X - - -
- X X X - -
but should be like this :
- - X - - -
- - - X - -
- X X X - -
- - - - - -
And my code looks like this
public Frame(int x, int y) {
setWidth(x);
setHeight(y);
if (x<1)
frame = null;
else if (y<1)
frame = null;
else {
frame = new String [x][y];
for (int i=0; i<frame.length; i++) {
for (int j=0; j<frame[i].length; j++) {
frame [i][j] = DEAD;
}
}
} // else
} // construktor
public Integer getNeighbourCount(int x, int y) {
Frame cell = new Frame(getHeight(), getWidth());
int counter = 0;
if(frame[x][y].equals(ALIVE))
{
counter = counter - 1;
}
for(int i=x-1; i<=x+1;i++){
if(i<frame.length && i>0){
for(int j=y-1; j<=y+1;j++){
if(j<frame[i].length && j>0){
if (frame[i][j]==ALIVE) {
counter++;
}
}
}
}
}
return counter;
}
public Frame nextFrame() {
// Returns next frame
Frame cell = new Frame(getWidth(), getHeight());
//cell.frame = new String[getWidth()][getHeight()];
for(int i = 0; i < frame.length; i++){
for(int j =0; j <frame[i].length;j++){
int n = getNeighbourCount(i,j);
if(cell.frame[i][j]==null) {
cell.frame[i][j] = DEAD;
}
if (isAlive(i, j) && n < 2 || n > 3) {
cell.frame[i][j] = DEAD;
}
if (isAlive(i, j) && n == 3 || n == 2){
cell.frame[i][j] = ALIVE;
}
if(!isAlive(i, j) && n == 3) {
cell.frame[i][j] = ALIVE;
}
if(isAlive(i, j) && n > 3){
cell.frame[i][j] = DEAD;
}
frame[i][j] = cell.frame[i][j];
}
}
cell.toString();
return cell;
}
`
Full code http://pastebin.com/LMwz724H
Here's a solution that works - using an enum for each cell and getting the i/j and x/y stuff right (I think). It certainly generates the correct first iteration:
static class GameOfLife {
final int w;
final int h;
State[][] frame;
enum State {
Dead, Alive;
}
public GameOfLife(int w, int h) {
this.w = w;
this.h = h;
frame = new State[h][w];
}
public void alive(int x, int y) {
frame[y][x] = State.Alive;
}
public void tick() {
frame = nextGeneration();
}
private int surroundingPopulation(int x, int y) {
int pop = 0;
for (int i = y - 1; i <= y + 1; i++) {
for (int j = x - 1; j <= x + 1; j++) {
// On frame - vertically.
if ((i >= 0 && i < h)
// On frame horizontally.
&& (j >= 0 && j < w)
// Alive
&& (frame[i][j] == State.Alive)
// Not the center.
&& (i != y || j != x)) {
pop += 1;
}
}
}
return pop;
}
private State[][] nextGeneration() {
State[][] next = new State[h][w];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int pop = surroundingPopulation(x, y);
// Any live cell
if (frame[y][x] == State.Alive) {
if (pop < 2) {
// ... with fewer than two live neighbours dies, as if caused by under-population.
next[y][x] = State.Dead;
} else if (pop > 3) {
// ... with more than three live neighbours dies, as if by overcrowding.
next[y][x] = State.Dead;
} else {
// ... with two or three live neighbours lives on to the next generation.
next[y][x] = State.Alive;
}
} else {
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
if (pop == 3) {
next[y][x] = State.Alive;
}
}
}
}
return next;
}
#Override
public String toString() {
StringBuilder s = new StringBuilder();
for (State[] row : frame) {
for (State c : row) {
s.append(c == State.Alive ? "X" : " ");
}
s.append("\r\n");
}
return s.toString();
}
}
public void test() {
GameOfLife g = new GameOfLife(6, 6);
g.alive(1, 0);
g.alive(2, 1);
g.alive(3, 1);
g.alive(1, 2);
g.alive(2, 2);
System.out.println("Before:\r\n" + g);
g.tick();
System.out.println("After:\r\n" + g);
}
I believe the problem is that you are copying the new value as you iterate through the loop. This means neighbours are using the value from the next tick rather than the current one.
You can fix this by waiting until you calculated all new values in your new frame: cell.frame and then iterate through the frame again and copy from cell.frame to frame.
An alternative (better in my view) is to have away of cloning a frame during construction. Then you could change your nextFrame method to create a clone of frame and use the clone to set the new values in frame.
You are changing the DEAD and ALIVE frames while you iterate through the grid. You need to store the coordinates which should die or become alive and perform that afterwards.
Store the coordinates in two ArrayLists (dead, alive). The first and second position is the x and y axis, and change those coordinates according to whether they should become alive or not.
Here's a snippet from a simple test I wrote a while back. As others have mentioned, don't change values on an active board while still reading them. Instead, clone the board and make changes to the copy while reading the current board.
Another problem I bumped into a few times was iterating over y, then x for each y, but referring to x,y when accessing a point. It feels back to front :)
// Rules:
// 1) Any live cell with fewer than two live neighbours dies, as if caused by under-population.
// 2) Any live cell with two or three live neighbours lives on to the next generation.
// 3) Any live cell with more than three live neighbours dies, as if by overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
void mutateGrid() {
// Copy existing grid into the next generation's grid
boolean[][] mutatedGrid = new boolean[gridXWidth][gridYHeight];
for (int i = 0; i < gridXWidth; i++) {
System.arraycopy(grid[i], 0, mutatedGrid[i], 0, gridYHeight);
}
// Start mutation rules
for (int y = 0; y < gridYHeight; y++) {
for (int x = 0; x < gridXWidth; x++) {
int liveNeighbours = countLiveNeighbours(x,y);
if (liveNeighbours < 2 || liveNeighbours > 3) {
mutatedGrid[x][y] = false;
}
else if (liveNeighbours == 3) {
mutatedGrid[x][y] = true;
}
}
}
grid = mutatedGrid;
}
int countLiveNeighbours(int x, int y) {
int count = 0;
for (int j = y-1; j <= y+1; j++) {
for (int i = x-1; i <= x+1; i++) {
if (i < 0 || j < 0 || i >= gridXWidth || j >= gridYHeight){
continue;
}
if (grid[i][j]) {
count++;
}
}
}
count -= grid[x][y]?1:0; // remove self from count
return count;
}

Error in tile game action listener loop

This is my ActionListen class that adds actionlisteners to the buttons on the grid based on what number is on them. If I click a button next to the blank spot(TileGame.tile[x][y]==0), then the two buttons should swap, however, when I click a button, nothing happens.
Here is my code :
public class ActionListen
{
int x;
int y;
public ActionListen()
{
for( x = 0 ; x <= 2 ; x++)
{
for( y = 0 ; y <= 2 ; y++)
{
if( x <2 && y <2)
{
if(TileGame.tile[x][y] !=0 && TileGame.tile[x+1][y] == 0)
{
TileGame.tilebutton[x][y].addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
TileGame.tile[x+1][y] = TileGame.tile[x][y];
TileGame.tile[x][y] = 0;
new DrawGame();
}
});
}
else if(TileGame.tile[x][y] !=0 && TileGame.tile[x][y+1] ==0)
{
TileGame.tilebutton[x][y].addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
TileGame.tile[x][y+1] = TileGame.tile[x][y];
TileGame.tile[x][y] = 0;
new DrawGame();
}
});
}
The code currently does not care about where the empty tile is placed. So you just swap the tile clicked with a fixed tile in the neighbourhood. This might be the blank one. But you should search for the blank tile (or store the blank tile coordinates somewhere accessible), and swap those coordinates, not just some random one.
Also maybe there should be a check if the blank tile is uberhaupt in the neighbourhood, aka can it be swapped?
TileGame.tile[x][y] = TileGame.tile[getXCoordinateBlankTile()][getYCoordinateBlankTile()];
TileGame.tile[getXCoordinateBlankTile()][getYCoordinateBlankTile()] = 0;
setXCoordinateBlankTile(x);
setYCoordinateBlankTile(y);

Connect Four Win Check Not Working

So I have been working on my final term project which is a Connect Four game. I ran into this issue where i believe my CheckWin logic should work, put is providing me with no output when i run the program. I have my CheckWin() being called in my actionPerformed and I am stuck as to what to do here. As a side note, is there any way to easily increase the size of text inside of a JButton? I would like to increase the size of the "X's" and "O's". I am relatively new at programming so sorry if these are simple fixes. My code is below:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Connect implements ActionListener {
private JFrame window = new JFrame();
private JPanel myPanel = new JPanel();
private JPanel myPanelB = new JPanel();
private JButton[][] myButtons = new JButton[6][7];
private JButton[] buttons = new JButton[7];
private boolean win = false;
private int count = 5;
private int count2 = 5;
private int count3 = 5;
private int count4 = 5;
private int count5 = 5;
private int count6 = 5;
private int count7 = 5;
private int countA = 0;
private String letter = "";
public boolean checkHorizontalWin(String letter) {
for (int y = 0; y < myButtons.length; y++) {
// going to length-3 to avoid IndexOutOfBounds exception
for (int x = 0; x < myButtons[y].length - 3; x++) {
if (myButtons[y][x].getText().equals(letter)
&& myButtons[y][x + 1].getText().equals(letter)
&& myButtons[y][x + 2].getText().equals(letter)
&& myButtons[y][x + 3].getText().equals(letter)
) {
return true;
}
}
}
return false;
}
public boolean checkVerticalWin(String letter) {
for (int y = 0; y < myButtons.length - 3; y++) {
for (int x = 0; x < myButtons[y].length; x++) {
if (myButtons[y][x].getText().equals(letter)
&& myButtons[y + 1][x].getText().equals(letter)
&& myButtons[y + 2][x].getText().equals(letter)
&& myButtons[y + 3][x].getText().equals(letter)
) {
return true;
}
}
}
return false;
}
public boolean checkDiagonalToTheLeftWin(String letter) {
for (int y = 0; y < myButtons.length - 3; y++) {
for (int x = 0; x < myButtons[y].length - 3; x++) {
if (myButtons[y][x].getText().equals(letter)
&& myButtons[y + 1][x + 1].getText().equals(letter)
&& myButtons[y + 2][x + 2].getText().equals(letter)
&& myButtons[y + 3][x + 3].getText().equals(letter)
) {
return true;
}
}
}
return false;
}
public boolean checkDiagonalToTheRightWin(String letter) {
for (int y = 0; y < myButtons.length - 3; y++) {
for (int x = 3; x < myButtons[y].length; x++) {
if (myButtons[y][x].getText().equals(letter)
&& myButtons[y + 1][x - 1].getText().equals(letter)
&& myButtons[y + 2][x - 2].getText().equals(letter)
&& myButtons[y + 3][x - 3].getText().equals(letter)
) {
return true;
}
}
}
return false;
}
public Connect(){
window.setSize(800,700);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myPanel.setLayout(new GridLayout(1,7));
myPanelB.setLayout(new GridLayout(6,7));
for (int i = 0; i < buttons.length; i ++){
buttons[i] = new JButton();
myPanel.add(buttons[i]);
buttons[i].addActionListener(this);
}
for (int i = 0; i < 6; i ++){
for (int j = 0; j < 7; j ++){
myButtons[i][j] = new JButton();
myPanelB.add(myButtons[i][j]);
}
}
window.add(myPanel, BorderLayout.NORTH);
window.add(myPanelB, BorderLayout.CENTER);
window.setVisible(true);
}
public void actionPerformed(ActionEvent e){
countA++;
if (countA % 2 == 0)
letter = "X";
else
letter = "O";
if (e.getSource() == buttons[0]){
myButtons[count][0].setText(letter);
count --;
}
if (e.getSource() == buttons[1]){
myButtons[count2][1].setText(letter);
count2 --;
}
if (e.getSource() == buttons[2]){
myButtons[count3][2].setText(letter);
count3--;
}
if (e.getSource() == buttons[3]){
myButtons[count4][3].setText(letter);
count4--;
}
if (e.getSource() == buttons[4]){
myButtons[count5][4].setText(letter);
count5--;
}
if (e.getSource() == buttons[5]){
myButtons[count6][5].setText(letter);
count6--;
}
if (e.getSource() == buttons[6]){
myButtons[count7][6].setText(letter);
count7--;
}
if (myButtons[0][0].getText().equals("O") || myButtons[0][0].getText().equals("X")){
buttons[0].setEnabled(false);
}
if (myButtons[0][1].getText().equals("O") || myButtons[0][1].getText().equals("X")){
buttons[1].setEnabled(false);
}
if (myButtons[0][2].getText().equals("O") || myButtons[0][2].getText().equals("X")){
buttons[2].setEnabled(false);
}
if (myButtons[0][3].getText().equals("O") || myButtons[0][3].getText().equals("X")){
buttons[3].setEnabled(false);
}
if (myButtons[0][4].getText().equals("O") || myButtons[0][4].getText().equals("X")){
buttons[4].setEnabled(false);
}
if (myButtons[0][5].getText().equals("O") || myButtons[0][5].getText().equals("X")){
buttons[5].setEnabled(false);
}
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X")){
buttons[6].setEnabled(false);
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X")){
buttons[6].setEnabled(false);
if (checkHorizontalWin(letter)
|| checkVerticalWin(letter)
|| checkDiagonalToTheLeftWin(letter)
|| checkDiagonalToTheRightWin(letter)
) {
win = true;
if (win == true) {
JOptionPane.showMessageDialog(null, letter + " has won!");
System.exit(0);
}
}
}
if(win == true){
JOptionPane.showMessageDialog(null, letter + " has won!");
System.exit(0);
} else if(count == 42 && win == false){
JOptionPane.showMessageDialog(null, "tie game");
System.exit(0);
}
}
}
public static void main(String[] args){
new Connect();
}
}
Identation helps.
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X"))
{
buttons[6].setEnabled(false);
// Missing brace on previous if
// checkXWin methods only invoked inside the above if-statement.
if (checkHorizontalWin(letter)
|| checkVerticalWin(letter)
|| checkDiagonalToTheLeftWin(letter)
|| checkDiagonalToTheRightWin(letter)
) {
win = true;
if (win == true) {
JOptionPane.showMessageDialog(null, letter + " has won!");
ystem.exit(0);
}
}
}
You haven't closed a brace in one of your if statements properly in the actionPerformed method. As a result, your program will only check for a win once the last column is full.
It also seems the condition if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X") is repeated twice. That wouldn't be the cause of your issue but I think you might want to remove one of those statements.
Your brackets on your if statements are incorrectly placed.
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X")){
buttons[6].setEnabled(false);
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X")){
buttons[6].setEnabled(false);
On both of theses if statements you have opening brackets but the closing brackets do not come until the end of the actionPerformed method.
This means the code to check for a winner does not get executed unless both of these conditions resulted in true, which is not what you want and I'm pretty sure is impossible...

My Game of life just keeps dying out all the time

I am trying to write the code to Conway's game of life but it just keeps dying out. I do not know what i should write so instead of making all the calculations as the code going forward it should just store what the code says and then make the changes. And to clarify i do not want my code to make one decision about one cell and the change it and then move on to the next cell but I want it to make a decision move on to the next cell and in the end of my code i want it to change all the cell att once.
This is the button to create the world:
private void btnSVActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
for (rad = 0; rad < 15; rad++){
for (kolumn = 0; kolumn < 15; kolumn++){
int x = 10 + 20 * kolumn;
int y = 10 + 20 * rad;
int diameter = 20;
int liv = (int) (Math.random()+0.5);
Cirkel cirkel = new Cirkel(x, y, diameter, liv);
cirklar.add(cirkel);
}
}
repaint();
}
This is a button to make the next generation:
private void btnNGActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
for (i=0; i<=225; i++){
rad=(i/15+1);
kolumn=(i%15+1);
if (rad==1 && kolumn==1) {
int levandeGrannarH1=cirklar.get(i+1).kollaLevande()
+cirklar.get(i+15).kollaLevande()
+cirklar.get(i+16).kollaLevande();
if ((levandeGrannarH1!=2 && levandeGrannarH1!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarH1==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==1 && kolumn==15 ) {
int levandeGrannarH2=cirklar.get(i-1).kollaLevande()+cirklar.get(i+14).kollaLevande()+cirklar.get(i+15).kollaLevande();
if ((levandeGrannarH2!=2 && levandeGrannarH2!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarH2==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==15 && kolumn==1 ) {
int levandeGrannarH3=cirklar.get(i+1).kollaLevande()+cirklar.get(i-14).kollaLevande()+cirklar.get(i-15).kollaLevande();
if ((levandeGrannarH3!=2 && levandeGrannarH3!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarH3==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==15 && kolumn==15 ) {
int levandeGrannarH4=cirklar.get(i-1).kollaLevande()+cirklar.get(i-15).kollaLevande()+cirklar.get(i-16).kollaLevande();
if ((levandeGrannarH4!=2 && levandeGrannarH4!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarH4==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==1 && kolumn>1 && kolumn<15) {
int levandeGrannarR1=cirklar.get(i-1).kollaLevande()+cirklar.get(i+1).kollaLevande()+cirklar.get(i+14).kollaLevande()+cirklar.get(i+15).kollaLevande()+cirklar.get(i+16).kollaLevande();
if ((levandeGrannarR1!=2 && levandeGrannarR1!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarR1==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad>1 && kolumn==15 && rad<15) {
int levandeGrannarR2=cirklar.get(i-15).kollaLevande()+cirklar.get(i-16).kollaLevande()+cirklar.get(i-1).kollaLevande()+cirklar.get(i+14).kollaLevande()+cirklar.get(i+15).kollaLevande();
if ((levandeGrannarR2!=2 && levandeGrannarR2!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarR2==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==15 && kolumn>1 && kolumn<15) {
int levandeGrannarR3=cirklar.get(i-1).kollaLevande()+cirklar.get(i+1).kollaLevande()+cirklar.get(i-14).kollaLevande()+cirklar.get(i-15).kollaLevande()+cirklar.get(i-16).kollaLevande();
if ((levandeGrannarR3!=2 && levandeGrannarR3!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarR3==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad>1 && kolumn==1 && rad<15 ) {
int levandeGrannarR4=cirklar.get(i-15).kollaLevande()+cirklar.get(i-14).kollaLevande()+cirklar.get(i+1).kollaLevande()+cirklar.get(i+15).kollaLevande()+cirklar.get(i+16).kollaLevande();
if ((levandeGrannarR4!=2 && levandeGrannarR4!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarR4==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad>1 && kolumn>1 && rad<15 && kolumn<15) {
int levandeGrannar = cirklar.get(i-16).kollaLevande()+cirklar.get(i-15).kollaLevande()+cirklar.get(i-14).kollaLevande()+cirklar.get(i-1).kollaLevande()+cirklar.get(i+1).kollaLevande()+cirklar.get(i+14).kollaLevande()+cirklar.get(i+15).kollaLevande()+cirklar.get(i+16).kollaLevande();
if ((levandeGrannar!=2 && levandeGrannar!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannar==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
repaint();
}
}
This is the explanation of how the cells should look like and if they are alive or not.
public class Cirkel {
private int x = 0;
private int y = 0;
private int diameter = 10;
private int liv = 1;
public Cirkel(int x, int y, int diameter, int liv){
this.x = x;
this.y = y;
this.diameter = diameter;
this.liv = liv;
}
public void rita(Graphics g){
if (this.liv==1)
g.setColor(Color.green);
else
g.setColor(Color.white);
g.fillOval(this.x, this.y, this.diameter, this.diameter);
}
public int kollaLevande(){
return this.liv;
}
public void gorLevande(){
this.liv=1;
}
public void gorDod(){
this.liv=0;
}
}
I would be grateful for any kind of help and if there is some problem whit my question please just ask and I will try to explain in an other way.
When you calculate your next generation, you appear to be trying to update the state of your current grid cells, in other words, you're setting the state of the cells in your cirklar ArrayList, while you're still using cirklar to calculate the state of the next generation of cells. But doing this before the entire grid has been checked will effect calculations of the grid cell neighbors down-stream. And in fact you already know that this is a problem, since you state:
And to clarify i do not want my code to make one decision about one cell and the change it and then move on to the next cell but I want it to make a decision move on to the next cell and in the end of my code i want it to change all the cell att once.
To fix this, you need to create a new grid, and then when doing your calculations, set the state of the new grid cells as dead or alive. Then when you've completed your iteration through the entire grid, swap the new grid in for the old grid.
Also note that you have a lot of unneeded redundancy in your code, and I think that you're doing this in order to handle the edges of the grid. This can be cleaned up greatly and greatly simplified by thinking through your coding a bit. Do something like:
// pseudo-code:
SomeArray newGrid = new SomeArray....
for (int currentRow = 0; currentRow <= NUMBER_OF_ROWS; currentRow++) {
for (int currentCol = 0; currentCol <= NUMBER_OF_COLS; currentCol++) {
int minumumRow = Math.max(currentRow - 1, 0); // *** check for edge!!!
int maximumRow = Math.min(currentRow + 1, NUMBER_OF_ROWS); // *** check for edge!!!
int minumumCol = Math.max(currentCol - 1, 0); // *** check for edge!!!
int maximumCol = Math.MIN(currentCol + 1, NUMBER_OF_COLS); // *** check for edge!!!
int neighborCount = 0;
for (row = minumumRow; row <= maximumRow; row++) {
for (col = minumumCol; col <= maximumCol; col++) {
if (row != currentRow || col != currentCol) {
// check if neighbors alive and increment neighborCount
}
}
}
// use neighbor count to set the state of the grid cell in a **new** grid
// silly pseudo-code:
newGrid.getCell(currentRow, currentCol).setState(....)
}
}
// now you've checked all the grid and set the new grid states.
// Time to swap grids
currentGrid = newGrid;

GUI with Reversi, refuses to wait for players move java

I wrote a Reversi program that makes a gui filled with a 2d array of buttons. there are several methods including validMoves() which makes the valid moves setEnabled(true); and shows a red dot so the user knows which buttons are active. it also flips the correct tiles when you pick which tile you want to move.
the problem i am running into is that the gui doesn't wait for the player to make a move. i wrote an ai which basically is the exact same as the player it finds the valid moves, finds which one will flip the most tiles and returns it in the format "x*y" which my method will then substring into x and y and make the move and flip the tiles.
i tried thread.sleep() and wait() and a while (!hasMoved) and a bunch of other things it just doesn't want to cooperate.
with the wait() i run into an infinite loop bc the gui is there but nothing is in it. however when i comment the wait out it shows up exactly as it should.
package reversi;
/*
* bugs need to make it check the edges too // it goes out of bounds
* refresh scores doesnt work
*
* add clear all readys after someone does a move
*/
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JApplet;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Timer;
/**
* #author 13ponchera
* the board for reversi that will play the game
*/
public class ReversiBoard extends JApplet
{
private int score1;
private int score2;
private int turn;
private Icon p1 = new ImageIcon("images/p1.png");
private Icon p2 = new ImageIcon("images/p2.png");
private Icon bGround = new ImageIcon("images/bGround.png");
private Icon ready = new ImageIcon("images/ready.png");
// will help the action listener determin which players turn it is
private int x; // the number of buttons
private JButton[][] buttons;
private JPanel settingPanel =
new JPanel();
private JButton newGame =
new JButton("New Game?");
private JLabel score1A;
private JLabel score2A;
private JPanel gameBoard =
new JPanel();
private AI ai = new AI(bGround,p1,p2);
private boolean hasMoved;
private Timer t;
/**
* Initialization method that
* will be called after the applet is loaded
* into the browser.
* sets up everything
*/
public void init()
{
score1 = 0;
score2 = 0;
// sets the viewer to say the score
score1A = new JLabel("Player: " + score1);
score2A = new JLabel("Computer:" + score2);
//adds components to the setting panel
settingPanel.add(newGame);
newGame.addActionListener(new NewGameListener());
settingPanel.add(score1A);//initialized at 0
settingPanel.add(score2A);
//creates a game board of any size as long as it is an even number
String a = JOptionPane.showInputDialog
(null, "please enter an even integer for x");
x = Integer.parseInt(a) + 2;
if ((x % 2 == 0) && (x > 4))
{
gameBoard = new JPanel(new GridLayout(x, x, 4, 4));
buttons = new JButton[x][x];
}// add 2 to x then set the edges to a new picture
else
{
//asks for a new number untill number is even
while ((x % 2 != 0) && (x < 4))
{
String responce = JOptionPane.showInputDialog
(null, "Must be an even "
+ "number rows and collums \n\tplease enter x");
x = Integer.parseInt(responce) + 2;
}
gameBoard = new JPanel(new GridLayout(x, x, 4, 4));
buttons = new JButton[x][x];
}
//creates the buttons for each slot and puts them into a 2d array
for (int c = 0; c < x; c++)
{
for (int d = 0; d < x; d++)
{
buttons[c][d] = new JButton();
buttons[c][d].setIcon(bGround);
// adds the background default pict
buttons[c][d].addActionListener
(new ButtonListener(buttons[c][d],c,d));
// adds a generic button listener
buttons[c][d].setEnabled(false);
// the buttons are non clickable except for the valid moves
gameBoard.add(buttons[c][d]);
buttons[c][d].setIcon(bGround);
buttons[c][d].setDisabledIcon(bGround);
// adds the buttons to the jpanel
}
}
//makes the edges a different color
// adds the jpanel with all of the buttons into the content pane
buttons[x/2][x/2]
.setIcon(p1);
buttons[x/2][x/2]
.setDisabledIcon(p1);
buttons[(x/2) - 1][(x/2) - 1]
.setIcon(p1);
buttons[(x/2) - 1][(x/2) - 1]
.setDisabledIcon(p1);
refreshTable();
// makes the middle upper left and lower right white pieces
buttons[(x/2) - 1][(x/2)]
.setIcon(p2);
buttons[x/2][(x/2) - 1]
.setIcon(p2);
buttons[(x/2) - 1][(x/2)]
.setDisabledIcon(p2);
buttons[x/2][(x/2) - 1]
.setDisabledIcon(p2);
refreshTable();
// makes the midle upper right and lower left black pieces
getContentPane()
.add(gameBoard, BorderLayout.CENTER);
getContentPane();//burp the applet
// after two days of hitting my head on the keyboard
getContentPane()
.add(settingPanel, BorderLayout.SOUTH);
//adds the setting panel (new game button
//and scores to the content pane)
refreshTable();
t = new Timer();
hasMoved = false;
validMoves();
refreshTable();
synchronized(t)
{
while(!hasMoved)
{
try
{
t.wait(50);
}
catch (InterruptedException ex)
{
Logger.getLogger(ReversiBoard.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}
refreshTable();
aiTurn();
// make the edges a different picture
}
/**
* refreshes the table so that pictures will appear
*/
public void refreshTable()
{
for (int a = 0; a < x; a++)
{
for (int b = 0; b < x; b++)
{
buttons[a][b].repaint();
}
}
setScores();
score1A.setText
("Player: " + score1);
score2A.setText
("Computer: " + score2);
gameBoard.repaint();
settingPanel.repaint();
}
/**
* finds all the valid moves and sets the
* buttons enabled and gives them an identifiable picture
*/
public void validMoves()
{
int c = 0;
int d = 0;
// temperary values so search can go on uninterupted
for(int a = 1; a < x - 1; a++)
{
for(int b = 1; b < x - 1; b++)
{
//looks at every tile
if (buttons[a][b].getIcon() ==bGround)
{
//if it is a background child look to
//see if there is an enemy peace adjacent
if (buttons[a + 1][b].getIcon() == p2)
{
// keeps checking that direction
//until it runs to the end of the
//board or hits an ally
// c is the cordinates of where it finds
c = a + 1;
while ((buttons[c][b].getIcon() == p2)
&& (c < x)
&& (c > 0))
{
if (buttons[c + 1][b].getIcon() == p1)
{
buttons[a][b].setEnabled(true);
buttons[a][b]
.setIcon(ready);
//JOptionPane.showMessageDialog(null,"");
}
c++;
}
}
//see if there is an enemy peace adjacent
if (buttons[a - 1][b].getIcon() == p2)
{
// keeps checking that direction
//until it runs to the end of the
//board or hits an ally
// c is the cordinates of where it finds
c = a - 1;
while ((buttons[c][b].getIcon() == p2)
&& (c < x)
&& (c > 0))
{
if (buttons[c - 1][b].getIcon() == p1)
{
buttons[a][b].setEnabled(true);
buttons[a][b]
.setIcon(ready);
//JOptionPane.showMessageDialog(null,"");
}
c--;
}
}
if (buttons[a][b + 1].getIcon() == p2)
{
// keeps checking that direction
//until it runs to the end of the
//board or hits an ally
// c is the cordinates of where it finds
c = b + 1;
while ((buttons[a][c].getIcon() == p2)
&& (c < x)
&& (c > 0))
{
if (buttons[a][c + 1].getIcon() == p1)
{
buttons[a][b].setEnabled(true);
buttons[a][b]
.setIcon(ready);
//JOptionPane.showMessageDialog(null,"");
}
c++;
}
}
if (buttons[a][b - 1].getIcon() == p2)
{
// keeps checking that direction
//until it runs to the end of the
//board or hits an ally
// c is the cordinates of where it finds
c = b - 1;
while ((buttons[a][c].getIcon() == p2)
&& (c < x)
&& (c > 0))
{
if (buttons[a][c - 1].getIcon() == p1)
{
buttons[a][b].setEnabled(true);
buttons[a][b]
.setIcon(ready);
//JOptionPane.showMessageDialog(null,"");
}
c--;
}
}
//starts checking diagonals
if (buttons[a + 1][b + 1].getIcon() == p2)
{
// keeps checking that direction
//until it runs to the end of the
//board or hits an ally
// c is the cordinates of where it finds
c = a + 1;
d = b + 1;
while ((buttons[c][d].getIcon() == p2)
&& (c < x)
&& (c > 0)
&& (d < x)
&& (d > 0))
{
if (buttons[c + 1][d + 1].getIcon() == p1)
{
buttons[a][b].setEnabled(true);
buttons[a][b]
.setIcon(ready);
// JOptionPane.showMessageDialog(null,"");
}
c++;
d++;
}
}
if (buttons[a - 1][b - 1].getIcon() == p2)
{
// keeps checking that direction
//until it runs to the end of the
//board or hits an ally
// c is the cordinates of where it finds
c = a - 1;
d = b - 1;
while ((buttons[c][d].getIcon() == p2)
&& (c < x)
&& (c > 0)
&& (d < x)
&& (d > 0))
{
if (buttons[c - 1][d -1].getIcon() == p1)
{
buttons[a][b].setEnabled(true);
buttons[a][b]
.setIcon(ready);
//JOptionPane.showMessageDialog(null,"");
}
c--;
d--;
}
}
if (buttons[a - 1][b + 1].getIcon() == p2)
{
// keeps checking that direction
//until it runs to the end of the
//board or hits an ally
// c is the cordinates of where it finds
c = a - 1;
d = b + 1;
while ((buttons[c][d].getIcon() == p2)
&& (c < x)
&& (c > 0)
&& (d < x)
&& (d > 0))
{
if (buttons[c - 1][d + 1].getIcon() == p1)
{
buttons[a][b].setEnabled(true);
buttons[a][b]
.setIcon(ready);
// JOptionPane.showMessageDialog(null,"");
}
c--;
d++;
}
}
if (buttons[a + 1][b - 1].getIcon() == p2)
{
// keeps checking that direction
//until it runs to the end of the
//board or hits an ally
// c is the cordinates of where it finds
c = a + 1;
d = b - 1;
while ((buttons[c][d].getIcon() == p2)
&& (c < x)
&& (c > 0)
&& (d < x)
&& (d > 0))
{
if (buttons[c + 1][d - 1].getIcon() == p1)
{
buttons[a][b].setEnabled(true);
buttons[a][b]
.setIcon(ready);
// JOptionPane.showMessageDialog(null,"");
}
c++;
d--;
}
}
}
}
}
refreshTable();
/*try
{
Thread.sleep(50); // 30 seconds NA
}
catch (InterruptedException ex)
{
Logger.getLogger(ReversiBoard.class.getName())
.log(Level.SEVERE, null, ex);
}*/
}
/**
* calculates the scores of each player
*/
/**
*
* #return boolean if game is over
*/
public boolean winner()
{
refreshTable();
if (!anyMove(1) && !anyMove(0))
return true;
//joptionpan the winner (if score1 > score 2).... and vv
return false;
}
/**
* #param player 1 for player 1 for computer
* #return boolean if there is a move
*/
public void clearReady()
{
for (int a = 0; a < x; a++)
{
for (int b = 0; b < x; b++)
{
if (buttons[a][b].getIcon() == ready)
{
buttons[a][b].setIcon(bGround);
buttons[a][b].setEnabled(false);
buttons[a][b].setDisabledIcon(bGround);
}
}
}
}
private void makeMove(String move)
{
int temp = 0;
char[] f = move.toCharArray();
for(int i = 0; i < f.length; i++)
{
if (f[i] == ('*'))
temp = i;
}
int x = Integer.parseInt(move.substring(0,temp));
int y = Integer.parseInt(move.substring(temp + 1));
buttons[x][y].setIcon(p2);
buttons[x][y].setEnabled(false);
buttons[x][y].setDisabledIcon(p2);
flip(1,x,y);
}
private void aiTurn()
{
String move = ai.makeMove(buttons);
// string move is a string with cordinates seperated by a *
makeMove(move);
turn++;
}
class ButtonListener implements ActionListener
{
private JButton a;
private int x;
private int y;
private ButtonListener(JButton jButton, int c, int d)
{
a = jButton;
x = c;
y = d;
}
public void actionPerformed(ActionEvent e)
{
//must differentiate between p1 and p2
switch (turn % 2)
{
case 0:
a.setIcon(p1);
a.setEnabled(false);
a.setDisabledIcon(p1);
flip(0,x,y);
turn++;
clearReady();
hasMoved = true;
/*synchronized(t)
{
t.notifyAll();
}*/
refreshTable();
break;
case 1:
a.setIcon(p2);
a.setEnabled(false);
a.setDisabledIcon(p2);
flip(1,x,y);
turn++;
clearReady();
hasMoved = true;
/*synchronized(t)
{
t.notifyAll();
}*/
refreshTable();
break;
}
}
}
}
See below how your GUI application should behave (more or less) :
create the widgets
register listeners to the widgets
wait for user action
update the Gui to display user's move
call the AI to do its move and display it
go back to point 3
You already have done the points 1 and 2 done in your init method. You should remove the last part of this method (the block with the while(!hasMoved) loop) : it's the point 3, and it is handled by the Applet after the init is finished. You have nothing to do.
When the user clicks on a JButton (provided the button is enabled), the method actionPerformed of ButtonListener is called: its the start of point 4, you should update your widgets (refreshTable() in your code), and make the AI move (aiTurn(), point 5). When the method actionPerformed is finsihed, the JApplet goes back automatically to point 3, you've nothing to do.
I don't know Applets very well, so I can't be more precise. You should search for JApplet examples/tutorials with similar behaviors as yours. Remember you should not have infinite loops in your code waiting for user's input : it's handled by the JApplet.

Categories