Asymmetrische KOTH: Fangen Sie die Katze (Cat Thread)


14

Asymmetrische KOTH: Fangen Sie die Katze

UPDATE : Die GIST-Dateien werden aktualisiert (einschließlich neuer Untermischungen), da die Controller.java keine Ausnahmen (nur Fehler) abfängt. Es werden nun Fehler und Ausnahmen abgefangen und auch gedruckt.

Diese Herausforderung besteht aus zwei Fäden, dies ist der Katzenfaden, den Fängerfaden finden Sie hier .

Der Controller kann hier heruntergeladen werden .

Dies ist eine asymmetrische KOTH: Jede Vorlage ist entweder eine Katze oder ein Fänger . Es gibt Spiele zwischen jedem Paar einer Katze und einem Fänger. Die Katzen und die Fänger haben getrennte Ranglisten.

Fänger

Es gibt eine Katze auf einem sechseckigen Gitter. Ihre Aufgabe ist es, es so schnell wie möglich zu fangen. In jeder Runde können Sie einen Wassereimer auf eine Gitterzelle stellen, um zu verhindern, dass die Katze dorthin kann. Aber die Katze ist (vielleicht) nicht so dumm, und wenn Sie einen Eimer platzieren, bewegt sich die Katze in eine andere Gitterzelle. Da das Gitter sechseckig ist, kann die Katze in 6 verschiedene Richtungen gehen. Ihr Ziel ist es, die Katze mit Wassereimern zu umgeben, je schneller desto besser.

Katze

Sie wissen, dass der Fänger Sie fangen möchte, indem er Wassereimer um Sie herum stellt. Natürlich versuchst du auszuweichen, aber da du eine faule Katze bist (so wie Katzen), machst du genau einen Schritt nach dem anderen. Dies bedeutet, dass Sie nicht an dem Ort bleiben können, an dem Sie sich befinden, sondern an einem der sechs umliegenden Orte. Immer wenn Sie sehen, dass der Fänger einen neuen Wassereimer aufgestellt hat, gehen Sie in eine andere Zelle. Natürlich versuchen Sie so lange wie möglich auszuweichen.

Gitter

Das Gitter ist hexagonal, aber da wir keine hexagonalen Datenstrukturen haben, nehmen wir ein 11 x 11quadratisches 2d-Array und ahmen das hexagonale "Verhalten" nach, das die Katze nur in 6 Richtungen bewegen kann:

Bildbeschreibung hier eingeben

Die Topologie ist toroidal, dh wenn Sie eine Zelle außerhalb des Arrays betreten, werden Sie nur in die entsprechende Zelle auf der anderen Seite des Arrays übertragen.

Spiel

Die Katze startet an einer bestimmten Position im Gitter. Der Fänger kann den ersten Zug machen, dann bewegen sich die Katze und ihr Fänger abwechselnd, bis die Katze gefangen ist. Die Anzahl der Schritte ist die Punktzahl für dieses Spiel. Die Katze versucht eine möglichst hohe Punktzahl zu erzielen, der Fänger versucht eine möglichst niedrige Punktzahl zu erzielen. Die durchschnittliche Summe aller Spiele, an denen Sie teilgenommen haben, ist die Punktzahl Ihrer Einreichung. Es gibt zwei separate Ranglisten, eine für die Katze und eine für die Fänger.

Regler

Der angegebene Controller ist in Java geschrieben. Als Fänger oder Katze müssen Sie jeweils eine Java-Klasse komplett implementieren (es gibt bereits einige primitive Beispiele) und diese in die einfügenplayers Paket einfügen (und die Liste der Katzen / Fänger in der Controller-Klasse aktualisieren). Sie können jedoch auch schreiben zusätzliche Funktionen innerhalb dieser Klasse. Der Controller enthält jeweils zwei Arbeitsbeispiele für einfache Katzen- / Fängerklassen.

