Logic check for a 10*10 game - java

I am doing a game called 1010! Probably some of you have heard of it. Bascially I encouter some trouble when writing the Algorithm for clearance.
The rule is such that if any row or any column is occupied, then clear row and column respectively.
The scoring is such that each move gains a+10*b points. a is the number of square in the input piece p and b is the total number of row&column cleared.
To start, I create a two dimensional Array board[10][10], poulate each elements in the board[][] with an empty square.
In the class of Square, it has public void method of unset()-> "empty the square" & boolean status() -> "judge if square is empty"In the class of piece, it has int numofSquare -> "return the number of square in each piece for score calculation"
In particular, I don't know how to write it if both row and column are occupied as they are inter-cross each other in an two dimensional array.
It fail the test under some condition, in which some of the squares are not cleared but they should have been cleared and I am pretty sure is the logic problem.
My thinking is that:
Loop through squares in first row and first column, record the number of square that are occupied (using c and r); if both are 10, clear row&column, otherwise clear row or column or do nothing.
reset the c &r to 0, loop through square in the second row, second column…
update score.
Basically the hard part is that if I seperate clear column and clear row algorithm ,I will either judge row or column first then clear them . However, as every column contains at least one square belong to the row, and every row contains at least one square belong to the column, there will be mistake when both row and column are full.
Thanks for help.
import java.util.ArrayList;
public class GameState{
public static final int noOfSquares = 10;
// the extent of the board in both directions
public static final int noOfBoxes = 3;
// the number of boxes in the game
private Square[][] board; // the current state of the board
private Box[] boxes; // the current state of the boxes
private int score; // the current score
// initialise the instance variables for board
// all squares and all boxes are initially empty
public GameState()
{
getboard();
score = 0;
board = new Square[10][10];
for(int i =0;i<board.length;i++){
for(int j =0;j<board[i].length;j++){
board[i][j] = new Square();
}
}
boxes = new Box[3];
for(int k =0;k<boxes.length;k++){
boxes[k] = new Box();
}
}
// return the current state of the board
public Square[][] getBoard()
{
return board;
}
// return the current score
public int getScore()
{
return score;
}
// place p on the board with its (notional) top-left corner at Square x,y
// clear columns and rows as appropriate
int r =0;
int c = 0;
int rowandcolumn = 0;
for (int row=0;row<10;row++){
for (int column=0;column<10;column++) {
if (board[row][column].status() == true){
c = c + 1;
if( c == 10 ) {
rowandcolumn = rowandcolumn + 1;
for(int z=0;z<10;z++){
board[row][z].unset(); //Clear column
}
}
}
if (board[column][row].status() == true){
r = r + 1;
if( r == 10) {
rowandcolumn = rowandcolumn + 1;
for(int q=0;q<10;q++){
board[q][row].unset(); //Clear row
}
}
}
}
r=0; //reset
c=0;
}
score = score + p.numberofBox()+10*rowandcolumn;
}

how about this
void Background::liquidate(int &score){
int arr_flag[2][10]; //0 is row,1 is column。
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 10; j++)
{
arr_flag[i][j] = 1;
}
}
//column
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (arr[i][j].type == 0)
{
arr_flag[0][i] = 0;
break;
}
}
}
//row
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (arr[j][i].type == 0)
{
arr_flag[1][i] = 0;
break;
}
}
}
//clear column
for (int i = 0; i < 10; i++)
{
if (arr_flag[0][i] == 1)
{
for (int j = 0; j < 10; j++)
{
arr[i][j].Clear();
}
}
}
//clear row
for (int i = 0; i < 10; i++)
{
if (arr_flag[1][i] == 1)
{
for (int j = 0; j < 10; j++)
{
arr[j][i].Clear();
}
}
}
}

I tried to write somme code for the idea I posted
// place p on the board with its (notional) top-left corner at Square x,y
// clear columns and rows as appropriate
int r =0;
int c = 0;
int rowandcolumn = 0;
int row=FindFirstRow();
int column=FindFirstColumn();
if(row!=-1 && column!=-1)
{
rowandcolumn++;
//actions here: row found and column found
//clear row and column
clearRow(row);
clearColumn(column);
}
else if(row!=-1)
{
//only row is found
//clear row
clearRow(row);
}
else if(column!=-1)
{
//only column is found
//clear column
clearColumn(column);
}
else
{
//nothing is found
}
public void clearRow(int row)
{
for(int i=0; i<10;i++)
{
board[row][i].unset();
}
}
public void clearColumn(int column)
{
for(int i=0; i<10;i++)
{
board[i][column].unset();
}
}
//this method returns the first matching row index. If nothing is found it returns -1;
public int FindFirstRow()
{
for (int row=0;row<10;row++)
{
int r=0;
for (int column=0;column<10;column++)
{
if (board[row][column].status() == true)
{
r = r + 1;
if( r == 10)
{
//row found
return row;
}
}
}
r=0; //reset
}
//nothing found
return -1;
}
//this method returns the first matching column index. If nothing is found it returns -1;
public int FindFirstColumn()
{
for (int column=0;column<10;column++)
{
int c=0;
for (int row=0;row<10;row++)
{
if (board[row][column].status() == true)
{
c = c + 1;
if( c == 10 )
{
//matching column found
return column;
}
}
}
c=0; //reset
}
//nothing found
return -1;
}

