diff --git a/src/SnakeBot.java b/src/SnakeBot.java index 91a7d90..9ee1d7c 100644 --- a/src/SnakeBot.java +++ b/src/SnakeBot.java @@ -10,163 +10,103 @@ * Für diese Funktion wird am 7.2.24 in einer gemeinsamen Arena mit allen Teams des Jahrgangs ein Wettbewerb durchgeführt. * Die besten acht Teams qualifizieren sich für die Königsdisziplin „Rumble“. */ + +import java.util.Random; + public class SnakeBot extends Bot{ private String moves = ""; - private int spiralNumber = 0; + boolean frontIsBlocked, backIsBlocked, leftIsBlocked, rightIsBlocked, trapped; + private char previousTurn = '<'; + private int spiralFactor = 1; + private char spiralDirection = '>'; private boolean goesForward = true; - private boolean ignoreStones = false; public static void main(String[] args) { - Bot snakeBot = new SnakeBot(args); - snakeBot.run(); + Bot SnakeBot = new SnakeBot(args); + SnakeBot.run(); } protected SnakeBot(String[] args) { super(args); } - //@TODO: find a better way to avoid collected stones - //@TODO: find a better way to collect stones - protected char nextMove(View view) { + + protected char nextMove(View view) throws Exception { boolean stoneDetected = view.data.contains("@"); char nextMove; - nextMove = (stoneDetected && !ignoreStones) ? goToStone(view) : walkBySpiral(view); - int centerCoordinateOfView = view.width / 2; - int frontCellIndex = calculateCharIndexFromCoordinates(view.width, centerCoordinateOfView, centerCoordinateOfView - 1); + checkBarriers(view); - if(nextMove == '^' && view.data.charAt(frontCellIndex) == '*'){ - nextMove = (countCollectedStonesLeft(view) <= countCollectedStonesRight(view)) ? '<' : '>'; - ignoreStones = true; - } + nextMove = stoneDetected ? goToStone(view) : walkBySpiral(view); - if(countUncollectedStones(view) > 1) ignoreStones = true; - if(countCollectedStones(view) <= 2 && countUncollectedStones(view) <= 1) ignoreStones = false; - - if(isStoneNearby(view)){ - nextMove = goToNearbyStone(view); - } + nextMove = checkMove(nextMove); + saveMove(nextMove); return nextMove; } - private boolean isStoneNearby(View view){ - int centerCoordinateOfView = view.width / 2; - int frontCellIndex = calculateCharIndexFromCoordinates(view.width, centerCoordinateOfView, centerCoordinateOfView - 1); - int leftCellIndex = calculateCharIndexFromCoordinates(view.width, centerCoordinateOfView - 1, centerCoordinateOfView); - int rightCellIndex = calculateCharIndexFromCoordinates(view.width, centerCoordinateOfView + 1, centerCoordinateOfView); + private void checkBarriers(View view) throws Exception { + int centerCoordinates = view.width / 2; + int centerIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates); - boolean stoneIsInFront = view.data.charAt(frontCellIndex) == '@'; - boolean stoneIsOnTheLeft = view.data.charAt(leftCellIndex) == '@'; - boolean stoneIsOneTheRight = view.data.charAt(rightCellIndex) == '@'; + int frontIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates - 1); + int backIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates + 1); + int leftIndex = centerIndex - 1; + int rightIndex = centerIndex + 1; - return stoneIsInFront || stoneIsOnTheLeft || stoneIsOneTheRight; - } + frontIsBlocked = view.data.charAt(frontIndex) == '*'; + backIsBlocked = view.data.charAt(backIndex) == '*'; + leftIsBlocked = view.data.charAt(leftIndex) == '*'; + rightIsBlocked = view.data.charAt(rightIndex) == '*'; + trapped = frontIsBlocked && backIsBlocked && leftIsBlocked && rightIsBlocked; - private char goToNearbyStone(View view){ - int centerCoordinateOfView = view.width / 2; - int frontCellIndex = calculateCharIndexFromCoordinates(view.width, centerCoordinateOfView, centerCoordinateOfView - 1); - int leftCellIndex = calculateCharIndexFromCoordinates(view.width, centerCoordinateOfView - 1, centerCoordinateOfView); - int rightCellIndex = calculateCharIndexFromCoordinates(view.width, centerCoordinateOfView + 1, centerCoordinateOfView); - - if(view.data.charAt(frontCellIndex) == '@') return '^'; - if(view.data.charAt(leftCellIndex) == '@') return '<'; - if(view.data.charAt(rightCellIndex) == '@') return '>'; - return 0; - } - - private void resetMoves() { - moves = ""; - spiralNumber = 0; - } - - private int countUncollectedStones(View view) { - int count = 0; - - for (char c : view.data.toCharArray()) { - if (c == '@') count++; + if (trapped) { + Exception trappedException = new Exception("Snake is trapped"); + System.err.println(trappedException.getMessage()); + throw trappedException; } - return count; } - private int countCollectedStonesLeft(View view) { - int[] leftSide = generateLeftSideArray(view.width); - int stones = 0; - for (int cellIndex : leftSide) { - if(view.data.charAt(cellIndex) == '*') stones++; + private char checkMove(char move) throws Exception { + if (frontIsBlocked) { + resetMovesSequence(); + if (leftIsBlocked) move = '>'; + else if (rightIsBlocked) move = '<'; + else if (previousTurn == '<') move = '>'; + else if (previousTurn == '>') move = '<'; + else { + Exception invalidTurnException = new Exception("The previous turn was neither '<' nor '>'."); + System.err.println(invalidTurnException.getMessage()); + throw invalidTurnException; + } } - return stones; + return move; } - private int countCollectedStonesRight(View view) { - int[] rightSide = generateRightSideArray(view.width); - int stones = 0; - for (int cellIndex : rightSide) { - if(view.data.charAt(cellIndex) == '*') stones++; + private void saveMove(char move) { + if (move == '<' || move == '>') { + previousTurn = move; } - return stones; - } - - private int countCollectedStones(View view) { - int count = 0; - - for (char c : view.data.toCharArray()) { - if (c == '*') count++; - } - return count; - } - - private char goToStone(View view) { - - int rowDifference = findStoneRow(view) - (view.width / 2); - return rowDifference < 0 ? '^' : '<'; - } - - private int findStoneRow(View view) { - return view.data.indexOf('@') / view.width; } private char walkBySpiral(View view) { if (moves.isEmpty()) { - spiralNumber++; - moves += "^".repeat(view.width * spiralNumber) + ">" + "^".repeat(view.width * spiralNumber) + ">"; + spiralFactor++; + moves += "^".repeat(view.width * spiralFactor) + spiralDirection + "^".repeat(view.width * spiralFactor) + spiralDirection; } char nextMove = moves.charAt(0); moves = moves.substring(1); return nextMove; } - private int calculateCharIndexFromCoordinates(int width, int x, int y){ - return width * y + x; - } - - private int[] generateLeftSideArray(int sideLength) { - int[] leftStones = new int[sideLength / 2 * sideLength]; - int index = 0; - - for (int row = 0; row < sideLength; row++) { - for (int col = 0; col < sideLength / 2; col++) { - leftStones[index++] = row * sideLength + col; - } - } - - return leftStones; - } - - private int[] generateRightSideArray(int sideLength) { - int[] rightStones = new int[sideLength / 2 * sideLength]; - int index = 0; - - for (int row = 0; row < sideLength; row++) { - for (int col = (sideLength / 2) + 1; col < sideLength; col++) { - rightStones[index++] = row * sideLength + col; - } - } - - return rightStones; - } - private char walkByColumns(View view) { if(moves.isEmpty()){ - moves = "^".repeat(28); + int min = 10; + int max = 100; + + Random random = new Random(); + int steps = random.nextInt((max - min) + 1) + min; + //int steps = 32 - view.width; + + moves = "^".repeat(steps); moves += (goesForward ? ">" + "^".repeat(view.width) + ">" : "<" + "^".repeat(view.width) + "<"); goesForward = !goesForward; } @@ -175,4 +115,73 @@ public class SnakeBot extends Bot{ return nextMove; } + private char goToStone(View view) { + resetMovesSequence(); + + int[] frontIndexes = getFrontIndexes(view); + int[] leftIndexes = getLeftIndexes(view); + int[] rightIndexes = getRightIndexes(view); + + for (int index : frontIndexes) { + if (view.data.charAt(index) == '@' && view.data.charAt(index + view.width) != '*' && !frontIsBlocked) return '^'; + } + + for (int index : leftIndexes) { + if (view.data.charAt(index) == '@' && view.data.charAt(index + 1) != '*' && !leftIsBlocked) return '<'; + } + + for (int index : rightIndexes) { + if (view.data.charAt(index) == '@' && view.data.charAt(index - 1) != '*' && !rightIsBlocked) return '>'; + } + + return '^'; + } + + private int[] getLeftIndexes(View view) { + int center = view.width / 2; + int[] leftIndexes = new int[center]; + int index = 0; + + for (int col = 0; col < center; col++) { + leftIndexes[index++] = getCharIndexFromCoordinates(view.width, col, center); + } + + return leftIndexes; + } + + private int[] getRightIndexes(View view) { + int center = view.width / 2; + int[] rightIndexes = new int[center]; + int index = 0; + + for (int col = center + 1; col < view.width; col++) { + rightIndexes[index++] = getCharIndexFromCoordinates(view.width, col, center); + } + + return rightIndexes; + } + + private int[] getFrontIndexes(View view) { + int center = view.width / 2; + int[] frontIndexes = new int[center]; + int index = 0; + + for (int row = 0; row < center; row++) { + frontIndexes[index++] = getCharIndexFromCoordinates(view.width, center, row); + } + + return frontIndexes; + } + + private int getCharIndexFromCoordinates(int width, int x, int y) { + return width * y + x; + } + + private void resetMovesSequence() { + moves = ""; + System.out.println("Previous spiralNumber: " + spiralFactor + ". Resetting."); + spiralFactor = 1; + spiralDirection = (spiralDirection == '>') ? '<' : '>'; + goesForward = true; + } } diff --git a/src/SuperSnakeBot.java b/src/SuperSnakeBot.java deleted file mode 100644 index c42b3bb..0000000 --- a/src/SuperSnakeBot.java +++ /dev/null @@ -1,174 +0,0 @@ -import java.util.Random; - -public class SuperSnakeBot extends Bot{ - private String moves = ""; - private char previousTurn = '<'; - boolean frontIsBlocked, backIsBlocked, leftIsBlocked, rightIsBlocked, trapped; - private int spiralFactor = 1; - private char spiralDirection = '>'; - private boolean goesForward = true; - public static void main(String[] args) { - Bot superSnakeBot = new SuperSnakeBot(args); - superSnakeBot.run(); - } - - protected SuperSnakeBot(String[] args) { - super(args); - } - - protected char nextMove(View view) throws Exception { - boolean stoneDetected = view.data.contains("@"); - char nextMove; - - checkBarriers(view); - - nextMove = stoneDetected ? goToStone(view) : walkBySpiral(view); - - nextMove = checkMove(nextMove); - - saveMove(nextMove); - return nextMove; - } - - private void checkBarriers(View view) throws Exception { - int centerCoordinates = view.width / 2; - int centerIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates); - - int frontIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates - 1); - int backIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates + 1); - int leftIndex = centerIndex - 1; - int rightIndex = centerIndex + 1; - - frontIsBlocked = view.data.charAt(frontIndex) == '*'; - backIsBlocked = view.data.charAt(backIndex) == '*'; - leftIsBlocked = view.data.charAt(leftIndex) == '*'; - rightIsBlocked = view.data.charAt(rightIndex) == '*'; - trapped = frontIsBlocked && backIsBlocked && leftIsBlocked && rightIsBlocked; - - if (trapped) { - Exception trappedException = new Exception("Snake is trapped"); - System.err.println(trappedException.getMessage()); - throw trappedException; - } - } - - private char checkMove(char move) throws Exception { - if (frontIsBlocked) { - resetMovesSequence(); - if (leftIsBlocked) move = '>'; - else if (rightIsBlocked) move = '<'; - else if (previousTurn == '<') move = '>'; - else if (previousTurn == '>') move = '<'; - else { - Exception invalidTurnException = new Exception("The previous turn was neither '<' nor '>'."); - System.err.println(invalidTurnException.getMessage()); - throw invalidTurnException; - } - } - return move; - } - - private void saveMove(char move) { - if(move == '<' || move == '>'){ - previousTurn = move; - } - } - - private char walkBySpiral(View view) { - if (moves.isEmpty()) { - spiralFactor++; - moves += "^".repeat(view.width * spiralFactor) + spiralDirection + "^".repeat(view.width * spiralFactor) + spiralDirection; - } - char nextMove = moves.charAt(0); - moves = moves.substring(1); - return nextMove; - } - - private char walkByColumns(View view) { - if(moves.isEmpty()){ - int min = 10; - int max = 100; - - Random random = new Random(); - int steps = random.nextInt((max - min) + 1) + min; - //int steps = 32 - view.width; - - moves = "^".repeat(steps); - moves += (goesForward ? ">" + "^".repeat(view.width) + ">" : "<" + "^".repeat(view.width) + "<"); - goesForward = !goesForward; - } - char nextMove = moves.charAt(0); - moves = moves.substring(1); - return nextMove; - } - - private char goToStone(View view) { - resetMovesSequence(); - - int[] frontIndexes = getFrontIndexes(view); - int[] leftIndexes = getLeftIndexes(view); - int[] rightIndexes = getRightIndexes(view); - - for (int index : frontIndexes) { - if (view.data.charAt(index) == '@' && view.data.charAt(index + view.width) != '*' && !frontIsBlocked) return '^'; - } - - for (int index : leftIndexes) { - if (view.data.charAt(index) == '@' && view.data.charAt(index + 1) != '*' && !leftIsBlocked) return '<'; - } - - for (int index : rightIndexes) { - if (view.data.charAt(index) == '@' && view.data.charAt(index - 1) != '*' && !rightIsBlocked) return '>'; - } - - return '^'; - } - - private int[] getLeftIndexes(View view) { - int center = view.width / 2; - int[] leftIndexes = new int[center]; - int index = 0; - - for (int col = 0; col < center; col++) { - leftIndexes[index++] = getCharIndexFromCoordinates(view.width, col, center); - } - - return leftIndexes; - } - - private int[] getRightIndexes(View view) { - int center = view.width / 2; - int[] rightIndexes = new int[center]; - int index = 0; - - for (int col = center + 1; col < view.width; col++) { - rightIndexes[index++] = getCharIndexFromCoordinates(view.width, col, center); - } - - return rightIndexes; - } - - private int[] getFrontIndexes(View view) { - int center = view.width / 2; - int[] frontIndexes = new int[center]; - int index = 0; - - for (int row = 0; row < center; row++) { - frontIndexes[index++] = getCharIndexFromCoordinates(view.width, center, row); - } - - return frontIndexes; - } - - private int getCharIndexFromCoordinates(int width, int x, int y) { - return width * y + x; - } - - private void resetMovesSequence() { - moves = ""; - System.out.println("Previous spiralNumber: " + spiralFactor + ". Resetting."); - spiralFactor = 1; - spiralDirection = (spiralDirection == '>') ? '<' : '>'; - goesForward = true; - } -}