My grid super class has become large with many public methods and I'm trying to figure out how I can break it up to become more manageable. Methods fall into a few categories, methods below are for getting index info:
class grid{
int tot, cols, rows;
float gw, gh, w, h,gx,gy,gcx,gcy;
ArrayList<cell> cells = new ArrayList<cell>();
grid(float width, float height, int cols, int rows){
this.gx = 0;
this.gy = 0;
this.gw = width;
this.gh = height;
this.cols = cols;
this.rows = rows;
w = gw/float(cols);
h = gh/float(rows);
}
// how to move these methods somewhere else?
int rc(int row, int col){ // get index at row# col#
int val = 0;
for(int i = 0; i < cells.size(); i++){
if(cells.get(i).row == row && cells.get(i).col == col){
val = i;
}
}
return val;
}
int col(int inst){
if(altFlow == 1){
return floor(inst/rows);
} else {
return inst%cols;
}
}
int[] listRow(int indexIn){
int stIndex = cols*indexIn;
int[] arrayOut = new int[cols];
for(int i = 0; i < cols; i++) arrayOut[i] = i+stIndex;
return arrayOut;
}
}
My thought was to use composition, but I would still need a method for each function in the main class? Is this the best way?
class grid{
gridInfo gi;
...
//still need one of these for each method?
int col(int inst){
return gi.col(inst);
}
}
class gridInfo(){
grid parent;
...
int col(int inst){
if(altFlow == 1){
return floor(inst/parent.rows);
} else {
return inst%parent.cols;
}
}
}
You can start with an abstract class defining some methods and then enhance it (derive from it) by adding more methods.
This tutorial explains abstract classes: https://www.javatpoint.com/abstract-class-in-java
But I would not do that unless you have different classes derived from the same abstract base. I see no problem having large source code files. Every IDE provides lots of features to navigate quickly, regardless if the class has 100 or 3000 lines.
Related
I'm currently working on a minesweeper game and I want to refactor my code so that it uses a single 2 Dimensional array of MineTile classes.
In the MineTile class, I currently have booleans for if the mine is visible, one for if it has been revealed and one for if the player marked it or not.
Any tips on how I can do this would be greatly appreciated.
Here is the code:
Minefield Class:
public class Minefield {
// Check that there are fields to hold the current state of the minefield
private boolean[][] minefield;
private int[][] minedNeighbours;
private int row;
private int col;
private int rows, columns, numMines;
/**
* Initialize the fields, and then populate the minefield
*
* #param rows
* #param columns
* #param numMines
*/
public Minefield(int rows, int columns, int numMines) {
this.rows = rows;
this.columns = columns;
this.numMines = numMines;
// Note that these could be rows+2, columns+2 if edge boundaries are
// used
minefield = new boolean[rows][columns];
minedNeighbours = new int[rows][columns];
}
public boolean mineTile(boolean Mine, int row, int column) {
Visible = false;
Flagged = false;
this.Mine = Mine;
if (minefield[row][column]) {
return false;
} else {
minefield[row][column] = true;
}
// There are a number of ways of doing this. I've chosen to precalculate
// the start and end points of the for loops
// However, these checks could be internal to the for loops
// or the arrays could have unused boundary row and columns
int startRow, endRow, startColumn, endColumn;
if (row == 0) {
startRow = 0;
} else {
startRow = row - 1;
}
if (column == 0) {
startColumn = 0;
} else {
startColumn = column - 1;
}
if (row == this.rows - 1) {
endRow = row;
} else {
endRow = row + 1;
}
if (column == this.columns - 1) {
endColumn = column;
} else {
endColumn = column + 1;
}
for (int i = startRow; i <= endRow; i++) {
for (int j = startColumn; j <= endColumn; j++) {
minedNeighbours[i][j]++;
}
}
return true;
}
public int getRows() {
return rows;
}
public int getColumns() {
return columns;
}
/**
* Provide the grid representation
*
* #return Stars for mines, ints for adjacent
*/
public String toString() {
String s = "";
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (minefield[i][j]) {
s += "*";
} else {
s += minedNeighbours[i][j];
}
}
s += "\n";
}
return s;
}
/**
* A simple loop creating random coordinates, mining the tile until the
* required number of mines have been laid
*/
public void populate() {
int created = 0;
while (created < this.numMines) {
int row = (int) (Math.random() * this.rows);
int col = (int) (Math.random() * this.columns);
if (!minefield[row][col] && !(row == 0 && col == 0)) {
mineTile(row, col);
created++;
}
}
}
MineTile Class:
public class MineTile {
private boolean Mine;
private int row;
private int col;
private boolean Visible;
private boolean Flagged;
public MineTile(boolean Mine, int row, int col){
this.Mine = Mine;
this.row = row;
this.col = col;
Visible = false;
Flagged = false;
}
}
Thank you so much in advance.
Using the constructor for the class MineTile you posted:
public MineTile(boolean Mine, int row, int col){
this.Mine = Mine;
this.row = row;
this.col = col;
Visible = false;
Flagged = false;
}
You can define a 2d array with a double loop like the example below:
MineTile[][] tiles = new MineTile[rows][columns];
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
tiles[i][j] = new MineTile(false, i, j);
}
}
This is a simple basic example you can adapt to your needs, with different values for initializations of the 2d array elements.
I am making a grid with the amounts determined by a scanner. I keep getting an error and I am not sure why. Here is the code for the grid that I am trying to make, I will also include the object and class for the maze/grid below.
public static void mazeSetup() {
System.out.println("How many rows and columns do you want? I would\n"
+ "suggest 10 minimum and 20 maximum.");
boolean mazeselect = true;
while(mazeselect) {
maze.columns = sc.nextInt();
maze.rows = maze.columns;
if (maze.rows > 30 || maze.rows < 10) {
System.out.println("Make sure that you make it within 10-30 rows.");
} else {
mazeselect = false;
}
}
mazeBuild();
}
public static void mazeBuild() {
for(int x = 0; x < maze.rows; x++) {
for(int y = 0; y < maze.columns; y++) {
maze.maze[x][y]= ".";
System.out.print(maze.maze[x][y]);
}
System.out.println();
}
characterPlacement();
}
I also have the object here:
static Maze maze = new Maze(null,0,0,0,0);
and the class with construtors for the maze/grid.
public class Maze {
String maze[][];
int rows;
int columns;
int xStart;
int yStart;
public Maze(String xMaze[][], int xRows, int xColumns, int xxStart, int xyStart) {
maze = xMaze;
rows = xRows;
columns = xColumns;
xStart = xxStart;
yStart = xyStart;
}
public String[][] maze() {
return maze;
}
public int rows() {
return rows;
}
public int columns() {
return columns;
}
public int xStart() {
return xStart;
}
public int yStart() {
return yStart;
}
}
Any help would be greatly appreciated. Thanks a lot! :D
Note: No errors occur until ran in console.
your String maze[][] is null because of this:
static Maze maze = new Maze(null,0,0,0,0); // notice that null
And you're trying to put values in it upon calling mazeBuild(). You should initialize it or pass an array instead of null. You can do this at the start of mazeBuild()
public static void mazeBuild() {
maze.maze = new String[maze.rows][maze.columns]; // <-- this one!
for(int x = 0; x < maze.rows; x++) { // <-- this loop tries to
for(int y = 0; y < maze.columns; y++) { // put values in your
maze.maze[x][y]= "."; // maze.maze (2D String array)
System.out.print(maze.maze[x][y]);
}
System.out.println();
}
You can also do this in exchange to the line of code I've added.
String[][] mazeArray = new String[maze.rows][maze.columns];
maze = new Maze(mazeArray, maze.rows, maze.columns, 0, 0);
I have the same problem as some guy who asked this.
I want to code some basic stuff for a little minesweeper game.
Now I have the problem that my code
public class Minesweeper1 {
public static int[][] makeRandomBoard(int s, int z, int n){
int feld[][] = new int [s][z];
for(int i = 0; i < s; i++){
for(int j = 0; j < z; j++){
feld[i][j] = 0;
}
}
for(int i = 0; i < n; i++){
selectRandomPosition(s, z);
feld[randomHeight][randomWidth] = 1;
}
}
so it starts the selectRandomPosition code:
public static int[] selectRandomPosition(int maxWidth, int maxHeight) {
int randomHeight = StdRandom.uniform(0, maxHeight);
int randomWidth = StdRandom.uniform(0, maxWidth);
return new int[]{randomHeight, randomWidth};
}
Here I am not allowed to change anything, but it returns a new array. Now my question is how can I use the new array in makeRandomBoard?, since I do not know any name of the array. When I use feld[randomHeight][randomWidth] = 1; it says that it does not know these variables.
And he did get the answer:
Call the method, and assign its return value to a variable. Now you have a name for the array:
// Make a call
int[] randomArray = selectRandomPosition(maxW, maxH);
// Access the width
int randomW = randomArray[0];
// Access the height
int randomH = randomArray[1];
but what do I have to write now?
I tried it with:
feld[randomW][randomH] = 1;
but it seems like it doesn't work. I also need a return statement.
Can anyone help me?
I believe this is the solution you are looking for:
Solution
public class Minesweeper1 {
// Note:
// s == Height
// z == Width
public static int[][] makeRandomBoard(int s, int z, int n) {
// Note: Misspelling of "field"?
int feld[][] = new int [s][z];
// Initialize the game board with no mines (value of 0)
for(int i = 0; i < s; i++) {
for(int j = 0; j < z; j++) {
feld[i][j] = 0;
}
}
// Iterate through n times to place "mines" (value of 1)
for(int i = 0; i < n; i++){
// selectRandomPosition returns an array of length 2
// the first index (0) = randomHeight
// the second index (1) = randomWidth
// Notice that z and s is flipped
// because the first parameter is for width, which is z
// and the second parameter is for height, which is s
int[] position = selectRandomPosition(z, s);
int positionX = position[1];
int positionY = position[0];
// The order of positionY/positionX is key!
// If it's in the wrong order you will get an
// IndexOutOfBoundsException!
feld[positionY][positionX] = 1;
}
// Return the newly created array
return feld;
}
public static int[] selectRandomPosition(int maxWidth, int maxHeight) {
int randomHeight = StdRandom.uniform(0, maxHeight);
int randomWidth = StdRandom.uniform(0, maxWidth);
// Notice that this is returning a fixed array of two elements
// the first being the Y component, and the second being the X
// component.
return new int[]{randomHeight, randomWidth};
}
}
Problems
Passing the wrong values
You were calling selectRandomPosition wrong. Remember that s is the Height, and z is the Width. So you were passing into selectRandomPosition the Height for the first parameter, and the Width for the second parameter. Look at the method declaration:
public static int[] selectRandomPosition(int maxWidth, int maxHeight)
That meant you passed the Height into the maxWidth, and the Width into the maxHeight. My solution flips it for you. This can be confusing because s and z don't really give you hints to what they are (Height and Width) - consider renaming these variables to help you.
Accessing in the wrong order
You have in your question:
feld[randomW][randomH] = 1;
This is wrong, it should be:
feld[randomH][randomW] = 1;
This image shows a visual representaion of what a two dimensional array looks like:
So the access would be:
feld[0][0] == 1
feld[0][1] == 1
feld[0][2] == 1
feld[1][0] == 1
feld[1][1] == 2
feld[1][2] == 4
feld[2][0] == 1
feld[2][1] == 3
feld[2][2] == 9
Nit-Pick: Misspellings
Other than having weird variable names like s and z that do not help you at all in remembering what means what, your main variable that you will eventually return is misspelled. Did you mean "field"?
Variable naming is important and can help you, and other readers, to easily understand your code. Also, comments in places where you think you need them also help!
The code I am working with is below. I feel like this should be simple, but I'm having an incredibly hard time focusing this week and need some help.
I'm not able to properly set the values for pt.x or pt.y in the nested for loops. IDEA is telling me that the symbol can't be resolved. The class is identified from another java file in the package that only identifies that class. it is as follows:
public class pointClass {
class point{
int x;
int y;
int z;
}
}
(Adding text to demonstrate these are 2 separate files)
This is for a class assignment, but I'm not sharing the whole assignment, just what I need help with. I'm trying to learn, not have things done for me.
public class main {
public static void main (String args[]){
ArrayList<pointClass.point> pointlist = new ArrayList<>();
//Creating map
int row = 40;
int col = 40;
int [][] bigarray = new int [row] [col];
//iterating through map
for (int i = 0; i < row; i++;){
for (int j=0; j< col; j++){
pointClass pt = new pointClass.point;
pt.x = row;
pt.y = col;
pt.z = ;//RNG HERE//
}
}
How do I need to more properly identify these class attributes? For context,this code cretes a 40x40 array and will assign a random value to each number. Another code stanza will be added to print the 2D array.
There doesn't seem to be a need for a Nested class here. Consider just using the following:
public class Point {
int x;
int y;
int z;
}
Now let's take a look at your syntax errors. Most are fairly simple, but deserve discussion nonetheless.
public class Main {
public static void main(String args[]){
ArrayList<Point> pointlist = new ArrayList<>(); //Now that we aren't using a nested class, Just <Point>
//Creating map
int row = 40;
int col = 40;
int [][] bigarray = new int [row] [col];
//iterating through map
for (int i = 0; i < row; i++){ //No semicolon after i++
for (int j=0; j< col; j++){
Point pt = new Point(); //Calling a constructor is a method, hence ()
pt.x = j; //You probably mean j and k here, not row and col (which don't change)
pt.y = k;
pt.z = 0;//RNG HERE// //Not sure what you mean here, but you can set pt.z to whatever you want
//You created pointlist, but never add to it. Did you mean to?
pointlist.add(pt);
}
}
}
}
I've just tested the above and it compiles and runs correctly. That said, you can do a lot better stylistically. Here are some tips.
Class names start with a capital letter. Point, not point. PointClass, not pointClass.
Non-final / mutable fields should be private. Thus your Point class, while correct, is fairly bad practice (the reasons for which are very well documented elsewhere). Consider using the following alternative:
public class Point {
private int x;
private int y;
private int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getX() { return x; }
public int getY() { return y; }
public int getZ() { return z; }
}
Well I made this method Resize with in my Class Object2D, which is supposed to resize the two-dimensional Color-Array PointInformation of the Object2D, that it is called onto, by a certain Percentage. (I found that easier to do when convertig the 2D-Array into an 1D Array)
public class Object2D
{
int width;
int height;
int ResizePercentage = 100;
Color PointInformation[][];
public void Resize(int Percentage)
{
Color[]temp = Standart_Methods.Reduce2DArray(this.PointInformation);
int temp_width = this.width;
int temp_height = this.height;
double Faktor = (Percentage+100)/100;
this.width = (int) (this.width*Faktor);
this.height = (int) (this.height*Faktor);
this.ResetPointInformation();
Color[]temp2 = Standart_Methods.Reduce2DArray(this.PointInformation);
int SamePixelCount = 0;
Color LastColor = temp[0];
for (int i = 0; i < temp.length; i++)
{
if (temp[i] == LastColor )
{
SamePixelCount += 1;
}
else
{
for (int i2 = (int) (i*Faktor); i == 1; i-- )
//Method Resize will only be called when i*Faktor is going to be 100% = X.0 (An Integer)
{
temp2[i*2-i] = LastColor;
}
SamePixelCount = 0;
}
}
Standart_Methods.PrintArray(temp2);
int a = 10;
int b = 0;
System.out.print(a/b); //No Exeption, Code unreachable!?
}
}
It basically starts at temp[0] and adds 1 to the int SamePixelCount as long as it finds the same Color.
When a different Color is found, the method writes the Color of the former Pixels into the right Places in the temp2 Array.
for (int i = 0; i < temp.length; i++)
{
if (temp[i] == LastColor )
{
SamePixelCount += 1;
}
else
{
for (int i2 = (int) (i*Faktor); i == 1; i-- )
//Method Resize will only be called when i*Faktor is going to be 100% = X.0 (An Integer)
{
temp2[i*2-i] = LastColor;
}
SamePixelCount = 0;
}
}
The correct translation of the manipulated Array temp2 into the Object's PointInformation is still missing, because I wanted to test, if temp2 was correctly resized out of temp, so I did
Standart_Methods.PrintArray(temp2); //the Method works btw
but it just did nothing! And even bader! Everything I put at the place of that command, also didn't!
int a = 10;
int b = 0;
System.out.print(a/b); //No Exeption!
And what is even stranger is, that as soon as I call the Method Resize, somewhere, everything after the Call turns into the same strange unreachable Code!?
I am seriously totally clueless about what could have caused this problem.
Any help would be nice!
dividing by zero certainly will give you ArithmeticException:
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 0;
System.out.println(a/b);
}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Test.main(Test.java:14)
I suggest use eclipse and trace your code using the debugger. Inspect your variables per code line and I'm sure you can figure our what's wrong