Related

JAVA one player version of the game "BattleShip

This game uses a 2d array(7x7) and uses two array lists to store the ship (of lengths 2,3,4) and user guesses. The user first types the row and column of each ship and the orientation (either extending down or right). Then a blank board is printed to console and the user will guess row and column. If there is a ship in that spot "hit!" is printed to console, else "miss!" is printed. After each guess, the new state of the board is printed where each hit is a "X" and each miss is a "M". also each guess is added to the guess array list. once the user guesses where each element of the ship is, the game is over and the guess history is printed. My code seems to be working however I am having trouble ending the game. It never gets out of the while loop in the main. Here is my code, is there something that I am doing wrong or need to change?
===========================================================================
My code:
class Ship {
int x;
int y;
//String orient;
public Ship (int x, int y) {
super();
this.x = x;
this.y = y;
//this.orient = orient;
}
}
class Guess {
int row;
int col;
public Guess (int row, int col) {
super();
this.row = row;
this.col = col;
}
}
public class CS125_Project5
{
//create the 2d arrays for the realBoard where the user will add the ships
// and the guessBoard which will update when user makes guesses
/////////what i had at first but kept getting nullpointerexception
//static String realBoard[][];
//static String guessBoard[][];
//with these i get the thing printed but it says null for all values
static String gameBoard[][] = new String[7][7];
static String guessBoard[][] = new String[7][7];
//creating the arrayList for both ships and guesses
static ArrayList<Ship> ships = new ArrayList<>();
static ArrayList<Guess> guesses = new ArrayList<>();
////////////////////////////////////////////////////////
////// Constructor
////////////////////////////////////////////////////////
public CS125_Project5() {
//initializing the arrays to have a fixed size of 7x7
//realBoard = new String[7][7];
//guessBoard = new String[7][7];
ships = new ArrayList<>();
guesses = new ArrayList<>();
//adding a '-' to each element of the 2d arrays for both boards
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7; j++) {
gameBoard[i][j] = "-";
guessBoard[i][j] = "-";
}
}
}
////////////////////////////////////////////////////////
/////// Method to Print the game maker board
////////////////////////////////////////////////////////
public static void printGameMakerBoard(){
System.out.print("r\\c\t");
//printing the column numbers
for(int i=0;i<7;i++){
System.out.print(i+"\t");
}
//printing the row numbers
System.out.println();
//printing the gameMaker board to show user what the board looks like
for(int i=0;i<7;i++){
System.out.print(i+"\t");
for(int j=0;j<7;j++){
System.out.print(gameBoard[i][j] +"\t");
}
System.out.println();
}
}
public static void updateBoard(int row, int col, String orient, int length) {
//if statement to determine orientation of ship
if (orient.contains("r")) {
int updateCol;
for (int j = 0; j < length; j++) {
updateCol = j + col;
gameBoard[row][updateCol] = "S";
}
} else {
int updateRow;
for (int j = 0; j < length; j++) {
updateRow = row + j;
gameBoard[updateRow][col] = "S";
}
}
printBoard(gameBoard);
}
public static void printBoard(String[][] board) {
System.out.print("r\\c"+"\t");
//printing the column numbers
for(int i=0;i<7;i++){
System.out.print(i+"\t");
}
System.out.println();
//printing the row numbers
// printing the guess board
for(int i=0;i<7;i++){
System.out.print(i+"\t");
for(int j=0;j<7;j++){
System.out.print(board[i][j] +"\t");
}
System.out.println();
}
}
private static void addShip(int x, int y, int length, String orient) {
gameBoard[x][y] = "S";
if (length == 2 || length == 3 || length == 4) {
if (orient.contains("d")) {
for (int i = 0; i < length; i++) {
Ship ship = new Ship(x, y+i);
ships.add(ship);
}
} else { //orient.contains("s")
for (int j = 0; j < length; j++) {
Ship ship = new Ship(x+j, y);
ships.add(ship);
}
}
}
// Ship ship = new Ship(x, y);
// ships.add(ship);
}
public void guess(int x, int y) {
//adding user guesses to ArrayList
Guess g = new Guess(x , y);
guesses.add(g);
//check to see if hit or miss, if hit replace user guess with 'X'
// else if its a miss replace guess with 'M'
if (gameBoard[x][y] == "S") {
guessBoard[x][y] = "X";
System.out.println("Hit!");
//now remove the ship from the list
for(int i = 0; i < ships.size(); i++) {
Ship ship = ships.get(i);
if (ship.x== x && ship.y == y){
ships.remove(i);
break;
}
}
} else {
guessBoard[x][y] = "M";
System.out.println("Miss!");
}
}
public static boolean gameOver() {
if(ships.size() == 0) {
return true;
} return false;
}
public static void printGuesses() {
System.out.println("Guess || Row Col");
System.out.println("=====================");
for(int i = 0; i < guesses.size(); i++) {
Guess g = guesses.get(i);
System.out.println(" " + i + " || " + g.row + " " + g.col);
}
}
////////////////////////////////////////////////////////
////// Main
////////////////////////////////////////////////////////
public static void main(String[] args)
{
// Your program should always output your name and the project number.
// DO NOT DELETE OR COMMENT OUT. Replace with relevant info.
System.out.println("Mason Sarna");
System.out.println("Project 5");
System.out.println("");
// Your code should go below this line
System.out.println("------------Welcome to BattleShip------------");
//printGameMakerBoard();
CS125_Project5 userShip = new CS125_Project5();
//CS125_Project5.printGameMakerBoard();
printBoard(guessBoard);
// create scanner
Scanner sc = new Scanner(System.in);
//initializing variables
int row = 0;
int col = 0;
String orient = "";
int length = 0;
/////////////////////
// Getting user input for row, col, and orientation of 3 different ships, updates/prints the board after each ship input
for (int i = 2; i < 5; i++) {
System.out.println("Please enter coordinates for ship of length "+ i);
System.out.println("Starting Row (0-6):");
row = sc.nextInt();
System.out.println("Starting column (0-6):");
col = sc.nextInt();
System.out.println("From the starting point, extend down or right? (d/r):");
orient = sc.next().toLowerCase();
length = i;
//CS125_Project5.updateBoard(row, col, orient, length);
updateBoard(row,col,orient,length);
CS125_Project5.addShip(row,col, i, orient);
}
System.out.println();
System.out.println("------------Final Game Maker Board------------");
CS125_Project5.printGameMakerBoard();
System.out.println();
System.out.println();
System.out.println("------------GAME STARTING NOW------------");
printBoard(guessBoard);
while(!gameOver()) {
System.out.println("Enter guess in row/col:");
int r = sc.nextInt();
int c = sc.nextInt();
if (guesses.contains(r) && guesses.contains(c)) {
System.out.println("r\\c = " + r + "\\" + c + " has already been guessed");
} else {
userShip.guess(r, c);
CS125_Project5.printBoard(guessBoard);
}
System.out.println("---------------------------------------------------");
}
System.out.println("------------Game Over------------");
CS125_Project5.printGuesses();
}