Das Feld ist ein 11 x 112D- intArray, das die Werte der aktuellen Zustände der Zellen speichert. Wenn eine Zelle leer ist, hat sie einen Wert 0, wenn es eine Katze gibt, hat sie einen Wert -1und wenn es einen Eimer gibt, gibt es einen 1.

Es gibt einige Funktionen, die Sie verwenden können: isValidMove()/isValidPosition() sind zu überprüfen , ob Ihr Zug (cat) / Position (Fänger) gültig ist.

Jedes Mal, wenn Sie an der Reihe sind, wird Ihre Funktion takeTurn()aufgerufen. Das Argument enthält eine Kopie des aktuellen Rasters und enthält Methoden read(i,j)zum Lesen der Zelle (i,j)unter sowieisValidMove()/ isValidPosition() Überprüfen der Gültigkeit Ihrer Antwort. Hiermit wird auch das Umbrechen der Toroid-Topologie verwaltet. Das bedeutet, dass Sie auch dann auf die Zelle (-5,13) zugreifen können, wenn das Raster nur 11 x 11 ist.

Die Methode sollte a zurückgeben int Array von zwei Elementen zurückgeben, die mögliche Bewegungen darstellen. Für die Katzen sind {-1,1},{0,1},{-1,0},{1,0},{0,-1},{1,-1}dies die relativen Positionen, in die die Katze gehen möchte, und die Fänger geben die absoluten Koordinaten zurück, in die sie einen Eimer stellen möchten {i,j}.

Wenn Ihre Methode einen ungültigen Zug ergibt, wird Ihr Beitrag disqualifiziert. Der Umzug gilt als ungültig, wenn sich an Ihrem Ziel bereits ein Eimer befindet oder der Umzug nicht erlaubt / Ziel bereits belegt ist (als Katze) oder wenn sich bereits ein Eimer / eine Katze befindet (als Fänger). Das können Sie vorher mit den angegebenen Funktionen überprüfen.

Ihre Einreichung sollte relativ schnell funktionieren. Wenn Ihre Methode für jeden Schritt länger als 200 ms dauert, wird sie ebenfalls disqualifiziert. (Am liebsten viel weniger ...)

Die Programme dürfen Informationen zwischen den Schritten speichern.

Einreichungen

  • Sie können so viele Beiträge einreichen, wie Sie möchten.
  • Bitte ändern Sie Ihre bereits eingereichten Beiträge nicht wesentlich.
  • Bitte jede Einsendung in einer neuen Antwort.
  • Jeder Beitrag sollte vorzugsweise einen eindeutigen Namen haben.
  • Die Einreichung sollte den Code Ihrer Klasse sowie eine Beschreibung enthalten, aus der hervorgeht, wie Ihre Einreichung funktioniert.
  • Sie können die Zeile <!-- language: lang-java -->vor Ihrem Quellcode schreiben , um eine automatische Hervorhebung der Syntax zu erhalten.

Wertung

Alle Katzen treten gleich oft gegen alle Fänger an. Ich werde versuchen, die aktuellen Ergebnisse regelmäßig zu aktualisieren. Die Gewinner werden ermittelt, wenn die Aktivität abgenommen hat.

Diese Herausforderung ist inspiriert von diesem alten Flash-Spiel

Vielen Dank an @PhiNotPi für das Testen und das konstruktive Feedback.

Aktuelle Ergebnisse (100 Spiele pro Paarung)

Name              Score      Rank   Author

RandCatcher       191962     8      flawr   
StupidFill        212688     9      flawr
Achilles          77214      6      The E
Agamemnon         74896      5      The E
CloseCatcher      54776      4      randomra
ForwordCatcher    93814      7      MegaTom  
Dijkstra          47558      2      TheNumberOne
HexCatcher        48644      3      randomra
ChoiceCatcher     43834      1      randomra

