vendredi 16 octobre 2020

I have a couple of flaws in my Java code and I can't identify where

The following code is for references of what's going on. I have a project I'm working on that is supposed to be a minesweeper variant. Basically, I input the grid size, one is created, and then I must find the hidden block in the least amount of turns possible.

There are multiple problems, however.

import java.util.Scanner;
import java.util.Random;

public class SweeperGame {
    private char[][] gameBoard;             // Represents the grid. [Rows][Columns]

    private int treasureX;
    private int treasureY;
    private int totalMoves;
    private boolean found;
    boolean flipped = false;

    public static void main(String[] args) {        // Driver File
        Scanner s = new Scanner(System.in);
        int height;
        int width;
        boolean done = false;
        int x;
        int y;

        do {
            System.out.println("Sweep the sand and find the treasure");
            System.out.println("Please enter the number of height and width"
                    + "\nof the game board");
            System.out.print("Height of board: ");
            height = s.nextInt();
            System.out.print("Width of board: ");
            width = s.nextInt();
            SweeperGame game = new SweeperGame(height, width);
            s.nextLine();
            do {
                do {
                    System.out.print("Enter treasure coordinates separated by a space: ");
                    x = s.nextInt();
                    y = s.nextInt();
                } while (!game.checkOutOfBounds(x, y) || game.beenSwept(x, y));
                done = game.digSand(x, y);
                System.out.println(game.toString());
                s.nextLine();
            } while (!done);
            System.out.println("You found the treasure in " + game.getTotalMoves() + " moves!");
            System.out.println("Out of " + game.getBoardHeight() * game.getBoardWidth() + " possible moves.");
            System.out.print("Would you like to find more treasure [Y/N]? ");
        } while (s.nextLine().equalsIgnoreCase("Y"));

    }

    public SweeperGame(int height, int width) {
        /*
        Receives two int parameters as the user's input for height and width of grid where treasure is buried
        instantiates the gameBoard array [x][y]
        Initialize gameBoard cells to contain a space ''. Done with single quotes only. (Why does the single quotes matter?)
        Set treasureX/treasureY randomly using the first/second parameter, respectively
        Set gameBoard[treasureX][treasureY] to 'T'
        Set total moves to 0
        Set found to false
         */

        totalMoves=0;
        found = false;

        // Build grid
        if (height == 0 && width == 0) {
            throw new IllegalArgumentException();
        }

        // Instantiates gameBoard
        gameBoard = new char[height][width];

        // Initialize gameBoard's cells
        for (int i=0; i<height; i++){
            for (int j=0; j<width; j++){
                gameBoard[i][j] = ' ';
            }
        }

This part of the code is supposed to create a random treasure in the 2D array. I'm using .length here to measure the length of each dimension and I'm using that for the cap of random. The problem is that more often than not I just end up with the treasure being (1,1). If I create a 2x2 grid or a 6x6, it's (almost) always in (1,1).

        // Set treasureX
        Random randomX = new Random(gameBoard.length);
        treasureX = randomX.nextInt(gameBoard.length);

        // Set treasureY
        Random randomY = new Random(gameBoard[1].length);
        treasureY = randomY.nextInt(gameBoard[1].length);

        // Setting the treasure 'T' into the gameBoard
        gameBoard[treasureX][treasureY] = 'T';

    }

This is the method I created to flip the first dimension of the 2D array so that (0,0) was always in the bottom left. The problem is that no matter where I call the function, even if I put it in a loop that only is ever supposed to loop once, it flips it over and over and screws it up. No idea why.

    public void flipArray() {
        int arrayX = gameBoard.length;
        char[] xValues = new char[arrayX];
        for (int i = 0; i < arrayX; i++){
            xValues[(arrayX-i)-1] = gameBoard[i][0];
        }
        for (int i = 0; i < arrayX; i++){
            gameBoard[i][0] = xValues[i];
        }
    }

    public boolean beenSwept(int x, int y){                          // Receives x & y and returns true if space has already been searched
        // Reversed because of dimensions
        if (gameBoard[x][y] != ' '){
            return true;
        }
        else{
            return false;
        }
    }

    public boolean treasureFound(int x, int y){                      // Receives x & y and returns true if treasure is at given locations
        if (this.treasureX == x && this.treasureY == y){
            return true;
        }
        else{
            return false;
        }
    }


    public boolean checkOutOfBounds(int x, int y){                   // Receives x & y and returns true if within array (gameBoard), false if not
        int h = gameBoard[1].length;    // X value of gameBoard
        int v = gameBoard.length;       // Y value of gameBoard
        if ((x >= 0 && x <= h) && (y >= 0 && y <= v)){
            return true;
        }
        else{
            return false;
        }
    }
    public int getBoardHeight(){                                    // Returns the height of the board
        return gameBoard.length;
    }
    public int getBoardWidth(){                                     // Returns the width of the board
        return gameBoard[1].length;
    }
    public int getTotalMoves(){                                     // Returns the total amount of moves taken
        return totalMoves;
    }

    public boolean digSand(int x, int y){           // Receives x & y and returns true if the treasure if found, false otherwise.
        int a = Math.abs(treasureX-x);
        int b = Math.abs(treasureY-y);
        int c = (a + b);
        char manDistance = (char)(c + '0');

        if (treasureFound(x,y)==true){              // Also displays "Manhattan distance" to treasure. Increment number of moves taken if the treasure isn't found and space hasn't been searched already
            found = true;
            return true;
        }
        else {
            if (beenSwept(x,y)==true){
                totalMoves += 1;
            }
            else if (beenSwept(x,y)==false){
                gameBoard[y][x] = manDistance;
                totalMoves += 1;
            }
            return false;
        }
    }

Lastly, there's a problem where sometimes I'll input (1,0) on a 3x3 grid and it won't register. I skips and asks for input again with the same println. I can't tell why it does this.

    public String toString(){                       // Displays the current gameBoard array and it's contents EXCEPT the location of the treasure

        if (found == false){
            gameBoard[treasureX][treasureY] = ' ';
        }
        else if (found == true){
            gameBoard[treasureX][treasureY] = 'T';
        }

        int rows = gameBoard.length;
        int columns = gameBoard[1].length;
        String finished = "";

        // Can't put return statements in for loop
        for (int i = 0; i < rows; i++) {                        // Rows of gameBoard
            finished += boxTop() + printSubRows();              // Prints top and the sub-rows
            for (int j = 0; j < columns; j++) {                 // Columns of gameBoard
                finished += ("|   " + gameBoard[i][j] + "   ");
            }
            finished += "|\n" + printSubRows();
        }
        return finished + boxBottom();
        /*
        Prints the following:
        --------------------------------
        |       |       |       |       |
        |   x   |   x   |   x   |   x   |
        |       |       |       |       |
        --------------------------------
         */
    }

    public String boxTop(){                     // Prints top line(s) plus new line
        int t = gameBoard.length;
        return ("--------".repeat(t)+"\n");
    }
    public String boxBottom(){                  // Prints bottom line(s)
        int b = gameBoard.length;
        return "--------".repeat(b);
    }
    public String printSubRows(){               // Prints the the rows of '|' that don't contain a gameBoard char
        String filler = ("|       ").repeat(gameBoard[1].length) + "|\n";
        return (filler);
    }

}

Any help is appreciated. I have no one to help and no one to turn to besides this site and google-foo. It's rather frustrating.




Aucun commentaire:

Enregistrer un commentaire