Stuck on recursion algorithm

I got a question about recursion for an entry exam of a job, but I failed to do it within 2 hours. I am very curious about how to do this after the pre-exam but I cannot work out a solution.
You can imagine there is a coin pusher with size n*m (2D array).
Each operation (moving up or down or left or right) will throw away one row or one column of coins
The question requires me to find the shortest possible moves that remains k coins at last. If it is impossible to remain k coins at last, then return -1
I stuck on how to determine the next move when there is more than one operation that having the same maximum number of coins (same value to be thrown away)
I believe that I need to calculate recursively that simulates all future possible moves to determine the current move operation.
But I do not know how to implement this algorithm, can anyone help?
Thank you!
Question :
There is a rectangular chessboard containing N‘M cells. each of
which either has one coin or nothing.
You can move all the coins together in one direction (such as up,
down, left, and right), but each time you can move these coins by
only one cell.
If any coins fall out of the chessboard, they must be thrown away.
If it is required to keep K coins on the board, what is the minimum
moves you have to take?
Output -1 if you can not meet this requirement.
The first line of the input are two positive
integers n, representing the size of the board.
For the next n line(s), each line has m numbers of
characters, with 'o' indicating a coin, '.' indicates an empty grid.
The last line is a positive integer k,
indicating the number of coins to be retained.
30% small input: 1 <= n,m <= 5, 0 < k < 25
40% medium input: 1 <= n,m <= 10, 0 < k < 100
30% large input: 1 <= n,m <= 100, 0 < k < 10000
sample input:
3 4
.o..
oooo
..o.
3
sample output:
2
My temporary answer
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
public class main {
String[][] inputArray;
int n;
int m;
int k;
int totalCoin = 0;
int step = 0;
public static void main(String[] args) {
main temp = new main();
temp.readData();
}
public void readData() {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
inputArray = new String [n][m];
sc.nextLine(); // skipping
for (int i = 0; i < n; i++) {
String temp = sc.nextLine();
for (int j = 0; j < m; j++) {
if ((temp.charAt(j) + "").equals("o")) totalCoin++;
inputArray[i][j] = temp.charAt(j) + "";
}
}
k = sc.nextInt();
int result = 0;
if (totalCoin >= k) {
result = findMaxAndMove();
System.out.println(result);
}
}
public String findNextMove() {
Map<String,Integer> tempList = new HashMap<String,Integer>();
tempList.put("up", up());
tempList.put("down", down());
tempList.put("left", left());
tempList.put("right", right());
Map.Entry<String, Integer> maxEntry = null;
for (Entry<String,Integer> temp : tempList.entrySet()) {
if (maxEntry == null || temp.getValue() > maxEntry.getValue()) {
maxEntry = temp;
}
}
Map<String,Integer> maxList = new HashMap<String,Integer>();
for (Entry<String,Integer> temp : tempList.entrySet()) {
if (temp.getValue() == maxEntry.getValue()) {
maxList.put(temp.getKey(), temp.getValue());
}
}
// return maxList.entrySet().iterator().next().getKey();
if (maxList.size() > 1) {
// how to handle this case when more than 1 operations has the same max value???????????
return ??????????????
}
else {
return maxList.entrySet().iterator().next().getKey();
}
//
}
public int findMaxAndMove() {
int up = up();
int down = down();
int left = left();
int right = right();
if ((totalCoin - up) == k) {
step++;
return step;
}
if ((totalCoin - down) == k) {
step++;
return step;
}
if ((totalCoin - left) == k) {
step++;
return step;
}
if ((totalCoin - right) == k) {
step++;
return step;
}
if (totalCoin - up < k && totalCoin - down < k && totalCoin - left < k && totalCoin - right < k) return -1;
else {
switch (findNextMove()) {
case "up" :
totalCoin -= up;
this.moveUp();
break;
case "down" :
totalCoin -= down;
this.moveDown();
break;
case "left" :
totalCoin -= left;
this.moveLeft();
break;
case "right" :
totalCoin -= right();
this.moveRight();
break;
}
step++;
return findMaxAndMove(); // going to next move
}
}
public String[] createBlankRow() {
String[] temp = new String[m];
for (int i = 0; i < m; i++) {
temp[i] = ".";
}
return temp;
}
public int up() {
int coinCounter = 0;
for (int i = 0; i < m; i++) {
if (inputArray[0][i].equals("o")) {
coinCounter++;
}
}
return coinCounter;
}
public void moveUp() {
// going up
for (int i = 0; i < n - 1; i++) {
inputArray[i] = inputArray[i + 1];
}
inputArray[n-1] = createBlankRow();
}
public int down() {
int coinCounter = 0;
for (int i = 0; i < m; i++) {
if (inputArray[n-1][i].equals("o")) {
coinCounter++;
}
}
return coinCounter;
}
public void moveDown() {
// going down
for (int i = n-1; i > 1; i--) {
inputArray[i] = inputArray[i - 1];
}
inputArray[0] = createBlankRow();
}
public int left() {
int coinCounter = 0;
for (int i = 0; i < n; i++) {
if (inputArray[i][0].equals("o")) {
coinCounter++;
}
}
return coinCounter;
}
public void moveLeft() {
// going left
for (int i = 0; i < n; i++) {
for (int j = 0; j < m-1; j++) {
inputArray[i][j] = inputArray[i][j+1];
}
inputArray[i][m-1] = ".";
}
}
public int right() {
int coinCounter = 0;
for (int i = 0; i < n; i++) {
if (inputArray[i][m-1].equals("o")) {
coinCounter++;
}
}
return coinCounter;
}
public void moveRight() {
// going right
for (int i = 0; i < n; i++) {
for (int j = m-1; j > 0; j--) {
inputArray[i][j] = inputArray[i][j-1];
}
inputArray[i][0] = ".";
}
}
public void printboard() {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.print(inputArray[i][j]);
}
System.out.println();
}
}
}
I suspect you didn't find the right algorithm to solve the problem. To find a solution, not only the reachable boards with some special coin count are of concern but all. You must build up a tree of reachable boards. Each node in this tree is connected to its child nodes by an operation. That's were recursion enters the scene. You stop
when you reach your goal (mark this branch as possible solution) or
when it got impossible to reach the goal with further operations (too few coins left)
when the next operation would reach a board already visited in this branch.
In this tree all shortest branches marked as possible solution are the actual solutions. If no branch is marked as possible solution there is no solution and you have to output -1.
Here is my solution
public class CoinsMover {
public static List<String> getMinMoves(Character[][] board, int k, List<String> moves) {
if (!movesAreValid(moves, board)) {
return null;
}
int currentAmountOfCoins = getCoinsOnBoard(board);
// All good no need to move any thing
if (currentAmountOfCoins == k) {
moves.add("done");
return moves;
}
// Moved to much wrong way
if (currentAmountOfCoins < k) {
return null;
}
List<String> moveRight = getMinMoves(moveRight(board), k, getArrayWithApendded(moves, "right"));
List<String> moveLeft = getMinMoves(moveLeft(board), k, getArrayWithApendded(moves, "left"));
List<String> moveUp = getMinMoves(moveUp(board), k, getArrayWithApendded(moves, "up"));
List<String> moveDown = getMinMoves(moveDown(board), k, getArrayWithApendded(moves, "down"));
List<List<String>> results = new ArrayList<>();
if (moveRight != null) {
results.add(moveRight);
}
if (moveLeft != null) {
results.add(moveLeft);
}
if (moveUp != null) {
results.add(moveUp);
}
if (moveDown != null) {
results.add(moveDown);
}
if (results.isEmpty()) {
return null;
}
List<String> result = results.stream().sorted(Comparator.comparing(List::size)).findFirst().get();
return result;
}
private static boolean movesAreValid(List<String> moves, Character[][] board) {
long ups = moves.stream().filter(m -> m.equals("up")).count();
long downs = moves.stream().filter(m -> m.equals("down")).count();
long lefts = moves.stream().filter(m -> m.equals("left")).count();
long rights = moves.stream().filter(m -> m.equals("right")).count();
boolean verticalIsFine = ups <= board.length && downs <= board.length;
boolean horizontalIsFine = lefts <= board[0].length && rights <= board[0].length;
return verticalIsFine && horizontalIsFine;
}
private static List<String> getArrayWithApendded(List<String> moves, String move) {
List<String> result = new ArrayList<>(moves);
result.add(move);
return result;
}
private static Character[][] moveRight(Character[][] board) {
Character result[][] = new Character[board.length][board[0].length];
// Cleaning left column
for (int i = 0; i < board.length; i++)
result[i][0] = '.';
for (int row = 0; row < board.length; row++) {
for (int column = 0; column < board[row].length - 1; column++) {
result[row][column + 1] = board[row][column];
}
}
return result;
}
private static Character[][] moveLeft(Character[][] board) {
Character result[][] = new Character[board.length][board[0].length];
// Cleaning right column
for (int i = 0; i < board.length; i++)
result[i][board[i].length - 1] = '.';
for (int row = 0; row < board.length; row++) {
for (int column = 1; column < board[row].length; column++) {
result[row][column - 1] = board[row][column];
}
}
return result;
}
private static Character[][] moveDown(Character[][] board) {
Character result[][] = new Character[board.length][board[0].length];
// Cleaning upper row
for (int i = 0; i < board[board.length - 1].length; i++)
result[0][i] = '.';
for (int row = board.length - 1; row > 0; row--) {
result[row] = board[row - 1];
}
return result;
}
private static Character[][] moveUp(Character[][] board) {
Character result[][] = new Character[board.length][board[0].length];
// Cleaning upper row
for (int i = 0; i < board[board.length - 1].length; i++)
result[board.length - 1][i] = '.';
for (int row = 0; row < board.length - 1; row++) {
result[row] = board[row + 1];
}
return result;
}
private static int getCoinsOnBoard(Character[][] board) {
int result = 0;
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
if (board[i][j] == 'o') {
result++;
}
}
}
return result;
}
public static void main(String... args) {
Character[][] mat = {{'.', 'o', '.', '.'}, {'o', 'o', 'o', 'o'}, {'.', '.', 'o', '.'}};
List<String> result = getMinMoves(mat, 3, new ArrayList<>());
if (result == null) {
System.out.println(-1);//output [right, right, done]
}
System.out.println(result);
}
}
I admit it was hard for me to search for duplicates so instead I am using a list of string which wrights the path you need to take to get to the solution. Now let's look at stopping condition first if current moves are invalid return null example of invalid moves is if you have a table with 4 columns in you moved right 5 times same goes for rows and moves up/down. Second, if board holds the neede amount we are done. And the last if board hold less we have failed. So now what algorithm is trying to do is to step in each direction in search of result and from here proceed recursivly.
You can find the solution below. A few points to note.
Whenever you see a problem that mentions moving an array in 1 direction, it's always a good idea to define an array of possible directions and loop through it in the recursive function. This would prevent you from confusing yourself.
The idea is to count coins by row and column so that you have a way to find out the remaining coins after each move in linear time.
The remaining job is to just loop through the possible directions in your recursive functions to find a possible solution.
As the recursive function may run in a circle and come back to one of the previous locations, you should/can improve the recursive function further by maintaining a Map cache of previous partial solutions using the curRowIdx and curColIdx as key.
public static void main(String[] args) {
char[][] board = {{'.', 'o', '.', '.'},
{'o', 'o', 'o', 'o'},
{'.', '.', 'o', '.'}};
CoinMoveSolver solver = new CoinMoveSolver(board);
System.out.println(solver.getMinimumMove(3));
}
static class CoinMoveSolver {
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
char[][] board;
int[] rowCount;
int[] colCount;
int height;
int width;
int totalCoins;
public CoinMoveSolver(char[][] board) {
// Set up the board
this.board = board;
this.height = board.length;
this.width = board[0].length;
// Count how many coins we have per row,
// per column and the total no. of coins
this.rowCount = new int[height];
this.colCount = new int[width];
for (int i = 0 ; i < board.length ; i++) {
for (int j = 0 ; j < board[i].length ; j++) {
if (board[i][j] == 'o') {
this.rowCount[i]++;
this.colCount[j]++;
totalCoins++;
}
}
}
}
// Returns the number of coins if the top left
// corner of the board is at rowIdx and colIdx
private int countCoins(int rowIdx, int colIdx) {
int sumRow = 0;
for (int i = rowIdx ; i < rowIdx + height ; i++) {
if (i >= 0 && i < height)
sumRow += rowCount[i];
}
int sumCol = 0;
for (int j = colIdx ; j < colIdx + width ; j++) {
if (j >= 0 && j < width)
sumCol += colCount[j];
}
return Math.min(sumRow, sumCol);
}
public int getMinimumMove(int targetCoinCount) {
if (totalCoins < targetCoinCount)
return -1;
else if (totalCoins == targetCoinCount)
return 0;
else
return this.recursiveSolve(0, 0, -1, 0, targetCoinCount);
}
private boolean isOppositeDirection(int prevDirectionIdx, int curDirectionIdx) {
if (prevDirectionIdx < 0)
return false;
else {
int[] prevDirection = directions[prevDirectionIdx];
int[] curDirection = directions[curDirectionIdx];
return prevDirection[0] + curDirection[0] + prevDirection[1] + curDirection[1] == 0;
}
}
private int recursiveSolve(int curRowIdx, int curColIdx, int prevDirectionIdx, int moveCount, int targetCoinCount) {
int minMove = -1;
for (int i = 0 ; i < directions.length ; i++) {
if (!this.isOppositeDirection(prevDirectionIdx, i)) {
int[] direction = directions[i];
int nextRowIdx = curRowIdx + direction[0];
int nextColIdx = curColIdx + direction[1];
int coinCount = this.countCoins(nextRowIdx, nextColIdx);
// If this move reduces too many coins, abandon
if (coinCount < targetCoinCount)
continue;
// If this move can get us the exact number of
// coins we're looking for, break the loop
else if (coinCount == targetCoinCount) {
minMove = moveCount + 1;
break;
} else {
// Look for the potential answer by moving the board in 1 of the 4 directions
int potentialMin = this.recursiveSolve(nextRowIdx, nextColIdx, i, moveCount + 1, targetCoinCount);
if (potentialMin > 0 && (minMove < 0 || potentialMin < minMove))
minMove = potentialMin;
}
}
}
// If minMove is still < 0, that means
// there's no solution
if (minMove < 0)
return -1;
else
return minMove;
}
}

