I need to make a simple(standart) minesweeper for my project.
I want to check the surrounding elements of a random(or specific) element of a 2d array.
lets say I have an array like that
boolean board[5][5]
I want to check the surrounding elements of
board[0][0]
I wrote that:
public int numberChecker(int h, int w) {
int checker = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int he = h - 1 + i;
int wi = w - 1 + i; <---- this i should be j that was the issue
if (board.getHeight() > he && he >= 0
&& wi >= 0 && board.getWidth() > wi) {
if (boomChecker(he, wi)) {
if (w != (wi) && h != (he)) {
checker++;
}
}
}
}
}
return checker;
}
the problem is I think it only checks " \ " way (do not know how to put it in words)
ex:
(output # means uncovered numbers mean surrounding mines)
uncover 4-2
######
######
0#####
#0####
##0### <-- unlocking this one
###0##
or
uncover 0-0
0#####
#0####
##0###
###### <-- there is a mine at check spot
######
######
the code itself is not important (I know I made it a bit complicated to explain myself)
all I need is a working surrounding checking for loop (or anything)
thanks in advance
Problem solved
simple stupid mistake
int he = h - 1 + i;
int wi = w - 1 + i; <--- i should be j
thanks
I think your mistake is in this 2 lines:
int he = h - 1 + i;
int wi = w - 1 + i;
you add to the height AND to the width the value of i.
So you just check every of the 3 diagonal fields 3 times.
I think it should be
int he = h - 1 + i;
int wi = w - 1 + j;
so you really iterate through all 9 possible fields and not just through the diagonale.
Hope that helps!
I'm going to write my answer as though answering a homework question
now what you really ought to do is, for each cell in your array, there are 8 other cells to check. so something like:
count += board[i-1][j-1] ? 1 : 0;
count += board[i-1][j] ? 1 : 0;
count += board[i-1][j+1] ? 1 : 0;
count += board[i][j-1] ? 1 : 0;
etc.
be sure to include some mechanism to prevent you from accessing elements outside the bounds of the array.
also, if you were wondering what the ? and : mean, look up the Ternary Operator It's useful in all sorts of situations.
By the way, you might be better off explicitly checking each of the 8 possible surrounding cells. It's entirely possible that the JVM might automatically unroll your loop, but I don't see why you wouldn't just check them explicitly. It will be faster, and easier to understand.
boolean upleft = board[row-1][column-1];
boolean up = board[row-1][column];
boolean upright = board[row-1][column+1];
boolean left = board[row][column-1];
boolean right = board[row][column+1];
boolean downleft = board[row+1][column-1];
boolean dow = board[row+1][column];
boolean downright = board[row+1][column+1];
You'll of course have to do bounds checking if your on the edge of the board, but it makes more sense as to what is going on.
Related
Hi I am trying to check the surrounding neighbours of a cell using this function, and I need it to logically wrap around the grid to count the amount of 1s in the surrounding 8 cells.
This is the code I have so far. I know I am supposed to use modulo for this to work but I have no idea how that would work, more importantly I have no idea how to implement it in this function. I also know that I am supposed to do something like r - 1 and y - 1 to check the cells, but again I have no idea how that works with modulo
The if statement above is my attempt at doing this, but I clearly lack understanding of what I am doing.
Currently, this function goes through each cell on the grid using the 2 for loops. Beyond that, I need it to check the surrounding 8 cells for "1"s, and on the border, I need it to check the other side of the grid (i.g. wrap around as if the grid was spherical).
Can someone please explain and give me a solution to this? Greatly appreciate any help.
public static int countNeighbours(int row, int col, Board b)
{
int count = 0;
for (int r = row - 1; r <= row + 1; r++)
{
for (int c = col - 1; c <= col + 1; c++)
{
if (b.get(r - 1 + row) % row)((c - 1 + col) % col) = 1); {
count++;
}
}
}
return count;
}
To this question:
The superqueen is a chess piece that can move like a queen, but also like a knight. What is the maximal number of superqueens on an 8X8 chessboard such that no one can capture an other?
I want to write a brute force algorithm to find the maximum. Here's what I wrote:
public class Main {
public static boolean chess[][];
public static void main(String[] args) throws java.lang.Exception {
chess = new boolean[8][8];
chess[0][0] = true;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
/*Loop to check various possibilities*/
if (!checkrow(i) && !checkcolumn(j) && !checkdiagonals(i, j) && !checkknight(i, j)) {
if (i != 0 || j != 0) {
chess[i][j] = true;
}
}
}
}/*printing the array*/
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(((chess[i][j]) ? "T" : "x") + "|");
}
System.out.println();
}
}
/*All working fine here*/
public static boolean checkrow(int a) {
for (int i = 0; i < 8; i++) {
if (chess[a][i]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkcolumn(int a) {
for (int i = 0; i < 8; i++) {
if (chess[i][a]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkdiagonals(int pi, int pj) {
int i = pi - Math.min(pi, pj);
int j = pj - Math.min(pi, pj);
for (int k = i, l = j; k < 8 && l < 8; k++, l++) {
if (chess[k][l]) {
return true;
}
}
int i_2 = pi - Math.min(pi, pj);
int j_2 = pj + Math.min(pi, pj);
for (int k = i_2, l = j_2; k < 8 && l > 1; k++, l--) {
if (chess[k][l]) {
return true;
}
}
return false;
}
/*Not All working fine here try commenting out this method above so that that it doesn't run during the check*/
public static boolean checkknight(int pi, int pj) {
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (0 <= pi + 2 * i && pi + 2 * i <= 8 && 0 <= pj + j && pj + j <= 8) {
if (chess[pi + 2 * i][pj + j]) {
return true;
}
}
if (0 <= pi + i && pi + i <= 8 && 0 <= pj + 2 * j && pj + 2 * j <= 8) {
if (chess[pi + i][pj + 2 * i]) {
return true;
}
}
}
}
return false;
}
}
I have two questions:
My algorithm for checkknight looks for all knight positions, is it wrong? or there is some coding error.Everything is working fine when I comment out it and I get a nice solution.
Secondly it'll result only in one solution.For other solutions I have to offset(or change position) of other pieces bit by bit after each mega-loop of this, I am confused about implementing it. My instincts guide me that I need to change whole of the code. Is there a modification or a way to do it?
Additional Thoughts: I think we would add to a counter each time we place a piece and add to a long array and output the maximum and array after storing the relevant data.
Code Location: You may view/edit/fork/download it at http://ideone.com/gChD8a
This a rough brute-force method starting from the opposite direction, i.e. from the solved eight-queens puzzle. This will allow us to find a bunch of viable solutions.
The brute-force technique for going from a single superqueen to potentially 8 seems to be especially complex due to the knight's traversal. Based on the runs, about 60% of the viable paths for normal queens are invalid with superqueens. So if we were to instead brute force normal queens, and then work backwards, that is potential time saved for finding a solution, and we can better determine the run-time. Because we know normal queens is easier.
We start off with the 12 fundamental solutions, we would then use these as inputs. Solving normal queens is outside this, but the wiki page has a fantastic article describing everything.
In my case, I stored them as Strings representing the coordinate of the queen (the rows are indices).
So: "17468253" = A1, B7, C4, D6, E8, F2, G5, H3
By brute-forcing the opposite direction from solved queens, we only have to test at most 12 x 8! possible solutions. Because order doesn't matter, additional optimization could occur by eliminating duplicate boards and solutions for processing.
First up, checkKnight, which appears to be your source of confusion. Using absolute values, you can reasonably determine whether or not a piece is within knight's range by checking whether the X offset is 2 and Y offset is 1, or vice versa. You've made a complex checkKnight function to check each individual location and whether or not a piece is on the border. Working the other way by hitscanning each queen to each other queen is logically simpler and less of a nightmare to debug.
Queen class
public class Queen {
int i, j;
public Queen(int i, int j) {
this.i = i;
this.j = j;
}
public boolean checkKnight(Queen queen) { // if any queen meets another
// queen at 2 and 1 offset, we
// eliminate it.
return (Math.abs(i - queen.i) == 2 && Math.abs(j - queen.j) == 1)
|| (Math.abs(i - queen.i) == 1 && Math.abs(j - queen.j) == 2);
}
}
This board has been modified since I originally posted. It takes a String input and converts it to a full chessboard. It has some minor work towards the potential any-size board, but right now it handles child board creation. When a child board is created, the queens are passed by reference rather than making a whole new set of queens. A total of 96 queens are stored in memory, 1 for each one on the original 12-board solution. Not perfectly optimized, but better than 96 -> 672 -> 4032 -> ...
Board class
public class Board {
static int boardSize = 8;
ArrayList<Queen> queens = new ArrayList<Queen>();
public Board(String s) {
for (int i = 0; i < s.length(); i++) {
queens.add(new Queen(i, s.charAt(i) - 49)); // you could implement
// base 16 here, for
// example, for a 15x15
// board
}
}
public Board(Board b) { // duplicates the board, but keeps references to
// queens to conserve memory, only 96 total queens
// in existence through search!
for (Queen q : b.queens) {
queens.add(q);
}
}
public boolean checkForImpact() {
for (int i = 0; i < queens.size(); i++) {
for (int j = i + 1; j < queens.size(); j++) {
if (queens.get(i).checkKnight(queens.get(j))) { // just check
// for any
// queens
// intersecting,
// one hit is
// enough
return true;
}
}
}
return false;
}
public ArrayList<Board> getChildBoards() { // create child boards with a
// single queen removed
ArrayList<Board> boards = new ArrayList<Board>();
for (int i = 0; i < queens.size(); i++) {
boards.add(new Board(this));
}
int i = 0;
for (Board b : boards) {
b.queens.remove(i);
i++;
}
return boards;
}
public String drawBoard() {
String s = "";
char[][] printableBoard = new char[boardSize][boardSize];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printableBoard[i][j] = '_';
}
}
for (Queen q : queens) {
printableBoard[q.i][q.j] = 'Q';
}
s += " A B C D E F G H\n";
for (int i = 0; i < 8; i++) {
s += (8 - i) + "|";
for (int j = 0; j < boardSize; j++) {
s += printableBoard[i][j];
s += "|";
}
s += "\n";
}
return s;
}
}
Test class
import java.util.ArrayList;
public class Test {
static String[] boards = { "24683175", "17468253", "17582463", "41582736",
"51842736", "31758246", "51468273", "71386425", "51863724",
"57142863", "63184275", "53172864" }; // all 12 solutions for the 8
// queens problem
static ArrayList<Board> boardObjects = new ArrayList<Board>();
public static void main(String[] args) {
for (String queens : boards) { // create starter boards
boardObjects.add(new Board(queens));
}
int i;
ArrayList<Board> foundBoards = null;
for (i = 8; i > 0; i--) {
ArrayList<Board> newBoards = new ArrayList<Board>();
foundBoards = new ArrayList<Board>();
for (Board b : boardObjects) {
if (b.checkForImpact()) { // if any queen intercepts we get
// children
ArrayList<Board> boardsToBeAdded = b.getChildBoards(); // pass
// all
// permutations
// of
// queens
// once
// removed
for (Board bo : boardsToBeAdded) {
newBoards.add(bo); // add it in to the next list
}
} else {
foundBoards.add(b); // if we have no impact, we have a
// solution
}
}
if (!foundBoards.isEmpty())
break;
boardObjects.clear();
boardObjects = newBoards;
}
System.out.println("The maximum number of super-queens is: " + i);
ArrayList<String> winningCombinations = new ArrayList<String>();
for (Board board : foundBoards) {
String createdBoard = board.drawBoard();
boolean found = false;
for (String storedBoard : winningCombinations) {
if (storedBoard.equals(createdBoard))
found = true;
}
if (!found)
winningCombinations.add(createdBoard);
}
for (String board : winningCombinations) {
System.out.println(board);
}
}
}
The end output is:
The maximum number of super-queens is: 6
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|Q|_|
6|_|_|_|Q|_|_|_|_|
5|_|_|_|_|_|_|_|_|
4|_|_|_|_|_|_|_|Q|
3|_|Q|_|_|_|_|_|_|
2|_|_|_|_|Q|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|_|_|
6|_|_|_|_|Q|_|_|_|
5|_|_|_|_|_|_|_|Q|
4|_|Q|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|_|_|_|Q|_|_|
1|_|_|Q|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|Q|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|_|_|_|_|_|
4|_|_|Q|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|_|_|_|_|_|_|
1|_|_|_|Q|_|_|_|_|
I've removed the duplicates and made a nice board printing method. don't remember the exact math, but this highlights 40 possible locations. There are others, just by looking, but we've found a fair chunk of them already! From here, we can gently shift individual queens around. From a cursory look, each board has a single piece that can be moved to 3 additional spaces, so now we know there are probably about 160 solutions.
Conclusions
With this application, the run-time on my machine was less than a second, meaning that if we attached this to a standard queens application, the additional knight's brute-forcing would have no impact on that process and have almost the same run-time. In addition, because only 6-piece puzzles are possible, we know that your eventual application run will finish its finding at the 6th piece being placed, as no more solutions are possible, since there are no viable 7-piece and 8-piece solutions.
In other words, finding the maximum super-queen layout is likely actually shorter than the maximum queen layout due to the additional restrictions!
Trying to brute-force such a question is a good way to get a feel for it. So I won't suggest looking up pre-cooked solutions at first.
One little remark though: I don't see the reason for the condition if (i != 0 || j != 0) { that you have there. You are working on Java arrays. Instead of 1 through 8, they go 0 through 7, but the 0 is the first column, you should not eliminate it, otherwise it's only a 7x7 board.
First, let me address your technical question: how to calculate the knight positions.
Take a sheet of quad paper, put a queen somewhere not less than two squares away from the edge. Then mark the end positions of a knight-move from it.
You'll end up with just 8 squares that need to be considered. There is no point in doing a 3x3 loop to find them. A better idea would be to prepare a static array with the relative coordinates of the knight moves - an array of 8 pairs of numbers - and loop on that. So you have only an 8-step loop. In each step of the loop, check for bounds (0 ≤ X + Xoffset < 8, 0 ≤ Y + Yoffset < 8 ), and you have the knight coordinates.
Second, there is no point checking the part of the board that's ahead of you. Since you have not covered the next row and those below it, there is no point in looking for queens there. The implications of this:
You'll never put another queen in the same row where you have just marked a queen position (because you threaten it horizontally). This means that if you mark a queen, you should use continue to break out of the inner loop to the next row.
You don't need checkrow(). When you start a row, there is no queen ahead of you. And if you followed the above bullet point, there is no queen on your back, either.
When you use checkcolumn, you start at row 0, but you can finish at the row before the one you are on (i-1). There are still no queens in the rows below you! The same is true for the diagonal checks.
Earlier I said that you need to prepare and check 8 knight positions. But now you know there is no queen at the knight positions ahead of you. So you only need to prepare an array with four knight positions - the ones above your position.
But most importantly... once you have finished and you have your queens in positions and print the board: you have a single solved board. You have proved that this number of queens is possible. But is it the highest number possible? You have not checked what happens if you don't put a queen on the first square of the first row, but on the second. Perhaps this will allow you to put in an extra queen later. And what about the queen in the second row? Maybe if you moved that, you would be able to put a queen somewhere below where you couldn't before?
So, now you have to actually do the same thing over again, changing one decision every time and working from there. In effect, you have many potential boards. Why? Because there may be more than one valid position on each row where you put that row's queen. So you have decided to put it in the first valid position. But what if you decide to put it in the second valid position? Or leave that row empty? Each such decision is followed by another set of decisions on the next row.
The different boards created by different decisions form a decision tree. The problem for you to consider, therefore, is how to work such a tree out. How to write your decision trail and then backtrack, change, fill another board and count the queens at each level. People here suggested recursion, because it lends itself nicely to such problems. Or you can keep a stack of decisions if you want. You can eliminate some of the potential boards based on symmetries.
I suggest you first make sure you understand your single board well, and then consider how to represent your decision tree and how to traverse it.
There are several questions here.
The first is: how many knight-queens can be placed on an nxn chessboard? Since a k-piece solution can trivially be reduced to a k-1 piece solution, it makes sense to start from the upper bound. That is, look for an n-piece solution, if that fails look for an n-1 piece solution, and so forth.
The second question is: how should I look for a k-piece solution? There are two classic strategies: depth-first and breadth-first. In the former, you consider one vertex of the search tree at a time and use backtracking on failure. In the latter, you consider one complete level of the search tree at a time.
Something that can make a great deal of difference to your search is to account for symmetry (in this case, rotations and reflections).
The third (implicit) question is: what is a good representation here? If your chess-boards are less than 8x8 in size then a 64-bit bit-pattern will do very nicely!
In practical terms, try to separate the three levels of your problem as far as you can. If you don't, you'll find that a choice in one level will severely limit your options at another level.
I am having a really stupid problem that has been bugging me for a couple of hours now. I have made a program to compare slope of an Array of points and draw a line through four points with the same slope. My problem is I take the initial slope as a comparator to each slope. Then compare the inital value to each other point in the array and if the slope of the initial comparator is the same as the next slope the counter increments. my problem is I done want the initial slope to change during the for loops but I cant get it to work. The code is below, I know im being kind of vague so if you need any more information just ask.
for(int initial = 0; initial < counter/2 ; initial ++)
{
int comparator = 1;
for(int next = 1 ; next < counter/2 ; initial ++)
{
Point finalCompare = points[initial];
Point initialCompare = points[comparator];
Point initialPoint = points[initial];
int counter_2 = 0;
Point nextPoint = points[next];
double initialSlope = (initialCompare.y - initialPoint.y/ initialCompare.x-initialPoint.x);
double nextSlope = (nextPoint.y - initialPoint.y/ nextPoint.x - initialPoint.x);
if(initialSlope == nextSlope)
{
counter_2++;
StdOut.println("Counter: " + counter_2);
finalCompare = points[next];
}
if(counter_2 >= 3)
{
StdOut.println("got here");
initialPoint.drawTo(finalCompare);
break;
}
StdOut.println(counter_2);
}
StdOut.println("comparator");
comparator++;
}
}
You're never changing next. I assume you want
for(int next = 1 ; next < counter/2 ; next++)
instead of
for(int next = 1 ; next < counter/2 ; initial ++)
Additionally, this condition seems to never be true: if(counter_2 >= 3)
You set counter_2 to 0 and increment it at most once before this statement:
int counter_2 = 0;
...
if(initialSlope == nextSlope)
{
counter_2++;
...
}
//counter_2 can either be 0 or 1 here
if(counter_2 >= 3)
{
...
}
I assume you want to move the initialization out of the inner loop:
int counter_2 = 0;
for(int next = 1 ; next < counter/2 ; next++)
Besides that, please step through your code with a debugger and see what is done at each step. This will help you find typing errors (if you understand the algorithm you're implementing, otherwise try and understand that first).
these lines
double initialSlope = (initialCompare.y - initialPoint.y/ initialCompare.x-initialPoint.x);
double nextSlope = (nextPoint.y - initialPoint.y/ nextPoint.x - initialPoint.x);
I think they are not doing what you want, remember that / has precedence , so first is going to divide initialPoint.y/ initialCompare.x , and then the rest of the operations, I think you want to do :
double initialSlope = ((initialCompare.y - initialPoint.y)/ (initialCompare.x-initialPoint.x));
double nextSlope = ((nextPoint.y - initialPoint.y)/ (nextPoint.x - initialPoint.x));
I am working on an algorithm that has three parts. The first is a recursive method that will wrap words to a specific length with the least penalty. The second is an algorithm that is a Dynamic implementation of the recursive method. The last one is a Greedy Algorithm of the problem. I already have the Greedy one coded but I'm struggling on the Recursive solution. I'm not quite sure where exactly I'm running into an issue with my Recursive method but I know it should be something similar to the Knuth-Plass Algorithm. The recursive algorithm is supposed to have a factorial running time, and used more to help with the dynamic solution. If anyone has a link to a Knuth-Plass implementation or can spot something huge in my code, any help would be appreciated.
Recursive Algorithm:
public static ArrayList<String> recursive(ArrayList<String> input, int size) {
if(input.size() <= 1)
return input;
ArrayList<String> temp1 = input;
ArrayList<String> temp2 = input;
for(int i = 0; i < input.size(); i++) {
if(input.size() - 1 >= size)
break;
else {
for(int j = 0; j < input.size(); j++) {
temp1.set(j, temp1.get(j) + " " + temp1.get(j + 1));
temp1.remove(j + 1);
if(totalPenalty(blankChars(temp1, size)) < totalPenalty(blankChars(temp2, size))) {
input = recursive(temp1, size);
} else {
input = recursive(temp2, size);
}
}
}
}
return input;
}
The totalPenalty() and blankChars return the amount of penalty at the end of each line.
EDIT: I'm still not seeing any immediate solutions. Any help would be appreciated.
That looks like Java, and in Java there is no implicit copy-constructor.
ArrayList<String> temp1 = input; <-- this will not create another object with the same content, but instead a reference to the same object.
You need to change line 4 and 5 to:
ArrayList<String> temp1 = new ArrayList<String>(input);
ArrayList<String> temp2 = new ArrayList<String>(input);
I haven't looked for any other mistakes, so try this out and update the question if you have any more problems.
About the Knuth-Pass breaking algorithm; You can find a Python implementation at http://oedipus.sourceforge.net/texlib/. I haven't looked closer at it, but the description seems to be what you are looking for.
I hope the following code runs. Here I have added the cost for the last line as well. Though word processors use greedy algorithms most of the time and they neglect the cost of the last line. Let me know if this is clear to you.
import java.lang.Math;
public int RCS(int[] l , int n , int m , int index) {
// first base condition - if index gets beyond the array 'l' , then return 0;
if (index > n - 1) return 0;
// second base condition - if index is the last word i.e there is only one word left in the
// array to be inserted in the line then return the cost if added in that line.
if (index == n - 1) return (m - l[n - 1]) * (m - l[n - 1]) * (m - l[n - 1]);
// make a global cost variable to be returned
int cost = Integer.MAX_VALUE;
// Here , we try to select words from the array and apply RCS on the rest of the array.
// From index to last element , we iteratvely select first , or first two and so on.
for (int i = index ; i < n ; i++) {
int current_space_sum = 0 ;
// we add the length of the selected word. We have selected words in array from index to i.
for (int k = index ; k <= i ; k++) {
current_space_sum = current_space_sum + l[k] ;
}
// Adding the space between the words choses. If 2 words are chosen , there is one space and so on
current_space_sum = current_space_sum + i - index;
// If the length of the chosen words is greater than the line can accept , no need of looking beyond.
if (current_space_sum > m) break;
// Iteratively find the minimum cost
cost = Math.min(cost , (m - current_space_sum) * (m - current_space_sum) * (m - current_space_sum) + RCS(l , n , m , i + 1));
}
return cost;
}
public static void main(String[] args) {
WordWrap w = new WordWrap();
int[] l = {3, 2 , 2 , 5};
int n = l.length;
int m = 6;
int result = w.RCS(l , n , m , 0);
System.out.println(result);
}
I am having trouble with a school assignment and would really appreciate some insight. I am asked to create a wordsearch using a 25x25 2d char array and somehow go through that array by developing an algorithm that will search through it to find 21 pre-defined words.
So far I have been able to create a ragged array of the words that I need to find and the 2d array with the chars placed in each position.
in = new ASCIIDataFile("wordsearch.txt");
display = new ASCIIDisplayer();
int numberWords = in.readInt();
wordlist = new char[numberWords][];
for (int i =0; i<wordlist.length; i++){
wordlist[i] = in.readLine().toUpperCase().toCharArray();
}
for(int i = 0;i<wordlist.length; i++){
display.writeLine(" ");
for(int j = 0;j<wordlist[i].length; j++){
display.writeChar(wordlist[i][j]);
}
}
//done wordlists
int gridLength = in.readInt();
int gridHeight = in.readInt();
grid = new char[gridHeight][gridLength];
for(int i = 0;i<gridLength; i++){
grid[i] = in.readLine().toCharArray();
}
My problem in creating the algorithm to search though the 2d array and match it with a character in the wordlist.
I am supposed to make different methods, for searching forwards, backwards and diagonal.
I have been struggling for days just to do the forward search.
I really how no idea about how to go about this problem, so far all I have is
for(int k = 0; k<wordlist.length; k++){
int p = 0;
for(int row = 0;row<gridLength; row++){
for(int col = 0;col<gridHeight; col++){
while(p<wordlist[k].length){
if(grid[row][col] == wordlist[k][p]){
//do something
}
}
}
}
}
}
Any help or pointers would be greatly appreciated!
The trick is, you don't need to consider all 8 possible directions separately. You can represent each with a vector. E.g., 'forward' direction would be (0, 1) (first row number, then column) - a vector pointing to the right. Diagonal top-left direction would be (-1, -1). Well, you get the idea.
Then, just create a function
boolean findWord(int row, int col, int d_row, int d_col, char[] word);
It can take current matrix position ((row, col), where word is supposed to start), search direction ((d_row, d_col)) and a word to look for. It returns whether the given word is here.
Then you can invoke it for different directions, e.g.
findWord(row, col, -1, 0, word);
findWord(row, col, -1, 1, word);
findWord(row, col, 0, 1, word);
...
(I'm listing them in clock-wise order)
Implementing findWord is just incrementing current position by d_row and d_col, until we find mismatch in characters or word ends. The basic routine is like this
while (row < total_rows && row >= 0 && col < total_columns && col >= 0) {
// check character here
...
row += d_row;
col += d_col;
}
I bet you'll have all processing code (except input-reading) in 40 lines.
You first need to understand how to search a short string inside a bigger string. There are couple of options here: from the simplest algorithm up to more complex (like Knuth Morris Pratt and the family). You can get a list of their descriptions here: http://en.wikipedia.org/wiki/String_searching_algorithm. I strongly recommend you try the naive search first.
Once you can search a string inside another string you will need to abstract the way you access the bigger string and adapt the matrix data to it.
Basically assuming this matrix:
1 2 3 4
-------
1| a b c d
2| b c d a
3| c d a b
4| d a b c
and this string abc
you will first make some code to be able to find abc inside abcd or bcda or cdab etc.
Once you can do that you should build the intermediate step of extracting (for each possible lookup type: horizontal, vertical, diagonal, reverse diagonal) series of chars and apply the previous algorithm on them.
For example if we want to search diagonally we would generate 7 strings from the matrix:
a
bb
ccc
dddd
aaa
bb
c
if you want to search horizontally you would generate those strings:
abcd
bcda
cdab
dabc
and seach inside each string.
Once this is working you should combine the searching with reading the proper chars from the matrix. Hopefully if you follow this path you will be able to figure it out :).
Good luck.
To travel diagonally in any 2D matrix of arbitrary dimensions, hope the below function helps.
public static void prinDiagonalsInGrid(char[][] grid, int rows, int cols)
{
String result = "";
int min = Math.min(rows, cols);
int max = Math.max(rows, cols);
int sameLengthDiagonals = max - min + 1;
int totalDiagonals = (rows + cols) - 1;
for (int p = 0; p < totalDiagonals; p++)
{
int xIndex;
int maxCnt;
if (p < (min - 1)) // First diagonals
{
maxCnt = xIndex = p;
}
// diagonals of equal length in the middle
else if (sameLengthDiagonals != 0 &&
p >= (min - 1) && p < (sameLengthDiagonals + min - 1))
{
if (rows < cols)
xIndex = rows - 1;
else
xIndex = p;
maxCnt = min - 1;
}
else // Last diagonals
{
xIndex = rows - 1;
maxCnt = totalDiagonals - p - 1;
}
for (int cnt = 0; cnt <= maxCnt; cnt++)
{
result += grid[xIndex][p - xIndex] + " ";
--xIndex;
}
result += "\n";
}
System.out.println(result);
}