1

Creating a small battleship game on Android that will use RMI and Tomcat.

I need to load data from a text file "boards.txt" and possibly store it in a HashMap in order to query it.

I cannot attach the file but below is a screenshot of the .txt file in Notepad. It displays the board layout for 10,000 Battleship game boards (I think it's that number anyway) which are 10x10 grids.

So each 100 characters of the file will be the locations of the different ships and blank spaces for a 10 x 10 grid with each separated by a line break.

What I'm struggling with is the actual parsing. I think saving the data to a HashMap will make it easier to search through for picking a random board layout. Below is the code that I am currently using to read in the data.

public static void main(String[] args) throws FileNotFoundException {
        Scanner scanner = new Scanner(new FileReader("C:\\Path\\boards.txt"));

        HashMap<String, String> map = new HashMap<String, String>();

        while (scanner.hasNextLine()) {
            String columns = scanner.nextLine();
            map.put(columns, columns);
        }

        System.out.println(map);
    }

Now the main reason I have it like this was just to get rid of errors. Previously my code was like this:

public static void main(String[] args) throws FileNotFoundException {
        Scanner scanner = new Scanner(new FileReader("C:\\Path\\boards.txt"));

        HashMap<String, String> map = new HashMap<String, String>();

        while (scanner.hasNextLine()) {
            String[] columns = scanner.nextLine().split(" ");
            map.put(columns[0], columns[1]);
        }

        System.out.println(map);
    }

But, I was getting an out of bounds exception. Due to the fact there is no blank spaces to split most likely.

OK so my main issue is, how do I either save the entire .txt file to a HashMap and only display one line of 100 characters at a time.

And Secondly (lower priority) - I would like to choose one line at random so I could create a random number between 1-10000 to display one line. I thought of using a String, Integer HashMap and somehow have a index value for each line but I'm not sure how I would do that.

**EDIT Sorry I forgot to add the screenshot. Here it is: enter image description here

Thank you for your answers, I'll read through them now

UserBruiser
  • 155
  • 1
  • 2
  • 17
  • 1
    No screenshot in your post. We can't tell what's going on. Can't you just post a few lines of the boards.txt file so we can see the format? It would be easier than a screenshot. – Ted Hopp Dec 19 '12 at 21:57
  • Is there any reason to pregenerate these? Why not generate them randomly? This would not require a data file (or a minimal data file) and you could have many more possible games. – Peter Lawrey Dec 19 '12 at 21:58
  • @PeterLawrey - OP may want to be able to replay particular games. (Although a file of prng seeds might work just as well for this.) – Ted Hopp Dec 19 '12 at 22:00
  • @TedHopp You can use the random seed. See my answer. – Peter Lawrey Dec 19 '12 at 22:28

4 Answers4

2

To answer your questions directly:

1) You pretty much had your file reader, but you needn't bother with the Map, a List will suffice.

Scanner scanner = new Scanner(new FileReader("C:\\Path\\boards.txt"));
List<String> lines = new ArrayList<String>();
while (scanner.hasNextLine()) {
    String columns = scanner.nextLine();
    lines.add(columns);
}

2) To grab a random line, just pick a random index into the List.

Random random = new Random();
int randomLineIndex = random.nextInt(lines.size());
String randomLine = lines.get(randomLineIndex);

Now, all that said, if you don't need to load the whole file, don't. If you just need to grab a random line from the file then go right for it and save yourself computation and memory.

To do so, you'll first need to known the number of lines in the file. This question gives you:

String file = "C:\\Path\\boards.txt";
BufferedReader reader = new BufferedReader(new FileReader(file));
int lineCount = 0;
while (reader.readLine() != null) lineCount++;
reader.close();

Now you know how many lines there are and can pick one at random:

Random random = new Random();
int randomLineIndex = random.nextInt(lineCount);

Then you can grab that line and ignore the rest:

