For a school project I have to complete a Conways game of life with recourse to some provided skeleton code.
My problem is that all of my cells seem to initialise as dead (and thus do not come alive) when I use the visualiser - I'm not looking for direct answer on the whole project, just some direction on where my code is broken (Apologise for the awful formatting, its my first time on here):
Below is the Cell.class and below that is the CellGrid - the visualiser was provided.
package simulation;
/**
* This class represents a single Cell in the grid.
*
* Complete this class as part of the core of the assessment.
* You must implement the constructor, isAlive, setAlive and isAliveNextStep.
*/
public class Cell
{
// true if the cell is alive and false if it is dead
private boolean alive;
/**
* Cell constructor - all cells should start out dead
*/
public Cell()
{
alive = false;
}
/**
* Accessor method for alive
*
* #return true if the cell is currently alive; false otherwise
*/
public boolean isAlive()
{
if (alive == true)
{
return true;
}
else
return false;
}
/**
* Mutator method for alive
*
* #param alive - the new state of the cell
*/
public void setAlive(boolean alive)
{
if (alive == true)
alive = false;
else alive = true;
}
/**
* Determine whether this cell should be alive in the next step,
* given the number of surrounding neighbours.
*
* See the assignment specification sheet to determine the rules
* for living and dead cells.
*
* #param numNeighbours - the number of living cells surrounding this cell
* #return true if the cell should be alive; false otherwise
*/
public boolean isAliveNextStep(int numNeighbours)
{
if (numNeighbours <= 2)
return false;
if (numNeighbours == 3)
return true;
if (numNeighbours == 4 && alive == true)
return true;
if (numNeighbours == 5)
return false;
if (numNeighbours > 5)
return true;
else return false;
}
}
CellGrid class:
package simulation;
/**
* This class represents an n x n grid of Cells.
*
* Complete this class as part of the core of the assessment.
* You must implement the constructor, simulateStep, isValidCoordinate,
* countNeighbours, getCell and setCell.
*/
public class CellGrid
{
// Store the cells of the game in this 2D array
private Cell[][] cells;
/**
* Constructor for a CellGrid. Populates the grid with cells that will be
* either living or dead. Consider using Math.random() in order to generate
* random numbers between 0.0 and 1.0, in conjunction with lifeChance.
*
* #param size - the size of the grid will be size x size
* #param lifeChance - the probability of each cell starting out
* alive (0.0 = 0%, 1.0 = 100%)
*/
public CellGrid(int size, double lifeChance)
{
cells = new Cell[size][size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
cells[i][j] = new Cell();
if (Math.random() < lifeChance);
{
cells[i][j].setAlive(false);
}
}
}
}
/**
* Run one step in the simulation. This has 2 stages in the following order:
*
* 1. (Core) Update all cells in the grid according to the rules given in the
* assignment specification sheet.
*
* 2. (Extension) Evolve the cells by calculating their new genes - also
* see the assignment specification sheet.
*/
public void simulateStep()
{
for (int i = 0; i < cells.length; i++)
{
for (int j = 0; j < cells.length; j++)
{
int Neighbours = countNeighbours(i, j);
cells[i][j].isAliveNextStep(Neighbours);
}
}
}
/**
* Check if the given coordinates are inside the grid of cells.
*
* #param x - the x coordinate (column) of the cell
* #param y - the y coordinate (row) of the cell
* #return true if the given coordinates are inside the grid of cells; false
* otherwise.
*/
public boolean isValidCoordinate(int x, int y)
{
int validc = 0; //*variable to check for validity of coordinate by traversal *//
for (int i = 0; i < cells.length; i++)
{
for (int j = 0; j > cells.length; j++)
{
if (x == i+1 && y == j+1)
{
validc = 1;
}
}
}
if (validc == 1)
{
return true;
}
else return false;
}
/**
* Count the number of living neighbours in the 8 cells surrounding the
* given coordinates.
*
* #param x - the x coordinate (column) of the cell
* #param y - the y coordinate (row) of the cell
* #return the number of living neighbours of the cell at the given
* coordinates; or 0 if the coordinates are invalid.
*/
public int countNeighbours(int x, int y)
{
int N = 0;
for (int i = 0; i < cells.length; i++)
{
for (int j = 0; j > cells.length; j++)
{
if (i-1 >= 0 && j-1 >= 0 && cells[i-1][j-1].equals(true))
N++;
if (i-1 >= 0 && cells[i-1][j].equals(true))
N++;
if (i-1 >= 0 && j+1 <= cells.length && cells[i-1][j+1].equals(true))
N++;
if (i >= 0 && j-1 >=0 && cells[i][j-1].equals(true))
N++;
if (i >= 0 && j >= 0 && cells[i][j].equals(true))
N++;
if (i >= 0 && j+1 <= cells.length && cells[i][j+1].equals(true))
N++;
if (i+1 <= cells.length && j-1 >= 0 && cells[i+1][j-1].equals(true))
N++;
if (i+1 <= cells.length && j >= 0 && cells[i+1][j].equals(true))
N++;
if (i+1 <= cells.length && j+1 <= cells.length && cells[i+1][j+1].equals(true))
N++;
}
}
return N;
}
/**
* Get the cell at the given coordinates.
*
* #param x - the x coordinate (column) of the cell
* #param y - the y coordinate (row) of the cell
* #return the cell at the given coordinates; or null if the coordinates are
* invalid
*/
public Cell getCell(int x, int y)
{
if (x < cells.length && y < cells.length)
return cells[x][y];
else return null;
}
/**
* Set the cell at the given coordinates to the cell provided, if the
* coordinates are valid.
*
* #param x - the x coordinate (column) of the cell
* #param y - the y coordinate (row) of the cell
* #param cell - the new cell to put at the coordinates given.
*/
public void setCell(int x, int y, Cell cell)
{
cells[x][y] = getCell(x,y);
}
}
Your setAlive method is incorrect.
public void setAlive(boolean alive){
if (alive == true)
alive = false;
else alive = true;
}
Due to variable shadowing, you never really change the field alive. It should look like this:
public void setAlive(boolean alive){
this.alive = alive;
}
Related
enter image description here /** Check that the borders of each cell are consistent with
* its neighbours. For instance, if a cell has no east wall,
* then its neighbour to the east should have no west wall.
*
* Specifically: for every cell in the grid, and for every direction,
* the cell may have a wall in that direction if
* the wall is on the edge of the grid, and must have a wall
* in that direction if its neighbour
* in that direction has a corresponding wall.
*
* #return Whether the cells in the grid have valid border values.
*/
public boolean bordersAreValid() {
boolean result = true;
for (int j=0; j< this.cells.length; j++) {
for (int i=0;i
if (i==0 && !this.cells[j][i].hasWest()) {
result = false;
}
if (j== this.cells.length -1 && this.cells[j][i].hasSouth()) {
result = false;
}
if (i== this.cells.length -1 && this.cells[j][i].hasEast()) {
result = false;
}
} else {
Cell northneighbour; Cell southneighbour; Cell eastNeighbour; Cell westNeighbour;
northneighbour = this.cells[j-1][i];
southneighbour = this.cells[j+1][i];
eastNeighbour = this.cells[j][i+1];
westNeighbour = this.cells[j][i-1];
if (this.cells[j][i].hasNorth() && !northneighbour.hasSouth() ){
result = false;
}
if (this.cells[j][i].hasEast() && !northneighbour.hasWest() ){
result = false;
}
if (this.cells[j][i].hasWest() && !northneighbour.hasEast() ){
result = false;
}
if (this.cells[j][i].hasSouth() && !northneighbour.hasNorth() ){
result = false;
}
}
}
}
return result;
}
I am trying to find a solution to the Eight Queens problem regardless of the starting point. Below is my Solver class, however it doesn't work for some reason when I place the queen in a row other than the first one.
import java.util.*;
public class Queens {
private static int x;
private static int y;
private static ArrayList<Integer> rows = new ArrayList<Integer>();
public Queens(int index, int row, int pos) {
for (int i = 0; i<index; i++)
rows.add(i);
rows.remove(row);
x = pos;
y = row;
}
public static boolean solve(int row, int[][] board, int N, int pos) {
board[y][x] = 1;
System.out.println("row: " + row);
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
if(board[i][j]==1) System.out.print("Q ");
else System.out.print("* ");
}
System.out.println();
}
System.out.println();
if(row>=N-1) return true;
for(int position = pos; position < N; position++) {
if(isValid(board, rows.get(row), position, N)) {
board[rows.get(row)][position] = 1;
if(!solve(row+1, board, N, 0)) {
board[rows.get(row)][position] = 0;
} else
return true;
}
}
return false;
}
public static boolean isValid(int[][] board, int y, int x, int N) {
int i, j;
for(i = 0; i < y; i++)
if(board[i][x]==1)
return false;
i = y - 1;
j = x - 1;
while((i>=0)&&(j>=0))
if(board[i--][j--]==1) return false;
i = y - 1;
j = x + 1;
while((i>=0)&&(j<N))
if(board[i--][j++]==1) return false;
return true;
}
}
For example, when I place the initial queen on board[2][2], this is the solution I get:
Q * * * * * * *
* * Q * * * * *
* * Q * * * * *
* * * * * Q * *
* * * * * * * Q
* Q * * * * * *
* * * Q * * * *
* * * * * * Q *
What is wrong with the code? Why does it disregard the initial piece? Thanks in advance.
What are the bounds for the for loop in isValid? Do they prevent you from placing a queen into a column where there's another queen below?
A similar question applies also to the while loops -- can they detect that there's a queen on the diagonal but below the one you're placing now?
I have to write the code that sets an 8x8 matrix, a chessboard, and then asks the user what row and what column they want to place the queen on. I then have to put a * on each square to which the queen can move. Putting a * on the row and column the queen could move to wasn't difficult but I'm having trouble correctly labeling the diagonals to on which the queen can move. This is the code I have written so far to try and locate the diagonal:
char[][] chessboard = new char[8][8];
System.out.print("What row do you want to place the queen on? ");
int row = console.nextInt();
System.out.print("What column do you want to place the queen on? ");
int column = console.nextInt();
char queen = 'Q';
chessboard[row - 1][column - 1] = queen;
// column and rows
for (int i = 0; i < chessboard.length; i++) {
for (int j = 0; j < chessboard[0].length; j++) {
if ((i == 2 || j == 6) && chessboard[i][j] != queen) {
chessboard[i][j] = '*';
}
}
}
if ((row - 1) != 0) {
// left diagonal
for (int i = 0; i < row; i++) {
for (int j = (column - 1 - (row - 1)); ((column - 1) - (row - 1)) <= j && j < column; j++) {
if (chessboard[i][j] != queen) {
chessboard[i][j] = '*';
}
}
}
for (int i = (row - 1) + (8 - (column)); i >= row - 1; i--) {
for (int j = 7; j >= (column - 1); j--) {
if (chessboard[i][j] != queen) {
chessboard[i][j] = '*';
}
}
}
// right diagonal
for (int i = 7; i >= row - 1; i--) {
for (int j = (column - 1 - (row - 1)); 0 <= j && j < column; j--) {
if (chessboard[i][j] != queen) {
chessboard[i][j] = '*';
}
}
}
}
for (int i = 0; i < chessboard.length; i++) {
for (int j = 0; j < chessboard[0].length; j++) {
System.out.print(chessboard[i][j] + " ");
}
System.out.println();
}
}
When I put in experimental values, for example row 3 and column 7, I get a really messy output. For the numbers above, I get:
[][][][] * * * []
[][][][] * * * []
* * * * * * Q *
* * * * * [] * *
* * * * * [] * []
* * * * * [] * []
* * * * * [] * []
* * * * * [] * []
Could someone tell me where I'm going wrong?
* This is a homework question so code only in the answers, please. Thanks!
If it were me, I'd simply loop through each square of the chessboard and test the validity of each square as being one that the queen can move to, of the three possible rules, namely
square.x == queen.x ||
square.y == queen.y ||
|square.x - queen.x| == |square.y - queen.y|
If your square matches any of the above rules, then it's a valid square to move to, otherwise it's not. Omitting the square that the queen currently resides on, of course
square.x != queen.x && square.y != queen.y
Pseudocode:
for (int i = 0; i < chessboard.length; i++) {
for (int j = 0; j < chessboard[0].length; j++) {
// You could encapsulate these lines in a isValidSquareForQueenMove(x, y) method.
boolean isSquareValid = false;
isSquareValid = isSquareValid || x == queen.x;
isSquareValid = isSquareValid || y == queen.y;
isSquareValid = isSquareValid || Math.abs(queen.x - x) == Math.abs(queen.y - y);
isSquareValid = isSquareValid && x != queen.x && y != queen.y;
// Do stuff here.
}
}
I have a question that I have been trying to figure out, but I am stuck. Basically I have been trying to implement the logic of a rook's movement in a game that's not chess, but I'm stuck on it. I'll give you the details:
The Board is a 5x5 multidimensional array where there are only pawns and rooks for each player
The goal is to capture all your opponent's pieces and the one that captures them all will win the game.
Rooks can move as far as they want in one direction, until they hit something blocking their path.
The thing my rook does right now is that it can go one direction but it can go anywhere in that line. I need help on trying to figure out how to add more logic to make sure it can only go as long as the path is clear. Here is an example:
The small "p" and "r" are player 2's pieces and the big "P" and "R" are player one's pieces. Right now the top-right R (rook) can only move right, but if you do that it will go beyond the pawns, and then can go as far down as it wants.
* R R R *
* P P P *
* * * * *
* p p p *
* r r r *
Here is the code for what I have for the rook:
public boolean isLegalMove(Location from,Location to)
{
// Row is XPosition (Up/Down)
// Column is YPosition(Left/Right)
int fromRow = from.getXPosition();
int fromColumn = from.getYPosition();
int toRow = to.getXPosition();
int toColumn = to.getYPosition();
// higher row or column or both
if(((fromColumn >= toColumn) || (fromColumn <= toColumn)) && ((fromRow == toRow))) {
return true;
}
if(((fromRow >= toRow) || (fromRow <= toRow)) && ((fromColumn == toColumn))) {
return true;
}
return false;
}
I guess I'm going to make another method to check the logics if there's any thing in the path, calling it isPathClear()
EDIT:
Here's the rest of the code:
public class Board
{
// The depth and width of the field.
public static final int ROW = 5;
public static final int COLUMN = 5;
public static final String EMPTYPIECE = " * ";
//Storage for the game pieces
private GamePiece [] [] gameBoard;
//Makes the balls and torches for player1
private Pawn1 p1Pawn1,p1Pawn2,p1Pawn3;
private Rook1 p1Rook1,p1Rook2,p1Rook3;
//Makes the ball and torchers for player2
private Pawn2 p2Pawn1,p2Pawn2,p2Pawn3;
private Rook2 p2Rook1,p2Rook2,p1Rook3;
/**
* Makes a 5x5 Gameboard
*/
public Board()
{
// initialise instance variables
gameBoard = new GamePiece [ROW][COLUMN];
//Makes pieces for player1
p1Pawn1 = new Pawn1();
p1Pawn2 = new Pawn1();
p1Pawn3 = new Pawn1();
p1Rook1 = new Rook1();
p1Rook2 = new Rook1();
p1Rook3 = new Rook1();
//Makes pieces for player2
p2Pawn1 = new Pawn2();
p2Pawn2 = new Pawn2();
p2Pawn3 = new Pawn2();
p2Rook1 = new Rook2();
p2Rook2 = new Rook2();
p2Rook3 = new Rook2();
}
/**
* Makes new games
*/
public void newGame()
{
// Assigns the piece of the board for player1
gameBoard[0][1] = p1Rook1;
gameBoard[0][2] = p1Rook2;
gameBoard[0][3] = p1Rook3;
gameBoard[1][1] = p1Pawn1;
gameBoard[1][2] = p1Pawn2;
gameBoard[1][3] = p1Pawn3;
// Assigns the pieces of the board for player2
gameBoard[4][1] = p2Rook1;
gameBoard[4][2] = p2Rook2;
gameBoard[4][3] = p2Rook3;
gameBoard[3][1] = p2Pawn1;
gameBoard[3][2] = p2Pawn2;
gameBoard[3][3] = p2Pawn3;
}
/**
* Displays the content of the board
*/
public void displayBoard()
{
System.out.println(" a b c d e");
int counter = 1;
for (int i = 0; i < gameBoard.length; i++){
System.out.print(counter);
for (int j = 0; j < gameBoard[i].length; j++) {
if (gameBoard[i][j] == null) {
System.out.print(EMPTYPIECE);
} else {
System.out.print(" " + gameBoard[i][j] + " ");
}
}
counter++;
System.out.println();
}
}
/**
* Moves the movepiece from one locatin to another
* #param from - where the location was from
* #param to - Where the location is going to
*/
public void movePiece(Location from,Location to) throws InvalidMoveException
{
int fromRow = from.getXPosition();
int fromColumn = from.getYPosition();
int toRow = to.getXPosition();
int toColumn = to.getYPosition();
if (gameBoard[fromRow][fromColumn] == null) {
throw new InvalidMoveException("Invalid input for source location.");
}
if (! checkBounds(from, to)) {
throw new InvalidMoveException("Invalid input for destination location.");
}
if (isSameLocation(from, to)){
throw new InvalidMoveException("Invalid move, source and destination cannot bethe same.");
}
if (! gameBoard[fromRow][fromColumn].isLegalMove(from, to)) {
throw new InvalidMoveException("Invalid move for this piece.");
}
gameBoard[toRow][toColumn] = gameBoard[fromRow][fromColumn];
gameBoard[fromRow][fromColumn] = null;
displayBoard();
}
/**
* Checks a proposed move to ensure it is within the bounds of the board.
* #param source location, destination location
* #return true if both source and destination are within bounds
*/
private boolean checkBounds(Location from, Location to)
{
int fromRow = from.getXPosition();
int fromColumn = from.getYPosition();
int toRow = to.getXPosition();
int toColumn = to.getYPosition();
boolean testFrom = (fromRow >= 0) && (fromColumn >= 0) && (fromRow < gameBoard.length) && (fromColumn < gameBoard[0].length);
boolean testTo = (toRow >= 0) && (toColumn >= 0) && (toRow < gameBoard.length) && (toColumn < gameBoard[0].length);
return testFrom && testTo;
}
/**
* Checks a proposed move to ensure source and destination are different.
* #param source location, destination location
* #return true if source and destination are the same
*/
private boolean isSameLocation(Location from, Location to)
{
int fromRow = from.getXPosition();
int fromColumn = from.getYPosition();
int toRow = to.getXPosition();
int toColumn = to.getYPosition();
return fromRow == toRow && fromColumn == toColumn;
}
You can't know if the path is clear without knowing what else is on the board. However, your method signature doesn't give this function access to the layout of the board. If you pass the entire board, you can use a loop to check all the squares in between for other pieces.
From Lord Torgamus:
You wouldn't check to see if the board is null. You'd have to check the individual spaces between the rook's source and destination locations.
Now that I know what board looks like, here's some code:
public boolean isLegalMove(Location from,Location to)
{
// Row is XPosition (Up/Down)
// Column is YPosition(Left/Right)
int fromRow = from.getXPosition();
int fromColumn = from.getYPosition();
int toRow = to.getXPosition();
int toColumn = to.getYPosition();
// Has to be same row or column
if(fromRow != toRow || fromColumn != toColumn) return false;
// Can't move to the same square
if(fromRow == toRow && fromColumn == toColumn) return false;
// Rows are the same
if(fromRow - toRow == 0) {
// this will hold the column of the we're going to check next
int newPos = fromColumn;
// Should we go up or down?
int amount = (toColumn - fromColumn < 0) ? -1 : 1;
while(newPos != toColumn) {
newPos += amount;
// if it's not null, we found a different piece
if(gameBoard[fromRow][newPos] != null) return false;
}
if(gameBoard[toRow][toColumn] != null) {
// return false if it's your own piece, true if it's not
}
// Columns are the same
} else {
// this will hold the row of the we're going to check next
int newPos = fromRow;
// Should we go up or down?
int amount = (toRow - fromRow < 0) ? -1 : 1;
while(newPos != toRow) {
newPos += amount;
// if it's not null, we found a different piece
if(gameBoard[newPos][fromColumn] != null) return false;
}
if(gameBoard[toRow][toColumn] != null) {
// return false if it's your own piece, true if it's not
}
}
return true;
}
Edited for the case where you want to be able to capture an opponent's piece... but I didn't put the last bit of code in because you have to change the method signature again. Look for my comment. Notice also it's a while loop now, not a do-while.
My question is boolean isLive = false; why is this assigned as false? I have seen very similer examples but I never quet understand it. could anyone explain what this line is doing?
/**
* Method that counts the number of live cells around a specified cell
* #param board 2D array of booleans representing the live and dead cells
* #param row The specific row of the cell in question
* #param col The specific col of the cell in question
* #returns The number of live cells around the cell in question
*/
public static int countNeighbours(boolean[][] board, int row, int col)
{
int count = 0;
for (int i = row-1; i <= row+1; i++) {
for (int j = col-1; j <= col+1; j++) {
// Check all cells around (not including) row and col
if (i != row || j != col) {
if (checkIfLive(board, i, j) == LIVE) {
count++;
}
}
}
}
return count;
}
/**
* Returns if a given cell is live or dead and checks whether it is on the board
*
* #param board 2D array of booleans representing the live and dead cells
* #param row The specific row of the cell in question
* #param col The specific col of the cell in question
*
* #returns Returns true if the specified cell is true and on the board, otherwise false
*/
private static boolean checkIfLive (boolean[][] board, int row, int col) {
boolean isLive = false;
int lastRow = board.length-1;
int lastCol = board[0].length-1;
if ((row >= 0 && row <= lastRow) && (col >= 0 && col <= lastCol)) {
isLive = board[row][col];
}
return isLive;
}
That's simply the default value, which may be changed if the test (if clause) is verified.
It defines the convention that cells outside the board aren't live.
This could have been written as :
private static boolean checkIfLive (boolean[][] board, int row, int col) {
int lastRow = board.length-1;
int lastCol = board[0].length-1;
if ((row >= 0 && row <= lastRow) && (col >= 0 && col <= lastCol)) {
return board[row][col];
} else {
return false;
}
}
First we assign boolean value as 'false' (ensuring default condition)
Then if valid condition is found we change the value, else default false will be returned.
boolean isLive = false;
It is a default value assigned to the boolean variable.
Just like:
int num = 0;
boolean isLive = false;
This is the default value of a boolean variable. If you declare as an instance variable it is automatically initialized to false.
why is this assigned as false?
Well, we do this, just to start with a default value, then we can change later on to true value, based on certain condition.
if ((row >= 0 && row <= lastRow) && (col >= 0 && col <= lastCol)) {
isLive = board[row][col];
}
return isLive;
So, in above code, if your if condition is false, then it is similar to returning a false value. Because, the variable isLive is not changed.
But if your condition is true, then the return value will depend upon the value of board[row][col]. If it is false, return value will still be false, else true.