RandCat            77490     9      flawr
StupidRightCat     81566     6      flawr
SpiralCat          93384     5      CoolGuy
StraightCat        80930     7      CoolGuy
FreeCat           106294     3      randomra
RabidCat           78616     8      cain
Dijkstra's Cat    115094     1      TheNumberOne
MaxCat             98400     4      Manu
ChoiceCat         113612     2      randomra

1
Ich denke, für diese Art von Herausforderung ist das Cops-and-Robbers-Tag gedacht.
SuperJedi224

4
@flawr Ich würde mich dafür aussprechen, das CnR-Tag auf alle Herausforderungen auszudehnen, an denen zwei untergeordnete Herausforderungen beteiligt sind (und diesbezüglich sowohl das als auch KotH als Tags zu verwenden). Das CnR-Tag-Wiki ist stark von den ersten Herausforderungen in diesem Genre beeinflusst. (Außerdem hast du die Bullen und Räuber falsch herum.;))
Martin Ender

1
Was hindert Katzen daran main.Controller, die getCatchers()Antworten der Fänger über ihre takeTurnMethoden zu importieren , anzurufen und zu simulieren / zu sabotieren ?
LegionMammal978

12
@ LegionMammal978 Sportlichkeit.
Martin Ender

2
@feersum hilft das ? (Die schwarzen (bzw. blauen) Punkte stellen dieselbe Zelle dar.)
Fehler

Antworten:


5

FreeCat

Wählt den Zug, der nach 3 Schritten die bestmöglichen Pfade ergibt, wenn sich das Feld nicht ändert.

FreeCat gegen Achilles:

FreeCat gegen Achilles

package players;
/**
 * @author randomra
 */

import java.util.Arrays;

import main.Field;

public class FreeCat implements Cat {

    final int[][] turns = { { -1, 1 }, { 0, 1 }, { -1, 0 }, { 1, 0 },
            { 0, -1 }, { 1, -1 } };// all valid moves
    final int turnCheck = 3;

    public String getName() {
        return "FreeCat";
    }

    public int[] takeTurn(Field f) {

        int[] pos = f.findCat();
        int[] bestMove = { 0, 1 };
        int bestMoveCount = -1;
        for (int[] t : turns) {
            int[] currPos = { pos[0] + t[0], pos[1] + t[1] };
            int moveCount = free_count(currPos, turnCheck, f);
            if (moveCount > bestMoveCount) {
                bestMoveCount = moveCount;
                bestMove = t;
            }
        }
        return bestMove;
    }

    private int free_count(int[] pos, int turnsLeft, Field f) {
        if (f.isValidPosition(pos) || Arrays.equals(pos, f.findCat())) {
            if (turnsLeft == 0) {
                return 1;
            }
            int routeCount = 0;
            for (int[] t : turns) {
                int[] currPos = { pos[0] + t[0], pos[1] + t[1] };
                int moveCount = free_count(currPos, turnsLeft - 1, f);
                routeCount += moveCount;
            }
            return routeCount;
        }
        return 0;
    }
}

3

Dijkstra's Cat

Er lernte und wendete den Master-Algorithmus seines Masters an. Beachten Sie, dass er von einigen Methoden in der Klasse seines entsprechenden Catchers abhängig ist.

Dijkstra's Cat vs Hexcatcher (muss aktualisiert werden):

Bildbeschreibung hier eingeben

package players;

import main.Field;
import players.Dijkstra; //Not needed import. Should already be available.

/**
 * @author TheNumberOne
 *
 * Escapes from the catcher.
 * Uses Dijkstras methods.
 */

public class DijkstrasCat implements Cat{

    private static final int[][] possibleMoves = {{-1,1},{0,1},{-1,0},{1,0},{0,-1},{1,-1}};
    @Override
    public String getName() {
        return "Dijkstra's Cat";
    }