Game of life malfunctioning

Why isn't my game of life working correctly?
They don't always die when they're too crowded.
Relevant code is grann(x,y) which is supposed to return the number of living cells surrounding matrix[x][y],
run is supposed to calculate the next generation:
private int grann(int x,int y) {
int n = 0;
for(int i=-1; i<2; i++) {
for(int j=-1; j<2; j++) {
if(i!=0 || j!=0) {
if(matrix[x+i][y+j]) {
n++;
}
}
}
}
return n;
}
public void run() {
boolean[][] next = matrix;
for(int i=1; i<w; i++) {
for(int j=1; j<h; j++) {
int n = grann(i,j);
if(matrix[i][j]) {
if(!(n==2 || n==3)) {
next[i][j] = false;
}
} else {
if(n==3) {
next[i][j] = true;
}
}
}
}
matrix = next;
}
The object has a matrix, width and height.
matrix is a boolean[w+2][h+2], and w and h are ints.
If you don't know the rules of Conway's game of life:
http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
I think the problem is that grann should say:
if(i != 0 && j != 0)
because you want to eliminate just the centre square of the 3x3 area you are checking (the cell itself), not the row and column it is in also.

Using Recursion in java

I'm working on the Conway's game of life program. I have the first two generations of cells printed out, but I can not get anymore printed. So I decided to use recursion so multiple batches of cells can be printed. My NewCells method creates the second generation. I thought that If I were to repeat said method by returning NewCells(c) instead of c, It would print out different results, but it prints out the same batch of cells over and over again.
public class Life {
public static boolean[][] NewCells(boolean[][] c)
{
int N = 5;
int o=0;
int p=0;
int livecnt = 0; //keeps track of the alive cells surrounding cell
int store = 0; //amount of surrounding cells for each individual cell
int livestore[] = new int[N*N];
System.out.println("Next Generation");
// Checks for the amount of "*" surrounding (o,p)
for (o=0; o < N; o++)
{
for (p=0; p<N; p++)
{
for (int k=(o-1); k <= o+1; k++)
{
for (int l =(p-1); l <=p+1; l++)
{
if ( k >= 0 && k < N && l >= 0 && l < N) //for the border indexes.
{
if (!(k== o && l==p)) //so livecnt won't include the index being checked.
{
if (c[k][l] == true)
{
livecnt++;
}
}
}
}
}
livestore[store]= livecnt;
livecnt = 0;
store++;
}
}
//Prints the next batch of cells
int counter= 0;
for (int i2 = 0; i2 <N; i2++)
{
for (int j2 = 0; j2 < N; j2++)
{
if (c[i2][j2] == false)
{
if (livestore[counter] ==3)
{
c[i2][j2]=true;
System.out.print("* ");
}
else
System.out.print("- ");
}
else if (c[i2][j2] == true)
{
if (livestore[counter] ==1)
{
c[i2][j2]= false;
System.out.print("- ");
}
else if (livestore[counter] >3)
{
c[i2][j2]= false;
System.out.print("- ");
}
else
System.out.print("* ");
}
counter++;
}
System.out.println();
}
return NewCell(c);
}
/*************************************************************************************************************************************************/
public static void main(String[] args)
{
int N = 5;
boolean[][] b = new boolean[N][N];
double cellmaker = Math.random();
int i = 0;
int j = 0;
int o=0;
int p=0;
int livecnt = 0; //keeps track of the alive cells surrounding cell
int store = 0; //amount of surrounding cells for each individual cell
int livestore[] = new int[N*N];
System.out.println("First Generation:");
// Makes the first batch of cells
for ( i = 0; i < N ; i++)
{
for ( j = 0; j< N; j++)
{
cellmaker = Math.random();
if (cellmaker > 0.5) // * = alive; - = dead
{
b[i][j]=true;
System.out.print( "* ");
}
if (cellmaker < 0.5)
{ b[i][j] = false;
System.out.print("- ");
}
}
System.out.println();
}
boolean[][] newcells = new boolean[N][N];
newcells = NewCells(b);
}
}
I do not think recursion is a good idea for this application. It leads to a StackOverflowError because each generation pushes another call stack frame. Recursion, as this program uses it, has no advantage over iteration.
Instead, put the main method call to NewCells in a loop. That way, you can run as many iterations as you like, regardless of stack size.
You are not calling NewCell from within NewCell, which is how recursion works.
I'm assuming it's not a typo in your question, but rather a lack of understanding of what it is and how it works, I recommend some reading on recursion in Java.
After you understand the basics, come back here for more help!

