Scan a Matrix for a number - java

I am currently looking for a way of scanning a 2D matrix in Java for a number. Precisely, if in my matrix, there are numbers from 0 to 9, how do I "locate" the 0? This is intended for creating a Minesweeper game.
Here is what I have written so far. It is not complete. All I want is a clue on how to complete it.
class DemineurStackOverflow {
public static void minesweeper () {
int champDeMine[][];
boolean résultat[][];
int mine;
char réponse;
champDeMine = new int[longueur][largeur]; //Differenf from the matrix "champDeMines" from the second method
Arrays.asList(champDeMine).contains(0);
mine = (int) Math.floor(Math.random()*nbMines + 1);
System.out.println("Ajustement du nombre de mines en cours...");
if (mine < nbMines) {
for (mine = (int) Math.floor(Math.random()*nbMines + 1); mine < nbMines; mine++);
} else {
for (mine = (int) Math.floor(Math.random()*nbMines + 1); mine > nbMines; mine--);
}
if (mine == nbMines){
System.out.println("Chargement des mines OK.");
}
}
public static int [][] calculeProximité ( boolean [][] champDeMines ){
int row; //row index for prescence of 0, same value as longueur
int col; //column index for presence of 0, same value as largeur
int mine;
champDeMines = new boolean[row][col];
if (champDeMines = 0) {
champDeMines = mine;
}
//Here I am trying to figure a way of finding the 0s in this champDeMines matrix.
return (new int[champDeMines.length][champDeMines[0].length]);
}
}
The first method consists in generating an array from variables "longueur" and "largeur". The number of "mines" is supposed to represent the number 0 (which is why I want to scan for a 0), at random places. The second method consists in finding the "mines" in the array created. That is what I have trouble doing. Do you have any clues for completing the second method? I am simply looking for clues because I am learning to program in Java!
Thank you very much, your help is most certainly appreciated!

This is how minesweeper field population could look from the code provided. I hope you get the clue from the comments and do not hesitate to ask if anything is unclear.
import java.util.Random;
public class Demineur
{
// Here come CONSTANTS
public static final int MAX_MINES = 30;
public static final boolean MINE = true;
// Let's have a field 12x12 size
public static final int LONGEUR = 12;
public static final int LARGEUR = 12;
// each field contains number of mines it has access to
public static int champDeMine[][] = new int[LONGEUR][LARGEUR];
// each field can contain mine or be empty
public static boolean champDeMines[][] = new boolean[LONGEUR][LARGEUR];
public static void minesweeper()
{
Random random = new Random();
int mine ;
System.out.println("Ajustement du nombre de mines en cours...");
int nbMines = random.nextInt(MAX_MINES);
/**
* Let's plant mines. :-E
* Unoptimal but will suffice for demonstration purpose.
*/
int minesLeftToPlant = nbMines;
int skip = 0;
boolean planted = false;
while (minesLeftToPlant > 0)
{
skip = random.nextInt(LONGEUR*LARGEUR);
planted = false;
while (!planted && minesLeftToPlant > 0 && skip > 0)
{
for (int y = 0; !planted && minesLeftToPlant > 0 && y < LONGEUR; y++)
{
for (int x = 0; !planted && minesLeftToPlant > 0 && x < LARGEUR; x++)
{
if ( !MINE == champDeMines[y][x]
&& 0 == skip)
{
champDeMines[y][x] = MINE;
minesLeftToPlant--;
planted = true;
}
else
{
skip--;
}
}
}
}
}
System.out.println("Chargement des "+ nbMines +" mines OK.");
}
public static void calculeProximite()
{
int row ; //row index for prescence of 0, same value as longueur
int col ; //column index for presence of 0, same value as largeur
int mine;
//Check for each field it's neighbors and calculate which of them are mines
for (row = 0; row < LONGEUR; row++)
{
for (col = 0; col < LARGEUR; col++)
{
champDeMine[row][col] = numberOfMines(row,col);
}
}
}
public static void printChampDeMine()
{
for (int row = 0; row < LONGEUR; row++)
{
for (int col = 0; col < LARGEUR; col++)
{
System.out.print("'" + champDeMine[row][col] + "' ");
}
System.out.println();
}
}
public static void printChampDemines()
{
for (int row = 0; row < LONGEUR; row++)
{
for (int col = 0; col < LARGEUR; col++)
{
System.out.print("'" + (champDeMines[row][col] ? "m" : "e") + "' ");
}
System.out.println();
}
}
public static int numberOfMines(int row, int col)
{
return add(hasMine(row , col + 1))
+ add(hasMine(row - 1, col + 1))
+ add(hasMine(row - 1, col ))
+ add(hasMine(row - 1, col - 1))
+ add(hasMine(row , col - 1))
+ add(hasMine(row + 1, col - 1))
+ add(hasMine(row + 1, col ))
+ add(hasMine(row + 1, col + 1));
}
public static boolean hasMine(int row, int col)
{
return row >= 0 && col >= 0 && row < LONGEUR && col < LARGEUR
&& isMine(champDeMines[row][col]);
}
public static boolean isMine(boolean x)
{
return MINE == x;
}
public static int add(boolean c)
{
return c ? 1 : 0;
}
public static void main(String[] args)
{
minesweeper();
System.out.println("Champ de mines");
printChampDemines();
System.out.println("Champ de mine");
calculeProximite();
printChampDeMine();
}
}

Related

DFS function for finding the clusters of same symbol in 2D matrix