    @Override
    public int[] takeTurn(Field f) {
        int[] me = f.findCat();
        int[] bestMove = {-1,1};
        int bestOpenness = Integer.MAX_VALUE;
        for (int[] move : possibleMoves){
            int[] newPos = Dijkstra.normalize(new int[]{me[0]+move[0],me[1]+move[1]});
            if (!f.isValidMove(move)){
                continue;
            }
            int openness = Dijkstra.openness(newPos, f, true)[1];
            if (openness < bestOpenness || (openness == bestOpenness && Math.random() < .5)){
                bestOpenness = openness;
                bestMove = move;
            }
        }
        return bestMove;
    }
}

Wie er arbeitet:

Er versucht, den Zug zu finden, der die Fadenzahl des Brettes im Verhältnis zu sich selbst minimiert. Weitere Informationen finden Sie im entsprechenden Beitrag des Catchers.

Mit Update:

Er vermeidet jetzt die seltsamen geometrischen Formen, die die Wassereimer manchmal bilden.


3

MaxCat

Ich habe versucht, den Minimax-Algorithmus zu implementieren. Es funktioniert jedoch aufgrund der begrenzten Zeit nicht sehr gut. Bearbeiten: Es wird jetzt Multithreading verwendet, aber (zumindest auf meinem Computer) kann ich die Tiefe nicht höher einstellen. Andernfalls tritt eine Zeitüberschreitung auf. Bei Verwendung eines PCs mit 6 oder mehr Kernen wäre diese Einreichung viel besser :)

MaxCat gegen Dijkstra:

MaxCat gegen Dijkstra

package players;

import java.util.ArrayList;
import java.util.List;

import main.Field;

public class MaxCat implements Cat {
    final int[][] turns = { { -1, 1 }, { 0, 1 }, { -1, 0 }, { 1, 0 }, { 0, -1 }, { 1, -1 } };

    public String getName() {
        return "MaxCat";
    }

    public int[] takeTurn(Field f) {
        List<CatThread> threads = new ArrayList<>();
        int[] pos = f.findCat();
        for (int[] turn : turns) {
            if(f.read(pos[0]+turn[0], pos[1]+turn[1]) == Field.EMPTY){
                CatThread thread = new CatThread();
                thread.bestMove = turn;
                thread.field = new Field(f);
                thread.start();
                threads.add(thread);
            }
        }
        for (CatThread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {}
        }
        int best = Integer.MIN_VALUE;
        int[] bestMove = { -1, 1 };
        for (CatThread thread : threads) {
            if (thread.score > best) {
                best = thread.score;
                bestMove = thread.bestMove;
            }
        }
        return bestMove;
    }

    class CatThread extends Thread {
        private Field field;
        private int[] bestMove;
        private int score;
        private final int DEPTH = 3;

        @Override
        public void run() {
            score = max(DEPTH, Integer.MIN_VALUE, Integer.MAX_VALUE);       
        }

        int max(int depth, int alpha, int beta) {
            int pos[] = field.findCat();
            if (depth == 0 || field.isFinished()) {
                int moveCount = 0;
                for (int[] turn : turns) {
                    if(field.read(pos[0]+turn[0], pos[1]+turn[1]) == Field.EMPTY)
                        moveCount++;
                }
                return DEPTH-depth + moveCount;
            }
            int maxValue = alpha;
            for (int[] turn : turns) {
                if(field.read(pos[0]+turn[0], pos[1]+turn[1]) == Field.EMPTY) {
                    field.executeMove(turn);
                    int value = min(depth-1, maxValue, beta);
                    field.executeMove(new int[]{-turn[0], -turn[1]});
                    if (value > maxValue) {
                        maxValue = value;
                        if (maxValue >= beta)
                            break;
                    }
                }
            }
            return maxValue;
        }

