I can't get the output to print, I've tried many diff. things to try and get it to print but it won't work. It's supposed to print error messages if I put in a negative # for height or edge. Also the output for valid #'s won't print either. I'm not sure where to put the block of code for that one. Can someone help me?
My Program: https://pastebin.com/D8FQv1yR
import java.util.Scanner;
/**
*The App for the Decagonal Prism program.
* #author Kathleen Tumlin - Fundamentals of Computing I - 1210
* #version 9/17/21
*/
public class DecagonalPrismApp {
//fields
String label = "";
double edge = 0;
double height = 0;
double edgeIn = 0;
double heightIn = 0;
// constuctor
/** Shows public decagonal prism, setLabel, and setEdge.
* #param labelIn takes input for label in the constructor.
* #param edgeIn takes input for the edge in the constructor.
*/
public DecagonalPrismApp(String labelIn, double edgeIn, double heightIn) {
setLabel(labelIn);
setEdge(edgeIn);
setHeight(heightIn);
}
//methods
/** Shows the return for label variable.
* #return returns the label variable.
*/
public String getLabel() {
return label;
}
/** Shows the set label.
* #param labelIn takes the labelIn for the method.
* #return returns the boolean if the variable was set.
*/
public boolean setLabel(String labelIn) {
if (labelIn != null) {
label = labelIn.trim();
return true;
} else {
return false;
}
}
/** Shows the return for the edge variable.
* #return returns the value for the variable edge.
*/
public double getEdge() {
return edge;
}
/** Shows the set edge.
* #param edgeIn takes the edgein and sets it as the edge variable.
* #return returns the boolean if the variable was set.
*/
public boolean setEdge(double edgeIn) {
if (edgeIn > -1) {
edge = edgeIn;
return true;
}
else {
System.out.println("Error: edge must be non-negative.");
return false;
}
}
/** Shows the return for the height variable.
*#return returns the value for the variable edge.
*/
public double getHeight() {
return height;
}
/** Shows the set height.
* #param heightIn takes the heightin and sets it as the height variable.
* #return returns the boolean if the variable was set.
*/
public boolean setHeight(double heightIn) {
if (heightIn > -1) {
height = heightIn;
return true;
}
else {
System.out.println("Error: height must be non-negative.");
return false;
}
}
public void start() {
do {
System.out.print("Error: height must be non-negative." );
} while (heightIn > -1);
do {
System.out.print("Error: edge must be non-negative." );
} while (edgeIn > -1);
}
public static void main(String[] args) {
/**
*Shows what prints.
* #param args not used.
*/
Scanner scan = new Scanner(System.in);
System.out.println("Enter label, edge, and height length for a "
+ "decagonal prism.");
System.out.print("\tlabel: ");
String label = scan.nextLine();
System.out.print("\tedge: ");
double edge = scan.nextDouble();
System.out.print("\theight: ");
double height = scan.nextDouble();
}
}
Valid #'s code: https://pastebin.com/DPuSpMEq
public String toString() {
DecimalFormat fmt = new DecimalFormat("#,##0.0##");
return "A decagonal prism \"" + label
+ "with edge = " + edge + " units.\n\t"
+ "and height = " + height + " units.\n\t has:"
+ "surface area = " + fmt.format(surfaceArea()) + " square units\n\t"
+ "base area = " + fmt.format(baseArea()) + " square units \n\t"
+ "lateral surface area = "
+ fmt.format(lateralSurfaceArea()) + " square units\n\t"
+ "volume = " + fmt.format(volume()) + " cubic units \n\t";
I am trying to create a program that when given the location of a chess knight and the destination, all marked in chess notation, to return the number of moves it takes the knight to get from the location the destination. I have tried before using the algorithm to calculate every single possibility on a list, but it is very slow and kind of has problems. Here is my code:
private static int translateChessNotation(String chess) {
int returned = 8 * (Integer.valueOf(String.valueOf(chess.charAt(1)))- 1);
return returned + (convertAlphabet(chess.charAt(0))); // File
}
public static int knight(String start, String finish) {
int knightPosition = translateChessNotation(start), end = translateChessNotation(finish), i = 0;
ArrayList<Integer> currentPossibleKnightPositions = new ArrayList<>();
currentPossibleKnightPositions.add(knightPosition);
for (; i < 8; i++) {
ArrayList<Integer> newList = new ArrayList<>();
for (int position : currentPossibleKnightPositions) {
newList.add(position + 17);
newList.add(position + 15);
newList.add(position + 10);
newList.add(position + 6);
newList.add(position - 6);
newList.add(position - 10);
newList.add(position - 15);
newList.add(position - 17);
}
ArrayList<Integer> removed = new ArrayList<>();
for (int j : newList) {if (j < 1 || j > 64) {removed.add(j);}}
newList.removeAll(removed);
currentPossibleKnightPositions.clear();
currentPossibleKnightPositions.addAll(newList);
for (int n : currentPossibleKnightPositions) {
if (n == end) {return i + 1;}
}
}
return -1;
}
Thanks a lot if you help!
Here's a little Proggy to solve the so-called Knights-Tour problem, visiting all squares on the board starting from a particular location, so you could adapt that to set a particular to-position as your end-condition.
Its just Brute-Force, trying all possible combinations & takes about 50 minutes to find each full Knights-Tour solution.
If that helps, I'd be honoured to receive your vote.
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
public class KnightMove {
#SuppressWarnings("serial")
private static final class KnightMoveSolvedException extends RuntimeException {
private final byte[][] solution;
private KnightMoveSolvedException(final byte[][] solution) {
this.solution = solution;
}
}
private static final int SIZE_X = 8;
private static final int SIZE_Y = 8;
private static final int SIZE_X_Y = SIZE_X * SIZE_Y; // Max 127! (=0x7F)
private static final int [][] KNIGHT_MOVES = new int[8][];
/**/ static {
final AtomicInteger moveIndex = new AtomicInteger();
IntStream.of(2, -2).forEach(deltaX ->
IntStream.of(1, -1).forEach(deltaY -> {
/*
* Mirror the 4 combinations above to get all 8 possible Knight moves...
*/
KNIGHT_MOVES[moveIndex.getAndIncrement()] = new int[] {deltaX, deltaY};
KNIGHT_MOVES[moveIndex.getAndIncrement()] = new int[] {deltaY, deltaX};
}));
}
private static void nextMoveToXY(int moveCount, final int x, final int y, final byte[][] board) {
moveCount++;
board[x][y] = (byte) moveCount;
if (moveCount >= SIZE_X_Y) {
System.out.println("Solved!.....: count=" + moveCount);
for ( final byte[] column : board ) {
for (final byte square : column) {
System.out.print(square + "\t");
}
System.out.println();
}
return; // (Back up & keep looking for next solution)
/*
* If 1 solution is enough, just throw the Exception...
*/
// throw new KnightMoveSolvedException(board);
}
for (final int[] knightMove : KNIGHT_MOVES) {
final int newX = x + knightMove[0]; if (newX < 0 || newX >= SIZE_X) {continue;}
final int newY = y + knightMove[1]; if (newY < 0 || newY >= SIZE_Y) {continue;}
if (board[newX][newY] == 0) {
/*
* Target Square is vacant, so try this move recursively...
*/
nextMoveToXY(moveCount, newX, newY, deepPrimitive2DArrayClone(board));
}
}
}
/**
* {#link Object#clone()} can create a Deep Clone of a 1D array of Primitives
* but will <b>not</b> deliver the desired result with 2D,
* so we have to wrap the rest by hand...
*/
private static byte[][] deepPrimitive2DArrayClone(final byte[][] source) {
final byte[][] clone = new byte[source.length][];
/**/ int cix = 0;
for (final byte[] col : source) {
clone[cix++] = col.clone();
}
return clone;
}
public static void main(final String[] args) throws Exception {
IntStream.range(0, SIZE_X).forEach(x ->
IntStream.range(0, SIZE_Y).forEach(y -> {
try {
System.out.println("Solve starting at X/Y.: " + x +"/" + y);
nextMoveToXY(0, x, y, new byte[SIZE_X][SIZE_Y]);
}
catch (final KnightMoveSolvedException e) {
System.out.println(e.solution);
}
}));
}
}
I got this answer online. Hope this helps to the others who have the same question!
public static int knight(String...pos) {
int[][] ab=Stream.of(pos).map(s->new int[]{"abcdefgh".indexOf(s.charAt(0)),s.charAt(1)-48}).toArray(int[][]::new);
int[] dxy=IntStream.range(0,2).map(i->Math.abs(ab[0][i]-ab[1][i])).sorted().toArray();
if(dxy[0]==0&&dxy[1]==1) return 3;
if(dxy[0]==2&&dxy[1]==2||dxy[0]==1&&dxy[1]==1&&(pos[0]+pos[1]).matches(".*?(a1|h1|a8|h8).*")) return 4;
int delta=dxy[1]-dxy[0];
return delta-2*(int)Math.floor(1.0*(delta-dxy[0])/(dxy[0]>delta?3:4));
}
I've replaced the Chessboard Array in the previous Posting with a long.
(with 64 bits, its just large enough to represent the board)
The new Version is significantly faster.
Depending on starting-coordinates, a solution takes anywhere between 1 Minute & 12 Hours...
(I've put a couple of the faster ones first)
This example is designed to show the basics. There are various Mathematical Methods (see Wikipedia) to optimise it, but they make the Solution more complex.
A couple of Takeaways:
- use Primitives (byte, short, int, long,...) if you can: they are very fast
- avoid Objects like ArrayList when using Brute-Force: they are very slow
- use recursion: it saves & restores State for you. It may cost a little, but it makes life so much easier
- use final whenever you can: it's no faster, but aids understanding
Hope you like it. :-)
I've honed this thing down now. It is massively faster than the original (which was no slouch!), uses the Warnsdorff algorithm & can solve multiple starting positions, running on all available Threads simultaneously.
Most of the work is getting the Data Structures right & Initialisation.
The recursive nextMoveToXY solver Method itself is trivially simple.
The Warnsdorff Version:
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;
public class KnightsTourWarnsdorff {
private interface IntIntConsumer {
void accept(int t, int u);
}
private static final int MAX_INSTANT_TO_STRING_LENGTH = "2020-12-31T23:59:59.123456Z".length();
private static final int SIZE_X = 8;
private static final int SIZE_Y = 8;
private static final int SIZE_X_Y = SIZE_X * SIZE_Y;
/**/ static { check_SIZE_X_Y_withinCapacity();}
/**
* Do this in a Method (we don't want to mark the Class with SuppressWarnings)
*/
#SuppressWarnings("unused")
private static void check_SIZE_X_Y_withinCapacity() {
if (SIZE_X_Y > Long.SIZE) {
throw new UnsupportedOperationException("Number of squares on board exceeds capacity of long Solution");
}
}
/**
* Returns the unique offset corresponding to a Move or our position on the Board.
*/
private static int getDeltaXY(final int deltaX, final int deltaY) {
return deltaX + deltaY * SIZE_X; /* Yes, SIZE_X ! */
}
/**
* Returns a long with a single bit set, corresponding to our position on the Board.
*/
private static long getXYmaskBit(final int x, final int y) {
return 1L << (63 - getDeltaXY(x, y));
}
private static void walkBoard(final IntIntConsumer doXY) {
walkBoard(null, doXY, null);
}
private static void walkBoard(final IntConsumer doRowStart, final IntIntConsumer doXY, final Runnable doRowEnd) {
IntStream .range(0, SIZE_Y).forEach(y -> {if (doRowStart != null) {doRowStart.accept( y);}
IntStream.range(0, SIZE_X).forEach(x -> {if (doXY != null) {doXY .accept(x,y);}
}); if (doRowEnd != null) {doRowEnd .run ( );}
});
}
private static String toBinary(final long value) {
return leftPad(Long.SIZE, Long.toBinaryString(value)).replace('0', '_');
}
private static String leftPad (final int paddedLength, final String value) {
final int padCount = Math.max(0, paddedLength - value.length());
final char[] pad = new char[padCount];
Arrays.fill (pad, '0');
return String.valueOf(pad).concat(value);
}
private static String rightPad (final int paddedLength, final String value) {
final int padCount = Math.max(0, paddedLength - value.length());
final char[] pad = new char[padCount];
Arrays.fill (pad, '0');
return value.concat(String.valueOf(pad));
}
private static String header () {
return rightPad (MAX_INSTANT_TO_STRING_LENGTH, Instant.now().toString()) + " " + Thread.currentThread().getName() + " ";
}
/**
* Square on Board not only knows its x/y location, but also its position as an xyMask<br>
* (for checking whether a square is occupied & marking as occupied).<br>
* <br>
* It knows all possible Moves from this Square within the Board<br>
* (thus obviating the need to check whether we're still on the Board).<br>
* <br>
* Each Specific Move contains a reference to the Target Square, which in turn...<br>
* (these 2 measures speed up Navigation massively)
*/
private static final class Square {
private final int x;
private final int y;
/**
* Used to mark the Square as occupied on the Board
*/
private final long xyMask;
/**
* All possible Moves from this Square.<br>
* (initially all null: filled after all Squares have been instantiated)
*/
private final Move[] targetMove;
private Square(final int x, final int y) {
this.x = x;
this. y = y;
this.xyMask = getXYmaskBit(x, y);
this.targetMove = KNIGHT_MOVE_MAP.values().stream().filter(move -> {
final int newX = x + move.deltaX;
final int newY = y + move.deltaY;
return newX >= 0 && newX < SIZE_X
&& newY >= 0 && newY < SIZE_Y;
}).toArray(Move[]::new);
}
}
/**
* Either a Generic or a Specific Move
*/
private static final class Move {
private final int deltaX;
private final int deltaY;
private final int deltaXY;
private final Square target;
/**
* Create a Generic Move
*/
private Move(final int deltaX, final int deltaY) {
this.deltaX = deltaX;
this.deltaY = deltaY;
this.deltaXY = getDeltaXY(deltaX, deltaY);
this.target = null;
}
/**
* Create a Move to a specific Target Square
*/
private Move(final Move genericMove, final Square target) {
this.deltaX = genericMove.deltaX;
this.deltaY = genericMove.deltaY;
this.deltaXY = genericMove.deltaXY;
this.target = target;
}
}
#SuppressWarnings("serial")
private static final class KnightMoveSolvedException extends RuntimeException {
private final int[] solution;
private KnightMoveSolvedException(final int moveCount, final int[] solution) {
/*
* Trim the solution array down to the number of moves...
* (for those performing a partial walk)
*/
this.solution = Arrays.stream(solution).limit(moveCount).toArray();
synchronized (KnightMoveSolvedException.class) { // One Thread (= Solution) at a time please!
final int solution0 = this.solution[0];
final Move initialMove = BOARD_MAP.get(solution0);
final int initialX = initialMove.deltaX;
final int initialY = initialMove.deltaY;
System.out.println(header() + "Solution found for....: x/y: " + initialX + "/" + initialY + " \t" + toBinary(0L) + " \tlength=" + this.solution.length + " \t" + solution0);
this.printSolutionDetail();
}
}
private void printSolutionDetail() {
int x = 0;
int y = 0;
long board = 0;
for (int i=0; i < this.solution.length; i++) {
final int positionOrMove = this.solution[i];
final Move move = i == 0 ? BOARD_MAP.get(positionOrMove) : KNIGHT_MOVE_MAP.get(positionOrMove);
/**/ x = i == 0 ? move.deltaX : x + move.deltaX;
/**/ y = i == 0 ? move.deltaY : y + move.deltaY;
board |= getXYmaskBit(x, y);
System.out.println(header() + "Solution walk.........: x/y: " + x + "/" + y + " \t" + toBinary(board) + " \t" + move.deltaX + "\t" + move.deltaY + "\t" + positionOrMove);
}
}
}
private static final Map<Integer, Move> KNIGHT_MOVE_MAP;
/**/ static {
final Map<Integer, Move> Knight_Move_Map = new TreeMap<>();
IntStream.of(2, -2).forEach(deltaX ->
IntStream.of(1, -1).forEach(deltaY -> {
/*
* Mirror the 4 combinations above to get all 8 possible Knight moves...
*/
{final Move move = new Move(deltaX, deltaY); Knight_Move_Map.put(move.deltaXY, move);}
{final Move move = new Move(deltaY, deltaX); Knight_Move_Map.put(move.deltaXY, move);}
}));
KNIGHT_MOVE_MAP = Collections.unmodifiableMap(Knight_Move_Map);
}
private static final Map<Integer, Move> BOARD_MAP;
/**/ static {
final Map<Integer, Move> Board_Map = new TreeMap<>();
walkBoard((x,y) -> {
final Move move = new Move(x, y);
Board_Map.put(move.deltaXY, move);
});
BOARD_MAP = Collections.unmodifiableMap(Board_Map);
}
private static final Square[][] BOARD = new Square[SIZE_X] [SIZE_Y];
/**/ static {
/*
* Fill the Board with Squares...
*/
walkBoard( (x,y) -> BOARD[x][y] = new Square(x, y));
/**/ System.out.println("Onward Target Count:");
walkBoard( ( y) -> { System.out.print ( y + " : ");},
/**/ (x,y) -> {final Square square = BOARD[x][y]; System.out.print (square.targetMove.length + " ");},
/**/ ( ) -> { System.out.println() ;} );
/*
* So far the Target Moves array is filled with nulls. We MUST fill it...
*/
Arrays.stream(BOARD).flatMap(Arrays::stream).forEach(square -> {
final Move[] targetsSortedByOnwardPointCount = Arrays
.stream(square.targetMove)
.sorted((moveA, moveB) -> {
/*
* We use the Warnsdorff algorithm to sort it by the number of Onward Targets...
*/
final Square targetA = BOARD[square.x + moveA.deltaX] [square.y + moveA.deltaY];
final Square targetB = BOARD[square.x + moveB.deltaX] [square.y + moveB.deltaY];
return Integer.compare(
targetA.targetMove.length, // number of Onward Targets
targetB.targetMove.length); // number of Onward Targets
})
.map(move -> new Move(move, BOARD[square.x + move.deltaX] [square.y + move.deltaY]))
.toArray(Move[]::new);
/*
* Original & sorted arrays should be the same length if we got it right,
* so take max. length as a precaution to force an IndexOutOfBoundsException if we didn't...
*/
final int copyLength = Math.max(square.targetMove.length, targetsSortedByOnwardPointCount.length);
/*
* Overwrite the original Moves with the sorted version...
*/
System.arraycopy(targetsSortedByOnwardPointCount, 0, square.targetMove, 0, copyLength);
});
}
private final int[] SOLUTION = new int[SIZE_X_Y];
private void solve(final int initialX, final int initialY) {
final long initialBoard = getXYmaskBit(initialX, initialY);
System.out.println(header() + "Solve starting at.....: x/y: " + initialX +"/" + initialY + "\t" + toBinary(initialBoard));
try {
SOLUTION [0] = getDeltaXY(initialX, initialY); // First Entry contains Starting-Point
nextMoveToXY(0, BOARD[initialX][initialY], initialBoard);
}
catch (final KnightMoveSolvedException justIgnore_WereDone) {}
}
private void nextMoveToXY(int moveCount, final Square square, final long board) {
moveCount++;
if (moveCount >= SIZE_X_Y) {
final KnightMoveSolvedException solution = new KnightMoveSolvedException(moveCount, SOLUTION);
// return; // (Back up & keep looking for next solution)
/*
* If 1 solution is enough, just throw the Exception...
*/
throw solution;
}
for (final Move move : square.targetMove) {
/*
* Is Target Square vacant? (i.e. Mask Bit not set)...
*/
if ((board & move.target.xyMask) == 0) {
/*
* Yes: try next move recursively with new Position & Board...
*/
SOLUTION [moveCount] = move.deltaXY;
nextMoveToXY(moveCount, move.target, board | move.target.xyMask /* Set Mask Bit on new Board */);
}
}
}
public static void main(final String[] args) throws Exception {
final ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
/*
* We can handle rectangular boards, but for square boards the following holds:
* we only need to solve for 1/8 of the board (a triangle)...
* (the remaining 7/8 are either Mirrors or Rotations of the 1/8)
*/
IntStream .range(0, SIZE_X / 2).forEach(x -> {
IntStream.range(0, x + 1 ).forEach(y -> {
pool.submit(() -> {
try { TimeUnit.SECONDS.sleep(1); } catch (final InterruptedException e) {}
/*
* (Sleep very briefly, so our Thread won't start before the Output below has finished)
*/
new KnightsTourWarnsdorff().solve(x, y);
});
System.out.print("x=" + x + " y=" + y + "\t");
});
System.out.println();
});
pool.shutdown();
}
}
Original Version:
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
public class KnightsTour {
#SuppressWarnings("serial")
private static final class KnightMoveSolvedException extends RuntimeException {
private final int[][] solution;
private KnightMoveSolvedException(final int[][] solution) {
this.solution = deepPrimitive2DArrayClone (solution);
}
}
private static final int SIZE_X = 8;
private static final int SIZE_Y = 8;
private static final int SIZE_X_Y = SIZE_X * SIZE_Y;
private static final int[][] SOLUTION = new int[SIZE_X_Y][];
private static final int INDEX_X = 0;
private static final int INDEX_Y = 1;
private static final int KNIGHT_MOVES_LENGTH = 8;
private static final int [][] KNIGHT_MOVES = new int[KNIGHT_MOVES_LENGTH][];
/**/ static {
checkLongSolutionCapacity();
final AtomicInteger moveIndex = new AtomicInteger();
IntStream.of(2, -2).forEach(deltaX ->
IntStream.of(1, -1).forEach(deltaY -> {
/*
* Mirror the 4 combinations above to get all 8 possible Knight moves...
*/
KNIGHT_MOVES[moveIndex.getAndIncrement()] = new int[] {deltaX, deltaY};
KNIGHT_MOVES[moveIndex.getAndIncrement()] = new int[] {deltaY, deltaX};
}));
}
#SuppressWarnings("unused")
private static void checkLongSolutionCapacity() {
if (SIZE_X_Y > Long.SIZE) {
throw new UnsupportedOperationException("Number of squares on board exceeds capacity of long Solution");
}
}
private static long getXYmaskBit(final int x, final int y) {
return Long.MIN_VALUE >>> (x + y * SIZE_X /* Yes, SIZE-X ! */);
}
public static void solve(final int initialX, final int initialY) {
final long initialBoard = getXYmaskBit(initialX, initialY);
System.out.println("Solve starting at X/Y.: " + initialX +"/" + initialY + "\t" + toBinary(initialBoard));
try {
SOLUTION [0] = new int[] {initialX, initialY}; // First Entry contains Starting-Point
nextMoveToXY(0, initialX, initialY, initialBoard);
}
catch (final KnightMoveSolvedException e) {
System.out.println("One possible solution.: " + e.solution);
}
}
private static void nextMoveToXY(int moveCount, final int x, final int y, final long board) {
moveCount++;
if (moveCount >= SIZE_X_Y) {
System.out.println("Solved!...............: count=" + moveCount);
/*
* Print the answer or remember it somewhere...
*/
final int initialX = SOLUTION[0][INDEX_X];
final int initialY = SOLUTION[0][INDEX_Y];
for(final int[] move : SOLUTION) {
final int solutionX = move[INDEX_X];
final int solutionY = move[INDEX_Y];
System.out.println("Move (starting at X/Y): " + initialX +"/" + initialY + "\t" + toBinary(board) + "\t" + solutionX + "\t" + solutionY);
}
// return; // (Back up & keep looking for next solution)
/*
* If 1 solution is enough, just throw the Exception...
*/
throw new KnightMoveSolvedException(SOLUTION);
}
for(final int[] move : KNIGHT_MOVES) {
final int deltaX = move[INDEX_X]; final int newX = x + deltaX; if (newX < 0 || newX >= SIZE_X) {continue;}
final int deltaY = move[INDEX_Y]; final int newY = y + deltaY; if (newY < 0 || newY >= SIZE_Y) {continue;}
/*
* ok: Checks above mean we're on the board, so lets find the new Position Mask...
*/
final long newXYmaskBit = getXYmaskBit(newX, newY);
/*
* Is Target Square vacant (= Mask Bit not set)?...
*/
if ((board & newXYmaskBit) == 0) {
/*
* Yes: try next move recursively with new Position & Board...
*/
SOLUTION [moveCount] = move;
nextMoveToXY(moveCount, newX, newY, board | newXYmaskBit /* Set Mask Bit on new Board */);
}
}
}
public static String toHex (final int value) {
return leftPad(Integer.BYTES * 2, Integer.toHexString (value));
}
public static String toHex (final long value) {
return leftPad(Long .BYTES * 2, Long .toHexString (value));
}
public static String toBinary(final int value) {
return leftPad(Integer.SIZE, Integer.toBinaryString(value));
}
public static String toBinary(final long value) {
return leftPad(Long .SIZE, Long .toBinaryString(value));
}
private static String leftPad (final int paddedLength, final String binaryOrHex) {
final char[] lead = new char[paddedLength - binaryOrHex.length()];
Arrays.fill (lead, '0');
return String.valueOf(lead).concat(binaryOrHex).replace('0', '_');
}
/**
* {#link Object#clone()} can create a Deep Clone of a 1D array of Primitives
* but with 2D will only provide a Shallow Copy (meaning if the content of source
* changes, the content of clone will change!!) so we have to wrap 2D by hand...
*/
private static int[][] deepPrimitive2DArrayClone(final int[][] source) {
final int[][] clone = new int[source.length][];
/**/ int cix = 0;
for (final int[] col : source) {
clone[cix++] = col.clone(); // (ok: 1D, so Deep Clone)
}
return clone;
}
public static void main(final String[] args) throws Exception {
solve(0, 1); // Fast!: 2 Minutes
solve(0, 3); // Fast!: 1 Minute
IntStream.range(0, SIZE_X).forEach(x ->
IntStream.range(0, SIZE_Y).forEach(y -> {
solve(x, y);
}));
}
}
I am currently working on a program where I take information from a text document, then I print it out into another file and from java but halfway through, i'm getting an no such exception error and i'm not sure why.
Tester code:
import java.util.ArrayList;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
public class HurricaneSelectorTester
{
public static void main (String [ ] args) throws IOException
{
//File scanner
File fileName = new File("HurricaneData.txt");
Scanner inFile = new Scanner(fileName);
PrintWriter outputFile = new PrintWriter(new File("OutputData.txt"));
Scanner in;
in = new Scanner(System.in);
//construct a Scanner object with one line
//Declare variables
int arrayLength = 156;
int [] years = new int[156];
int index = 0;
int cat1 = 0;
int cat2 = 0;
int cat3 = 0;
int cat4 = 0;
int cat5 = 0;
double windAvg = 0;
double windTotal = 0;
double windMax = Integer.MIN_VALUE;
double windMin = Integer.MAX_VALUE;
double pressureAvg = 0;
double pressureTotal = 0;
int pressureMax = Integer.MIN_VALUE;
int pressureMin = Integer.MAX_VALUE;
double catAvg = 0;
double catTotal = 0;
int catMax = Integer.MIN_VALUE;
int catMin = Integer.MAX_VALUE;
int rangeMax = 0;
int rangeMin = 0;
//Ask for range
System.out.println("Please enter minimum year (1995-2015)");
rangeMin = in.nextInt();
System.out.println("Please enter maximum year (1995-2015)");
rangeMax = in.nextInt();
//Print title info
System.out.println("Hurricanes "+ ""+ rangeMin + "-" + "" + rangeMax);
System.out.println();
System.out.println("Year Hurricane Category Pressure (mb) Wind Speed (mph)");
System.out.println("****************************************************************");
ArrayList<HurricaneSelector> hurricanes = new ArrayList<HurricaneSelector>();
//Load all the info into the arrays
while (inFile.hasNext())
{
hurricanes.add(new HurricaneSelector(inFile.nextInt(),inFile.next(),inFile.nextInt(),inFile.nextInt(),inFile.next()));
}
for(index = 0; index < 156; index++){
years[index] = inFile.nextInt();
}
inFile.close();
HurricaneSelector dataRecord; //Data record for HurricaneSelector
for(index = 0; index < 156; index++)
{if(years[index]>= rangeMin && years[index]<= rangeMax){
dataRecord = hurricanes.get(index);
dataRecord.calcCategoriesAndTotals();
dataRecord.calcNewWind();
dataRecord.calcWindMax();
dataRecord.calcWindMin();
dataRecord.calcPressureMax();
dataRecord.calcPressureMin();
dataRecord.calcCategoryMax();
dataRecord.calcCategoryMin();
}
}
dataRecord = hurricanes.get(index);
dataRecord.calcWindAverage();
dataRecord.calcCategoryAverage();
dataRecord.calcPressureAverage();
//Print out data
outputFile.println("Year Name Category Pressure Wind Speed");
for (index = 0; index < 156; index++){
if(years[index]>= rangeMin && years[index]<= rangeMax){
System.out.println(" "+hurricanes.get(index));
System.out.println();
outputFile.println(" "+hurricanes.get(index));
}
}
outputFile.close();
System.out.println("****************************************************************");
System.out.print(" Average:");
System.out.printf("%15.1f%13.1f%20.2f",catAvg,pressureAvg,windAvg);
System.out.println();
System.out.print(" Maximum:");
System.out.printf("%15d%13d%20.2f",catMax , pressureMax , windMax);
System.out.println();
System.out.print(" Minimum:");
System.out.printf("%15d%13d%20.2f",catMin , pressureMin , windMin);
System.out.println();
System.out.println();
System.out.println("Summary of categories");
System.out.println(" Category 1: " + cat1);
System.out.println(" Category 2: " + cat2);
System.out.println(" Category 3: " + cat3);
System.out.println(" Category 4: " + cat4);
System.out.println(" Category 5: " + cat5);
}
Methods:
public class HurricaneSelector
{
private int myYear, myPressure, myWind, myRangeMin, myRangeMax, myCategory, category1, category2,category3, category4, category5;
private String myMonth, myName;
private double myNewWind;
public double myWindAverage, myPressureAverage, myCategoryAverage, myWindMax = Integer.MIN_VALUE,
myWindMin = Integer.MAX_VALUE, myPressureMax = Integer.MIN_VALUE, myPressureMin = Integer.MAX_VALUE,
myCatMax = Integer.MIN_VALUE,myCatMin = Integer.MAX_VALUE;
public int total;
/**
* Constructor for objects of type HurricaneSelector
* #param year is the year of the hurricane
* #param month is the month of the hurricane
* #param pressure is the pressure of the hurricane
* #param wind is the wind speed of the hurricane
* #param name is the name of the hurricane
*/
HurricaneSelector(int year, String month, int pressure, int wind, String name)
{
myYear = year;
myMonth = month;
myPressure = pressure;
myWind = wind;
myName = name;
}
/**
* Mutator method to calculate the wind speed in mph (no parameters)
*/
public void calcNewWind()
{
myNewWind = (myWind* 1.15);
}
/**
* Mutator method to calculate if the value is the new Maximum (no parameters)
*/
public void calcWindMax()
{
if (myNewWind > myWindMax){
myWindMax = myNewWind;
}
}
/**
* Mutator method to calculate if the value is the new Minimum (no parameters)
*/
public void calcWindMin()
{
if (myNewWind > myWindMin){
myWindMin = myNewWind;
}
}
/**
* Mutator method to calculate if the value is the new Maximum (no parameters)
*/
public void calcPressureMax()
{
if (myPressure > myPressureMax){
myPressureMax = myPressure;
}
}
/**
* Mutator method to calculate if the value is the new Minimum (no parameters)
*/
public void calcPressureMin()
{
if (myPressure > myPressureMin){
myPressureMin = myPressure;
}
}
/**
* Mutator method to calculate if the value is the new Maximum (no parameters)
*/
public void calcCategoryMax()
{
if (myCategory > myCatMax){
myCatMax = myCategory;
}
}
/**
* Mutator method to calculate if the value is the new Minimum (no parameters)
*/
public void calcCategoryMin()
{
if (myCategory > myCatMin){
myCatMin = myCategory;
}
}
/**
* Mutator method to calculate which category the Hurricane fits into and get the totals(no parameters)
*/
public void calcCategoriesAndTotals()
{
myWindAverage += myNewWind;
myPressureAverage += myPressure;
if (myNewWind > 74 && myNewWind < 95)
{
myCategory = 1;
myCategoryAverage += myCategory;
category1++;
}
else if(myNewWind > 96 && myNewWind < 110)
{
myCategory = 2;
myCategoryAverage += myCategory;
category2++;
}
else if(myNewWind > 111 && myNewWind < 129)
{
myCategory = 3;
myCategoryAverage += myCategory;
category3++;
}
else if(myNewWind > 130 && myNewWind < 156)
{
myCategory = 4;
myCategoryAverage += myCategory;
category4++;
}
else if(myNewWind > 157)
{
myCategory = 5;
myCategoryAverage += myCategory;
category5++;
}
total++;
}
/**
* Mutator method to calculate the wind speed average (no parameters)
*/
public void calcWindAverage()
{
myWindAverage = myWindAverage/total;
}
/**
* Mutator method to calculate the category average (no parameters)
*/
public void calcCategoryAverage()
{
myCategoryAverage = myCategoryAverage/total;
}
/**
* Mutator method to calculate the pressure average (no parameters)
*/
public void calcPressureAverage()
{
myPressureAverage = myPressureAverage/total;
}
/**
* Getter method to return the year of the hurricane (no parameters)
*/
public int getYear()
{
return myYear;
}
/**
* Getter method to return the month of the hurricane (no parameters)
*/
public String getMonth()
{
return myMonth;
}
/**
* Getter method to return the pressure of the hurricane (no parameters)
*/
public int getPressure()
{
return myPressure;
}
/**
* Getter method to return the wind speed of the hurricane (no parameters)
*/
public double getNewWind()
{
return myNewWind;
}
/**
* Getter method to return the name of the hurricane (no parameters)
*/
public String getName()
{
return myName;
}
/**
* Getter method to return the wind average (no parameters)
*/
public Double getWindAverage()
{
return myWindAverage;
}
/**
* Getter method to return the pressure average (no parameters)
*/
public Double getPressureAverage()
{
return myPressureAverage;
}
/**
* Getter method to return the category average (no parameters)
*/
public Double getCategoryAverage()
{
return myCategoryAverage;
}
/**
* Getter method to return the category maximum (no parameters)
*/
public Double getWindMax()
{
return myWindMax;
}
/**
* Getter method to return the category minimum (no parameters)
*/
public Double getWindMin()
{
return myWindMin;
}
/**
* Getter method to return the category maximum (no parameters)
*/
public Double getPressureMax()
{
return myPressureMax;
}
/**
* Getter method to return the category minimum (no parameters)
*/
public Double getPressureMin()
{
return myPressureMin;
}
/**
* Getter method to return the category maximum (no parameters)
*/
public Double getCategoryMax()
{
return myCatMax;
}
/**
* Getter method to return the category minimum (no parameters)
*/
public Double getCategoryMin()
{
return myCatMax;
}
public String toString(){
return String.format("%10d%10s%10d%10d%10.2f",myYear,myName, myCategory, myPressure, myNewWind);
}
The links to the text files: https://drive.google.com/file/d/1eazHCEwT0Se6hfx2SDilqCqY8ZMi4E9k/view?usp=sharing
https://drive.google.com/file/d/1CN0JnlbMWNEB7B4nomgJ_-6mkwR1wgYc/view?usp=sharing
I know there are other problems with the code such as useless variables, formatting, etc. but right now I need to fix the program so that it can actually run and print out most of the data right now.
You need to reset() the Scanner because you've reached the end in your loop, and you want to start from the beginning for the next set of operations.
From JavaSE docs:
public int nextInt()
Scans the next token of the input as an int.
An invocation of this method of the form nextInt() behaves in exactly the same way as the invocation nextInt(radix), where radix is the default radix of this scanner.
Returns:
the int scanned from the input
Throws:
InputMismatchException - if the next token does not match the Integer regular expression, or is out of range
NoSuchElementException - if input is exhausted
IllegalStateException - if this scanner is closed
I get the following error when compiling my java implementation of a Sokoban game:
<<< Process finished. (Exit code 1) javac Sokobantest.java Process
started >>> .\Level.java:44: error: expected myPlayer =
new Player(this.room);
^ .\Level.java:44: error: cannot find symbol myPlayer = new Player(this.room); ^ symbol: class myPlayer location: class
Level Sokobantest.java:43: error: cannot find symbol Level myLevel =
new Level(this.room);
Here is my code so far:
Sokobantest.java
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
/**
* This class is the second part for the Sokoban game
*
* #author Jane Doe 1234567 Group 42h
* #author John Doe 1234567 Group 42h
*/
class Sokobantest {
private final static int X = 0;
private final static int Y = 1;
private final static char WALL = '#';
private final static char PLAYER = '#';
private final static char BOX = '$';
private final static char GOAL = '.';
private final static char PLAYER_ON_GOAL = '+';
private final static char BOX_ON_GOAL = '*';
private final static char FREE = ' ';
private final static int[] UP = {0, -1};
private final static int[] DOWN = {0, 1};
private final static int[] LEFT = {-1, 0};
private final static int[] RIGHT = {1, 0};
//private static char[][] room;
private static int freeBox;
private static int emptyGoal;
private static int[] size = {-1, 0};
private static int[] player;
Level myLevel = new Level();
myLevel = new Level(this.room);
/**
* Function for vector addition
*
* #param first first vector
* #param second second vector
* #return new vector = first + second
*/
private static int[] add(int[] first, int[] second) {
return new int[]{first[X] + second[X], first[Y] + second[Y]};
}
/**
* The Main method for the Sokoban game with contains all of the game logic
*
* #param args args[0] the path to the level
*/
public static void main(String[] args) {
String file = "sokoban.txt";
if (args.length > 0) {
file = args[0];
}
if (!myLevel.isValidLevel(file)) {
System.err.println("Level has an invalid format");
return;
}
if (myLevel.isCompleted()) {
System.out.println("Yeah you have solved the level :)");
} else {
System.out.println("You have not solved the level :(");
}
System.out.println(myLevel.toString());
System.out.println("Goodbye");
}
}
Player.java
class Player{
//Standardkontruktor
public Player()
{
}
//Parametrisierter Konstruktor
public Player(char[][] room)
{
this.room = room;
}
//Attribut Raum
private static char[][] room;
//Attribut Spilerposition
//move Methode
/**
* Makes a move
*
* #param direction as a vector
* #return true iff it was successful, otherwise false
*/
private static boolean move(int[] direction) {
int[] next = add(player, direction);
switch (room[next[Y]][next[X]]) {
case BOX_ON_GOAL:
case BOX:
int[] behind = add(next, direction);
if (!(room[behind[Y]][behind[X]] == FREE || room[behind[Y]] [behind[X]] == GOAL)) {
return false;
}
if (room[next[Y]][next[X]] == BOX_ON_GOAL) {
emptyGoal++;
freeBox++;
}
if (room[behind[Y]][behind[X]] == GOAL) {
room[behind[Y]][behind[X]] = BOX_ON_GOAL;
emptyGoal--;
freeBox--;
} else {
room[behind[Y]][behind[X]] = BOX;
}
if (room[next[Y]][next[X]] == BOX_ON_GOAL) {
room[next[Y]][next[X]] = GOAL;
} else {
room[next[Y]][next[X]] = FREE;
}
case GOAL:
case FREE:
if (room[player[Y]][player[X]] == PLAYER_ON_GOAL) {
room[player[Y]][player[X]] = GOAL;
} else {
room[player[Y]][player[X]] = FREE;
}
player = next;
if (room[player[Y]][player[X]] == FREE) {
room[player[Y]][player[X]] = PLAYER;
} else {
room[player[Y]][player[X]] = PLAYER_ON_GOAL;
}
return true;
default:
return false;
}
}
}
Level.java
class Level{
//Standardkontruktor
public Level()
{
}
//Parametrisierter Konstruktor
public Level(char[][] room)
{
this.room = room;
}
//Objekt Namens myPlayer vom Typ Player als Attribut eines Levels
Player myPlayer = new Player();
myPlayer = new Player(this.room);
//Attribut Raum
private static char[][] room;
private boolean isValidLevel(String file){
return this.loadLevel(file);
}
//Methode LoadLevel
/**
* Loads the level from the "file" and validate it
*
* #param file path to the file
* #return false iff an error occurs or the level is invalid, true otherwise
*/
private static boolean loadLevel(String file) {
BufferedReader bufferedReader;
try {
bufferedReader = Files.newBufferedReader(Paths.get(file));
bufferedReader.mark(100 * 100);
String line;
while ((line = bufferedReader.readLine()) != null) {
size[Y]++;
if (size[X] > -1 && size[X] != line.length()) {
return false;
} else {
size[X] = line.length();
}
}
bufferedReader.reset();
room = new char[size[Y]][];
int i = 0;
while ((line = bufferedReader.readLine()) != null) {
room[i] = new char[line.length()];
for (int j = 0; j < line.length(); j++) {
room[i][j] = line.charAt(j);
}
i++;
// oder room[i++] = line.toCharArray();
}
bufferedReader.close();
} catch (IOException e) {
return false;
}
for (int i = 0; i < room.length; i++) {
for (int j = 0; j < room[i].length; j++) {
switch (room[i][j]) {
case FREE:
case BOX_ON_GOAL:
case WALL:
break;
case PLAYER_ON_GOAL:
emptyGoal++;
case PLAYER:
if (player != null) {
return false;
} else {
player = new int[]{j, i};
}
break;
case BOX:
freeBox++;
break;
case GOAL:
emptyGoal++;
break;
default:
return false;
}
}
}
return !(player == null || emptyGoal != freeBox);
}
//Methode toString für die Ausgabe des Spielfeldes
/**
* Prints the level to the output stream
*/
public String toString() {
String safwensTempString= "";
for (char[] row : room) {
safwensTempString=safwensTempString+row;
}
}
/**
* Game logic for Sokoban
*
* #return true if the level was solved, otherwise false
*/
private static boolean isCompleted() {
// create new Scanner that reads from console
Scanner input = new Scanner(System.in);
// flag if we quit the program
boolean run = true;
int[] direction;
do {
System.out.println(myLevel.toString());
System.out.println("Do you want to go up, down, left, right or exit the program?");
// check which command was chosen and execute it
switch (input.next()) {
case "w":
case "up":
direction = UP;
break;
case "s":
case "down":
direction = DOWN;
break;
case "a":
case "left":
direction = LEFT;
break;
case "d":
case "right":
direction = RIGHT;
break;
case "exit":
run = false;
continue;
default: // if the user input is not one of our commands print help
System.out.println("Command unknown! Please type up, down, left or right to move or exit to quit this program");
continue;
}
if (!myPlayer.move(direction)) {
System.out.println("You can not go there!");
}
} while (run && emptyGoal != 0 && freeBox != 0);
return run;
}
}
Thanks in advance for any hints or help!
EDIT
I compile in Notepad++ like this:
Statements have to be placed inside methods (or an initialiser block which is added to the constructor). You can only declare and initialise a field outside a method.
Instead of
Level myLevel = new Level();
myLevel = new Level(this.room);
you can write
Level myLevel = new Level(this.room);
Let me give an example of a hello world program with two classes
$ vi A.java
class A {
static B b = new B();
public static void main(String...a) {
System.out.println(b.message);
}
}
$ vi B.java
class B {
String message = "Hello World";
}
$ javac A.java
$ java A
prints
Hello World
So i got this program which sets subject, and grades it.
now i got this piece of code:
package ectsmonitor;
import java.util.Scanner;
import java.util.stream.IntStream;
/**
*
* #author JasperF
*/
public class ECTSMonitor {
private int aantalvakken;
private final double voldoende = 5.5;
private String[] vak = new String[aantalvakken];
private Scanner input = new Scanner(System.in);
private int[] ECTS = new int[aantalvakken];
private double[] Cijfer = new double[aantalvakken];
private int totaalECTS;
/**
* #param args the command line arguments
*/
/**
* Asks for amount of Subjects, and sets instance variable for size of
* Arrays
*/
public void setSubjects() {
//System.out.println("Hoeveel vakken heb je?");
//aantalvakken = input.nextInt();
System.out.println(vak.length);
for (int x = 0; x < getAantalvakken(); x++) {
System.out.println("Voer de naam in van je vak!");
vak[x] = input.next();
System.out.println("Voer het aantal punten in voor " + vak[x]);
ECTS[x] = input.nextInt();
System.out.println("Vak Toegevoegd!!");
}
}
public void setCijfer() {
for (int x = 0; x < vak.length; x++) {
System.out.println("Wat is je Cijfer voor " + vak[x] + "?");
Cijfer[x] = input.nextDouble();
System.out.println("Voor het vak " + vak[x] + "heb je als cijfer ingevuld " + Cijfer[x]);
}
}
public void Checkscore() {
for (int x = 0; x < vak.length; x++) {
if (Cijfer[x] >= voldoende) {
System.out.println("vak:" + vak[x] + "\t\t\t\t Cijfer: " + Cijfer[x] + "ECTS behaald: " + ECTS[x]);
} else {
System.out.println("vak:" + vak[x] + "\t\t\t\t Cijfer: " + Cijfer[x] + "ECTS behaald: 0");
}
}
}
public void BAS() {
totaalECTS = IntStream.of(ECTS).sum();
if (totaalECTS < (totaalECTS * (5 / 6))) {
System.out.println("PAS OP!!: Je ligt op schema voor een BAS!");
} else {
System.out.println("Gefeliciteerd!!: Je bent op weg naar je Propodeuse!!");
}
}
/**
* #return the aantalvakken
*/
public int getAantalvakken() {
return aantalvakken;
}
/**
* #param aantalvakken the aantalvakken to set
*/
public void setAantalvakken(int aantalvakken) {
this.aantalvakken = aantalvakken;
}
}
and i got this piece of code to run it:
public class Run {
/**
*
* #author JasperF
* #param args
*/
public static void main(String[] args) {
ECTSMonitor mon = new ECTSMonitor();
mon.setSubjects();
mon.setCijfer();
mon.Checkscore();
mon.BAS();
}
}
now in the first code, the lenght of the arrays is set by the variable 'aantalvakken',
but when i run my program, and print the lenght of te array it says 0.
how can i set the variable aantalvakken to set the array length
Pass aantalvakken value to constructor. And create ArrayList's depends on aantalvakken at constructor.
public class ECSTMonitor {
private int aantalvakken;
private final double voldoende = 5.5;
private String[] vak;
private Scanner input = new Scanner(System.in);
private int[] ECTS;
private double[] Cijfer;
private int totaalECTS;
public ECSTMonitor(int aantalvakken) {
this.aantalvakken = aantalvakken;
vak = new String[aantalvakken];
ECTS = new int[aantalvakken];
Cijfer = new double[aantalvakken];
}
private int aantalvakken;
is not initialized and therefore 0 by default.
try using static variables like below, initialize the variable(aantalvakken) how much array length you want.
public static final int aantalvakken;
or
public static final int aantalvakken=10;