I am trying to write a DFS code for finding the clusters of size greater than or equal to 2 inside a 2D matrix of integers. I am trying to write the DFS for that. Here I am unable to get any output inside the win cluster list of Cluster Object. Can anybody suggest what is going wrong. I have written a DFS function that calls for all neighbouring locations(horizontally and vertically).
Also checking for the valid condition for checking whether the indices are inside the row and column constraints. When the DFS is terminating I am checking for the condition if count of cluster is greater than 2 then I'll add it to the win clusters list else simply return.Please suggest why am I not getting any value in the win_clusters list.
import java.util.*;
public class sample {
static int grid[][]= {{1,3,0,4,0},
{3,2,0,0,1},
{0,4,1,0,1},
{4,0,0,0,2},
{2,4,0,2,4}};
static int ROW;
static int COLUMN;
public static int[][] grid_creation(int numRows, int numCols){
ROW= numRows;
COLUMN=numCols;
int [][]grid = new int[numRows][numCols];
Random rand = new Random();
for(int i = 0; i<numRows ; i++){
for(int j = 0; j<numCols; j++){
grid[i][j]= rand.nextInt(5);
}
}
return grid;
}
public static void print_matrix(int[][]matrix){
for(int i = 0; i< matrix.length;i++){
for(int j = 0; j<matrix[0].length; j++){
System.out.print(matrix[i][j]+" ");
}
System.out.println();
}
}
public static boolean isValid(boolean[][] visited, int row, int col){
if(row<0 ||col<0 || row>=ROW || col>=COLUMN || visited[row][col] )
return false;
return true;
}
public static class Cluster{
List<Integer> cluster_symbol_positions = new ArrayList<Integer>();
int symbol = -1;
int count = 0;
int win = 0;
public void create_new_Cluster(){
cluster_symbol_positions = new ArrayList<>();
symbol = -1;
count = 0;
win= 0;
}
public List<Integer> get_cluster_symbol_positions(){
return cluster_symbol_positions;
}
public int getSymbol(){return symbol;}
public void setSymbol(int a){symbol = a;}
public int getCount(){return count;}
public void add_to_cluster(int row1, int col1 ){
int row = row1;
int col = col1;
cluster_symbol_positions.add(getReelPositionNumber(row,col));
count++;
}
public int cluster_win(Cluster cluster){
int win_amount = 0;
//return win amount from the paytable
return win_amount;
}
}
public static void DFS(int[][] grid,List<Cluster> win_clusters) {
int h = grid.length;
if (h == 0)
return;
int l = grid[0].length;
//created visited array
boolean [][] visited = new boolean[h][l];
System.out.println("Depth-First Search: ");
for( int i =0; i< ROW ; i++){
for(int j = 0 ;j<COLUMN; j++){
if(!visited[i][j]) {
DFSUtil(grid, i, j, visited, win_clusters);
}
}
}
}
static Cluster global_cluster= new Cluster();
static int cluster_length =0;
public static void DFSUtil(int[][]grid, int row, int col, boolean[][] visited, List<Cluster>win_clusters){
if (row < 0 || col < 0 || row >= ROW|| col >= COLUMN || visited[row][col] ) {
if(global_cluster.getCount()>=2) win_clusters.add(global_cluster);
return;
}
int symbol = grid[row][col];
visited[row][col] = true;
cluster_length++;
global_cluster.add_to_cluster(row,col);
global_cluster.setSymbol(symbol);
if(isValid(visited, row+1, col) && grid[row+1][col]==symbol){
DFSUtil(grid, row+ 1, col,visited,win_clusters); // go down
}
if(isValid(visited, row-1, col) && grid[row-1][col]==symbol) {
DFSUtil(grid, row - 1, col, visited, win_clusters); //go up
}
if(isValid(visited, row, col+1) && grid[row][col+1]==symbol){
DFSUtil(grid, row, col + 1,visited,win_clusters); //go right
}
if(isValid(visited, row, col-1) && grid[row][col-1]==symbol){
DFSUtil(grid, row, col - 1,visited,win_clusters); // go left
}
}
public static int getReelPositionNumber(int row, int col) {
return (row*COLUMN) + col;
}
public static List<Integer> getReelPositionsIndex(int positionNumber) {
List<Integer> tempData = new ArrayList<Integer>();
int numReels =COLUMN;
int display = ROW;
if(positionNumber >= numReels*display)
throw new RuntimeException( positionNumber+" is out of range "+ numReels*display +"(rows*cols) in the game." );
if(positionNumber < numReels) {
tempData.add(0);
tempData.add(positionNumber);
} else if(positionNumber == (numReels*display)) {
tempData.add(display - 1);
tempData.add(numReels - 1);
} else {
int row = positionNumber / numReels;
int col = positionNumber % numReels;
tempData.add(row);
tempData.add(col);
}
return tempData;
}
public static void main(String args[]){
System.out.println("Modified function for cluster win ");
List<Cluster> win_clusters = new ArrayList<Cluster>();
DFS(grid,win_clusters);
print_matrix(grid);
System.out.println(win_clusters.size());
}
}

'Undo Move' feature Implementation for a 2D Array Board Game