        int min(int depth, int alpha, int beta) {
            if (depth == 0 || field.isFinished()) {
                int moveCount = 0;
                for (int[] turn : turns) {
                    int pos[] = field.findCat();
                    if(field.read(pos[0]+turn[0], pos[1]+turn[1]) == Field.EMPTY)
                        moveCount++;
                }   
                return -depth - moveCount;
            }
            int[][] f = field.field;
            int minValue = beta;
            List<int[]> moves = generateBucketMoves();
            for (int[] move : moves) {
                f[move[0]][move[1]] = Field.BUCKET;
                int value = max(depth-1, alpha, minValue);
                f[move[0]][move[1]] = Field.EMPTY;
                if (value < minValue) {
                    minValue = value;
                    if (minValue <= alpha)
                        break;
                }
            }
            return minValue;
        }

        private List<int[]> generateBucketMoves() {
            int[][] f = field.field;
            List<int[]> list = new ArrayList<>();
            for (int i = 0; i < f.length; i++) {
                for (int j = 0; j < f[i].length; j++) {
                    if (f[i][j] == Field.EMPTY) {
                        list.add(new int[]{i,j});
                    }
                }
            }
            return list;
        }
    }
}

Eigentlich kann man den Konstruktor Fieldöffentlich machen. Es tut mir leid, dass ich die Dateien noch nicht aktualisiert habe, aber wir haben dies bereits besprochen!
Fehler

@flawr Oh cool, danke!
CommonGuy

2

SpiralCat

Bewegt sich spiralförmig. Es

  • Versucht, zum Kreis oben links zu wechseln
  • Wenn nicht möglich, wird versucht, zum oberen rechten Kreis zu gelangen
  • Wenn nicht möglich, wird versucht, zum rechten Kreis zu gelangen
  • Wenn nicht möglich, wird versucht, in den unteren rechten Kreis zu wechseln
  • Wenn nicht möglich, wird versucht, zum unteren linken Kreis zu gelangen

SpiralCat gegen Agamemnon:

SpiralCat gegen Agamemnon

package players;
/**
 * @author Cool Guy
 */

import main.Field;

public class SpiralCat implements Cat{
    public String getName(){
        return "SpiralCat";
    }
    public int[] takeTurn(Field f){
        int[][] turns = {{-1,1},{0,1},{1,0},{1,-1},{0,-1},{-1,0}};//all valid moves
        int[] move;
        int i = -1;
        do {
            i++;
            move = turns[i];
        } while(f.isValidMove(move) == false);
        return move;
    }
}

Wissen Sie, auf welche Bugs Sie gestoßen sind? Das einzige, was ich ändern würde, wäre zu ändern turns[i], turns[i%6]um Grenzen zu überschreiten (was in dieser Station NICHT vorkommen sollte).
Fehler

@flawr, verdammt. Schlechte Wortwahl. Ich meinte, dass diese Katze nicht sehr intelligent ist.
Manchmal

@flawr, muss ich verwenden turns[i%6]? Ich meine, takeTurnwerde nicht angerufen, wenn die Katze blockiert ist, oder?
Spikatrix

Nein, ich dachte, Sie meinten, Sie stießen auf einen Programmfehler, also suchte ich nach möglichen Gründen. Aber Sie haben natürlich Recht (wenn alles in Ordnung ist ) i>=6sollte nie passieren.
Fehler

2

RabidCat

RabidCat hat Hydrophobie, deshalb hat er Angst vor den Wassereimern. Er findet den nächsten und rennt in die entgegengesetzte Richtung.

RabidCat vs ForwordCatcher:

rabidcat_vs_forwordcatcher

package players;

import java.util.Random;

import main.Field;

/**
* Run away from water buckets
* @author cain
*
*/

