I'm new to this forum so I hope I'm posting this question in the right way - otherwise, please let me know.
I'm trying to write the code for a simple Game of Life animation in Java, and most of it seems to work as intended.
However, there is a problem with one of the neighbour 'rules' that is supposed to "kill" a cell if it has less than 2 neighbours, meaning that cells can have one or no neighbours and still survive - can be seen here: http://peecee.dk/upload/view/435109. All other rules seem to work fine.
Can anyone help me figure out why it ignores the rule (Live cells are equal to '1', dead to '0'.):
if (this.state[i][j] == 1 &&
liveNeighbours(i, j) > 3 || liveNeighbours(i, j) < 2) {
this.tempState[i][j] = 0;
Thanks a ton in advance!
The code is as follows:
import java.util.*;
public class GameOfLife {
private int[][] state;
private int[][] tempState;
//Constructor that creates n x n grid of randomly placed live cells
public GameOfLife(int n) {
this.state = new int[n+2][n+2];
this.tempState = new int[n+2][n+2];
createRandomBoard(n);
}
//Sets up the initial state
public void createRandomBoard(int n) {
//Creates (n+2) x (n+2) grid of dead cells
for (int i = 0; i < n+2; i++) {
for (int j = 0; j < n+2; j++) {
this.state[i][j] = 0;
}
}
//Creates n x n grid of randomly placed live cells. Live cells are equal to '1', dead to '0'.
for (int i = 1; i < n + 1; i++) {
for (int j = 1; j < n + 1; j++) {
int a = (int)Math.round(Math.random());
this.state[i][j] = a;
}
}
drawBoard();
}
//Draws the live cells as dots based on current state
public void drawBoard() {
StdDraw.show(50);
StdDraw.clear();
for (int i = 1; i < this.state.length-2; i++) {
for (int j = 1; j < this.state.length-2; j++) {
StdDraw.setXscale(1,this.state.length-3);
StdDraw.setYscale(1,this.state.length-3);
StdDraw.setPenRadius((double)1/this.state.length);
if (this.state[i][j] == 1) {
StdDraw.point(i, j);
}
}
}
StdDraw.show(50);
}
//Determines which cells live or die in the next state
public void nextState() {
//Copies the state array to a temporary state(array) during killing/reviving
for (int i = 1; i < this.state.length-2; i++) {
for (int j = 1; j < this.state.length-2; j++) {
this.tempState[i][j] = this.state[i][j];
}
}
//Kills cells with more than 3 or less than 2 neighbours and revives dead cells with 3 neighbours
for (int i = 1; i < this.state.length-2; i++) {
for (int j = 1; j < this.state.length-2; j++) {
if (this.state[i][j] == 1 && liveNeighbours(i, j) > 3 || liveNeighbours(i, j) < 2) {
this.tempState[i][j] = 0;
}
else if (this.state[i][j] == 0 && liveNeighbours(i, j) == 3) {
this.tempState[i][j] = 1;
}
}
}
//Copies the modified temporary state array to the original state(array) again
for (int i = 1; i < this.state.length-2; i++) {
for (int j = 1; j < this.state.length-2; j++) {
this.state[i][j] = this.tempState[i][j];
}
}
drawBoard();
}
//Counts the number of live neighbours to a cell
private int liveNeighbours(int x, int y) {
int numLiveNeighbours = 0;
for (int i = x-1; i < x+2; i++) {
for (int j = y-1; j < y+2; j++) {
if (this.state[i][j] == 1) {
numLiveNeighbours++;
}
}
}
numLiveNeighbours --;
return numLiveNeighbours;
}
public String toString() {
return Arrays.deepToString(this.state);
}
public int[][] getState() {
return this.state;
}
}
Your condition doesn't seem to express what you want. You need to change it to:
if (this.state[i][j] == 1 && (liveNeighbours(i, j) > 3 || liveNeighbours(i, j) < 2))
Check operators precedence rules in Java. You were killing those cells being alive and having more than 3 neighbours or those cells with less than two of them.
With this change you will be killing those cells alive and with more than 3 or less than 2 neighbours.
I think your liveNeighbours has a little flaw too: Your are counting (x,y) neighbours and (x,y) itself. You should change it for:
private int liveNeighbours(int x, int y) {
int numLiveNeighbours = 0;
for (int i = x-1; i < x+2; i++) {
for (int j = y-1; j < y+2; j++) {
if (this.state[i][j] == 1 && (x != i || j != y)) {
numLiveNeighbours++;
}
}
}
return numLiveNeighbours;
}
Related
I made the 8x8 chess board and have a lot of the code done, but for some reason it only print out one solution, does anyone know why this may be and how I can fix it?
public class NonAttackingQueens {
private int[][] board;
private int solutionCount = 0;
private boolean solutionFound = false;
public NonAttackingQueens() {
board = new int[8][8];
}
public boolean canPlace(int x, int y) {
// Check if a queen is already placed at position (x, y)
if (board[x][y] == 1) {
return false;
}
// Check horizontal positions
for (int i = 0; i < 8; i++) {
if (board[x][i] == 1) {
return false;
}
}
// Check vertical positions
for (int i = 0; i < 8; i++) {
if (board[i][y] == 1) {
return false;
}
}
// Check diagonal positions
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (board[i][j] == 1 && (Math.abs(i - x) == Math.abs(j - y))) {
return false;
}
}
}
return true;
}
public void solve() {
// Check if the solutionCount has reached 92
if (solutionCount == 92) {
return;
}
// Check if all 8 queens have been placed
int queensPlaced = 0;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (board[i][j] == 1) {
queensPlaced++;
}
}
}
if (queensPlaced == 8) {
// All positions have been checked, so we have found a solution
solutionCount++;
System.out.println("Solution " + solutionCount + ":");
print();
return;
}
// Try to place a queen at each position on the board
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (canPlace(i, j)) {
// Place a queen at position (i, j) and try to solve the rest of the board
board[i][j] = 1;
solve();
// Backtrack: remove the queen from position (i, j) and try the next position
board[i][j] = 0;
}
}
}
}
public void print() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (board[i][j] == 1) {
System.out.print(" X");
} else {
System.out.print(" O");
}
}
System.out.println();
}
System.out.println("---------------");
}
}
I'm doing this in blueJ, so I tried to run the void solve(); method and it runs, but it only prints out the first of 92 solutions 92 times. It should print out all 92 different solutions.
I recently completed the code for a Four in a Row Game with 7 columns (represented by i below) and 6 rows (represented by j below), however, I keep getting out of bounds errors and I'm not sure why. If anyone can help spot and fix the errors, that would be awesome. Below is the code I have (the issues lie in the play, isGameOver and winner functions):
package hw4;
public class CFGame {
//state[i][j]= 0 means the i,j slot is empty
//state[i][j]= 1 means the i,j slot has red
//state[i][j]=-1 means the i,j slot has black
private final int[][] state;
private boolean isRedTurn;
{
state = new int[7][6];
for (int i=0; i<7; i++)
for (int j=0; j<6; j++)
state[i][j] = 0;
isRedTurn = true; //red goes first
}
public int[][] getState() {
int[][] ret_arr = new int[7][6];
for (int i=0; i<7; i++)
for (int j=0; j<6; j++)
ret_arr[i][j] = state[i][j];
return ret_arr;
}
public boolean isRedTurn() {
return isRedTurn;
}
public boolean play(int column) {
for(int j = 0; j < state[column].length; j++) {
if(state[column][j] != 0 || state[column][j] < 0 || state[column][j] > 6 ) {
return false;
}
}
return true;
}
public boolean isGameOver() {
for(int j = 0; j < state.length; j++) {
for(int i = 0; i < state[j].length; i++) {
if (state[i][j] != 0) {
return true;
}
}
}
return false;
}
public int winner() {
//Checking horizontal win
for(int j = 0; j < state.length; j++) {
for(int i = 0; i < state[j].length-3; i++) {
if(state[i][j] == state[i+1][j] && state[i][j] == state[i+2][j] &&
state[i][j] == state[i+3][j]) {
return state[i][j];
}
}
}
//Checking vertical win
for(int j = 0; j < state.length-3; j++) {
for(int i = 0; i < state[0].length; i++) {
if(state[i][j] == state[i][j+1] && state[i][j] == state[i][j+2] &&
state[i][j] == state[i][j+3]) {
return state[i][j];
}
}
}
//Checking diagonal(s) win
for(int j = 0; j < state.length - 3; j++) {
for(int i = 0; i < state[j].length - 3; i++) {
if(state[i][j] == state[i+1][j+1] && state[i][j] == state[i+2][j+2] &&
state[i][j] == state[i+3][j+3]) {
return state[i][j];
}
}
}
for(int j = 0; j < state.length - 3; j++) {
for(int i = 3; i <= state[j].length; i++) {
if(state[j][i] == state[j+1][i-1] && state[j][i] == state[j+2][i-2] &&
state[j][i] == state[j-3][i+3]) {
return state[i][j];
}
}
}
return 0;
}
}
To me, the code seems fine but when I run it, it brings up the error.
If you spot any other mistakes, kindly let me know too.
Any help is much appreciated.
You use index j and i differently in different loops. It looks like j should be the index for the first dimension and i is for the second, but you have state[i][j] in some places. That will definitely cause outofbound error because j can go as high as 6 but i is capped at 5 based on your code.
This is an N Queens problem where the board has been given and you must use methods to check where the rows, the columns and diagonally. My method for checking the row is here:It works if you were counting the Queens as a whole but I only want to check row by row, resetting the count and rowcount.
private boolean oneQueenPerRow() //ensures that there is only 1 queen in each row
{
int count = 0;
int rowcount = 0;
for (int i = 0; i < board.length; i++)
{
//count = 0;
for (int j = 0; j < board.length; j++)
{
//rowcount = 0;
while (rowcount <= size-1)
{
if (board[i][j] == QUEEN)
{
count++;
rowcount++;
}
if (board[i][j] == BLANK)
{
rowcount++;
}
}
if (count != 1) // if size replaces 1 then it works, but counts Q's as a whole
{
return false;
}
}
}
return true;
}
The idea is that all the methods return true or false and then are called by final boolean method. If all are true than the board is a valid solution. If one is false, the board is not a valid solution. Here is a text file example I was given:
4
BQBB
BBBQ
QBBB
BBQB
(They should be stacked..)
I don't have enough knowledge about arrays and for loops to tell if this is going all the way through the whole file or just a row at a time, although trust me when I say I have exhausted all resources.
I have been working on this for days and I can't figure it out and connection with my Prof is spotty because of this virus! I desperately need help!
private boolean noDiagonalAttacks() //makes sure that Queens cannot attack diagonally
{
for (int i = 0; i < board.length; i++)
{
int count = 0;
for (int j = 0; j < board.length; j++)
{
if (board[i][j] == QUEEN)
{
if(this.toRight() == false || this.toLeft() == false)
{
return false;
}
count++;
}
}
}
return true;
}
private boolean toRight()
{
for (int i = 0; i < board.length; i++)
{
for (int j = 0; j < board.length; j++)
{
while (board[i][j] != board[i][size-1] || board[i][j] != board[size-1][j]) //add a count to this?
{
if (board[i][j] == QUEEN)
{
return false;
}
}
}
}
return true;
}
private boolean toLeft()
{
for (int i = 0; i < board.length; i++)
{
for (int j = 0; j < board.length; j++)
{
while (board[i][j] != board[i][0] || board[i][j] != board[size-1][j])
{
if (board[i][j] == QUEEN)
{
return false;
}
}
}
}
return true;
}
I tried it once ago and it worked, Hope it help you.
private boolean oneQueenPerRow() {
int foundQueens;
for (int i = 0; i < board.length; i++) {
foundQueens = 0;//each loop is a checked row
for (int j = 0; j < board.length; j++) {
if (board[i][j] == QUEEN)
foundQueens++;
}
if (foundQueens > 1) return false;
}
return true;
}
private boolean oneQueenPerDiagonal() {
int inLeftRight = 0;
int inRightLeft = 0;
for (int i = 0; i < board.length; i++) {
if (board[i][i] == QUEEN)
inLeftRight++;
if (board[i][board.length-i-1] == QUEEN)
inRightLeft++;
}
return inLeftRight < 1 && inRightLeft < 1;
}
I am working on a Connect Four project, but am struggling with the win check. I think it has something to do with how I am looping over the grid. It works horizontally but not vertically, and it kinda works diagonally.
public boolean gameStatus(MyBoard gameBoard, int columnPosition, CellState gameToken) {
int rowPosition = 0;
for (int i = 0; i < gameBoard.getWidth(); i++)
for (int j = 0; j < gameBoard.getHeight(); j++)
if (gameBoard.get(i, columnPosition) != CellState.FREE)
rowPosition = i;
if (checkColumn(gameBoard, columnPosition, gameToken, rowPosition))
return true;
}
public boolean checkColumn(MyBoard gameBoard, int columnPosition, CellState gameToken, int rowPosition) {
int tokenCounter = 1;
if ((rowPosition + 4) <= 6)
for (int i = rowPosition + 1; i <= rowPosition + 3; i++)
if (gameToken == gameBoard.get(i, columnPosition))
tokenCounter++;
else
break;
if (tokenCounter == 4)
return true;
return false;
}
I think this only checks the last row which is non-empty.
Java doesn't care about indentation, so without braces, if and for only use the statement after them. This means your if (checkColumn... only runs once, not once for each column.
You might want to try something like
public boolean gameStatus(MyBoard gameBoard, int columnPosition, CellState gameToken) {
int rowPosition = 0;
for (int i = 0; i < gameBoard.getWidth(); i++) {
for (int j = 0; j < gameBoard.getHeight(); j++) {
if (gameBoard.get(i, columnPosition) != CellState.FREE) {
rowPosition = i;
}
}
if (checkColumn(gameBoard, columnPosition, gameToken, rowPosition)) {
return true;
}
}
In general. I'd advise against writing if, for and while statements without braces. The two characters it saves is not worth the bugs you may accidentally introduce
basically I need to input two numbers and they will be the side size of two squares (drawn one inside of the other, being the inside square positioned in the middle of the biggest square).
I really have no idea how to do this, and the only thing that I was able to come up with was inputing a value and having one drawn square:
package teste;
import java.util.Scanner;
public class Main {
private static Scanner sc;
public static void main(String a[])
{
int size=0;
System.out.print("Enter size: ");
sc = new Scanner(System.in);
size = sc.nextInt();
for(int i=1; i <= size; i++){
for(int j=1; j <= size; j++){
if(i==1 || i==size || j==1 || j==size)
System.out.print("*");
else
System.out.print(" ");
}
System.out.println();
}
}
}
I know it is not much, but my java skills are limited. Can you guys show a way to do it? I have no idea how to draw the square inside.
Thanks in advance.
The simplest way i see is just make a buffer where you will fill the characters you want to draw in console
// init buffer
char buffer[][] = new char[size][];
for (int i = 0; i < size; i ++) {
buffer[i] = new char[size];
}
// borders of first square
final int sq1Start = 0;
final int sq1End = size-1;
// draw outer square
for(int i = sq1Start; i <= sq1End; i ++){
for (int j = sq1Start; j <= sq1End; j ++) {
if (i == sq1Start || i == sq1End || j == sq1Start || j == sq1End) {
buffer[i][j] = '*';
}
}
}
// borders of second square
final int sq2Start = size / 4;
final int sq2End = size * 3 / 4;
// draw inner square
for (int i = sq2Start; i <= sq2End; i++) {
for (int j = sq2Start; j <= sq2End; j++) {
if (i == sq2Start || i == sq2End || j == sq2Start || j == sq2End) {
buffer[i][j] = '*';
}
}
}
for (int i = 0; i < size; i ++) {
for (int j = 0; j < size; j ++) {
System.out.print(buffer[i][j]);
}
System.out.println();
}
Hope it would be helpful