'Undo Move' feature Implementation for a 2D Array Board Game
Hi all
Using an ArrayList, I am trying to implement an undo move feature whereby, a user can select an option ‘Z’, which makes possible a multi-level ‘undo’. In other words, if the user selects ‘Z’ then the previous move is undone, if he immediately selects ‘Z’ again, the move before that is undone, and so on.
I have been able to get the code to add new move objects each time a valid move ‘U’, ’D’, ’L’, ’R’ is made and to also remove the last object, each time ‘Z’ is pressed.
My question is, how do I make the player movements (coordinates) and eaten doughnuts (Boolean) rely on the last object in the ArrayList so that when ‘Z’ is pressed and the last object in the ArrayList is removed, the player movements and eaten doughnuts will now rely on the new last object in the ArrayList to create the ‘undo’ effect? Hope my question makes sense.
The ‘Z’ implementation is the last case in the switch statement in the move method.
My classes are below:
package secondproject;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class Game {
private static final int BOARD_SIZE = 10;
private static final int INITIAL_PLAYER_COL = 0;
private static final int INITIAL_PLAYER_ROW = BOARD_SIZE - 1;
private static final int HOME_COL = BOARD_SIZE - 1;
private static final int HOME_ROW = 0;
private static final int WALL_LENGTH = 5;
private static final char PLAYER_CHAR = 'P';
private static final char HOME_CHAR = 'H';
private static final char WALL_CHAR = 'X';
private static final char FREE_SQUARE_CHAR = '.';
private static final char DOUGHNUT_CHAR = '#';
private static final char UP_MOVE_CHAR = 'U';
private static final char DOWN_MOVE_CHAR = 'D';
private static final char LEFT_MOVE_CHAR = 'L';
private static final char RIGHT_MOVE_CHAR = 'R';
private static final char UNDO_MOVE_CHAR = 'Z';
private static final char TRAIL_CHAR = 'M';
private static char[][] board = new char[BOARD_SIZE][BOARD_SIZE];
private static Scanner scan = new Scanner(System.in);
private static Scanner keyBoard = new Scanner(System.in);
private static int playerCol = INITIAL_PLAYER_COL;
private static int playerRow = INITIAL_PLAYER_ROW;
private static int nbrDoughnuts = 0;
private static int nbrMoves = 0;
private static Random random = new Random();
private static int lives = 1;
private static int doughnutLives;
private static boolean doughnutCheck;
static ArrayList<Move> movement = new ArrayList<Move>();
public static void main(String[] args) {
setUpBoard();
showBoard();
String opt;
do {
System.out.print("Next option ?");
opt = scan.next();
char opt1 = opt.charAt(0);
if (opt1 == UP_MOVE_CHAR || opt1 == DOWN_MOVE_CHAR || opt1 == LEFT_MOVE_CHAR || opt1 == RIGHT_MOVE_CHAR || opt1 == UNDO_MOVE_CHAR) {
move(opt1);
} else {
System.out.println("Allowed commands are: + " + UP_MOVE_CHAR + "," + DOWN_MOVE_CHAR + "," + LEFT_MOVE_CHAR + "," + RIGHT_MOVE_CHAR);
}
showBoard();
System.out.println("Number of moves made = " + nbrMoves);
System.out.println("Number of doughnuts eaten = " + nbrDoughnuts);
System.out.println("Lives = " + lives);
} while (board[HOME_ROW][HOME_COL] == HOME_CHAR);
System.out.println("Thank you and goodbye");
}
/**
* Set up the initial state of the board
*/
private static void setUpBoard() {
intialiseBoard(); // Fill the board with . characters
//Add the first vertical wall
int v1StartCol = 1 + random.nextInt(BOARD_SIZE - 2);
int v1StartRow = 1 + random.nextInt(BOARD_SIZE - WALL_LENGTH - 1);
addVerticalWall(v1StartCol, v1StartRow, WALL_LENGTH);
//Add the second vertical wall
int v2StartCol;
do {
v2StartCol = 1 + random.nextInt(BOARD_SIZE - 2);
} while (v2StartCol == v1StartCol);
int v2StartRow = 1 + random.nextInt(BOARD_SIZE - WALL_LENGTH - 1);
addVerticalWall(v2StartCol, v2StartRow, WALL_LENGTH);
//Add the horizontal wall
int h1StartRow = 1 + random.nextInt(BOARD_SIZE - 2);
int h1StartCol = 1 + random.nextInt(BOARD_SIZE - WALL_LENGTH - 1);
addHorizontalWall(h1StartCol, h1StartRow, WALL_LENGTH);
//Add the dougnuts
int nbrDoughnutsAdded = 0;
while (nbrDoughnutsAdded < 5) {
int dRow = 1 + random.nextInt(BOARD_SIZE - 2);
int dCol = 1 + random.nextInt(BOARD_SIZE - 2);
if (board[dRow][dCol] == FREE_SQUARE_CHAR) {
board[dRow][dCol] = DOUGHNUT_CHAR;
nbrDoughnutsAdded++;
}
}
//Add the player and the home square
board[playerRow][playerCol] = PLAYER_CHAR;
board[HOME_ROW][HOME_COL] = HOME_CHAR;
}
/**
* Add a vertical wall to the board
*
* #param startCol Column on which wall is situated
* #param startRow Row on which top of wall is situated
* #param length Number of squares occupied by wall
*/
private static void addVerticalWall(int startCol, int startRow, int length) {
for (int row = startRow; row < startRow + length; row++) {
board[row][startCol] = WALL_CHAR;
}
}
/**
* Add a horizontal wall to the board
*
* #param startCol Column on which leftmost end of wall is situated
* #param startRow Row on which wall is situated
* #param length Number of squares occupied by wall
*/
private static void addHorizontalWall(int startCol, int startRow, int length) {
for (int col = startCol; col < startCol + length; col++) {
board[startRow][col] = WALL_CHAR;
}
}
/**
* Display the board
*/
private static void showBoard() {
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
System.out.print(board[row][col]);
}
System.out.println();
}
}
/**
* Fill the board with FREE_SQUARE_CHAR characters.
*/
private static void intialiseBoard() {
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
board[row][col] = FREE_SQUARE_CHAR;
}
System.out.println();
}
}
/**
* Move the player
*
* #param moveChar Character indicating the move to be made
*/
private static void move(char moveChar) {
int newCol = playerCol;
int newRow = playerRow;
switch (moveChar) {
case UP_MOVE_CHAR:
if (lives == 1) {
newRow--;
} else if (lives > 1) {
int number = keyBoard.nextInt();
if (number <= lives) {
newRow = newRow - number;
} else {
checkLives();
}
}
break;
case DOWN_MOVE_CHAR:
if (lives == 1) {
newRow++;
} else if (lives > 1) {
squareNumberPrompt();
int number = keyBoard.nextInt();
if (number <= lives) {
newRow = newRow + number;
} else {
checkLives();
}
}
break;
case LEFT_MOVE_CHAR:
if (lives == 1) {
newCol--;
} else if (lives > 1) {
squareNumberPrompt();
int number = keyBoard.nextInt();
if (number <= lives) {
newCol = newCol - number;
} else {
checkLives();
}
}
break;
case RIGHT_MOVE_CHAR:
if (lives == 1) {
newCol++;
} else if (lives > 1) {
squareNumberPrompt();
int number = keyBoard.nextInt();
if (number <= lives) {
newCol = newCol + number;
} else {
checkLives();
}
}
break;
case UNDO_MOVE_CHAR:
if (movement.size() >= 1) {
movement.remove(movement.size() - 1);
System.out.println("The decreasing size of the arraylist is now " + movement.size());
} else if (movement.size() < 1) {
System.out.println("There is no move to be undone!");
}
break;
}
if (newRow < 0 || newRow >= BOARD_SIZE || newCol < 0 || newCol >= BOARD_SIZE) {
System.out.println("Sorry that move takes you off the board!");
} else {
char dest = board[newRow][newCol];
if (dest == WALL_CHAR) {
System.out.println("Sorry you landed on a wall!");
} else {
nbrMoves++;
if (dest == DOUGHNUT_CHAR) {
doughnutCheck = true;
nbrDoughnuts++;
doughnutLives++;
lives = (doughnutLives + 1);
}
board[playerRow][playerCol] = FREE_SQUARE_CHAR;
playerCol = newCol;
playerRow = newRow;
board[playerRow][playerCol] = PLAYER_CHAR;
}
}
if (moveChar == UP_MOVE_CHAR || moveChar == DOWN_MOVE_CHAR || moveChar == LEFT_MOVE_CHAR || moveChar == RIGHT_MOVE_CHAR) {
movement.add(new Move(playerCol, playerRow, newCol, newRow, doughnutCheck));
System.out.println("The increasing size of the arraylist is now " + movement.size());
}
}
public static void squareNumberPrompt() {
System.out.println("Enter the number of squares to be moved");
}
public static void checkLives() {
System.out.println("Invalid number! The number must be"
+ " equal to or less than the number of lives you have");
}
}
package secondproject;
import java.util.ArrayList;
public class Move {
private static int pColumn;
private static int pRow;
private static int nCol;
private static int nRow;
private static boolean dCheck;
public Move(int playerCol, int playerRow, int newCol, int newRow, boolean doughnutCheck) {
pColumn = playerCol;
pRow = playerRow;
nCol = newCol;
nRow = newRow;
dCheck = doughnutCheck;
}
public int getFromCol() {
return pColumn;
}
public int getFromRow() {
return pRow;
}
public int getToCol() {
return nCol;
}
public int getToRow() {
return nRow;
}
public boolean isDoughnutEaten() {
return dCheck;
}
}
After looking a bit closer at your code, you basically already have everything you need for that undo in place.
Maybe even a bit too much :D You don't actually need from and to positions. only the position the move put you into would suffice.
So when you press Z, your code should look somewhat like this:
Move lastMove = movement.remove(movement.size() - 1);
playerCol = movement.get(movement.size() - 1).getToCol();
playerRow = movement.get(movement.size() - 1).getToRow();
board[playerRow][playerCol] = PLAYER_CHAR;
if (lastMove.isDoughnutEaten()) {
int dCol = lastMove.getToCol();
int dRow = lastMove.getToRow();
board[dRow][dCol] = DOUGHNUT_CHAR;
nbrDoughnutsAdded--;
}
Right now, you could read the new player position from the pColumn and pRow values of lastMove, but as I said, that's kind of overkill because you can read it from the new last element of the list anyway.
Keep in mind that you still need to catch special cases (like when you undo the very first move. In this case, you'd need to read the former player position from your static variables that define the starting point instead of the last element of the list (that won't exist anymore))