public class RabidCat implements Cat {

public RabidCat() {
}

@Override
public String getName() {
    return "RabidCat";
}

@Override
public int[] takeTurn(Field f) {
    int[][] directions = {{-1,1},{0,1},{-1,0},{1,0},{0,-1},{1,-1}};

    //where am I?
    int[] position = {0,0};
    for(int i = 0; i < 12; i++){
        for(int j = 0; j < 12; j++){
            if(f.read(i,j) == -1){
                position[0] = i;
                position[1] = j;
            }
        }
    }

    //Find the closest water
    int direction = 0;
    for(int d = 0; d < 10; d++){
        if(f.read(position[0] + d, position[1] - d) == 1 && f.isValidMove(directions[0])){
            direction = 1;
            break;
        }
        if(f.read(position[0], position[1] - d) == 1 && f.isValidMove(directions[1])){
            direction = 2;
            break;
        }
        if(f.read(position[0] + d, position[1]) == 1 && f.isValidMove(directions[2])){
            direction = 3;
            break;
        }
        if(f.read(position[0] - d, position[1]) == 1 && f.isValidMove(directions[3])){
            direction = 4;
            break;
        }
        if(f.read(position[0], position[1] + d) == 1 && f.isValidMove(directions[4])){
            direction = 5;
            break;
        }
        if(f.read(position[0] - d, position[1] + d) == 1 && f.isValidMove(directions[5])){
            direction = 6;
            break;
        }
    }

    //If there is no water near, wander
    while(direction == 0){
        Random rand = new Random();
        direction = rand.nextInt(6) + 1;
        if(!f.isValidMove(directions[direction - 1])){
            direction = 0;
        }
    }
    return directions[direction - 1];
}

}

Wow, wird wirklich von CloseCatcher ruiniert
Cain

2

ChoiceCat

Für jede mögliche neue Katzenposition prüfen wir die Güte und wählen die beste aus. Güte ist die Funktion der beiden besten Nachbarzellen, die weiter von der Katzenposition entfernt sind als die Position, deren Punktzahl wir berechnen. Wir verwenden nur zwei Zellen, da eine blockiert werden kann und die Katze nur noch eine benötigt, um zu entkommen. Unsere Funktion bevorzugt zwei ziemlich gute Zellen als eine große und eine schlechte. Positionen mit Eimern haben eine Punktzahl von 0 und die am weitesten entfernten freien Zellen haben eine Punktzahl von 1.

ChoiceCat scheint besser zu punkten als die aktuellen Katzen.

ChoiceCat vs ChoiceCatcher:

ChoiceCat gegen ChoiceCatcher

package players;
/**
 * @author randomra
 */
import java.util.Arrays;

import main.Field;

public class ChoiceCat implements Cat {

    private class Values {
        public final int size;
        private double[][] f;

        Values(int size) {
            this.size = size;
            f = new double[size][size];
        }

        public double read(int[] p) {
            int i = p[0];
            int j = p[1];
            i = (i % size + size) % size;
            j = (j % size + size) % size;
            return f[i][j];
        }

        private double write(int[] p, double v) {
            int i = p[0];
            int j = p[1];
            i = (i % size + size) % size;
            j = (j % size + size) % size;
            return f[i][j] = v;
        }
    }

    final int[][] turns = { { -1, 1 }, { 0, 1 }, { 1, 0 }, { 1, -1 },
            { 0, -1 }, { -1, 0 } };// all valid moves CW order
    final int stepCheck = 5;

    public String getName() {
        return "ChoiceCat";
    }

    public int[] takeTurn(Field f) {

        int[] pos = f.findCat();
        int[] bestMove = { 0, 1 };
        double bestMoveValue = -1;
        for (int[] t : turns) {
            int[] currPos = { pos[0] + t[0], pos[1] + t[1] };
            double moveValue = movePosValue(currPos, f);
            if (moveValue > bestMoveValue) {
                bestMoveValue = moveValue;
                bestMove = t;
            }
        }
        return bestMove;
    }

