/* * SnakeBot. * Eine weitere wichtige Funktion des Rovers ist es, Gesteinsproben zu sammeln. * Interessante Steine sind im Scan mit einem @ gekennzeichnet. * Mit jeder aufgesammelten Gesteinsprobe wird an den Rover ein Wagen angehängt, der zukünftig hinter dem Rover mitgezogen wird. * Die Wagen sind im Scan mit * zu identifizieren. * Vorsicht: fährt der Rover in einen Wagen, ist er schwer beschädigt und kann keine weiteren Steine mehr sammeln. * Sie können Ihre Implementierung wieder testen mit: * docker run --rm -p 63187:63187 mediaeng/bots snakes * 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“. */ public class SnakeBot extends Bot{ String moves = ""; private int spiralNumber = 0; private boolean ignoreStones = false; public static void main(String[] args) { Bot snakeBot = new SnakeBot(args); snakeBot.run(); } protected SnakeBot(String[] args) { super(args); } //@TODO: find a better way to avoid collectedStones protected char nextMove(View view) { 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); if(nextMove == '^' && view.data.charAt(frontCellIndex) == '*'){ nextMove = (countCollectedStonesLeft(view) <= countCollectedStonesRight(view)) ? '<' : '>'; ignoreStones = true; } /* * @TODO: * Avoiding endless loops due to trying to collect two stones at once. * Problem: stones located near to each other are ignored. */ if(countUncollectedStones(view) > 1) ignoreStones = true; if(countCollectedStones(view) <= 2 && countUncollectedStones(view) <= 1) ignoreStones = false; return nextMove; } private int countUncollectedStones(View view) { int count = 0; for (char c : view.data.toCharArray()) { if (c == '@') count++; } 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++; } return stones; } private int countCollectedStonesRight(View view) { int[] rightSide = generateRightSideArray(view.width); int stones = 0; for (int cellIndex : rightSide) { if(view.data.charAt(cellIndex) == '*') stones++; } 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) + ">"; } 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; } }