reader = new BufferedReader(new FileReader(file));
int i = 0;
while (++i < randomLineIndex)
    // Skip all lines before the one we want
    reader.readLine();
String randomLine = reader.readLine();
Community
  • 1
  • 1
Sean Connolly
  • 5,692
  • 7
  • 37
  • 74
2

This is how I would do it. You have up to 2^48 different games which you can replay by using the same seed. This avoids the need to read files or store an index in memory. You can recreate any board game as required.

public class Baord {
    private static final int[] SHIP_SIZES = {4, 4, 3, 3, 3, 2, 2, 2, 2,  1, 1};
    public static final char EMPTY = '.';

    private final Random random;
    private final char[][] grid;
    private char letter = 'a';
    private final int width;
    private final int height;

    public Baord(int height,int width,  int seed) {
        this.width = width;
        this.height = height;
        this.random = new Random(seed);
        this.grid = new char[height][width];
        for (char[] chars : grid)
            Arrays.fill(chars, EMPTY);
        for (int len : SHIP_SIZES)
            placeShip(len);
    }

    private void placeShip(int len) {
        OUTER:
        while (true) {
            if (random.nextBoolean()) {
                // across
                int x = random.nextInt(width - len + 1);
                int y = random.nextInt(height);
                for (int j = Math.max(0, y - 1); j < Math.min(height, y + 2); j++)
                    for (int i = Math.max(0, x - 1); i < Math.min(width, x + len + 2); i++)
                        if (grid[j][i] > EMPTY)
                            continue OUTER;
                for (int i = 0; i < len; i++)
                    grid[y][x + i] = letter;

            } else {
                // down
                int y = random.nextInt(height - len + 1);
                int x = random.nextInt(width);
                for (int j = Math.max(0, x - 1); j < Math.min(width, x + 2); j++)
                    for (int i = Math.max(0, y - 1); i < Math.min(height, y + len + 2); i++)
                        if (grid[i][j] > EMPTY)
                            continue OUTER;
                for (int i = 0; i < len; i++)
                    grid[y + i][x] = letter;
            }
            break;
        }
        letter++;
    }

    public String toString() {
        StringBuilder ret = new StringBuilder();
        for (int y = 0; y < grid.length; y++)
            ret.append(new String(grid[y])).append("\n");
        return ret.toString();
    }

    public static void main(String... args) {
        for (int i = 0; i < 3; i++)
            System.out.println(new Baord(8, 16, i));
    }
}

prints

..........ddd...
.....aaaa.......
eee.......j.....
.............i..
..bbbb.......i.c
.......g.......c
.k.h...g...f...c
...h.......f....

ii..............
.....ccc..ff...b
...............b
aaaa...........b
.........j..h..b
....gg......h...
..............k.
eee..ddd........

.d.....eee.....f
.d.............f
.d..............
......j.ccc....g
.............b.g
.............b..
h.i..........b..
h.i...aaaa.k.b..

.......h....aaaa
.......h........
.e.........ccc..
.e..............
.e.bbbb...ii..ff
........d.......
.g..j...d.......
.g......d.....k.

............ccc.
.....bbbb.......
.ii.......k..d..
.....f.......d..
eee..f.......d..
................
.j.g........hh..
...g.aaaa.......
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Thank you, Peter! This is a nice alternative to using the .txt file. Mind you, it's a lot more lines of code but it adds reduces the chance of repetition. – UserBruiser Dec 20 '12 at 14:33
0

Why are you using a HashMap with the key and value the same? What you are describing is essentially just an array where each bucket contains a line of 100 chars. Pulling out a random map would mean creating a random number between 1-10000 and printing the contents of that bucket.

Regarding the parsing we would need to see an example from your file itself to help with any syntax issues you have.

thedan
  • 1,230
  • 2
  • 9
  • 13
0

Just for reference.

scanner.next().split(":"); worked for me while scanner.nextLine().split(":"); not.

aLogic
  • 125
  • 1
  • 8