    private double movePosValue(int[] pos, Field f) {

        Values v = new Values(f.SIZE);

        for (int ring = stepCheck; ring >= 0; ring--) {
            for (int phase = 0; phase < 2; phase++) {
                for (int sidepos = 0; sidepos < Math.max(1, ring); sidepos++) {
                    for (int side = 0; side < 6; side++) {
                        int[] evalPos = new int[2];
                        for (int coord = 0; coord < 2; coord++) {
                            evalPos[coord] = pos[coord] + turns[side][coord]
                                    * sidepos + turns[(side + 1) % 6][coord]
                                    * (ring - sidepos);
                        }
                        if (phase == 0) {
                            if (ring == stepCheck) {
                                // on outmost ring, init value
                                v.write(evalPos, -1);
                            } else {
                                v.write(evalPos, posValue(evalPos, v, f));
                            }
                        } else {
                            // finalize position value for next turn
                            v.write(evalPos, -v.read(evalPos));
                        }
                    }
                }
            }
        }

        return -v.read(pos);
    }

    private double posValue(int[] pos, Values v, Field f) {
        if (f.read(pos[0], pos[1]) == Field.BUCKET) {
            return 0;
        }
        int count = 0;
        double[] product = new double[6];
        for (int[] t : turns) {
            int[] tPos = new int[] { pos[0] + t[0], pos[1] + t[1] };
            if (v.read(tPos) > 0) {
                product[count] = 1 - 1 / (v.read(tPos) + 1);
                count++;
            }
        }
        Arrays.sort(product);
        double fp = 1;
        for (int i = 0; i < Math.min(count,2); i++) {
            fp *= product[5-i];
        }
        double retValue = Math.min(count,2) + fp;
        return -retValue;
    }
}

1

StupidRightCat

Dies wurde nur zum Testen des Controllers gemacht. Die Katze bewegt sich wann immer möglich nach rechts, ansonsten in eine zufällige Richtung.

package players;

import main.Field;

public class StupidRightCat implements Cat{
    public String getName(){
        return "StupidRightCat";
    }
    public int[] takeTurn(Field f){
        int[][] turns = {{-1,1},{0,1},{-1,0},{1,0},{0,-1},{1,-1}};//all valid moves
        int[] move;

        if(f.isValidMove(turns[3])){
            return turns[3];
        } else {
            do {
                move = turns[(int) (turns.length * Math.random())];
            } while(f.isValidMove(move)==false);
            return move;//chose one at random
        }
    }
}

1

RandCat

Dies wurde nur zum Testen des Controllers gemacht. Die Katze bewegt sich nur zufällig.

package players;

import main.Field;

public class RandCat implements Cat{
    public String getName(){
        return "RandCat";
    }
    public int[] takeTurn(Field f){
        int[][] turns = {{-1,1},{0,1},{-1,0},{1,0},{0,-1},{1,-1}};//all valid moves
        int[] move;
        do {
            move = turns[(int) (turns.length * Math.random())];
        } while(f.isValidMove(move)==false);
        return move;//chose one at random
    }
}

1

StraightCat

Diese Katze bewegt sich gerade.

Zu Beginn wählt es eine zufällige Richtung und bewegt sich so lange in diese Richtung, bis dies nicht mehr möglich ist. In diesem Fall verschiebt es die Richtung im Uhrzeigersinn in die nächste gültige Richtung und wiederholt diesen Vorgang.

StraightCat gegen Agamemnon:

StraightCat gegen Agamemnon

package players;
/**
 * @author Cool Guy
 */

import main.Field;

public class StraightCat implements Cat{

    int lastDirection = -1; //Holds the last direction the cat moved
    public String getName(){
        return "StraightCat";
    }
    public int[] takeTurn(Field f){
        int[][] turns = {{-1,1},{0,1},{1,0},{1,-1},{0,-1},{-1,0}};//all valid moves

        if(lastDirection == -1)
          lastDirection = (int) (turns.length * Math.random());

        int[] move = turns[lastDirection];
        int i = lastDirection;

        while(true)
        {
            if(f.isValidMove(move))
                break;
            i = (i+1)%6;
            lastDirection = i;
            move = turns[i];
        }
        return move;
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.