You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SnakeBot.java 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * SnakeBot.
  3. * Eine weitere wichtige Funktion des Rovers ist es, Gesteinsproben zu sammeln.
  4. * Interessante Steine sind im Scan mit einem @ gekennzeichnet.
  5. * Mit jeder aufgesammelten Gesteinsprobe wird an den Rover ein Wagen angehängt, der zukünftig hinter dem Rover mitgezogen wird.
  6. * Die Wagen sind im Scan mit * zu identifizieren.
  7. * Vorsicht: fährt der Rover in einen Wagen, ist er schwer beschädigt und kann keine weiteren Steine mehr sammeln.
  8. * Sie können Ihre Implementierung wieder testen mit:
  9. * docker run --rm -p 63187:63187 mediaeng/bots snakes
  10. * Für diese Funktion wird am 7.2.24 in einer gemeinsamen Arena mit allen Teams des Jahrgangs ein Wettbewerb durchgeführt.
  11. * Die besten acht Teams qualifizieren sich für die Königsdisziplin „Rumble“.
  12. */
  13. public class SnakeBot extends Bot{
  14. String moves = "";
  15. private int spiralNumber = 0;
  16. private boolean ignoreStones = false;
  17. public static void main(String[] args) {
  18. Bot snakeBot = new SnakeBot(args);
  19. snakeBot.run();
  20. }
  21. protected SnakeBot(String[] args) {
  22. super(args);
  23. }
  24. //@TODO: find a better way to avoid collectedStones
  25. protected char nextMove(View view) {
  26. boolean stoneDetected = view.data.contains("@");
  27. char nextMove;
  28. nextMove = (stoneDetected && !ignoreStones) ? goToStone(view) : walkBySpiral(view);
  29. int centerCoordinateOfView = view.width / 2;
  30. int frontCellIndex = calculateCharIndexFromCoordinates(view.width, centerCoordinateOfView, centerCoordinateOfView - 1);
  31. if(nextMove == '^' && view.data.charAt(frontCellIndex) == '*'){
  32. nextMove = (countCollectedStonesLeft(view) <= countCollectedStonesRight(view)) ? '<' : '>';
  33. ignoreStones = true;
  34. }
  35. /*
  36. * @TODO:
  37. * Avoiding endless loops due to trying to collect two stones at once.
  38. * Problem: stones located near to each other are ignored.
  39. */
  40. if(countUncollectedStones(view) > 1) ignoreStones = true;
  41. if(countCollectedStones(view) <= 2 && countUncollectedStones(view) <= 1) ignoreStones = false;
  42. return nextMove;
  43. }
  44. private int countUncollectedStones(View view) {
  45. int count = 0;
  46. for (char c : view.data.toCharArray()) {
  47. if (c == '@') count++;
  48. }
  49. return count;
  50. }
  51. private int countCollectedStonesLeft(View view) {
  52. int[] leftSide = generateLeftSideArray(view.width);
  53. int stones = 0;
  54. for (int cellIndex : leftSide) {
  55. if(view.data.charAt(cellIndex) == '*') stones++;
  56. }
  57. return stones;
  58. }
  59. private int countCollectedStonesRight(View view) {
  60. int[] rightSide = generateRightSideArray(view.width);
  61. int stones = 0;
  62. for (int cellIndex : rightSide) {
  63. if(view.data.charAt(cellIndex) == '*') stones++;
  64. }
  65. return stones;
  66. }
  67. private int countCollectedStones(View view) {
  68. int count = 0;
  69. for (char c : view.data.toCharArray()) {
  70. if (c == '*') count++;
  71. }
  72. return count;
  73. }
  74. private char goToStone(View view) {
  75. int rowDifference = findStoneRow(view) - (view.width / 2);
  76. return rowDifference < 0 ? '^' : '<';
  77. }
  78. private int findStoneRow(View view) {
  79. return view.data.indexOf('@') / view.width;
  80. }
  81. private char walkBySpiral(View view) {
  82. if (moves.isEmpty()) {
  83. spiralNumber++;
  84. moves += "^".repeat(view.width * spiralNumber) + ">" + "^".repeat(view.width * spiralNumber) + ">";
  85. }
  86. char nextMove = moves.charAt(0);
  87. moves = moves.substring(1);
  88. return nextMove;
  89. }
  90. private int calculateCharIndexFromCoordinates(int width, int x, int y){
  91. return width * y + x;
  92. }
  93. private int[] generateLeftSideArray(int sideLength) {
  94. int[] leftStones = new int[sideLength / 2 * sideLength];
  95. int index = 0;
  96. for (int row = 0; row < sideLength; row++) {
  97. for (int col = 0; col < sideLength / 2; col++) {
  98. leftStones[index++] = row * sideLength + col;
  99. }
  100. }
  101. return leftStones;
  102. }
  103. private int[] generateRightSideArray(int sideLength) {
  104. int[] rightStones = new int[sideLength / 2 * sideLength];
  105. int index = 0;
  106. for (int row = 0; row < sideLength; row++) {
  107. for (int col = (sideLength / 2) + 1; col < sideLength; col++) {
  108. rightStones[index++] = row * sideLength + col;
  109. }
  110. }
  111. return rightStones;
  112. }
  113. }