Java Matrix erasing

I'm trying to erase every X in a .txt file. When a coordinate is chosen, if it is an X is should be replaced with a 0 then also every X that is touching it (except diagonally) should be replaced until there are no more X's that can be touched. I'm not getting these results with my current code.
I'm getting this error java.lang.ArrayIndexOutOfBoundsException: 9 when I input in 0 for getCoord(grid.length, "row") and 2 for getCoord(grid[0].length, "column") in main().
thank you for your help.
image1.txt
00X000000
0XXXXXXX0
0X00000XX
0X0X000XX
0X00000X0
0XXXXXXX0
XXXX00XX0
000XX0000
eraseImage.java
import java.io.*;
import java.util.StringTokenizer;
/**
* eraseImage.java
*
* Your Name Goes Here!
*
* will dimension and load a 2-dimensional array of Strings
* from a text file. The first line of the file will contain
* the dimensions of the grid. Each additional line will have
* String made up of 'X's and '0's (that's zeros) to represent
* part of an image (X) or a non-image cell(0).
*/
public class eraseImage
{
public static void main(String[] args) throws IOException
{
String[][] grid = load();
display(grid);
do
{
int targetRow = getCoord(grid.length, "row");
int targetCol = getCoord(grid[0].length, "column");
rubOut(grid, targetRow, targetCol);
display(grid);
}
while(again());
}
/**
* Please provide documentation here
*/
public static String[][] load() throws IOException
{
BufferedReader innie = new BufferedReader(new FileReader("/Users/laxgoalie1996/Desktop/image1.txt"));
String str = innie.readLine();
StringTokenizer tokens = new StringTokenizer(str);
int rows = Integer.parseInt(tokens.nextToken());
int cols = Integer.parseInt(tokens.nextToken());
String[][] image = new String[rows][cols];
for(int row = 0; row < rows; row++)
{
str = innie.readLine();
for(int col = 0; col < str.length(); col++)
image[row][col] = str.substring(col, col+1);
System.out.println(str);
}
return image;
}
/**
* Please provide documentation here
*/
public static void display(String[][] g)
{
System.out.println("\nHere is the current image...\n");
for (int row = 0; row < g.length; row++) {
for (int column = 0; column < g[row].length; column++) {
System.out.print(g[row][column] + " ");}
System.out.println();}
System.out.println();
}
/**
* Please provide documentation here
*/
public static void rubOut(String[][] g, int tRow, int tCol)
{
String str = g[tRow][tCol];
System.out.println(str);
if(str.equals("0"))
return;
g[tRow][tCol] = "0";
rubOut(g, tRow, tCol + 1);
rubOut(g, tRow, tCol - 1);
rubOut(g, tRow + 1, tCol);
rubOut(g, tRow - 1, tCol);
return;
}
/**
* Please provide documentation here
*/
public static int getCoord(int max, String prompt)
{
java.util.Scanner scan = new java.util.Scanner(System.in);
System.out.print("Enter the " + prompt + " number (0 to " + (max-1) + ") -> ");
int coord = scan.nextInt();
while(coord < 0 || coord >= max)
{
System.out.print("HEY! The " + prompt + " number needs to be between 0 and " + (max-1) + " -> ");
coord = scan.nextInt();
}
return coord;
}
/**
* Please provide documentation here
*/
public static boolean again()
{
return false;
}
}
You need to add bounds checks to your rubOut function:
public static void rubOut(String[][] g, int tRow, int tCol)
{
if((tRow < 0) || (tRow >= g.length))
return;
if((tCol < 0) || (tCol >= g[tRow].length))
return;
...
}
Even though your initial indices of row = 0 and column = 2 are within bounds, you are going to go out of bounds when you call rubOut(g, tRow - 1, tCol); because tRow will then be -1.
Use this for loop for replace X over 0
public static void main(String [] args){
String[][] str ={{"0","0","X","0","0","0","0","0","0"},
{"0","X","X","X","X","X","X","X","0"},{"0","X","0","0","0","0","0","X","X"},
{"0","X","0","X","0","0","0","X","X"},{"0","X","0","0","0","0","0","X","0"},};
for (int i=0; i<str.length; i++) {
for(int j=0; j<str[i].length; j++){
System.out.print(str[i][j]);
}
System.out.println();
}
System.out.println();
for (int i=0; i<str.length; i++) {
for(int j=0; j<str[0].length; j++){
if(i==j){
str[i][j]="0";
}
System.out.print(str[i][j]);
}
System.out.println();
}
}
This will replace X over 0

