I am essentially trying to make a program that will decide where the best place to put a piece (tetris-esque pieces) on a 10x10 grid. I determine the best place in a given game state by the amount of empty spaces (more is better). Full rows and columns clear. My method insertPiece(grid,piece,x,y) seems to be mutating the grid variable in my findBestMove method as it next iteration contains the piece.
public static int[][] findBestMove(int[][] grid,Piece piece){
int mostEmpty = 0;
int bestX = 0;
int bestY = 0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++){
if(isPlaceable(grid,piece,i,j)){
int[][] temp = insertPiece(grid,piece,i,j);
if(countEmpty(temp)>mostEmpty){
bestX = i;
bestY = j;
}
}
}
}
int[][] temp = insertPiece(grid,piece,bestX,bestY);
return clearRows(temp);
}
public static int[][] insertPiece(int[][] grid, Piece piece, int x, int y){
printGrid(grid);
int[][] pieceGrid = piece.getGrid();
for(int i=0;i<pieceGrid.length;i++){
for(int j=0;j<pieceGrid[i].length;j++){
try {
if (grid[i + x][j + y] < pieceGrid[i][j]) {
grid[i + x][j + y] = pieceGrid[i][j];
} else if (grid[i + x][j + y] == 1) {
break;
}
}
catch(Exception e){
// break;
}
}
}
printGrid(grid);
return grid;
}
This is what the final print looks like
0000000000
0100100100
1111111110
0100100100
1111111110
0100100100
1111111110
0100100100
1111111110
0000000000
This is the piece im inserting
int[][] gridPyramid = {{0,0,0},
{0,1,0},
{1,1,1}};
I left out large chunks of code to avoid cluttering the post, let me know if you need any clarification
You are actually changing the grid in:
grid[i + x][j + y] = pieceGrid[i][j];
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 months ago.
Improve this question
DISCLAIMER This problem is part of a COMPLETED competition and will not be reused
I was hoping someone could create and explain a solution efficient enough to run file sizes at most 15 x 15 tiles. Below is the problem:
Tiled Floor (40 points)
Sam recently hired a tile installer to tile a kitchen floor. The floor was supposed to be very colorful with no two
adjacent tiles having the same color. Unfortunately, the installer failed to ensure adjacent tiles have different
colors. The mortar is still wet, but it is difficult to lift just one tile at a time, so the installer is limited to swapping
adjacent tiles. The question is how to exchange adjacent tiles in as few moves as possible so that the floor meets
the criteria that no two adjacent tiles have the same color.
A sample input is
RGR
RPC
GRB
YPG
Representing the tiles on a three by four floor where R is a red tile, G is green, B is blue, C is cyan, P is purple, and
Y is yellow. In general, the input will be a series of lines of R, G, B, C, P, and Y. Each line will have the same length
and there will be a maximum of 15 lines with 15 characters in each line. The output is to be an integer
representing the number of swaps of adjacent tiles. For this problem, “adjacent” means touching and in the same
row or column; for example, the only two tiles are adjacent to the yellow tile in the lower left corner of the above
floor: the green tile at the start of the third row and the purple tile in the middle of the fourth row.
The output for the above floor will be
2
since the red tile at the start of row 2 can be swapped with the green tile at the start of row three, and then the
red tile in middle of row 3 can be swapped with the blue tile at the end. This gives the arrangement
RGR
GPC
RBR
YPG
Other fixes are possible such as exchanging the first two tiles on row 2 to get PRC and then exchanging the middle
tiles in rows 3 and 4. Your program does not print the resulting floor arrangement, just the minimum number of
tile swaps that must take place. Sometimes it is not possible to fix a floor:
GGYGP
CGGRG
This isn’t possible to tile because there are 6 Gs and a floor this size can fit only 5 without two being adjacent. In
cases where there is no solution, the output is to be
not possible
I have created a solution but it works only for approximately 16 tiles (4 x 4), any more takes an enormous amount of time. This is because of the recursive and naive nature of this function, for every call it calls itself at least 4 times.
Below is my attempted solution, keep in mind that there are extra methods from previous attempts and that minimumSwaps() is the main recursive method:
import java.util.*;
import java.io.*;
class Main {
private static ArrayList<String[][]> solutions = new ArrayList<String[][]>();
private static ArrayList<Integer> moves = new ArrayList<Integer>();
private static int min = Integer.MAX_VALUE;
public static void main(String[] args) throws Exception {
File file = new File("Tiles.txt");
Scanner scan = new Scanner(file);
Scanner scan1 = new Scanner(file);
int length = 0;
while (scan1.hasNextLine()) {
scan1.nextLine();
length++;
}
String[][] tiles = new String[length][];
for (int i = 0; i < length; i++) {
String line = scan.nextLine();
tiles[i] = new String[line.length()];
for (int l = 0; l < tiles[i].length; l++) {
tiles[i][l] = line.substring(l, l + 1);
}
}
System.out.println("Start");
minimumSwaps(tiles, 0, new ArrayList<String>());
//System.out.println(Arrays.toString(findCount(tiles)));
//findSolutions(new String[tiles.length][tiles[0].length], findCount(tiles), 0, 0);
//System.out.println(solutions.size());
System.out.println(min);
//display();
}
//tilesIDs: more efficient way to check if computer has seen previous situation
//how to know if there are moves that do not involve problem areas that reduces total number of moves?
public static void minimumSwaps (String[][] tiles, int moves, ArrayList<String> tilesIDs) {
if (moves < min) {
String newID = computeID(tiles);
if (linearSearch(tilesIDs, newID)) return;
tilesIDs.add(newID);
if (solved(tiles)) {
//Main.moves.add(moves);
if (moves < min) min = moves;
//solutions.add(cloneTiles(tiles));
}
else if (moves < min - 1) {
for (int i = 0; i < tiles.length; i++) {
for (int l = 0; l < tiles[i].length; l++) {
if (adjacentPresent(tiles, tiles[i][l], i, l)) {
try {
String[][] newTiles = cloneTiles(tiles);
String current = newTiles[i][l];
newTiles[i][l] = newTiles[i][l - 1];
newTiles[i][l - 1] = current;
minimumSwaps(newTiles, moves + 1, (ArrayList<String>)(tilesIDs.clone()));
}
catch (Exception e) {}
try {
String[][] newTiles = cloneTiles(tiles);
String current = newTiles[i][l];
newTiles[i][l] = newTiles[i][l + 1];
newTiles[i][l + 1] = current;
minimumSwaps(newTiles, moves + 1, (ArrayList<String>)(tilesIDs.clone()));
}
catch (Exception e) {}
try {
String[][] newTiles = cloneTiles(tiles);
String current = newTiles[i][l];
newTiles[i][l] = newTiles[i - 1][l];
newTiles[i - 1][l] = current;
minimumSwaps(newTiles, moves + 1, (ArrayList<String>)(tilesIDs.clone()));
}
catch (Exception e) {}
try {
String[][] newTiles = cloneTiles(tiles);
String current = newTiles[i][l];
newTiles[i][l] = newTiles[i + 1][l];
newTiles[i + 1][l] = current;
minimumSwaps(newTiles, moves + 1, (ArrayList<String>)(tilesIDs.clone()));
}
catch (Exception e) {}
}
}
}
}
}
}
public static boolean linearSearch(ArrayList<String> IDs, String newID) {
for (String ID : IDs) if (ID.equals(newID)) return true;
return false;
}
public static String computeID(String[][] tiles) {
String ID = "";
for (String[] letters : tiles) {
for (String letter : letters) {
ID += letter;
}
}
return ID;
}
public static String[][] cloneTiles(String[][] tiles) {
String[][] newTiles = new String[tiles.length][tiles[0].length];
for (int i = 0; i < tiles.length; i++) {
newTiles[i] = tiles[i].clone();
}
return newTiles;
}
public static boolean solved(String[][] tiles) {
for (int i = 0; i < tiles.length; i++) {
for (int l = 0; l < tiles[i].length; l++) {
if (adjacentPresent(tiles, tiles[i][l], i, l)) return false;
}
}
return true;
}
public static int minMoves() {
int min = Integer.MAX_VALUE;
for (int num : moves) if (num < min) min = num;
return min;
}
public static void findSolutions(String[][] tiles, int[] count, int i, int l) {
String[] colors = {"R", "G", "B", "C", "P", "Y"};
for (int z = 0; z < 6; z++) {
//System.out.println("testing");
if (!adjacentPresent(tiles, colors[z], i, l) && count[z] > 0) {
String[][] newTiles = new String[tiles.length][tiles[0].length];
for (int a = 0; a < newTiles.length; a++) {
for (int b = 0; b < newTiles[0].length; b++) {
newTiles[a][b] = tiles[a][b]; // clone does not work properly?
}
}
newTiles[i][l] = colors[z];
//System.out.println(Arrays.deepToString(newTiles));
int[] newCount = count.clone();
newCount[z]--;
if (l == tiles[0].length - 1 && i != tiles.length - 1) {
findSolutions(newTiles, newCount, i + 1, 0);
}
else if (l < tiles[0].length - 1) {
findSolutions(newTiles, newCount, i, l + 1);
}
else if (l == tiles[0].length - 1 && i == tiles.length - 1) {
solutions.add(newTiles);
}
}
}
}
public static boolean adjacentPresent(String[][] tiles, String color, int i, int l) {
try {
if (tiles[i][l + 1].equals(color)) return true;
}
catch (Exception e) {}
try {
if (tiles[i][l - 1].equals(color)) return true;
}
catch (Exception e) {}
try {
if (tiles[i + 1][l].equals(color)) return true;
}
catch (Exception e) {}
try {
if (tiles[i - 1][l].equals(color)) return true;
}
catch (Exception e) {}
return false;
}
public static int[] findCount(String[][] tiles) {
int[] count = new int[6];
for (String[] line : tiles) {
for (String letter : line) {
switch (letter) {
case "R": count[0]++;
break;
case "G": count[1]++;
break;
case "B": count[2]++;
break;
case "C": count[3]++;
break;
case "P": count[4]++;
break;
case "Y": count[5]++;
break;
}
}
}
return count;
}
public static void display() {
for (String[][] lines : solutions) {
for (String[] line : lines) {
for (String letter : line) {
System.out.print(letter);
}
System.out.println();
}
System.out.println("\n\n");
}
}
}
Improving the algorithm
A breadth-first search would yield, as first result, an optimal solution. It could still be slow on larger problems where the solution is deeper in; or in the worst case, when there is no solution at all.
Your current algorithm looks like backtracking, which is depth-first, and therefore you need to look at all possible solutions before being sure you have found the shortest one. This is very wasteful.
Improving the data representation
You have 6 colors in a 15x15 grid. You are currently storing up to 15x15=225 strings, and constantly copying that String[][] over. It would be a lot more efficient to use a single byte[] (of length dim x dim), which can be copied over faster. Use integers (1, 2, ...) instead of color-chars ("R", "Y", ...). With a single dimension you have to do some math to check for adjacency, but it is nothing too fancy; and you win a lot of memory locality.
I am teaching myself java using the cs106a course from Stanford.
Currently I am on chapter 10 of the book "The Art and Science of Java".
The problem is to write a 3x3 Magic Square.
The exercise:
You have to write a 3x3 array
Each side of the array(Magic Square) has to equal 15
The problem:
The program I wrote works, the assignment is complete, this question is for self learning. As a beginner I would like to improve the method SumOfSides() and make it smaller and more efficient. I tried iterating the array in this method but still have issues. Is there a way to make it more efficient?
public void run() {
//set the font
setFont("Helvetica-40");
//fill the array
fillArray();
//sum up all sides
SumOfSides();
//check if all of the sides in the magic square array equal 15:
checkSides(mSqr);
//I used this for debugging purposes only:
//showSides();
}
//for debugging purposes:
public void showSides() {
println(sumRight0);
println(sumRight1);
println(sumRight2);
println(sumBottom0);
println(sumBottom1);
println(sumBottom2);
println(sumDiagonalUp);
println(sumDiagonalDown);
}
public void SumOfSides() {
sumRight0 = mSqr[0][0] + mSqr[0][1] + mSqr[0][2];
sumRight1 = mSqr[1][0] + mSqr[1][1] + mSqr[1][2];
sumRight2 = mSqr[2][0] + mSqr[2][1] + mSqr[2][2];
sumBottom0 =mSqr[0][0] + mSqr[1][0] + mSqr[2][0];
sumBottom1 =mSqr[0][1] + mSqr[1][1] + mSqr[2][1];
sumBottom2 =mSqr[0][2] + mSqr[1][2] + mSqr[2][2];
sumDiagonalUp = mSqr[2][0] + mSqr[1][1]+ mSqr[0][2];
sumDiagonalDown = mSqr[0][0] + mSqr[1][1] + mSqr[2][2];
}
/*This predicate method checks if the sides
of the array add up to 15: */
public boolean checkSides(int[][] myArray) {
if (sumRight0 ==15 && sumRight1 ==15&& sumRight2==15 && sumBottom0==15&& sumBottom1==15&&
sumBottom2==15&& sumDiagonalUp==15&&sumDiagonalDown==15) {
println("True, this is a Magic Square");
return true;
} else {
println("False, the sides do not equal 15");
return false;
}
}
public void fillArray() {
int num =0;
for(int row=0; row <3; row++) {
for (int col=0; col<3; col++) {
num=readInt("");
mSqr[row][col]=num;
}
}
/*Test array values here to see
* if they were entered correctly.
*/
//println(mSqr[1][2]); //should be 6
//println(mSqr[2][0]); //should be 7
}
//instance variables:
int[][] mSqr= new int[3][3];
List<List<Integer>> new1 = new ArrayList<>();
private int sumRight0;
private int sumRight1;
private int sumRight2;
private int sumBottom0;
private int sumBottom1;
private int sumBottom2;
private int sumDiagonalUp;
private int sumDiagonalDown;
}
Perhaps the only thing is readability. You could take the values and move them into more readable variables:
int topLeft = mSqr[0][0];
int topMid = mSqr[0][1];
...
int sumLeft = topLeft + midLeft + bottomLeft;
int sumRight = topRight = midRight + bottomRight;
...
To address your concern of making it smaller, I would argue that converting the sums into loops, as you mentioned, is certainly not worth it in the case that you are doing 6 sums of 3 values each. Furthermore, each term of each sum is common to either one or two other sums, which does not provide much overlap. If you were performing larger sums (larger in number of terms in the sum, not the total value), then perhaps it would be worth it on a readability/SLOC argument.
Suppose you did want to do a loop still though, you could do something like
sumLeft = 0;
sumRight = 0;
sumTop = 0;
sumBottom = 0;
sumDiagonalUp = 0;
sumDiagonalDown = 0;
for(int i = 0; i < mSqr.length; i++) {
for(int j = 0; j < mSqr[i].length; j++) {
if (i == 0) {
sumLeft += mSqr[i][j];
}
if (i == mSqr.length - 1) {
sumRight += mSqr[i][j];
}
if (j == 0) {
sumTop += mSqr[i][j];
}
if (j == mSqr[i].length) {
sumBottom += mSqr[i][j];
}
if (i == j) {
sumDiagonalDown += mSqr[i][j];
}
if (i + j == mSqr.length - 1) {
sumDiagonalUp += mSqr[i][j];
}
}
}
The loops only provide benefit on large magic squares.
Also, I am confused by your description contrasted with your implementation. It seems you are summing each row and column, and the two diagonals of the square, as opposed to the 4 sides and the diagonals.
I need some help making my Java method (getNumGroupsOfSize) work. It should tally how large an array "group" (consecutive elements that share the same value) is, and then print out how many other groups share that size. So for example, array [1,1,1,2,2,2,3,3,3,4,5,6,7] would print:
size 1=4
size 3=3
and then would stop running.
This is what I have so far:
import static java.lang.System.*;
import java.util.Arrays;
import java.util.Scanner;
public class ArrayStats {
int[] numArray;
int number;
public ArrayStats(int[] array) {
setArray(array);
}
public void setArray(int[] array) {
numArray = array;
}
public int getNumGroupsOfSize() {
int cnt = 0;
for (int x = 0; x < numArray.length - 1; x++) {
if (numArray[x] == numArray[x + 1]);
cnt++;
for (int y = 2; y <= 9; y++) {
if (cnt == y)
number = cnt;
else if (cnt == 1)
number = 1;
}
}
return number;
}
public String toString() {
return "size count" + " == " + getNumGroupsOfSize() + Arrays.toString(numArray);
}
}
I'm pretty sure my getNumGroupsOfSize is not coded correctly, but I'm not sure how to make it work. I would genuinely appreciate any help that can be offered. If you need any more information, don't hesitate to comment. Thank you!
Your method getNumGroupsSize() doesn't make much sense. For example how do you print out all the groups if you just store one number? I wrote the method new and it prints the numbers directly. You can also store them in an array if you want to.
public void getNumGroupsOfSize() {
int cnt = 1;
int currentNumber = numArray[0];
for (int x = 0; x < numArray.length - 1; x++) {
if (numArray[x] == numArray[x + 1]){
cnt++;
}
else{
System.out.println(currentNumber + ": " + cnt);
currentNumber=numArray[x+1];
cnt=1;
}
}
System.out.println(currentNumber + ": " + cnt);
}
For each encountered series, you have to count its size and update the information about how many series has this size.
So the int number field you are using is clearly not enough to achieve it as it persists only a very elementary information.
In your case, you need to have two associated information : for each series size, you want to know the number of series that have this size.
A Map object should do the job.
It would use as key the size of the series and as value the number of series that have this size.
Map<Integer, Integer> occurrenceBySeriesSize = new HashMap<>();
At each time an encountered series is finished, update the map with the new count :
int serieSize = ...;
Integer occurrences = occurrenceBySeriesSize.get(serieSize);
if (occurrences == null){
occurrences = 0;
}
occurrenceBySeriesSize.put(serieSize, ++occurrences);
I want to solve an DFS algorithm. It is about the game 8-puzzles or N x N puzzle. At the beginning i have two arrays like (the Zero represents an empty field):
int[][] start = {{0,1,2}, {4,5,3}, {7,8,6}};
int[][] target = {{1,2,3}, {1,5,6}, {7,8,0}};
This arrays goes into my generic DFS class, which works fine. I used it of other tasks correctly. But for the completeness here is the basic part of my DFS class:
private static boolean search(State node, State target) {
if (node.equals(target))
return true;
for (State neighbour : node.getNeighbours()) {
if (!visited.contains(neighbour)) {
predMap.put(neighbour,node);
visited.add(neighbour);
if (search(neighbour, target)){
return true;
}
}
}
return false;
}
So at first my start array will pass as the first parameter and my target array as the second.
In my Stateclass i want to implement the getNeighbours()method which should return all possibles states. In the first Round something like:
First:
|0|1|2|
|4|5|3|
|7|8|6|
Second (rotated zero):
|1|0|2|
|4|5|3|
|7|8|6|
etc...
And here is my problem. How can u do that? It works for the first 4 operations but then i get an exception (The zero or the empty field is not on the position as excepted or there are two zeros). What is wrong there?
#Override
public List<State> getNeighbours() {
List<State> neighbours = new LinkedList<>();
// possibles moves...
final int startX = (freeX - 1 < 0) ? freeX : freeX - 1;
final int startY = (freeY - 1 < 0) ? freeY : freeY - 1;
final int endX = (freeX + 1 > N - 1) ? freeX : freeX + 1;
final int endY = (freeY + 1 > N - 1) ? freeY : freeY + 1;
for (int row = startX; row <= endX; row++) {
for (int column = startY; column <= endY; column++) {
int tmp = board[row][column];
board[row][column] = board[freeX][freeY];
board[freeX][freeY] = tmp;
// Just show the table...
System.out.println("=== BEFORE ===");
for (int[] x : board) {
System.out.println(Arrays.toString(x));
}
neighbours.add(new State(board, freeX + row, freeY + column));
board[freeX][freeY] = board[row][column];
board[row][column] = tmp;
// Just show the table...
System.out.println("=== AFTER ===");
for (int[] x : board) {
System.out.println(Arrays.toString(x));
}
}
}
return neighbours;
}
complete code https://gist.github.com/T0bbes/66d36326aa8878d5961880ce370ba82d
I checked your code, the reason of get that exception is, the board array is shared by every state. You should make a deep copy of that array, and you can try this code:
public Board(int[][] board, int x, int y){
if (board[x][y]!=0)
throw new IllegalArgumentException("Field (" +x+","+y+") must be free (0).");
this.board = new int[board.length][board[0].length];
for (int i = 0; i < this.board.length; i++)
for (int j = 0; j < this.board[i].length; j++)
this.board[i][j] = board[i][j];
this.freeX = x;
this.freeY = y;
this.N = board.length;
}
But there are still some problems in your code:
DFS may recursion a lot and get a StackOverflow -- you should increase stack size(-Xss100m works for me). After increase stack size, your code can output a solution, but it takes 197144 steps...
Indeed, as you see, DFS output only a valid solution(if your code is correct), not optimal solution. You should try BFS.
I am creating a simple maze game in java. The code reads a data file and assigns it to a String array. The player inputs what direction he or she would like to go in and each position contains a certain number of points (0, 1, or 2) that corresponds to the obstacleNumber (0, 1, or 2). I want to keep track of the points as well as the number of times the player has moved but I cannot figure out where to call my methods to make sure that the counting is correct. I'm sorry if this is a really stupid question but I am new to java!
The array is being filled correctly but I cannot count the moves and points.
import java.util.*;
import java.io.File;
public class Program12
{
static public void main( String [ ] args ) throws Exception
{
if(args.length != 1) {
System.out.println("Error -- usage is: java Lab11 roomData.txt");
System.exit(0);
}
File newFile = new File(args[0]);
Scanner inputFile = new Scanner(newFile);
int numberOfRows = inputFile.nextInt();
int numberOfColumns = inputFile.nextInt();
Room[][] game;
game = new Room[numberOfRows][numberOfColumns];
int rowNumber = 0;
int columnNumber = 0;
int moves = 0;
int points = 0;
for(int i = 0; i < numberOfRows; i++)
{
for (int j = 0; j < numberOfColumns; j++)
{
String obstacle = inputFile.nextLine();
int obstacleNumber = inputFile.nextInt();
Room room = new Room(obstacle, obstacleNumber);
game[i][j] = room;
}
System.out.println();
countPoints(obstacleNumber, points);
}
while(true)
{
printPlayerLocation(numberOfRows, numberOfColumns, rowNumber, columnNumber);
System.out.println();
System.out.print("Enter up, down, left, or right to move: ");
Scanner userInput = new Scanner(System.in);
String in = userInput.nextLine();
if(in.equals("left") || in.equals("right") || in.equals("up") || in.equals("down"))
{
if (in.equalsIgnoreCase("up"))
{
rowNumber = rowNumber - 1;
}
if (in.equalsIgnoreCase("down"))
{
rowNumber = rowNumber + 1;
}
if (in.equalsIgnoreCase("left"))
{
columnNumber = columnNumber - 1;
}
if (in.equalsIgnoreCase("right"))
{
columnNumber = columnNumber + 1;
}
}
else
{
System.out.println("Input invalid! Please enter up, down, left, or right.");
}
try
{
System.out.println(game[columnNumber][rowNumber].toString());
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("You cannot leave the boardwalk during the hunt! Please start over.");
System.exit(0);
}
countMoves(in, moves);
//countPoints(obstacleNumber, points);
}
}
public static void printPlayerLocation(int numberOfRows, int numberOfColumns, int rowNumber, int columnNumber)
{
System.out.println();
System.out.print("***** PLAYER LOCATION *****");
String[][] game = new String[numberOfRows][numberOfColumns];
for (int i = 0; i < numberOfRows; i++)
{
for (int j = 0; j < numberOfColumns; j++)
{
game[i][j] = "*";
}
}
game[rowNumber][columnNumber] = "P";
for (int i = 0; i < numberOfRows; i++)
{
System.out.println();
for (int j = 0; j < numberOfColumns; j++)
{
System.out.printf("%-5s", game[i][j]);
}
}
System.out.println();
}
//doesn't correctly count the moves
public static void countMoves(String in, int moves)
{
if(in.equals("left") || in.equals("right") || in.equals("up") || in.equals("down"))
{
moves++;
}
System.out.println("You have used " + moves + " moves.");
}
//doesn't correctly count the points
public static void countPoints(int obstacleNumber, int points)
{
if(obstacleNumber == 0)
{
points = points;
}
if(obstacleNumber == 1)
{
points++;
}
if(obstacleNumber == 2)
{
points = points + 2;
}
System.out.println("You have obtained " + points + " points so far. Keep hunting!");
}
The data file has the size of the array (4 4) and an obstacleNumber and obstacle
0 this obstacleNumber would award 0 points
1 this obstacleNumber would award 1 point
2 this obstacleNumber would award 2 points
16 times to fill the array.
I would like the sample output to print the player location (which it does correctly), ask the user to input a direction (which it does correctly), print the text in the data file (again already done) and then print the number of moves already used and the amount of points the player has gained so far.
How do you correctly calculate the number of times the user typed "up, down, right, or left" and how many points does the user have so far? Thank you in advance for your help I sincerely appreciate your time.
The moves arent count right, because countMoves doesnt increment the Variable moves from the main function.
If you do :
System.out.println(moves);
countMoves(in, moves);
System.out.println(moves);
You will see that the value didnt changed.
So you could add a return value to countMoves and assingn moves with it :
moves = countMoves(in,moves);
Or you could increment the moves here :
if(in.equals("left") || in.equals("right") || in.equals("up") || in.equals("down"))
{
moves++;
if (in.equalsIgnoreCase("up"))
{
rowNumber = rowNumber - 1;
}
if (in.equalsIgnoreCase("down"))
{
rowNumber = rowNumber + 1;
}
if (in.equalsIgnoreCase("left"))
{ columnNumber = columnNumber - 1;
}
if (in.equalsIgnoreCase("right"))
{ columnNumber = columnNumber + 1;
}
}
The same with Points i think.
The line
points = points;
Would only make sense if you have a classvariable that would get the point value but assign a variable with its own value doenst make sense .
So maybe add a return to the countPoints and assign points with it :
points = countPoints(obstacleNumber, points);
In Java, arguments to methods are always passed by value. It can get confusing with objects though. But with primitive types like int it's very simple. To the functions countMoves and countPoints you are only giving the value of the moves and points, respectively, but not their reference. That is, the methods are working in fact with another variable. This variable is initialized to the value you give in and you can change it as you want, but the changes made to this variable are only visible to the method. Therefore in order to make the changes visibile to the outer variables you must reset their values. For instance you could do this:
public static int countMoves(String in, int moves) {
//... change the value of moves as you want
return moves; //return the new value
}
And then use the method like:
moves = countMoves(in, moves);
Where the set variable is the one you define in main. Analogously for countPoints. Another possibility would be to define moves and points in the class Program12 and make the methods count methods modify these variables directly without passing them, like:
public static void countMoves(String in) {
moves = ...
}
In this case the moves moves defined in Program12 is visible to the countMoves and so you are changing directly the variable you want; there is no need to reset it.
--
But big but. The code you have is rather spaghetti. You should think how to better structure and compartmentalize the code into closely-related logical units. In object-oriented programming you do it with classes. For example, you could define a class called GameState that keeps the variables moves and points or anything else shall you need it, and define there the count methods or other methods to modify the statistics of the game. Don't make the main method define the logic of the program. It should merely be used to read the input to initialize some sort of class Game and write to output the results of the Game.
I might be wrong here (early in the morning...) but I'm guessing you always get the same moves and points value? This is because you are not increasing the values of the actual moves and points. When you send an Int as a parameter to a method you are not sending a pointer to the Int but a copy of it which will be used by the method and then removed when leaving it. You need to either return moves and points after increasing the values or put them as static attributes. Try doing it this way instead:
...
moves = countMoves(String in, int moves);
...
public static int countMoves(String in, int moves) {
if(in.equals("left") || in.equals("right") || in.equals("up") || in.equals("down")) {
moves++;
}
System.out.println("You have used " + moves + " moves.");
return moves;
}
Or you could increase them when identifying the moving direction (which is more efficient since you don't have to redo the check if the move was valid):
if (in.equalsIgnoreCase("up")) {
rowNumber = rowNumber - 1;
moves++;
}
...
EDIT
Points Problem:
Since you didn't post how Room is implemented I just improvise, but I figure it should look something like this:
...
points = countPoints(game[rowNumber][columnNumber].getObstacleNumber(), points);
...
and change countPoints() to:
public static int countPoints(int obstacleNumber, int points) {
if(obstacleNumber == 0) points = points;
if(obstacleNumber == 1) points++;
if(obstacleNumber == 2) points += 2;
System.out.println("You have obtained " + points + " points so far. Keep hunting!");
return points;
}
or just (provided you know that the input is correct):
public static int countPoints(int obstacleNumber, int points) {
points += obstableNumber;
System.out.println("You have obtained " + points + " points so far. Keep hunting!");
return points;
}