From c66f1ba2cbfb4f86d19123611e483a5374d26454 Mon Sep 17 00:00:00 2001 From: Illia Soloviov <74905269+wav3solo@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:40:07 +0100 Subject: [PATCH] added a functioning version of rumbleBot --- src/RumbleBot.java | 169 ++++++++++++++++++++++++++++++++++++++-- src/RumbleBotTest1.java | 64 --------------- 2 files changed, 163 insertions(+), 70 deletions(-) delete mode 100644 src/RumbleBotTest1.java diff --git a/src/RumbleBot.java b/src/RumbleBot.java index 2379a5e..d74be96 100644 --- a/src/RumbleBot.java +++ b/src/RumbleBot.java @@ -1,3 +1,5 @@ +import java.util.Random; + /* * RumbleBot. * Der Rover ist auch mit einem Geschütz ausgestattet, dass nur in Fahrrichtung feuern kann. @@ -8,6 +10,11 @@ */ public class RumbleBot extends Bot{ private String moves = ""; + private int spiralFactor = 1; + private char spiralDirection = '>'; + private boolean goesForward = true; + private boolean frontIsBlocked, leftIsBlocked, rightIsBlocked; + public static void main(String[] args) { Bot rumbleBot = new RumbleBot(args); rumbleBot.run(); @@ -17,15 +24,165 @@ public class RumbleBot extends Bot{ super(args); } - //@TODO: add nextMove() logic protected char nextMove(View view){ - return walk(); + char nextMove = checkForEnemy(view) ? takeAimAndShoot(view) : walkByColumns(view); + + checkBarriers(view); + + nextMove = checkMove(nextMove); + + return nextMove; } - //@TODO: add walk() logic - private char walk() { - if(moves.isEmpty()){ - moves += ' '; + private char takeAimAndShoot(View view) { + resetMovesSequence(); + + int[] frontIndexes = getFrontIndexes(view); + int[] leftIndexes = getLeftIndexes(view); + int[] rightIndexes = getRightIndexes(view); + + char[] enemies = {'^', '<', '>', 'v'}; + + for (int index : frontIndexes) { + for (char enemy : enemies) { + if (view.data.charAt(index) == enemy) return 'f'; + } + } + + for (int index : leftIndexes) { + for (char enemy : enemies) { + if (view.data.charAt(index) == enemy) return '<'; + } + } + + for (int index : rightIndexes) { + for (char enemy : enemies) { + if (view.data.charAt(index) == enemy) 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 = ""; + spiralFactor = 1; + spiralDirection = (spiralDirection == '>') ? '<' : '>'; + goesForward = true; + } + + + private boolean checkForEnemy(View view) { + char[] enemies = {'^', '<', '>', 'v'}; + + boolean enemyDetected = false; + + for (char enemy : enemies) { + if (view.data.contains(Character.toString(enemy))) { + enemyDetected = true; + System.out.println("There is an enemy!"); + break; + } + } + return enemyDetected; + } + + private void checkBarriers(View view) { + int centerCoordinates = view.width / 2; + int centerIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates); + + int frontIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates - 1); + int leftIndex = centerIndex - 1; + int rightIndex = centerIndex + 1; + + char[] obstacles = {'#', '~', 'X'}; + + frontIsBlocked = containsChar(obstacles, view.data.charAt(frontIndex)); + leftIsBlocked = containsChar(obstacles, view.data.charAt(leftIndex)); + rightIsBlocked = containsChar(obstacles, view.data.charAt(rightIndex)); + + } + + public boolean containsChar(char[] array, char target) { + for (char c : array) { + if (c == target) { + return true; + } + } + return false; + } + + private char checkMove(char move) { + if (frontIsBlocked) { + resetMovesSequence(); + if (leftIsBlocked) move = '>'; + else if (rightIsBlocked) move = '<'; + } + return 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); diff --git a/src/RumbleBotTest1.java b/src/RumbleBotTest1.java deleted file mode 100644 index bc3cdf6..0000000 --- a/src/RumbleBotTest1.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * RumbleBot. - * Der Rover ist auch mit einem Geschütz ausgestattet, dass nur in Fahrrichtung feuern kann. - * Der Feuerbefehl ist „f“. Die Reichweite des Geschützes entspricht der Scanreichweite. - * Wälder, Felsen und Wasser blockieren Schüsse. - * Der Rover ist beim ersten Treffer zerstört. Wer überlebt am längsten? - * docker run --rm -p 63187:63187 mediaeng/bots rumble - */ - -public class RumbleBotTest1 extends Bot { - - private char currentDirection = '^'; // Start-Richtung des Bots - - protected RumbleBotTest1(String[] args) { - super(args); - } - - public static void main(String[] args) { - - Bot rumbleBot = new RumbleBot(args); - rumbleBot.run(); - System.out.println("hello"); - } - - @Override - protected char nextMove(View view) { - // Scanne das Spielfeld nach Gegnern in Fahrtrichtung - if (isEnemyInSight(view)) { - return 'f'; // Feuere, wenn ein Gegner in Reichweite ist - } - - // Wenn kein Gegner in Sicht, wähle eine Bewegung - return chooseMove(view); - } - - private boolean isEnemyInSight(View view) { - // Prüfe, ob ein Gegner in der aktuellen Fahrtrichtung ist - // Annahme: Gegner sind als ^, <, >, v gekennzeichnet - String enemySymbols = "^<>v"; - return view.data.contains(String.valueOf(currentDirection)) && enemySymbols.contains(String.valueOf(currentDirection)); - } - - private char chooseMove(View view) { - // Wähle eine sichere Bewegung, vermeide Hindernisse und versuche, Gegner zu finden - // Einfache Implementierung: Wechsle die Richtung bei jedem Zug - currentDirection = getNextDirection(currentDirection); - return currentDirection; - } - - private char getNextDirection(char currentDirection) { - switch (currentDirection) { - case '^': - return '>'; - case '>': - return 'v'; - case 'v': - return '<'; - case '<': - return '^'; - default: - return '^'; // Standardrichtung, falls etwas schiefgeht - } - } -}