I am working on Conway's game of life java code and I am having a struggle with my update method also known as the next generation creator. I will post my code I have written so far and please let me know what I can do to fix the update method.
A cell is born if there was none at time T
1 and exactly three of its neighbors were alive.
An existing cell remains alive if at time T
1 there were either two or three neighbors
A cell dies from isolation if at time T
1 there were fewer than two neighbors.
A cell dies from overcrowding if at time T
1 there were more than three neighbors.
public class GameOfLife {
private char [][] grid;
private int rows;
private int columns;
public GameOfLife(int rows, int columns) {
grid=new char[rows][columns];
for(int i=0;i<grid.length;i++)
{
for(int j=0;j<grid[i].length;j++)
grid[i][j]=' ';
}
}
public int numberOfRows() {
int countRows=0;
for(int i=0;i<grid.length;i++){
countRows++;
rows=countRows;
}
return rows;
}
public int numberOfColumns() {
int countColumns=0;
for(int i=0;i<1;i++){
for(int j=0;j<grid[i].length;j++)
countColumns++;
columns=countColumns;
}
return columns;
}
public void growCellAt(int row, int col) {
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++)
grid[row][col]='O';
}
}
public boolean cellAt(int row, int col) {
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++)
if(grid[row][col]=='O')
return true;
}
return false;
}
public String toString() {
String result="";
for(int i=0;i<rows;i++){
for(int j=0;j<columns;j++)
result+=grid[i][j];
}
return result;
}
public int neighborCount(int row, int col) {
int count=0;
int i=row;
int j=col;
int left;
int right;
int up;
int down;
if(i > 0)
up = i-1;
else
up = grid.length-1;
if(i < (grid.length-1))
down = i+1;
else
down = 0;
if(j > 0)
left = j-1;
else
left = grid[i].length - 1;
if(j < (grid[i].length-1))
right = j+1;
else
right = 0;
if(grid[up][left] == 'O')
count++;
if(grid[up][j] == 'O')
count++;
if(grid[up][right] == 'O')
count++;
if(grid[i][left] == 'O')
count++;
if(grid[i][right] == 'O')
count++;
if(grid[down][left] == 'O')
count++;
if(grid[down][j] == 'O')
count++;
if(grid[down][right] == 'O')
count++;
return count;
}
public void update() {
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++){
if(grid[i][j]==' ' && neighborCount(i,j)==3)
grid[i][j]='O';
if(neighborCount(i,j)<2 || neighborCount(i,j)>3)
grid[i][j]= ' ';
if(grid[i][j]=='O' && neighborCount(i,j)==2 || neighborCount(i,j)==3)
grid[i][j]='O';
}
}
}
}
Ok regarding making a new array in the update method, is this all that needs to be done? Also, how would I go about making assertion tests for the update method?
public void update() {
char[][] newGrid = new char[grid.length][grid[0].length];
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++){
if(grid[i][j]==' ' && neighborCount(i,j)==3)
newGrid[i][j]='O';
if(neighborCount(i,j)<2 || neighborCount(i,j)>3)
newGrid[i][j]= ' ';
if(grid[i][j]=='O' && neighborCount(i,j)==2 || neighborCount(i,j)==3)
newGrid[i][j]='O';
}
}
}
It looks like you are trying to modify the same grid you are looping through. As you loop through your grid, changes should be made based on the previous state of the grid. Try constructing a new grid instead of writing over the old one.
That's how I would go about it.
Note that this is C++11 implementation
template<std::size_t X, std::size_t Y>
class GameOfLife {
private:
std::pair<int, int> neighbors[8];
public:
typedef std::array<std::array<uint16_t,Y>,X> Grid;
private:
uint16_t getCellStatus(Grid const& conway, int x, int y) {
uint16_t liveCount = 0;
for(auto&& neighbor: neighbors) {
int nX = x + neighbor.first;
int nY = y + neighbor.second;
if(nX>=0 && nX<X && nY>=0 && nY<Y){
if(conway[nX][nY]>0) liveCount++;
}
}
if(conway[x][y]>0){
if(liveCount==2 ||liveCount == 3) return 1;
}
else {
if(liveCount==3) return 1;
}
return 0;
}
public:
GameOfLife() {
size_t index = 0;
for(int i=-1; i<=1; ++i) {
for(int j=-1; j<=1; ++j){
if((i|j)==0) continue;
neighbors[index].first = i;
neighbors[index++].second = j;
}
}
}
Grid getNextConway(Grid const& conway) {
Grid output;
for(size_t i=0; i<X; ++i)
for(size_t j=0; j<Y; ++j) output[i][j]=getCellStatus(conway,i,j);
return output;
}
Grid printGrid(Grid const& conway) {
for (int i = 0; i < X; ++i){
for (int j = 0; j < Y; ++j) {
if(conway[i][j]==0) std::cout<<"0";
else std::cout<<"1";
}
std::cout<<std::endl;
}
std::cout<<std::endl;
}
};
int main() {
size_t const DIM = 8;
size_t const NUM_GENS = 10;
typedef GameOfLife<DIM,DIM> Game;
typename Game::Grid gameGrid;
for (int i = 0; i < DIM; ++i) {
for (int j = 0; j < DIM; ++j) {
gameGrid[i][j] = rand()%2;
}
}
Game conway;
conway.printGrid(gameGrid);
for (int i = 0; i < NUM_GENS; ++i) {
gameGrid = conway.getNextConway(gameGrid);
conway.printGrid(gameGrid);
}
return 0;
}
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.
This program working quite well. i wrote some exception ex N=1,2 and find others.
I have a problem with a bord part when I give a number above 30 program waiting and freezing how can I solve that? I want to write for at least 255 or 150(max value). in there if N=30 or more program will stop when you want to run.
package com.company;
import java.util.Scanner;
public class NQueenProblem {
Scanner scanner = new Scanner(System.in);
final int N = Integer.valueOf(scanner.nextLine());
void printSolution(int board[][]) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
System.out.print(" " + board[i][j]
+ " ");
System.out.println();
}
}
safe condition is working correctly in big boards
boolean isSafe(int board[][], int row, int col) {
int i, j;
for (i = 0; i < col; i++)
if (board[row][i] == 1)
return false;
for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
if (board[i][j] == 1)
return false;
for (i = row, j = col; j >= 0 && i < N; i++, j--)
if (board[i][j] == 1)
return false;
return true;
}
boolean solveNQUtil(int board[][], int col) {
if (col >= N)
return true;
for (int i = 0; i < N; i++) {
if (isSafe(board, i, col)) {
board[i][col] = 1;
if (solveNQUtil(board, col + 1) == true)
return true;
board[i][col] = 0;
}
}
return false;
}
boolean solveNQ() {
int board[][]=new int[N][N];
if (solveNQUtil(board, 0) == false) {
System.out.print("Solution does not exist");
return false;
}
printSolution(board);
return true;
}
// driver program to test above function
public static void main(String args[]) {
NQueenProblem Queen = new NQueenProblem();
Queen.solveNQ();
}
}
I have no idea what the problem is .I printed the moveVal all the time it prints 0 and its going in a horizontal order.
The I have been editing a changing the code by using Google and YouTube but, there was no good
static class Move {
int row, col;
}
private boolean equals(JButton a, JButton b, JButton c){
return a.getText().equals(b.getText()) && b.getText().equals(c.getText()) && !a.getText().equals("");
}
private boolean isGameOver() {
for (int i = 0; i < 3; i++) {
if (equals(board[i][0], board[i][1], board[i][2])) {
return true;
}
}
for (int i = 0; i < 3; i++) {
if (equals(board[0][i], board[1][i], board[2][i])) {
return true;
}
}
if (equals(board[0][0], board[1][1], board[2][2])) {
return true;
}
else if (equals(board[2][0], board[1][1], board[0][2])) {
return true;
}
int openSpots = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j].getText().equals("")) {
openSpots++;
}
}
}
return openSpots == 0;
}
private int evaluate(JButton[][] b) {
for (int row = 0; row < 3; row++)
{
if (b[row][0] == b[row][1] &&
b[row][1] == b[row][2])
{
if (b[row][0].getText().equals(ai))
return 20;
else if (b[row][0].getText().equals(human))
return -10;
}
}
for (int col = 0; col < 3; col++)
{
if (b[0][col] == b[1][col] &&
b[1][col] == b[2][col])
{
if (b[0][col].getText().equals(ai))
return 20;
else if (b[0][col].getText().equals(human))
return -10;
}
}
if (b[0][0] == b[1][1] && b[1][1] == b[2][2])
{
if (b[0][0].getText().equals(ai))
return 20;
else if (b[0][0].getText().equals(human))
return -10;
}
if (b[0][2] == b[1][1] && b[1][1] == b[2][0])
{
if (b[0][2].getText().equals(ai))
return 20;
else if (b[0][2].getText().equals(human))
return -10;
}
return 0;
}
private int minimax(JButton[][] position, int depth, boolean isMax) {
if (isGameOver() || depth == 0){
return evaluate(position);
}
else if (isMax)
{
int best = -1000000000;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (position[i][j].getText().equals(""))
{
position[i][j].setText(ai);
JButton[][] position1 = position;
best = Math.max(best, minimax(position1, depth - 1, false));
System.out.println(best);
position[i][j].setText("");
}
}
}
return best;
}
else
{
int best1 = 1000000000;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (position[i][j].getText().equals(""))
{
position[i][j].setText(human);
JButton[][] position1 = position;
best1 = Math.min(best1, minimax(position1, depth - 1, true));
position[i][j].setText("");
}
}
}
return best1;
}
}
private void BestMove(JButton[][] board) {
int bestVal = -1000000000;
Move bestMove = new Move();
bestMove.row = -1;
bestMove.col = -1;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i][j].getText().equals(""))
{
board[i][j].setText(ai);
int moveVal = minimax(board, 3, false);
board[i][j].setText("");
if (moveVal > bestVal)
{
bestVal = moveVal;
bestMove.row = i;
bestMove.col = j;
}
}
}
}
board[bestMove.row][bestMove.col].setText(ai);
playersTurn = true;
CheckWinner();
}
Any ideas & please help is needed
past 3 days I have been debugging I know this code is not the best in fact this code might be the worst you have ever seen.
Blockquote
You have only 3 possible evaluations:
20, if the AI wins
-10, if the human wins
0, in all other cases
As you only look at 4 turns (ai, human, ai, human), it's impossible to find a winning position, so the evaluation is always 0.
There is no obvious issue with your implementation of the minimax, however your evaluation function is too simple.
You can, for example:
Give more points to playing in a position that creates a row of 2
Give more points to playing in a position that creates multiple rows of 2
Give less points to a position that is already blocked
However, there is only so much you can do. This game is obviously solved, and a perfect player can always get a draw playing either sides.
I have written a program for an assignment where we had to write a simple Gomoku program. I thought I had it all, but when I compile and run, it sets off the win scenario even if I only have 4 of a kind and even if they're not next to each other. (It should only set off a win if there are five in a row of one kind...X's or O's). I feel like I should be resetting my counter back to 0 before each turn, but I'm not sure where I should be doing that. Any tips would be appreciated!
import java.util.Scanner;
public class Gomoku1
{
public static void main (String[] args)
{
Scanner input = new Scanner(System.in);
char[][] map = new char [19][19];
int row = 0;
int column = 0;
//fill game with dots
for (int i = 0; i < map.length; i++)
{
for (int j = 0; j < map[i].length; j++)
{
map[i][j] = '.';
}
}
printMap(map);
char player1Choice = 'X';
char player2Choice = 'O';
int [] place;
while (true)
{
System.out.println("Player 1's turn!");
place = userTurn(map, player1Choice);
if (isValidMove(map, place[0], place[1]) == false)
{
System.out.println("Invalid move! Try again!");
place = userTurn(map, player1Choice);
}
if (isValidMove(map, place[0], place[1])) {
map[place[0]][place[1]] = player1Choice;
printMap(map);
}
if (isBoardFull(map) == true)
{
System.out.println("Board is full. Tied game.");
break;
}
if (hasPlayerWon(map, player1Choice) == true)
{
System.out.println("Player 1 Wins!");
break;
}
else
{
System.out.println("Player 2's turn!: ");
place = userTurn(map, player2Choice);
//System.out.println(isValidMove(map, row, column));
if (isValidMove(map, place[0], place[1]) == false)
{
System.out.println("Invalid move! Try again!");
place = userTurn(map, player2Choice);
}
if (isValidMove(map, place[0], place[1])) {
map[place[0]][place[1]] = player2Choice;
printMap(map);
}
if (isBoardFull(map) == true)
{
System.out.println("Board is full. Tied game.");
break;
}
if (hasPlayerWon(map, player2Choice) == true)
{
System.out.println("Player 2 Wins!");
break;
}
}
}
}
public static void printMap (char[][] map)
{
for (int i = 0; i < map.length; i++)
{
for (int j = 0; j < map[i].length; j++)
{
System.out.printf("%2c", map[i][j]);
}
System.out.println();
}
}
public static int [] userTurn (char[][] map, char playerChoice)
{
Scanner input = new Scanner(System.in);
System.out.print("Enter row: ");
int row = input.nextInt();
System.out.print("Enter column: ");
int column = input.nextInt();
int place [] = {row, column};
return place;
}
public static boolean isValidMove (char[][] map, int row, int column)
{
//System.out.println ("n is valid move");
if (row < 0 || row > 18 || column < 0 || column > 18 || map[row][column]=='O' || map[row][column]=='X')
{
return false;
}
else
{
return true;
}
}
public static boolean isBoardFull (char[][] map)
{
int openSpots = 0;
for (int i = 0; i < map.length; i++)
{
for (int j = 0; j < map.length; j++)
{
if (!(map[i][j]=='.'))
openSpots++;
}
}
if (openSpots == 361)
{
return true;
}
return false;
}
public static boolean hasPlayerWon(char[][] map, int player)
{
if (isHorizontalWin(map, player) == true || isVerticalWin(map, player) == true || isDiagonalWin(map, player) == true)
{
return true;
}
return false;
}
public static boolean isHorizontalWin(char[][] map, int player)
{
int count = 0;
int r;
int c;
for (int i = 0; i < map.length; i++)
{
for (int j = 0; j < map.length; j++)
{
if (map[i][j]==(player))
{
r = i;
c = j;
while (r >= 0 && r <= 18 && c >= 0 && c <= 18 && map[r][c] == player)
{
count ++;
r += 0;
c += 1;
}
}
}
}
if (count == 5)
{
return true;
}
return false;
}
public static boolean isVerticalWin(char[][] map, int player)
{
int count = 0;
int r;
int c;
for (int i = 0; i < map.length; i++)
{
for (int j = 0; j < map.length; j++)
{
if (map[i][j]==(player))
{
r = i;
c = j;
while (r >= 0 && r <= 18 && c >= 0 && c <= 18 && map[r][c] == player)
{
count ++;
r += 1;
c += 0;
}
}
}
}
if (count == 5)
{
return true;
}
return false;
}
public static boolean isDiagonalWin(char[][] map, int player)
{
int count = 0;
int r;
int c;
for (int i = 0; i < map.length; i++)
{
for (int j = 0; j < map.length; j++)
{
if (map[i][j]==(player))
{
r = i;
c = j;
while (r >= 0 && r <= 18 && c >= 0 && c <= 18 && map[r][c] == player)
{
count++;
r += 1;
c += 1;
}
}
}
}
if (count == 5)
{
return true;
}
return false;
}
}
You have problems in all three of the function that check win conditions: isHorizontalWin, isVerticalWin, and isDiagonalWin. All three increment the variable count, but this variable is never set back to zero. Additionally, the check to see if count == 5 should be made inside the loop. Here is an example on how to fix isHorizontalWin:
public static boolean isHorizontalWin(char[][] map, int player)
{
int count = 0;
int r;
int c;
for (int i = 0; i < map.length; i++)
{
for (int j = 0; j < map.length; j++)
{
if (map[i][j]==(player))
{
r = i;
c = j;
while (r >= 0 && r <= 18 && c >= 0 && c <= 18 && map[r][c] == player)
{
count ++;
r += 0;
c += 1;
}
if (count == 5)
{
return true;
} else {
count = 0;
}
}
}
}
return false;
}
I'm trying to code a method which checks for duplicates on my Sudoku board. Currently, my method getFrontier() always returns true, and I've come to learn that it's because it's only checking for one value rather than an array or values. I use the method 3 times in squareCheck(), rowCheck() and columnCheck(). Is there any way to code the method so it would retain the previous value which was input and then check it against the new value?
My current code:
public class validCheck {
public boolean isSolved(int[][][] board)
{
for(int index = 0; index < board.length;index++)
{
for(int r = 0; r < board[0].length; r++)
{
for(int c = 0; c < board[0].length;c++)
{
if(board[index][r][c] == 0)
return false;
}
}
}
return true;
}
public boolean getFrontier(int value)
{
Set<Integer> reserve = new HashSet<>();
for(int n = 1; n < 10; n++)
{
if(value == n && reserve.contains(n))
return false;
else if(value == n) reserve.add(n);
}
return true;
}
public boolean squareCheck(int[][][] board, int index)
{
for(int r = 0; r < board[0].length; r++)
{
for(int c = 0; c < board[0].length; c++)
{
if(!getFrontier(board[index][r][c]))
{
System.out.println("Square error at ["+index + r + c +"]");
return false;
}
}
}
return true;
}
public boolean isValid(int[][][] board)
{
if(isSolved(board))
{
for(int i = 0; i < board.length; i++)
{
for(int r = 0; r < board[0].length;r++)
{
for(int c = 0; c < board[0].length;c++)
{
if(!rowCheck(board,i,r) || !columnCheck(board,i,c) || !squareCheck(board,i))
{
return false;
}
}
}
}
}
return true;
}
public boolean columnCheck(int[][][] board, int index, int col)
{
int target = 0;
if(index <=2)
{
target = index + 6;
}
else if(index > 2 && index < 6)
{
target = index +3;
index = index - 3;
}
else if (index > 5)
{
target = index;
index = index - 6;
}
while(index <= target)
{
for(int r = 0; r < board[0].length;r++)
{
if(!getFrontier(board[index][r][col]))
{
System.out.println("Column error at " + index + r + col);
return false;
}
}
index = index + 3;
}
return true;
}
public boolean rowCheck(int[][][] board, int index, int row)
{
int target = 0;
if(index <= 2)
{
index = 0;
target = 2;
}
else if (index <= 5)
{
index = 3;
target = 5;
}
else if(index <= 8)
{
index = 6;
target = 8;
}
while(index <= target)
{
for(int c = 0; c < board[0].length; c++)
{
if(!getFrontier(board[index][row][c]))
{
System.out.println("Row error at "+index+row+c);
return false;
}
}
index++;
}
return true;
}
}
Usage:
public static void main(String[] args) {
int[][][] solved = {{{5,3,4},{6,7,2},{1,9,8}},
{{6,7,8},{1,9,5},{3,4,2}},
{{9,1,2},{3,4,8},{5,6,7}},
{{8,5,9},{4,2,6},{7,1,3}},
{{7,6,1},{8,5,3},{9,2,4}},
{{4,2,3},{7,9,1},{8,5,6}},
{{9,6,1},{2,8,7},{3,4,5}},
{{5,3,7},{4,1,9},{2,8,6}},
{{2,8,4},{6,3,5},{1,7,9}}};
validCheck checker = new validCheck();
if(checker.isValid(solved))
System.out.println(true);
else System.out.println(false);
}
Any help will be greatly be appreciated!!!
Here is what I would do to find a valid board config in a 2D sudoku board. I would use a HashSet for a row and another for the column, as long as we never encounter repeats and the values contain 1 to the length of the array we know the board is valid.
int [][] board = {{1,2,3},
{2,3,1},
{3,1,2}
};
HashSet<Integer> rowDuplicates = new HashSet<>();
HashSet<Integer> colDuplicates = new HashSet<>();
boolean invalidBoard = false;
for(int i = 0 ; i < board.length; i++)
{
for(int j = 0; j < board[i].length; j++)
{
if(rowDuplicates.contains(board[i][j]) || colDuplicates.contains(board[j][i]))
{
//this board is not valid
invalidBoard = true;
}
else
{
rowDuplicates.add(board[i][j]);
colDuplicates.add(board[j][i]);
}
}
//now check they contain the correct numbers from 1 to the size of the array
if(colDuplicates.size() == rowDuplicates.size())
{
for(int index = 0; index < colDuplicates.size(); index++)
{
if(!(colDuplicates.contains(index + 1) && rowDuplicates.contains(index + 1)))
{
invalidBoard = true;
break;
}
}
}
else
{
invalidBoard = true;
}
colDuplicates.clear();
rowDuplicates.clear();
}
System.out.println("invalid board: " + invalidBoard);
You should be able to expand this to your 3D array but you can see how much easier it is to use HashSets to verify a valid 2D array Sudoku board.