Java count the size of chars in array

I have to write a program that will read a picture and then print out the number of blocks inside it.
I have to read the picture as a binary matrix of the size r × c (number of rows times number of
columns).
The blocks are groups of one or more adjacent elements with the value 1.
Blocks are built exclusively of elements with value 1
Each element with value 1 is a part of some block
Adjacent elements with value 1 belong to the same block.
We only take into account the horizontal and vertical adjacency but not diagonal.
INPUT:
In the first line of the input we have the integers r and c, separated with one space.
Then we have the r lines, where each contains s 0's and 1's.
The numbers inside the individual lines are NOT separated by spaces.
The OUTPUT only print the number of blocks in the picture.
For example:
EXAMPLE 1
INPUT:
7 5
01000
00010
00000
10000
01000
00001
00100
OUTPUT:
6
EXAMPLE 2:
INPUT:
25 20
00010000000000000000
00010000000000000000
00010000000000000100
00000000000000000100
00011111111000000100
00000000000000000100
00000000000000000100
00000000000000000100
00000000000000000100
01111111111000000100
00000000000000000100
00000000000000100100
00000000000000100100
00000000000000100100
01000000000000100000
01000000000000100000
01000000000000100000
01000000000000100000
00000000000000100000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00011111111111100000
00000000000000000000
OUTPUT:
7
THE PROBLEM:
The problem that I have is that my program only works for inputs such as in example 1.
So pictures that only consist of blocks of size 1. But it doesnt work if there are multiples 1's in a picture, such as EXAMPLE 2.
In example 2 where the output should be 7(Blocks are elements of 1.They can either be vertial or horizontal).... my programs output is 30.
I don't know how to adjust the program in a correct manner so it will give me the correct input.
Thank you for your help in advance, here is my code that I am posting bellow.
import java.util.Scanner;
class Blocks{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int rowNum=sc.nextInt();
int columnNum=sc.nextInt();
char[][] matrix = new char[rowNum][columnNum];
int nbrOfBlocks = 0;
for (int a = 0; a < rowNum; a++) {
matrix[a] = sc.next().toCharArray();
int index = 0;
while (index < matrix[a].length) {
if (matrix[a][index] == '1') {
++nbrOfBlocks;
while (index < matrix[a].length && matrix[a][index] == '1') {
++index;
}
}
++index;
}
}
System.out.println(nbrOfBlocks);
}
}
EDIT: Ok, here is a solution that will work for complex shapes
public class BlockCounter {
public static void main(String[] args) {
Board board = null;
try {
board = new Board("in3.txt");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Block count: " + board.getBlockCount());
}
}
class Board {
ArrayList<String> data = new ArrayList<>();
boolean[][] used;
int colCount = 0;
public Board(String filename) throws FileNotFoundException, IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
data.add(line);
colCount = Math.max(colCount, line.length());
}
}
}
public int getBlockCount() {
used = new boolean[data.size()][colCount];
int count = 0;
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
used[row][col] = peek(row, col) == '1';
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
if (used[row][col]) {
fill(row, col);
count++;
}
used = null;
return count;
}
public char peek(int row, int col) {
if (row < 0 || row >= data.size() || col < 0)
return '0';
String rowData = data.get(row);
if (col >= rowData.length())
return '0';
return rowData.charAt(col);
}
public void fill(int row, int col) {
if (used[row][col]) {
used[row][col] = false;
if (row > 0 && used[row - 1][col])
fill(row - 1, col);
if (col > 0 && used[row][col - 1])
fill(row, col - 1);
if (col < colCount - 1 && used[row][col + 1])
fill(row, col + 1);
if (row < data.size() - 1 && used[row + 1][col])
fill(row + 1, col);
}
}
public int getRowCount() {
return data.size();
}
public int getColCount() {
return colCount;
}
}
Explanation:
When Board.getBlockCount() is called if creates a temporary array of booleans to work with so the original board is not messed up. Then it searches the entire board for "trues" (which correspond to '1's on the board). Every time a "true" is found, a flood fill algorithm clears the entire shape to which it is connected.
If you need more performance and less memory usage (specially stack) for larger boards, you can use another flood fill algorithm like in the example that follows. The big advantage here is that it doesn't use the stack for every pixel like the one above. It is considerably more complex though.
public class BlockCounter2 {
public static void main(String[] args) {
Board2 board = null;
try {
board = new Board2("in4.txt");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Block count: " + board.getBlockCount());
}
}
class Board2 {
ArrayList<String> data = new ArrayList<>();
boolean[][] used;
Deque<Point> pointStack = new LinkedList<>();
int colCount = 0;
public Board2(String filename) throws FileNotFoundException, IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
data.add(line);
colCount = Math.max(colCount, line.length());
}
}
}
public int getBlockCount() {
used = new boolean[data.size()][colCount];
int count = 0;
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
used[row][col] = peek(row, col) == '1';
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
if (used[row][col]) {
fill(row, col);
count++;
}
used = null;
return count;
}
public char peek(int row, int col) {
if (row < 0 || row >= data.size() || col < 0)
return '0';
String rowData = data.get(row);
if (col >= rowData.length())
return '0';
return rowData.charAt(col);
}
public void fill(int row, int col) {
pointStack.push(new Point(col, row));
Point p;
while (pointStack.size() > 0) {
p = pointStack.pop();
fillRow(p.y, p.x);
}
}
private void checkRow(int row, int col, int minCol, int maxCol) {
boolean uu = false;
for (int x = col; x < maxCol; x++) {
if (!uu && used[row][x])
pointStack.add(new Point(x, row));
uu = used[row][x];
}
uu = true;
for (int x = col; x > minCol; x--) {
if (!uu && used[row][x])
pointStack.add(new Point(x, row));
uu = used[row][x];
}
}
private void fillRow(int row, int col) {
int lx, rx;
if (used[row][col]) {
for (rx = col; rx < colCount; rx++)
if (used[row][rx])
used[row][rx] = false;
else
break;
for (lx = col - 1; lx >= 0; lx--)
if (used[row][lx])
used[row][lx] = false;
else
break;
if (row > 0)
checkRow(row - 1, col, lx, rx);
if (row < data.size() - 1)
checkRow(row + 1, col, lx, rx);
}
}
public int getRowCount() {
return data.size();
}
public int getColCount() {
return colCount;
}
}
EDIT2: Both solutions were made using input from txt files in order to make the debugging and testing easier for larger arrays. If you need them to work with user input (the same you have in your code) as well, just make the following changes:
Change the main method so it will listen from user input (again):
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int rowNum=sc.nextInt();
int columnNum=sc.nextInt(); // Note columnNum is not necessary
String[] matrix = new String[rowNum]; // I hope char[][] is not a requirement
for (int a = 0; a < rowNum; a++) // Read array data from user input
matrix[a] = sc.next();
sc.close();
Board2 board = new Board2(matrix); // Call the new constructor
System.out.println("Block count: " + board.getBlockCount());
}
Add a new constructor to Board2, that takes a String[] as input:
public Board2(String[] data) {
for (String line : data) {
this.data.add(line);
colCount = Math.max(colCount, line.length());
}
}
You may remove the previous constructor Board2(String filename) if it is not useful for you but it's not necessary.
Are you searching for this:
import java.util.Scanner;
class Blocks {
public static void removeBlock(char[][] matrix, int posX, int posY) {
if(0 <= posX && posX < matrix.length
&& 0 <= posY && posY < matrix[posX].length) {
if(matrix[posX][posY] == '0') {
return;
}
matrix[posX][posY] = '0';
} else {
return;
}
removeBlock(matrix, posX - 1, posY);
removeBlock(matrix, posX + 1, posY);
removeBlock(matrix, posX, posY - 1);
removeBlock(matrix, posX, posY + 1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// read in
char[][] matrix = new char[sc.nextInt()][sc.nextInt()];
for(int a = 0; a < matrix.length; a++) {
matrix[a] = sc.next().toCharArray();
}
// calculate number of blocks
int nrBlocks = 0;
for(int i = 0; i < matrix.length; i++) {
for(int j = 0; j < matrix[i].length; j++) {
if(matrix[i][j] == '1') {
// we have found a block, so increment number of blocks
nrBlocks += 1;
// remove any 1's of the block from the array, so that they each block is not counted multiple times
removeBlock(matrix, i, j);
}
}
}
System.out.println(nrBlocks);
}
}
There's a linear time (in number of cells) solution to this. If I get time, I'll add the code to this answer, but if not the Wikipedia article (see EDIT below) gives pseudo code.
The idea is to scan line-by-line, assigning an incrementing unique run numbers to each runs of 1s we see (and changing the cell content to be that unique number) If in any run, the cells immediately above in the previous line were also 1 (that is, they now have a run number), then we know that their unique-run-number and the current unique-run number form part of a single block. So record that the run-above-run-number, and the current-run-number are equivalent (but don't bother to change anything on the board)
At the end, we have a count of the runs we've seen. and a set of equivalence relationships of unique-run-numbers. For each set of equivalent-numbers (say runs 3, 5, 14 form a block), we subtract from the run count the number of runs, minus 1 (in other words, replacing the multiple runs with a single block count).
I think I have some ideas to mitigate the worst case, but they're probably not worth it.
And that's the number of blocks.
The worst case for the equivalence classes is O(size of board) though (1-wide vertical blocks, with one space between them will do this). Fortunately, the entirely-black board will need only O(height of board) - each row will get one number, which will be marked equivalent with the next row.
EDIT: There's a Stackoverflow question about this already: can counting contiguous regions in a bitmap be improved over O(r * c)?
and it turns out I've just re-invented the two-pass "Connected Component Labelling" algorithm discussed on Wikipedia

Optimizing N queens puzzle

I'm trying to solve the problem of positioning N queens on NxN board without row, column and diagonal conflicts. I use an algorithm with minimizing the conflicts. Firstly, on each column randomly a queen is positioned. After that, of all conflict queens randomly one is chosen and for her column are calculated the conflicts of each possible position. Then, the queen moves to the best position with min number of conflicts. It works, but it runs extremely slow. My goal is to make it run fast for 10000 queens. Would you, please, suggest me some improvements or maybe notice some mistakes in my logic?
Here is my code:
public class Queen {
int column;
int row;
int d1;
int d2;
public Queen(int column, int row, int d1, int d2) {
super();
this.column = column;
this.row = row;
this.d1 = d1;
this.d2 = d2;
}
#Override
public String toString() {
return "Queen [column=" + column + ", row=" + row + ", d1=" + d1
+ ", d2=" + d2 + "]";
}
#Override
public boolean equals(Object obj) {
return ((Queen)obj).column == this.column && ((Queen)obj).row == this.row;
}
}
And:
import java.util.HashSet;
import java.util.Random;
public class SolveQueens {
public static boolean printBoard = false;
public static int N = 100;
public static int maxSteps = 2000000;
public static int[] queens = new int[N];
public static Random random = new Random();
public static HashSet<Queen> q = new HashSet<Queen>();
public static HashSet rowConfl[] = new HashSet[N];
public static HashSet d1Confl[] = new HashSet[2*N - 1];
public static HashSet d2Confl[] = new HashSet[2*N - 1];
public static void init () {
int r;
rowConfl = new HashSet[N];
d1Confl = new HashSet[2*N - 1];
d2Confl = new HashSet[2*N - 1];
for (int i = 0; i < N; i++) {
r = random.nextInt(N);
queens[i] = r;
Queen k = new Queen(i, r, i + r, N - 1 + i - r);
q.add(k);
if (rowConfl[k.row] == null) {
rowConfl[k.row] = new HashSet<Queen>();
}
if (d1Confl[k.d1] == null) {
d1Confl[k.d1] = new HashSet<Queen>();
}
if (d2Confl[k.d2] == null) {
d2Confl[k.d2] = new HashSet<Queen>();
}
((HashSet<Queen>)rowConfl[k.row]).add(k);
((HashSet<Queen>)d1Confl[k.d1]).add(k);
((HashSet<Queen>)d2Confl[k.d2]).add(k);
}
}
public static void print () {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(queens[i] == j ? "♕ " : "◻◻◻ ");
}
System.out.println();
}
System.out.println();
}
public static boolean checkItLinear() {
Queen r = choseConflictQueen();
if (r == null) {
return true;
}
Queen newQ = findNewBestPosition(r);
q.remove(r);
q.add(newQ);
rowConfl[r.row].remove(r);
d1Confl[r.d1].remove(r);
d2Confl[r.d2].remove(r);
if (rowConfl[newQ.row] == null) {
rowConfl[newQ.row] = new HashSet<Queen>();
}
if (d1Confl[newQ.d1] == null) {
d1Confl[newQ.d1] = new HashSet<Queen>();
}
if (d2Confl[newQ.d2] == null) {
d2Confl[newQ.d2] = new HashSet<Queen>();
}
((HashSet<Queen>)rowConfl[newQ.row]).add(newQ);
((HashSet<Queen>)d1Confl[newQ.d1]).add(newQ);
((HashSet<Queen>)d2Confl[newQ.d2]).add(newQ);
queens[r.column] = newQ.row;
return false;
}
public static Queen choseConflictQueen () {
HashSet<Queen> conflictSet = new HashSet<Queen>();
boolean hasConflicts = false;
for (int i = 0; i < 2*N - 1; i++) {
if (i < N && rowConfl[i] != null) {
hasConflicts = hasConflicts || rowConfl[i].size() > 1;
conflictSet.addAll(rowConfl[i]);
}
if (d1Confl[i] != null) {
hasConflicts = hasConflicts || d1Confl[i].size() > 1;
conflictSet.addAll(d1Confl[i]);
}
if (d2Confl[i] != null) {
hasConflicts = hasConflicts || d2Confl[i].size() > 1;
conflictSet.addAll(d2Confl[i]);
}
}
if (hasConflicts) {
int c = random.nextInt(conflictSet.size());
return (Queen) conflictSet.toArray()[c];
}
return null;
}
public static Queen findNewBestPosition(Queen old) {
int[] row = new int[N];
int min = Integer.MAX_VALUE;
int minInd = old.row;
for (int i = 0; i < N; i++) {
if (rowConfl[i] != null) {
row[i] = rowConfl[i].size();
}
if (d1Confl[old.column + i] != null) {
row[i] += d1Confl[old.column + i].size();
}
if (d2Confl[N - 1 + old.column - i] != null) {
row[i] += d2Confl[N - 1 + old.column - i].size();
}
if (i == old.row) {
row[i] = row[i] - 3;
}
if (row[i] <= min && i != minInd) {
min = row[i];
minInd = i;
}
}
return new Queen(old.column, minInd, old.column + minInd, N - 1 + old.column - minInd);
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
init();
int steps = 0;
while(!checkItLinear()) {
if (++steps > maxSteps) {
init();
steps = 0;
}
}
long endTime = System.currentTimeMillis();
System.out.println("Done for " + (endTime - startTime) + "ms\n");
if(printBoard){
print();
}
}
}
Edit:
Here is my a-little-bit-optimized solution with removing some unused objects and putting the queens on diagonal positions when initializing.
import java.util.Random;
import java.util.Vector;
public class SolveQueens {
public static boolean PRINT_BOARD = true;
public static int N = 10;
public static int MAX_STEPS = 5000;
public static int[] queens = new int[N];
public static Random random = new Random();
public static int[] rowConfl = new int[N];
public static int[] d1Confl = new int[2*N - 1];
public static int[] d2Confl = new int[2*N - 1];
public static Vector<Integer> conflicts = new Vector<Integer>();
public static void init () {
random = new Random();
for (int i = 0; i < N; i++) {
queens[i] = i;
}
}
public static int getD1Pos (int col, int row) {
return col + row;
}
public static int getD2Pos (int col, int row) {
return N - 1 + col - row;
}
public static void print () {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(queens[i] == j ? "Q " : "* ");
}
System.out.println();
}
System.out.println();
}
public static boolean hasConflicts() {
generateConflicts();
if (conflicts.isEmpty()) {
return false;
}
int r = random.nextInt(conflicts.size());
int conflQueenCol = conflicts.get(r);
int currentRow = queens[conflQueenCol];
int bestRow = currentRow;
int minConfl = getConflicts(conflQueenCol, queens[conflQueenCol]) - 3;
int tempConflCount;
for (int i = 0; i < N ; i++) {
tempConflCount = getConflicts(conflQueenCol, i);
if (i != currentRow && tempConflCount <= minConfl) {
minConfl = tempConflCount;
bestRow = i;
}
}
queens[conflQueenCol] = bestRow;
return true;
}
public static void generateConflicts () {
conflicts = new Vector<Integer>();
rowConfl = new int[N];
d1Confl = new int[2*N - 1];
d2Confl = new int[2*N - 1];
for (int i = 0; i < N; i++) {
int r = queens[i];
rowConfl[r]++;
d1Confl[getD1Pos(i, r)]++;
d2Confl[getD2Pos(i, r)]++;
}
for (int i = 0; i < N; i++) {
int conflictsCount = getConflicts(i, queens[i]) - 3;
if (conflictsCount > 0) {
conflicts.add(i);
}
}
}
public static int getConflicts(int col, int row) {
return rowConfl[row] + d1Confl[getD1Pos(col, row)] + d2Confl[getD2Pos(col, row)];
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
init();
int steps = 0;
while(hasConflicts()) {
if (++steps > MAX_STEPS) {
init();
steps = 0;
}
}
long endTime = System.currentTimeMillis();
System.out.println("Done for " + (endTime - startTime) + "ms\n");
if(PRINT_BOARD){
print();
}
}
}
Comments would have been helpful :)
Rather than recreating your conflict set and your "worst conflict" queen everything, could you create it once, and then just update the changed rows/columns?
EDIT 0:
I tried playing around with your code a bit. Since the code is randomized, it's hard to find out if a change is good or not, since you might start with a good initial state or a crappy one. I tried making 10 runs with 10 queens, and got wildly different answers, but results are below.
I psuedo-profiled to see which statements were being executed the most, and it turns out the inner loop statements in chooseConflictQueen are executed the most. I tried inserting a break to pull the first conflict queen if found, but it didn't seem to help much.
Grouping only runs that took more than a second:
I realize I only have 10 runs, which is not really enough to be statistically valid, but hey.
So adding breaks didn't seem to help. I think a constructive solution will likely be faster, but randomness will again make it harder to check.
Your approach is good : Local search algorithm with minimum-conflicts constraint. I would suggest try improving your initial state. Instead of randomly placing all queens, 1 per column, try to place them so that you minimize the number of conflicts. An example would be to try placing you next queen based on the position of the previous one ... or maybe position of previous two ... Then you local search will have less problematic columns to deal with.
If you randomly select, you could be selecting the same state as a previous state. Theoretically, you might never find a solution even if there is one.
I think you woud be better to iterate normally through the states.
Also, are you sure boards other than 8x8 are solvable?
By inspection, 2x2 is not, 3x3 is not, 4x4 is not.

Categories

Resources