This is the kata: https://www.codewars.com/kata/snail/train/java
I came up with this code.
import java.util.ArrayList;
import java.util.Arrays;
public class Snail {
public static int[] snail(int[][] array) {
ArrayList<Integer> snailArrayList = new ArrayList<>();
int direction = 3;
int x = 0;
int y = 0;
if (array.length != 0) {
while (snailArrayList.size() < array.length * array.length) {
if (direction == 3) {
while (y <= array.length - 1 && array[x][y] != -1) {
snailArrayList.add(array[x][y]);
array[x][y] = -1;
y++;
}
y--;
x++;
direction = 6;
} else if (direction == 6) {
while (x <= array.length - 1 && array[x][y] != -1) {
snailArrayList.add(array[x][y]);
array[x][y] = -1;
x++;
}
x--;
y--;
direction = 9;
} else if (direction == 9) {
while (y >= 0 && array[x][y] != -1) {
snailArrayList.add(array[x][y]);
array[x][y] = -1;
y--;
}
y++;
x--;
direction = 12;
} else if (direction == 12) {
while (x > 0 && array[x][y] != -1) {
snailArrayList.add(array[x][y]);
array[x][y] = -1;
x--;
}
x++;
y++;
direction = 3;
}
}
}
int[] snailArray = new int[snailArrayList.size()];
if (snailArray.length != 0) {
for (int i = 0; i < snailArrayList.size(); i++) {
snailArray[i] = snailArrayList.get(i);
}
}
return snailArray;
}
}
It works fine on my phone, but for some reason it fails to pass the test when an empty array is given. The error I get is:
[[]] should be sorted to [].
and
java.lang.ArrayIndexOutOfBoundsException: 0
at Snail.snail(Snail.java:15)
at SnailTest.test(SnailTest.java:35)
at SnailTest.SnailTest2Empty(SnailTest.java:62)
What's confusing for me is that with an empty array, the program doesn't even enter the if(array.length != 0) statement. I'm sure the solution is simple, but I just can't see it. Any help would be appreciated, thank you.
if (array[0].Length == 0)
{
return new int[0];
}
Related
How do I prevent the same tic tac toe coordinate from being inputted by the user?
The user input is taken at the main method in the Game Class.
The tic tac toe cells with [x, y] coordinates ranging from (0-2) can be either:
0(_), 1 (X) or 2 (O)
Grid Class with alpha beta search tree pruning algorithm
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Grid {
List<Cell> availableCells;
int[][] board = new int[3][3];
Scanner scan = new Scanner(System.in);
// Set limit to search tree depth
int treeDepth = 9;
List<CellsAndScores> rootsChildrenScore = new ArrayList<>();
public int score() {
int score = 0;
// Check all columns
for (int j = 0; j < 3; ++j) {
int X = 0;
int O = 0;
for (int i = 0; i < 3; ++i) {
if (board[i][j] == 0) {
} else if (board[i][j] == 1) {
X++;
} else {
O++;
}
}
score += changeInScore(X, O);
}
// Check all rows
for (int i = 0; i < 3; ++i) {
int X = 0;
int O = 0;
for (int j = 0; j < 3; ++j) {
if (board[i][j] == 0) {
} else if (board[i][j] == 1) {
X++;
} else {
O++;
}
}
score += changeInScore(X, O);
}
int X = 0;
int O = 0;
// Check diagonal (first)
for (int i = 0, j = 0; i < 3; ++i, ++j) {
if (board[i][j] == 1) {
X++;
} else if (board[i][j] == 2) {
O++;
} else {
}
}
score += changeInScore(X, O);
X = 0;
O = 0;
// Check Diagonal (Second)
for (int i = 2, j = 0; i > -1; --i, ++j) {
if (board[i][j] == 1) {
X++;
} else if (board[i][j] == 2) {
O++;
} else {
}
}
score += changeInScore(X, O);
return score;
}
private int changeInScore(int X, int O) {
int change;
if (X == 3) {
change = 100;
} else if (X == 2 && O == 0) {
change = 10;
} else if (X == 1 && O == 0) {
change = 1;
} else if (O == 3) {
change = -100;
} else if (O == 2 && X == 0) {
change = -10;
} else if (O == 1 && X == 0) {
change = -1;
} else {
change = 0;
}
return change;
}
public int alphaBetaMinimax(int alpha, int beta, int depth, int turn) {
if (beta <= alpha) {
System.out.println("Pruning at tree depth = " + depth + " alpha: " + alpha + " beta: " + beta);
if (turn == 1)
return Integer.MAX_VALUE;
else
return Integer.MIN_VALUE;
}
if (depth == treeDepth || gameOver()) {
return score();
}
List<Cell> cellsAvailable = getAvailableStates();
if (cellsAvailable.isEmpty()) {
return 0;
}
if (depth == 0) {
rootsChildrenScore.clear();
}
int maxValue = Integer.MIN_VALUE, minValue = Integer.MAX_VALUE;
for (int i = 0; i < cellsAvailable.size(); ++i) {
Cell cell = cellsAvailable.get(i);
int currentScore = 0;
if (turn == 1) {
placeAMove(cell, 1);
currentScore = alphaBetaMinimax(alpha, beta, depth + 1, 2);
maxValue = Math.max(maxValue, currentScore);
// Set alpha
alpha = Math.max(currentScore, alpha);
if (depth == 0) {
rootsChildrenScore.add(new CellsAndScores(currentScore, cell));
}
} else if (turn == 2) {
placeAMove(cell, 2);
currentScore = alphaBetaMinimax(alpha, beta, depth + 1, 1);
minValue = Math.min(minValue, currentScore);
// Set beta
beta = Math.min(currentScore, beta);
}
// reset board
board[cell.x][cell.y] = 0;
// Do not evaluate the rest of the branches after search tree is pruned
if (currentScore == Integer.MAX_VALUE || currentScore == Integer.MIN_VALUE)
break;
}
return turn == 1 ? maxValue : minValue;
}
public boolean gameOver() {
// Game is over is someone has won, or board is full (draw)
return (hasXWon() || hasOWon() || getAvailableStates().isEmpty());
}
public boolean hasXWon() {
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 1)
|| (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 1)) {
// System.out.println("X Diagonal Win");
return true;
}
for (int i = 0; i < 3; ++i) {
if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 1)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 1))) {
// System.out.println("X Row or Column win");
return true;
}
}
return false;
}
public boolean hasOWon() {
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 2)
|| (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 2)) {
// System.out.println("O Diagonal Win");
return true;
}
for (int i = 0; i < 3; ++i) {
if ((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 2)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 2)) {
// System.out.println("O Row or Column win");
return true;
}
}
return false;
}
public List<Cell> getAvailableStates() {
availableCells = new ArrayList<>();
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (board[i][j] == 0) {
availableCells.add(new Cell(i, j));
}
}
}
return availableCells;
}
public void placeAMove(Cell Cell, int player) {
board[Cell.x][Cell.y] = player; // player = 1 for X, 2 for O
}
public Cell returnBestMove() {
int MAX = -100000;
int best = -1;
for (int i = 0; i < rootsChildrenScore.size(); ++i) {
if (MAX < rootsChildrenScore.get(i).score) {
MAX = rootsChildrenScore.get(i).score;
best = i;
}
}
return rootsChildrenScore.get(best).cell;
}
public void displayBoard() {
System.out.println();
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (board[i][j] == 0)
System.out.print("_" + " ");
if (board[i][j] == 1)
System.out.print("X" + " ");
if (board[i][j] == 2)
System.out.print("O" + " ");
}
System.out.println("");
}
System.out.println();
}
public void resetGrid() {
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
board[i][j] = 0;
}
}
}
}
Cell class
class Cell {
int x, y;
public Cell(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "[" + x + ", " + y + "]";
}
}
class CellsAndScores {
int score;
Cell cell;
CellsAndScores(int score, Cell cell) {
this.score = score;
this.cell = cell;
}
}
Game Class with main method - takes user input
import java.util.Random;
public class Game {
public static void main(String[] args) {
Grid grid = new Grid();
Random random = new Random();
grid.displayBoard();
System.out.print("Who moves first? [1]Computer(X) [2]User(O): ");
int turn = grid.scan.nextInt();
if (turn == 1) {
Cell p = new Cell(random.nextInt(3), random.nextInt(3));
grid.placeAMove(p, 1);
grid.displayBoard();
}
while (!grid.gameOver()) {
int x = 0, y = 0;
System.out.print("Please enter an x coordinate [0-2]: ");
x = grid.scan.nextInt();
System.out.print("Please enter an y coordinate [0-2]: ");
y = grid.scan.nextInt();
Cell userMove = new Cell(y, x);
grid.placeAMove(userMove, 2); // 2 for O and O is the user
grid.displayBoard();
if (grid.gameOver())
break;
grid.alphaBetaMinimax(Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 1);
for (CellsAndScores pas : grid.rootsChildrenScore)
System.out.println("Cell: " + pas.cell + " Score: " + pas.score);
grid.placeAMove(grid.returnBestMove(), 1);
grid.displayBoard();
}
if (grid.hasXWon()) {
System.out.println("Unfortunately, you lost!");
grid.resetGrid();
} else if (grid.hasOWon()) {
System.out.println("You win!");
grid.resetGrid();
} else {
System.out.println("It's a draw!");
grid.resetGrid();
}
}
}
My answer would be to add a boolean check method into your Grid.java class and then in your main method - call this boolean check method before the placeAMove() method.
For example, in your Grid.java class, adding the following method:
/*
* Return true if space is ok to use.
*/
public boolean isMoveOK(Cell cell) {
return board[cell.x][cell.y] == 0;
}
This way, using your pre-existing 0/1/2 values that keep track of empty/X/O space values, you may provide a check to see if the space value is zero or not.
This would be one way to use it in your main method, to answer your question of, 'How do I prevent the same tic tac toe coordinate from being inputted by the user?'
Cell userMove = new Cell(y, x);
if (grid.isMoveOK(userMove)) {
grid.placeAMove(userMove, 2); // 2 for O and O is the user
} else {
System.out.println("Please try a different space/cell");
continue;
}
grid.displayBoard();
if (grid.gameOver())
break;
In this way, I am skipping the remaining loop code in your main method loop, until there's a valid open space. (When there is, then the program should proceed to check for winning values or whether to proceed playing)
Hope this answers your question! :)
Cheers
EDIT: I don't know why somebody links me a TicTacToe as duplicate for my question, there isn't even a MinMax-Algorithm in it.
Currently i'm working on a Connect4 game against the computer which should use the MinMax-Algorithm.
Before that, we wrote a TicTacToe which also uses the MinMax, but i'm not sure how to change my old algorithm to match the Connect4-Game :/.
In TicTacToe i evaluated each possible move with the win-conditions i wrote, it worked fine, but now it won't work with my new conditions.
My makeAMove etc. works fine!
These are my old conditions and the MinMax for TicTacToe:
//Player 1 wins
static boolean has1Won(int[][] array) {
gameBoard = array;
//Diagonal
if ((gameBoard[0][0] == gameBoard[1][1] && gameBoard[0][0] == gameBoard[2][2] && gameBoard[0][0] == 1)
|| (gameBoard[0][2] == gameBoard[1][1] && gameBoard[0][2] == gameBoard[2][0] && gameBoard[0][2] == 1)) {
return true;
}
//Spalten/Zeilen
for (int i = 0; i < 3; ++i) {
if (((gameBoard[i][0] == gameBoard[i][1] && gameBoard[i][0] == gameBoard[i][2] && gameBoard[i][0] == 1)
|| (gameBoard[0][i] == gameBoard[1][i] && gameBoard[0][i] == gameBoard[2][i] && gameBoard[0][i] == 1))) {
return true;
}
}
return false;
}
// Player 2 wins
static boolean has2Won(int[][] array) {
gameBoard = array;
//Diagonal
if ((gameBoard[0][0] == gameBoard[1][1] && gameBoard[0][0] == gameBoard[2][2] && gameBoard[0][0] == 2)
|| (gameBoard[0][2] == gameBoard[1][1] && gameBoard[0][2] == gameBoard[2][0] && gameBoard[0][2] == 2)) {
return true;
}
//Spalten/Zeilen
for (int i = 0; i < 3; ++i) {
if (((gameBoard[i][0] == gameBoard[i][1] && gameBoard[i][0] == gameBoard[i][2] && gameBoard[i][0] == 2)
|| (gameBoard[0][i] == gameBoard[1][i] && gameBoard[0][i] == gameBoard[2][i] && gameBoard[0][i] == 2))) {
return true;
}
}
return false;
}
As I said, i used these conditions for my MinMax like this:
public static int minimax(int depth, int turn) {
if (Board.has1Won(Board.gameBoard)){
return +1; // Der Computer gewinnt
}
if (Board.has2Won(Board.gameBoard)){
return -1; // Der Spieler gewinnt
}
List<GameMove> gameMovesAvailable = GameMove.getAvailableGameMoves();
if (gameMovesAvailable.isEmpty()){
return 0; // Das Spiel endet unentschieden
}
...
I'm not sure how i can get this to work with my new conditions:
I think i have to write an evaluating function which checks this for example (this is my wincondition for Rows):
boolean getWinnerInRow (Playboard brd){
int count = 0;
for (int i = 0; i < 6; i++){
for (int j = 0; j < 7; j++){
if (brd.gameBoard[i][j] != 0 && brd.gameBoard[i][j] == brd.gameBoard[i][j+1]){
count++;
} else {
count = 1;
}
if (count >= 4){
return true;
}
}
}
return false;
I know it's a lot of text, but maybe somebody can give me some useful tips :)
Thanks!
Max
I'm not sure that your test to find the winner is correct. Try this (you'll need to change it a little bit, but at least I'm sure that it's correct):
public static boolean testWinner(int[][] game, int lastColumn, Integ e) {
int lastRow = 0;
while (lastRow < 6 && game[lastRow][lastColumn] == 0) {
lastRow++;
}
lastRow = lastRow;
int i = 0;
int j = 0;
int currentPlayer = game[lastRow][lastColumn];
e.setI(currentPlayer);
int sequence = 0;
i = lastRow;
boolean b = i < 3
&& game[i][lastColumn] == currentPlayer
&& game[i+1][lastColumn] == currentPlayer
&& game[i+2][lastColumn] == currentPlayer
&& game[i+3][lastColumn] == currentPlayer;
if(b) {
return true;
}
sequence = 0;
j = lastColumn;
do {
j--;
} while(0 < j && game[lastRow][j] == currentPlayer);
if(j < 0 || game[lastRow][j] != currentPlayer) {
j++;
}
while(j <= 6 && game[lastRow][j] == currentPlayer) {
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
sequence = 0;
i = lastRow;
j = lastColumn;
do {
i--;
j--;
} while(0 < i && 0 < j && game[i][j] == currentPlayer);
if(i < 0 || j < 0 || game[i][j] != currentPlayer) {
i++;
j++;
}
while(i <= 5 && j <= 6 && game[i][j] == currentPlayer) {
i++;
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
sequence = 0;
i = lastRow;
j = lastColumn;
do {
i++;
j--;
} while(i < 5 && 0 < j && game[i][j] == currentPlayer);
if (5 < i || j < 0 || game[i][j] != currentPlayer) {
i--;
j++;
}
while(0 <= i && j <= 6 && game[i][j] == currentPlayer) {
i--;
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
return false;
}
Integ is just a class with an integer. I've created it because the wrapper is not really an object (can't pass by reference).
private static class Integ {
private int i;
public Integ() {
this.i = 0;
}
public void increment() {
this.i = this.i + 1;
}
public int getI() {
return this.i;
}
public void setI(int i) {
this.i = i;
}
}
The purpose of the program is to generate a two-dimensional grid array made of periods ( . ). The user designates a starting point for the 'walker' which is marked by 'A', and then the walker will generate numbers from 0-3 to represent the four cardinal directions. It will move in these random directions while incrementing the alphabet with each mark it leaves until it either runs in to the wall and is "arrested" or reaches 'Z' at which it "made it home". If it runs in to a space it has already been to, it has to jump ahead in the same direction until it reaches an empty space or hits the wall.
My problem now is that I have it on a counter to make sure it doesn't run past 'Z', and will "make it home" if it reaches that point. But even the movements that it is taking to avoid overwriting where it has already been are registering on the counter (which they shouldn't be), so its returning true even though it hasn't hit Z yet, and its also still calling my random number generator so its not keeping to the same direction when it tries to correct itself. It also seems to be occasionally even jumping over empty spaces.
The problem is in processing()
package walktester;
import java.lang.Math;
import java.util.Random;
import java.util.Scanner;
class DrunkWalker {
private char[][] walkgrid = new char[10][10];
private static int randNSEW;
private int randomnum;
private int startrow;
private int startcol;
private char alpha = 'A';
private int nextrow;
private int nextcol;
public DrunkWalker(int r, int c) {
startrow = r;
startcol = c;
nextrow = startrow;
nextcol = startcol;
for (int i = 0; i < 10; i ++) {
for (int j = 0; j < 10; j++)
walkgrid[i][j] = '.';
}
walkgrid[r][c] = alpha++;
}
public static void getRand(){
int x100 = 0;
double randomNum = 0.0;
randomNum = Math.random();
x100 = (int) (randomNum * 100);
randNSEW = x100 % 4;
}
public int getNextRow(){
return nextrow;
}
public int getNextCol(){
return nextcol;
}
public boolean processing(){
for(int i = 1; i < 26; i ++){
getRand();
if(randNSEW == 0){
nextcol--;
}
if(randNSEW == 1){
nextrow++;
}
if(randNSEW == 2){
nextcol++;
}
if(randNSEW == 3){
nextrow--;
}
if(nextrow < 0 || nextrow >= 10 || nextcol < 0 || nextcol >= 10) {
return false;
}
if(randNSEW == 0 && walkgrid[nextrow][nextcol] != '.'){
nextcol--;
continue;
}
if(randNSEW == 1 && walkgrid[nextrow][nextcol] != '.'){
nextrow++;
continue;
}
if(randNSEW == 2 && walkgrid[nextrow][nextcol] != '.'){
nextcol++;
continue;
}
if(randNSEW == 3 && walkgrid[nextrow][nextcol] != '.'){
nextrow--;
continue;
}
walkgrid[nextrow][nextcol] = alpha++;
}
return true;
}
public char[][] DisplayGrid() {
for(int y = 0; y < 10; y++) {
for(int x = 0; x < 10; x++) {
System.out.print(walkgrid[x][y] + " ");
}
System.out.println();
}
return walkgrid;
}
}
public class WalkTester {
public static void main(String[] args) {
Scanner inpr = new Scanner(System.in);
Scanner inpc = new Scanner(System.in);
Scanner inpchoice = new Scanner(System.in);
int r = 0;
int c = 0;
char choice = 'y';
while(choice == 'y' || choice == 'Y') {
System.out.println("Please enter x coordinate between 1 and 10.");
r = inpr.nextInt();
r = r - 1;
System.out.println("Please enter y coordinate between 1 and 10");
c = inpr.nextInt();
c = c - 1;
if(r < 0 || r > 9 || c < 0 || c > 9){
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
if(choice == 'y' || choice == 'Y'){
continue;
}
else if(choice == 'n' || choice == 'N'){
return;
}
else{
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
}
}
DrunkWalker drunkwalker = new DrunkWalker(r, c);
boolean walkerSucceeded = drunkwalker.processing();
drunkwalker.DisplayGrid();
if(walkerSucceeded) {
System.out.println("You made it home");
} else {
System.out.println("You were arrested");
}
System.out.println("Restart? y/n");
choice = inpchoice.next().charAt(0);
if(choice == 'y' || choice == 'Y'){
continue;
}
else if(choice == 'n' || choice == 'N'){
return;
}
else{
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
}
}
}
}
The following code fixes your problems. You basically did not have 'state' distinguishing a valid move, vs. moving to 'jump' over past visit points. I tried to keep the code as close as possible to your existing code.
class DrunkWalker {
private char[][] walkgrid = new char[10][10];
private static int randNSEW;
private int randomnum;
private int startrow;
private int startcol;
private char alpha = 'A';
private int nextrow;
private int nextcol;
public DrunkWalker(int r, int c) {
startrow = r;
startcol = c;
nextrow = startrow;
nextcol = startcol;
for (int i = 0; i < 10; i ++) {
for (int j = 0; j < 10; j++)
walkgrid[i][j] = '.';
}
walkgrid[r][c] = alpha++;
}
public static void getRand(){
int x100 = 0;
double randomNum = 0.0;
randomNum = Math.random();
x100 = (int) (randomNum * 100);
randNSEW = x100 % 4;
}
public int getNextRow(){
return nextrow;
}
public int getNextCol(){
return nextcol;
}
enum Mode {WALKING, CORRECTING};
Mode mode = Mode.WALKING;
public boolean processing(){
for(int i = 1; i < 26; i ++){
if (mode == Mode.WALKING) {
getRand();
if(randNSEW == 0){
nextcol--;
}
if(randNSEW == 1){
nextrow++;
}
if(randNSEW == 2){
nextcol++;
}
if(randNSEW == 3){
nextrow--;
}
}
if(nextrow < 0 || nextrow >= 10 || nextcol < 0 || nextcol >= 10) {
return false;
}
if(randNSEW == 0 && walkgrid[nextrow][nextcol] != '.'){
i--;
nextcol--;
mode = Mode.CORRECTING;
continue;
}
if(randNSEW == 1 && walkgrid[nextrow][nextcol] != '.'){
i--;
nextrow++;
mode = Mode.CORRECTING;
continue;
}
if(randNSEW == 2 && walkgrid[nextrow][nextcol] != '.'){
i--;
nextcol++;
mode = Mode.CORRECTING;
continue;
}
if(randNSEW == 3 && walkgrid[nextrow][nextcol] != '.'){
i--;
nextrow--;
mode = Mode.CORRECTING;
continue;
}
mode = Mode.WALKING;
walkgrid[nextrow][nextcol] = alpha++;
}
return true;
}
I am trying to create the game of life in java but I have difficulty writing the part that checks the number of neighbours. I understand that the problem is when the program gets to the edges of the grid it won't work because the indexes are greater/smaller than the bounds of the array. So the problem is in my Neighbours(). I am not sure how to fix it, I tried expanding the if statements and I also tried putting the whole set of statements in a while loop. The program seems to be working unless there are live cells at the edges of the grid. Any suggestions on this? Thanks in advance.
import java.io.*;
import java.util.Scanner;
public class LifeGrid
{
public int[][] grid;
public int[][] newgrid;
public int getX()
{
return grid[0].length;
}
public int getY()
{
return grid.length;
}
public int getcurrentgen()
{
return currentgen;
}
public int currentgen=0;
// modify neighbours out of boundary problem.
int Neighbours(int x, int y)
{
int neighbours = 0;
if (grid[y][x-1] == 1)
{ neighbours++; }
if (grid[y][x+1] ==1)
{ neighbours++; }
if (grid[y+1][x-1] ==1)
{ neighbours++; }
if (grid[y+1][x+1] ==1)
{ neighbours++; }
if (grid[y+1][x] ==1)
{ neighbours++; }
if (grid[y-1][x-1] ==1)
{ neighbours++; }
if (grid[y-1][x+1] ==1)
{ neighbours++; }
if (grid[y-1][x] ==1)
{ neighbours++; }
return neighbours;
}
public LifeGrid(int x, int y, String filename)
{
grid = new int [y][x];
newgrid = new int[y][x];
File input = new File(filename);
Scanner sc;
try
{
sc = new Scanner(input);
}
catch (FileNotFoundException e)
{
System.out.println("File error");
return;
}
for ( y=0; y< getY(); y++)
{
String line = sc.nextLine();
for( x = 0; x < getX(); x++)
{
if (line.charAt(x) == '*')
{
grid[y][x] = 1;
}
else
{
grid[y][x] = 0;
}
}
}
}
public void run()
{
show();
while(getcurrentgen() < 3)
{
setup();
grid = newgrid;
currentgen++;
show();
}
}
public void setup()
{
for (int y = 0; y < getY(); y++)
{
for (int x = 0;x < getX();x++)
{
if (grid[y][x]== 1)
{
if (Neighbours(x,y) < 2)
{
newgrid[y][x] = 0;
}
if (Neighbours(x,y) > 3)
{
newgrid[y][x] = 0;
}
if (Neighbours(x,y) == 3 || Neighbours(x,y) == 2)
{
newgrid[y][x] = 1;
}
}
if(grid[y][x]==0)
{
if(Neighbours(x,y) == 3)
{
newgrid[y][x]= 1;
}
}
}
}
}
public void show()
{
for(int y =0; y < getY(); y++)
{
for(int x = 0; x < getX(); x++)
{
System.out.print(grid[y][x]);
}
System.out.println();
}
System.out.println("Current generation: "+getcurrentgen());
}
}
you need to add checks for all your points to make sure they are not on boundary. This means checking for both x and y coordinates:
if (x > 0 && grid[y][x - 1] == 1) {
neighbours++;
}
if (x < grid[y].length - 1 && grid[y][x + 1] == 1) {
neighbours++;
}
if (x > 0 && y < grid.length - 1 && grid[y + 1][x - 1] == 1) {
neighbours++;
}
if (x < grid[y].length - 1 && y < grid.length - 1 && grid[y + 1][x + 1] == 1) {
neighbours++;
}
if (y < grid.length - 1 && grid[y + 1][x] == 1) {
neighbours++;
}
if (x > 0 && y > 0 && grid[y - 1][x - 1] == 1) {
neighbours++;
}
if (y > 0 && x < grid[y].length - 1 && grid[y - 1][x + 1] == 1) {
neighbours++;
}
if (y > 0 && grid[y - 1][x] == 1) {
neighbours++;
}
int Neighbours(int x, int y) is called with x=0 and y=0, right?
How do you then evaluate grid[y-1][x-1]?
Where you have
if (grid[y][x-1] == 1)
You just need to skip if this would go out of bounds:
if (x > 0 && grid[y][x-1] == 1)
And similar for all of the others.
If I have a 2D int array called myArray that is for example 3x3 size and its elements can only have either 1 or 0 for values, what would be an efficient way to calculate how many 1s there are around a particular element? E.g:
[0][0][0]
[0][1][0]
[1][1][1]
The element myArray[0][0] would have neighbourCount of 1 while myArray[0][1] would have a neighbourCount of 3.
This is my current brute force code. myArray = currentGeneration
public int neighbours(int x, int y) { //x and y are 0 index based coordinates, they are swapped inside to corespond with actual x and y coordinates
int neighbourCounter = 0;
if(x == 0 && y == 0) {
if(currentGeneration[y+1][x] == 1) {
neighbourCounter++;
}
if(currentGeneration[y][x+1] == 1) {
neighbourCounter++;
}
if(currentGeneration[y+1][x+1] == 1) {
neighbourCounter++;
}
} else if(x == 0 && y == currentGeneration.length - 1) {
if(currentGeneration[y-1][x] == 1) {
neighbourCounter++;
}
if(currentGeneration[y][x+1] == 1) {
neighbourCounter++;
}
if(currentGeneration[y-1][x+1] == 1) {
neighbourCounter++;
}
} else if(x == currentGeneration[0].length - 1 && y == currentGeneration.length - 1) {
if(currentGeneration[y-1][x] == 1) {
neighbourCounter++;
}
if(currentGeneration[y][x-1] == 1) {
neighbourCounter++;
}
if(currentGeneration[y-1][x-1] == 1) {
neighbourCounter++;
}
} else if( y == 0 && x == currentGeneration[0].length - 1) {
if(currentGeneration[y][x-1] == 1) {
neighbourCounter++;
}
if(currentGeneration[y+1][x] == 1) {
neighbourCounter++;
}
if(currentGeneration[y+1][x-1] == 1) {
neighbourCounter++;
}
} else if(y == 0) {
for(int i = -1; i <= 1; i+=2) {
if(currentGeneration[y][x+i] == 1) {
neighbourCounter++;
}
}
if(currentGeneration[y+1][x] == 1) {
neighbourCounter++;
}
for(int i = -1; i <= 1; i+=2) {
if(currentGeneration[y+1][x+i] == 1) {
neighbourCounter++;
}
}
} else if(x == 0) {
for(int i = -1; i <= 1; i+=2) {
if(currentGeneration[y+i][x] == 1) {
neighbourCounter++;
}
}
if(currentGeneration[y][x+1] == 1) {
neighbourCounter++;
}
for(int i = -1; i <= 1; i+=2) {
if(currentGeneration[y+i][x+1] == 1) {
neighbourCounter++;
}
}
} else if(y == currentGeneration.length - 1) {
for(int i = -1; i <= 1; i+=2) {
if(currentGeneration[y][x+i] == 1) {
neighbourCounter++;
}
}
if(currentGeneration[y-1][x] == 1) {
neighbourCounter++;
}
for(int i = -1; i <= 1; i+=2) {
if(currentGeneration[y-1][x+i] == 1) {
neighbourCounter++;
}
}
} else if(x == currentGeneration[0].length - 1) {
for(int i = -1; i <= 2; i+=2) {
if(currentGeneration[y+i][x] == 1) {
neighbourCounter++;
}
}
if(currentGeneration[y][x-1] == 1) {
neighbourCounter++;
}
for(int i = -1; i <= 2; i+=2) {
if(currentGeneration[y+i][x-1] == 1) {
neighbourCounter++;
}
}
} else {
for(int i = -1; i <= 1; i+=2) {
if(currentGeneration[y+i][x] == 1) {
neighbourCounter++;
}
if(currentGeneration[y][x+i] == 1) {
neighbourCounter++;
}
if(currentGeneration[y+i][x+i] == 1) {
neighbourCounter++;
}
if(currentGeneration[y+i][x-i] == 1) {
neighbourCounter++;
}
}
}
return neighbourCounter;
}
How about that:
public static int findNeighbors(int x, int y, int[][] a) {
int sum = 0;
for ( int i = (y>0 ? y-1 : 0); i <= (y<a.length-1 ? y+1 : a.length-1); ++i )
for ( int j = (x>0 ? x-1 : 0); j <= (x<a[0].length-1 ? x+1 : a[0].length-1); ++j )
sum += a[i][j];
sum -= a[y][x];
return sum;
}