Java Sudoku Generator(easiest solution)

In my last question seen here: Sudoku - Region testing I asked how to check the 3x3 regions and someone was able to give me a satisfactory answer (although it involved a LOT of tinkering to get it working how I wanted to, since they didn't mention what the class table_t was.)
I finished the project and was able to create a sudoku generator, but it feels like it's contrived. And I feel like I've somehow overcomplicated things by taking a very brute-force approach to generating the puzzles.
Essentially my goal is to create a 9x9 grid with 9- 3x3 regions. Each row / col / region must use the numbers 1-9 only once.
The way that I went about solving this was by using a 2-dimensional array to place numbers at random, 3 rows at a time. Once the 3 rows were done it would check the 3 rows, and 3 regions and each vertical col up to the 3rd position. As it iterated through it would do the same until the array was filled, but due to the fact that I was filling with rand, and checking each row / column / region multiple times it felt very inefficient.
Is there an "easier" way to go about doing this with any type of data construct aside from a 2d array? Is there an easier way to check each 3x3 region that might coincide with checking either vert or horizontal better? From a standpoint of computation I can't see too many ways to do it more efficiently without swelling the size of the code dramatically.
I built a sudoku game a while ago and used the dancing links algorithm by Donald Knuth to generate the puzzles. I found these sites very helpful in learning and implementing the algorithm
http://en.wikipedia.org/wiki/Dancing_Links
http://cgi.cse.unsw.edu.au/~xche635/dlx_sodoku/
http://garethrees.org/2007/06/10/zendoku-generation/
import java.util.Random;
import java.util.Scanner;
public class sudoku {
/**
* #antony
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int p = 1;
Random r = new Random();
int i1=r.nextInt(8);
int firstval = i1;
while (p == 1) {
int x = firstval, v = 1;
int a[][] = new int[9][9];
int b[][] = new int[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if ((x + j + v) <= 9)
a[i][j] = j + x + v;
else
a[i][j] = j + x + v - 9;
if (a[i][j] == 10)
a[i][j] = 1;
// System.out.print(a[i][j]+" ");
}
x += 3;
if (x >= 9)
x = x - 9;
// System.out.println();
if (i == 2) {
v = 2;
x = firstval;
}
if (i == 5) {
v = 3;
x = firstval;
}
}
int eorh;
Scanner in = new Scanner(System.in);
System.out
.println("hey lets play a game of sudoku:take down the question and replace the 0's with your digits and complete the game by re entering your answer");
System.out.println("enter your option 1.hard 2.easy");
eorh = in.nextInt();
switch (eorh) {
case 1:
b[0][0] = a[0][0];
b[8][8] = a[8][8];
b[0][3] = a[0][3];
b[0][4] = a[0][4];
b[1][2] = a[1][2];
b[1][3] = a[1][3];
b[1][6] = a[1][6];
b[1][7] = a[1][7];
b[2][0] = a[2][0];
b[2][4] = a[2][4];
b[2][8] = a[2][8];
b[3][2] = a[3][2];
b[3][8] = a[3][8];
b[4][2] = a[4][2];
b[4][3] = a[4][3];
b[4][5] = a[4][5];
b[4][6] = a[4][6];
b[5][0] = a[5][0];
b[5][6] = a[5][6];
b[6][0] = a[6][0];
b[6][4] = a[6][4];
b[6][8] = a[6][8];
b[7][1] = a[7][1];
b[7][2] = a[7][2];
b[7][5] = a[7][5];
b[7][6] = a[7][6];
b[8][4] = a[8][4];
b[8][5] = a[8][5];
b[0][0] = a[0][0];
b[8][8] = a[8][8];
break;
case 2:
b[0][3] = a[0][3];
b[0][4] = a[0][4];
b[1][2] = a[1][2];
b[1][3] = a[1][3];
b[1][6] = a[1][6];
b[1][7] = a[1][7];
b[1][8] = a[1][8];
b[2][0] = a[2][0];
b[2][4] = a[2][4];
b[2][8] = a[2][8];
b[3][2] = a[3][2];
b[3][5] = a[3][5];
b[3][8] = a[3][8];
b[4][0] = a[4][0];
b[4][2] = a[4][2];
b[4][3] = a[4][3];
b[4][4] = a[4][4];
b[4][5] = a[4][5];
b[4][6] = a[4][6];
b[5][0] = a[5][0];
b[5][1] = a[5][1];
b[5][4] = a[5][4];
b[5][6] = a[5][6];
b[6][0] = a[6][0];
b[6][4] = a[6][4];
b[6][6] = a[6][6];
b[6][8] = a[6][8];
b[7][0] = a[7][0];
b[7][1] = a[7][1];
b[7][2] = a[7][2];
b[7][5] = a[7][5];
b[7][6] = a[7][6];
b[8][2] = a[8][2];
b[8][4] = a[8][4];
b[8][5] = a[8][5];
break;
default:
System.out.println("entered option is incorrect");
break;
}
for (int y = 0; y < 9; y++) {
for (int z = 0; z < 9; z++) {
System.out.print(b[y][z] + " ");
}
System.out.println("");
}
System.out.println("enter your answer");
int c[][] = new int[9][9];
for (int y = 0; y < 9; y++) {
for (int z = 0; z < 9; z++) {
c[y][z] = in.nextInt();
}
}
for (int y = 0; y < 9; y++) {
for (int z = 0; z < 9; z++)
System.out.print(c[y][z] + " ");
System.out.println();
}
int q = 0;
for (int y = 0; y < 9; y++) {
for (int z = 0; z < 9; z++)
if (a[y][z] == c[y][z])
continue;
else {
q++;
break;
}
}
if (q == 0)
System.out
.println("the answer you have entered is correct well done");
else
System.out.println("oh wrong answer better luck next time");
System.out
.println("do you want to play a different game of sudoku(1/0)");
p = in.nextInt();
firstval=r.nextInt(8);
/*if (firstval > 8)
firstval -= 9;*/
}
}
}
I think you can use a 1D array, in much the same way a 1D array can model a binary tree. For example, to look at the value below a number, add 9 to the index.
I just made this up, but could something like this work?
private boolean makePuzzle(int [] puzzle, int i)
{
for (int x = 0; x< 10 ; x++)
{
if (//x satisfies all three conditions for the current square i)
{
puzzle[i]=x;
if (i==80) return true //terminal condition, x fits in the last square
else
if makePuzzle(puzzle, i++);//find the next x
return true;
}// even though x fit in this square, an x couldn't be
// found for some future square, try again with a new x
}
return false; //no value for x fit in the current square
}
public static void main(String[] args )
{
int[] puzzle = new int[80];
makePuzzle(puzzle,0);
// print out puzzle here
}
Edit: its been a while since I've used arrays in Java, sorry if I screwed up any syntax. Please consider it pseudo code :)
Here is the code as described below in my comment.
public class Sudoku
{
public int[] puzzle = new int[81];
private void makePuzzle(int[] puzzle, int i)
{
for (int x = 1; x< 10 ; x++)
{
puzzle[i]=x;
if(checkConstraints(puzzle))
{
if (i==80)//terminal condition
{
System.out.println(this);//print out the completed puzzle
puzzle[i]=0;
return;
}
else
makePuzzle(puzzle,i+1);//find a number for the next square
}
puzzle[i]=0;//this try didn't work, delete the evidence
}
}
private boolean checkConstraints(int[] puzzle)
{
int test;
//test that rows have unique values
for (int column=0; column<9; column++)
{
for (int row=0; row<9; row++)
{
test=puzzle[row+column*9];
for (int j=0;j<9;j++)
{
if(test!=0&& row!=j&&test==puzzle[j+column*9])
return false;
}
}
}
//test that columns have unique values
for (int column=0; column<9; column++)
{
for(int row=0; row<9; row++)
{
test=puzzle[column+row*9];
for (int j=0;j<9;j++)
{
if(test!=0&&row!=j&&test==puzzle[column+j*9])
return false;
}
}
}
//implement region test here
int[][] regions = new int[9][9];
int[] regionIndex ={0,3,6,27,30,33,54,57,60};
for (int region=0; region<9;region++) //for each region
{
int j =0;
for (int k=regionIndex[region];k<regionIndex[region]+27; k=(k%3==2?k+7:k+1))
{
regions[region][j]=puzzle[k];
j++;
}
}
for (int i=0;i<9;i++)//region counter
{
for (int j=0;j<9;j++)
{
for (int k=0;k<9;k++)
{
if (regions[i][j]!=0&&j!=k&&regions[i][j]==regions[i][k])
return false;
}
}
}
return true;
}
public String toString()
{
String string= "";
for (int i=0; i <9;i++)
{
for (int j = 0; j<9;j++)
{
string = string+puzzle[i*9+j];
}
string =string +"\n";
}
return string;
}
public static void main(String[] args)
{
Sudoku sudoku=new Sudoku();
sudoku.makePuzzle(sudoku.puzzle, 0);
}
}
Try this code:
package com;
public class Suduku{
public static void main(String[] args ){
int k=0;
int fillCount =1;
int subGrid=1;
int N=3;
int[][] a=new int[N*N][N*N];
for (int i=0;i<N*N;i++){
if(k==N){
k=1;
subGrid++;
fillCount=subGrid;
}else{
k++;
if(i!=0)
fillCount=fillCount+N;
}
for(int j=0;j<N*N;j++){
if(fillCount==N*N){
a[i][j]=fillCount;
fillCount=1;
System.out.print(" "+a[i][j]);
}else{
a[i][j]=fillCount++;
System.out.print(" "+a[i][j]);
}
}
System.out.println();
}
}
}

Categories