Nahrungsmittelknappheit in der Schlangengrube

17

Nahrungsmittelknappheit in der Schlangengrube

Zum ersten Mal seit 35 Jahren geht der Schlangengrube die Nahrung aus. Die einheimischen Schlangen müssen sich nun gegenseitig bekämpfen, um diese Nahrungsmittelknappheit zu überstehen. Nur eine Schlange kann an der Spitze der Nahrungskette stehen!


Bestenliste

Noch nicht hier!

Letzte Aktualisierung am 24. Februar

Link zu Visualisierungen der letzten Spiele


Beschreibung

Wenn Sie um die letzten verbleibenden Äpfel / Kirschen / was auch immer kämpfen möchten, müssen Sie eine Schlange in Form eines Programms bereitstellen, das eine bestimmte Eingabe akzeptiert und ihren nächsten Zug zurückgibt.

Die einzige Wendung ist, dass Sie in Ihrer Grube nicht allein sind. Eine andere Schlange wird auch versuchen, das seltene Futter zu bekommen! Aber es ist dunkel in der Schlangengrube, so dass Sie nur sich selbst und den Apfel sehen können. Ein Zusammenstoß mit deinem Gegner führt zu deinem Tod, genau wie wenn du dich beißt oder gegen eine Wand stößt. Weil Äpfel heutzutage selten sind, hungern Sie außerdem, wenn Ihr Gegner genug gegessen hat, um eine Länge von 7 zu erreichen.

Die Schlangengrube ist eine zweidimensionale Karte mit einer Breite und Höhe von 15, während die äußersten Kacheln eine unpassierbare Wand bilden:

  0 1 2 . . . c d e
0 # # # # # # # # #
1 #               #
2 #           x   #
. #               #
. #               #
. #               #
c #               #
d #               #
e # # # # # # # # #

Koordinaten sind nullindexiert, also der Punkt, an dem xsich das befindet 12,2.

Ihr Bot wird mit zwei Argumenten aufgerufen:

  • Die Lage des Essens
  • Die Positionen Ihrer Körpersegmente, getrennt durch /

Es sollte dann eine der folgenden Angaben zu stdout schreiben:

  • L für eine viertel Linkskurve als nächste Bewegung
  • R für eine viertel rechts abbiegen
  • Alles andere für eine Bewegung in die gleiche Richtung

Beispiel:

Projects/Snakepit> python bot.py 12,2 4,8/4,9/3,9/2,9
'R'
Projects/Snakepit>

Regeln

Ihr Bot darf:

  • Alles ausgeben, weil alles ein gültiger Zug ist
  • Lesen / Schreiben Sie Dateien in einem eigenen Verzeichnis, das sich unter ./snakes/ThisIsYourSnake befindet
  • Laufen auf Ubuntu 14.04 und Windows 7 (muss es eigentlich)

Ihr Bot darf nicht:

  • Dateien außerhalb des eigenen Verzeichnisses lesen / schreiben
  • Verwenden Sie externe Ressourcen wie das Internet
  • Haben Sie eine Laufzeit von mehr als 10 Sekunden pro Ausführung

Sie müssen in Ihrer Antwort angeben:

  • Der Quellcode des Bots
  • Ein Bot / Snake Name
  • (Dein eigener Name)
  • Ein Befehl, um Ihren Bot auszuführen

Wenn Sie mir das Leben erleichtern möchten, geben Sie bitte eine Zeile wie CoolSnake MyOwnName python bot.py.


Wertung

Deine Schlange bekommt einen Punkt, wenn sie ein Spiel gegen eine andere Schlange gewinnt. Ein Spiel wird unter folgenden Umständen gewonnen:

  • Ihr Gegner trifft sich selbst, Sie oder eine Wand
  • Sie erreichen die Länge 7

Außerdem verhungern beide Schlangen nach 200 Zyklen.

Jede Schlange kämpft gegen jede andere Schlange um ihr Überleben.


Beispiel Bots

Um Ihnen eine Idee zu geben, stelle ich diese beiden (teilnehmenden) Beispielschlangen zur Verfügung:

SneakySnake

#!/usr/bin/env python

import sys, random

def main(food, me) :
    food = [int(i) for i in food.split(",")]
    me = [[int(i) for i in seg.split(",")] for seg in me.split("/")]
    head = me[0]
    v = [head[0] - me[1][0], head[1] - me[1][1]]

    if food[0] < head[0] :
        vn = [-1, 0]
    elif food[0] > head[0] :
        vn = [1, 0]
    elif food[0] == head[0] :
        if food[1] < head[1] :
            vn = [0, -1]
        elif food[1] > head[1] :
            vn = [0, 1]

    if v == vn :
        return "..."
    elif [-v[1], v[0]] == vn :
        return "R"
    elif [v[1], -v[0]] == vn :
        return "L"
    else :
        return random.choice(("R", "L"))

if __name__ == "__main__" :
    print main(*sys.argv[1:3])

SneakySnake Cipher python bot.py

ViciousViper

#!/usr/bin/env python

import sys, random

def main(food, me) :
    food = [int(i) for i in food.split(",")]
    me = [[int(i) for i in seg.split(",")] for seg in me.split("/")]
    head = me[0]
    v = [head[0] - me[1][0], head[1] - me[1][1]]
    vn = [food[0] - head[0], food[1] - head[1]]
    if 0 not in vn :
        vn[v.index(0)-1] = 0
    vn[vn.index(0)-1] = vn[vn.index(0)-1] / abs(vn[vn.index(0)-1])

    if v == vn :
        return "..."
    elif [v[0] + vn[0], v[1] + vn[1]] == [0, 0] :
        return random.choice(("R", "L"))
    else :
        return "R" if [-v[1], v[0]] == vn else "L"

if __name__ == "__main__" :
    print main(*sys.argv[1:3])

ViciousViper Cipher python bot.py

Und ihre Übereinstimmungen:

Beispiel Match 1 Beispiel Match 2

Beispiel Match 3

Steuerungsprogramm

Sie finden das Steuerungsprogramm auf github sowie alle Bots und Aufzeichnungen vergangener Spiele.

Bedarf:

  • Python 2 + die Bibliotheken numpyund pillow(Sie können überprüfen, ob sie über vorhanden sindpython -c "import numpy, PIL" , wenn es Fehler auslöst, fehlen die Module)
  • Damit die Steuerung funktioniert, muss die gesamte Ordnerstruktur kopiert werden
  • Registrieren Sie Ihren / Ihre Bot (s) im ./snakes/list.txt Datei im Stil vonCoolSnake MyOwnName Command To Run My Bot
  • Platzieren Sie Ihren Bot in einem Verzeichnis mit dem Namen unter ./snakes
  • Weder Ihr noch der Name Ihres Bots dürfen Leerzeichen enthalten!

Verwendung:

python run.py [-h] [-n int] [-s int] [-l int] [-c int] [-g]

python run.pyführt das Turnier mit allen in list.txt registrierten Bots und den Standardeigenschaften aus. Erweiterte Optionen sind:

  • -h Zeigt eine Hilfemeldung an
  • -n int Kampfrunden für jede Kombination von Gegnern
  • -s int bestimmt die Größe des Rasters (Breite und Höhe)
  • -l int Legt die erforderliche Länge fest, um zu gewinnen
  • -c int Legt die Grenze der Zyklen fest
  • -goder --no-gifserstellt keine Gifs der Übereinstimmungen
Chiffre
quelle
12
Ich bin mir nicht sicher, wie viele interessante Interaktionsstrategien Sie erhalten, wenn Bots fast keine Möglichkeit haben zu wissen, wo sich andere Bots befinden.
Martin Ender
6
Da wir auf Länge <7 begrenzt sind, ist es nur wichtig zu wissen, wo der Gegner ist, um zu vermeiden. Du bist nicht lange genug, um etwas anderes als das einfachste Blockieren zu tun. Ich vermute, dass die meisten Übereinstimmungen nur darauf zurückzuführen sind, wer dem jeweiligen Essen am nächsten war, als es auftauchte.
Geobits
7
Ich hatte einen erstaunlichen Plan, wie ich das wirklich gut machen kann. Dann lese ich die Regeln mehr. Wenn Sie die andere Schlange nicht sehen können, haben Sie folgende Optionen: "Nehmen Sie den direkten Weg" oder "Nehmen Sie einen längeren Weg". Keiner von beiden ist sehr interessant, wenn es nur dummes Glück ist, der anderen Schlange auszuweichen.
Captncraig
8
Ich glaube nicht, dass ihr das durchdacht habt. Wenn dein Feind einen Apfel nimmt, weißt du genau, wo er ist. Sie können dann den Weg vorhersagen, den er zum aktuellen Apfel nehmen wird. Sie können herausfinden, dass Sie es zuerst erreichen können, ohne dass die Gefahr einer Kollision besteht, oder Sie können eine Falle stellen, indem Sie Ihren Schwanz über seinen wahrscheinlichen Weg ziehen. Sie können seine Strategie auch danach einschätzen, wie lange er braucht, um einen Apfel zu bekommen, oder wann er in früheren Spielen mit Ihrem Schwanz kollidiert ist. Und natürlich weiß er, dass Sie wissen, dass er weiß ... usw. Ausgezeichnete Puzzle-Chiffre +1.
Logic Knight
4
Ich denke darüber nach, ein getrenntes Turnier mit mehr Fokus auf das ursprüngliche Spiel zu erstellen und Dinge wie den Gegner zu sehen, das Längenlimit zu erhöhen usw. Interessiert?
Chiffre

Antworten:

6

Zen - C ++Bildbeschreibung hier eingeben

Dieses Codémon ist nicht hier, um zu essen, sondern um zu kämpfen. Er weiß, dass ein toter Feind seine Äpfel nicht stehlen wird.


Name| Author |Launch with

Zen GholGoth21 Zen.exe


Strategie

Alle (außer CircleOfLife) eilen zu den Äpfeln, aber nicht immer zu Zen. Wenn der Feind das Essen vor sich erreichen kann, wartet er einfach in der Mitte (was? Aber was machst du hier, CircleOfLife?). Ansonsten geht Zen zum Apfel und dreht sich um, während er darauf wartet, dass etwas passiert. Tatsächlich benutzt er den Apfel als Köder.

Ich habe nichts gegen die merkwürdige Strategie von CircleOfLife geschrieben, weil er nur mit sehr viel Glück gewinnen kann.

Der Code

Dies ist der vollständige Code des C ++ - Projekts. Schneide die 11 Quelldateien und das Makefile aus und kompiliere mitmake

$ cat src/* Makefile
/* 
 * @file    Enemy.cpp
 * @author  GholGoth21
 * @date    Créé le 1 mars 2015 à 14:10
 */

#include "Enemy.h"

#include <fstream>

Enemy::Enemy()
{
}

Enemy::~Enemy()
{
}

std::ostream &operator<<(std::ostream &os, const Enemy& e)
{
    return os<<e.m_pos<<" "<<e.m_date;
}

std::istream &operator>>(std::istream &is, Enemy& e)
{
    return is>>e.m_pos>>e.m_date;
}

int Enemy::distTo(int2 const &target, int date) const
{
    return m_pos.distTo(target)-(date-m_date);
}

bool Enemy::recentActivity(int2 const &pos, int date, int maxDelay) const
{
    return pos.distTo(m_pos)<=date-m_date && date-m_date<=maxDelay;
}
/* 
 * @file    Enemy.h
 * @author  GholGoth21
 * @date    Créé le 1 mars 2015 à 14:10
 */

#ifndef ENEMY_H
#define ENEMY_H

#include "int2.h"

class Enemy
{
public:
    Enemy();
    virtual ~Enemy();

public:
    void setPos(int2 const &pos, int date) { m_pos=pos; m_date=date; }
    int distTo(int2 const &target, int date) const;
    int2 const &pos() const { return m_pos; }
    bool recentActivity(int2 const &pos, int date, int maxDelay) const;
    friend std::ostream &operator<<(std::ostream &os, const Enemy& e);
    friend std::istream &operator>>(std::istream &is, Enemy& e);

private:
    int2 m_pos;
    int m_date;
};

#endif  /* ENEMY_H */
/* 
 * @file    Snake.cpp
 * @author  GholGoth21
 * @date    Créé le 28 février 2015 à 17:47
 */

#include "Snake.h"
#include "enums.h"
#include "StrManip.h"
#include "Enemy.h"

#include <vector>
#include <cmath>

Snake::Snake(std::string const &body)
{
    std::vector<std::string> posList;
    split(body, '/', posList);
    for(auto &pos : posList)
        m_body.push_back(int2(pos));
}

Snake::~Snake()
{
}

Command Snake::move(int2 food, int date, Enemy const &enemy)
{
    Command bestCommand[Command::count];

    int myDist=curPos().distTo(food);
    int enemyDist=enemy.distTo(food,date);

    if(myDist>=enemyDist && enemyDist>2)
    {
        orderCommand(int2(MAPSIZE/2,MAPSIZE/2), bestCommand);
        for(int i=0; i<Command::count; i++)
            if(validCommand(bestCommand[i]) && !enemy.recentActivity(nextPos(bestCommand[i]),date,5))
                return bestCommand[i];
    }
    if((myDist==1 && enemyDist>((len()-1)/2)*2+3) || enemyDist<-5)
    {
        orderCommand(food, bestCommand);
        for(int i=0; i<Command::count; i++)
            if(validCommand(bestCommand[i]))
                return bestCommand[i];
    }
    int2 embushPoint;
    int minDist=-1;
    foreach_enum(Direction, d)
    {
        int2 point(food+d.vector());
        int dist=point.quadDistTo(enemy.pos());
        if(dist<minDist || minDist<0)
        {
            minDist=dist;
            embushPoint=point;
        }
    }
    if(curPos().distTo(embushPoint)<enemy.distTo(embushPoint,date)-((len()-1)/2)*2)
    {
        int minimalAction=-1;
        int qMinDist = curPos().quadDistTo(embushPoint);
        Command minimalCommand;
        foreach_enum(Command, c)
        {
            int2 np=nextPos(c);
            int qDist = np.quadDistTo(embushPoint);
            if((qDist<minimalAction || minimalAction<0) && qDist>qMinDist && validCommand(c))
            {
                minimalAction=qDist;
                minimalCommand=c;
            }
        }
        return minimalCommand;
    }
    else
    {
        orderCommand(embushPoint, food, bestCommand);
        for(int i=0; i<Command::count; i++)
            if(validCommand(bestCommand[i]) && nextPos(bestCommand[i])!=food)
                return bestCommand[i];
    }



    return Command::forward;
}

bool Snake::validCommand(Command c) const
{
    if(!c.isValid())
        return false;
    int2 np = nextPos(c);
    if(!(0<np.x && np.x<MAPSIZE-1 && 0<np.y && np.y<MAPSIZE-1))
        return false;
    for(unsigned int i=2; i<m_body.size()-1; i++)
        if(np==m_body.at(i))
            return false;
    return true;
}

bool Snake::isStarting() const
{
    if(m_body.size()==3)
    {
        if(m_body.at(0)==int2(3,(MAPSIZE)/2) && m_body.at(1)==int2(2,(MAPSIZE)/2) && m_body.at(2)==int2(1,(MAPSIZE)/2))
            return true;
        else if(m_body.at(0)==int2(MAPSIZE-4,(MAPSIZE)/2) && m_body.at(1)==int2(MAPSIZE-3,(MAPSIZE)/2) && m_body.at(2)==int2(MAPSIZE-2,(MAPSIZE)/2))
            return true;
    }
    return false;
}

void Snake::orderCommand(int2 target, Command *tab)
{
    int weight[Command::count];
    foreach_enum(Command, c)
    {
        int2 np = nextPos(c);
        weight[c]=np.quadDistTo(target);
        tab[c]=c;
    }
    for(int i=0; i<Command::count-1; i++)
    {
        while(i>=0 && weight[tab[i]]>weight[tab[i+1]])
        {
            varSwitch(tab[i], tab[i+1]);
            i--;
        }
    }
}

void Snake::orderCommand(int2 target1, int2 target2, Command *tab)
{
    int weight[Command::count];
    foreach_enum(Command, c)
    {
        int2 np = nextPos(c);
        weight[c]=np.quadDistTo(target1)+np.quadDistTo(target2);
        tab[c]=c;
    }
    for(int i=0; i<Command::count-1; i++)
    {
        while(i>=0 && weight[tab[i]]>weight[tab[i+1]])
        {
            varSwitch(tab[i], tab[i+1]);
            i--;
        }
    }
}
/* 
 * @file    Snake.h
 * @author  GholGoth21
 * @date    Créé le 28 février 2015 à 17:47
 */

#ifndef SNAKE_H
#define SNAKE_H

#include "int2.h"

#include <vector>

#define MAPSIZE 15

class Enemy;

class Snake
{
public:
    Snake(std::string const &body);
    virtual ~Snake();

public:
    Command move(int2 food, int date, Enemy const &enemy);
    Direction curDir() const { return (m_body.at(0)-m_body.at(1)).direction(); }
    int2 curPos() const { return m_body.at(0); }
    int2 nextPos(Command c) const { return curPos()+curDir().applyCommand(c).vector(); }
    bool validCommand(Command c) const;
    bool isStarting() const;
    void orderCommand(int2 target, Command *tab);
    void orderCommand(int2 target1, int2 target2, Command *tab);
    int len() const { return m_body.size(); }

private:
    std::vector<int2> m_body;
};

#endif  /* SNAKE_H */
/* 
 * @file    StrManip.cpp
 * @author  GholGoth21
 * @date    Créé le 7 février 2015 à 17:26
 */

#include "StrManip.h"

#include <sstream>

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim))
        elems.push_back(item);
    return elems;
}

int atoi(std::string const &text)
{
    std::stringstream ss(text);
    int val;
    ss >> val;
    return val;
}
/* 
 * @file    StrManip.h
 * @author  GholGoth21
 * @date    Créé le 7 février 2015 à 17:26
 */

#ifndef STRMANIP_H
#define STRMANIP_H

#include <string>
#include <vector>

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems);
int atoi(std::string const &text);

#endif  /* STRMANIP_H */
/* 
 * @file    enums.cpp
 * @author  GholGoth21
 * @date    Créé le 28 février 2015 à 17:55
 */

#include "enums.h"
#include "int2.h"

Command Direction::turnTo(Direction newDir) const
{
    if(!isValid() || !newDir.isValid())
        return Command::count; //Invalid
    else if((m_value==Direction::up && newDir==Direction::left) || (m_value==Direction::left && newDir==Direction::down) ||
            (m_value==Direction::down && newDir==Direction::right) || (m_value==Direction::right && newDir==Direction::up))
        return Command::left;
    else if((m_value==Direction::up && newDir==Direction::right) || (m_value==Direction::right && newDir==Direction::down) ||
            (m_value==Direction::down && newDir==Direction::left) || (m_value==Direction::left && newDir==Direction::up))
        return Command::right;
    else if(m_value==newDir)
        return Command::forward;
    else
        return Command::count; // Invalid
}

Direction Direction::applyCommand(Command c) const
{
    if(c==Command::forward)
        return m_value;
    else if(c==Command::left)
    {
        switch(m_value)
        {
            case Direction::left:
                return Direction::down;
            case Direction::up:
                return Direction::left;
            case Direction::right:
                return Direction::up;
            case Direction::down:
                return Direction::right;
            default:
                break;
        }
    }
    else if(c==Command::right)
    {
        switch(m_value)
        {
            case Direction::left:
                return Direction::up;
            case Direction::up:
                return Direction::right;
            case Direction::right:
                return Direction::down;
            case Direction::down:
                return Direction::left;
            default:
                break;
        }
    }
    return Direction::count; // Invalid
}

int2 Direction::vector() const
{
    switch(m_value)
    {
        case Direction::left:
            return int2(-1,0);
        case Direction::up:
            return int2(0,-1);
        case Direction::right:
            return int2(1,0);
        case Direction::down:
            return int2(0,1);
        default:
            return int2(0,0);
    }
}

std::ostream &operator<<(std::ostream &os, const Command& c)
{
    switch(c.m_value)
    {
        case Command::left:
            return os<<"L";
        case Command::right:
            return os<<"R";
        default:
            return os<<"F";
    }
}
/* 
 * @file    enums.h
 * @author  GholGoth21
 * @date    Créé le 28 février 2015 à 17:55
 */

#ifndef ENUMS_H
#define ENUMS_H

#include <ostream>

struct int2;

#define DECL_ENUM_STRUCT(_name) \
_name() : m_value(static_cast<Type>(0)) {} \
_name(Type value) : m_value(value) {} \
_name(int value) : m_value(static_cast<Type>(value)) {} \
static Type begin() { return static_cast<Type>(0); } \
static Type end() { return count; } \
_name &operator++() { m_value=static_cast<Type>(static_cast<int>(m_value)+1); return *this; } \
operator int() const { return static_cast<Type>(m_value); } \
Type m_value;

#define foreach_enum(_type,_var) for(_type _var = _type::begin(); _var<_type::end(); ++_var)

struct Command
{
    enum Type
    {
        left,
        forward,
        right,
        count
    };

    bool isValid() const { return m_value<count; }
    friend std::ostream &operator<<(std::ostream &os, const Command& c);

    DECL_ENUM_STRUCT(Command)
};

struct Direction
{
    enum Type
    {
        left,
        up,
        right,
        down,
        count
    };

    bool isValid() const { return m_value<count; }
    Command turnTo(Direction newDir) const;
    Direction applyCommand(Command c) const;
    int2 vector() const;
    DECL_ENUM_STRUCT(Direction)
};

#endif  /* ENUMS_H */
/* 
 * @file    int2.cpp
 * @author  GholGoth21
 * @date    Créé le 28 février 2015 à 17:37
 */

#include "int2.h"
#include "enums.h"
#include "StrManip.h"

#include <vector>
#include <cmath>

int2::int2()
{
}

int2::~int2()
{
}

int2::int2(std::string const &text)
{
    std::vector<std::string> posList;
    split(text, ',', posList);
    x=atoi(posList.at(0));
    y=atoi(posList.at(1));
}

Direction int2::direction() const
{
    if(x==0 && y==0)
        return Direction::count; // Invalid
    else if(y>=std::abs(x))
        return Direction::down;
    else if(x>=std::abs(y))
        return Direction::right;
    else if(x<=-std::abs(y))
        return Direction::left;
    else
        return Direction::up;
}

Direction int2::secondary() const
{
    if(x==0 || y==0)
        return Direction::count; //Invalid
    else if(y<=std::abs(x) && y>=0)
        return Direction::down;
    else if(x<=std::abs(y) && x>=0)
        return Direction::right;
    else if(x>=-std::abs(y) && x<=0)
        return Direction::left;
    else
        return Direction::up;
}

int int2::distTo(int2 const &other) const
{
    return std::abs(x-other.x)+std::abs(y-other.y);
}

int int2::quadDistTo(int2 const &other) const
{
    return sq(x-other.x)+sq(y-other.y);
}

int2 int2::operator+(int2 const &other) const
{
    return int2(x+other.x,y+other.y);
}

int2 int2::operator-(int2 const &other) const
{
    return int2(x-other.x,y-other.y);
}

std::ostream &operator<<(std::ostream &os, const int2& c)
{
    return os<<c.x<<","<<c.y;
}

std::istream &operator>>(std::istream &is, int2& c)
{
    std::string text;
    is>>text;
    c=int2(text);
    return is;
}
/* 
 * @file    int2.h
 * @author  GholGoth21
 * @date    Créé le 28 février 2015 à 17:37
 */

#ifndef INT2_H
#define INT2_H

#include "enums.h"

#include <string>

struct int2
{
public:
    int2();
    int2(int p_x, int p_y) : x(p_x), y(p_y) {}
    int2(std::string const &text);
    virtual ~int2();

public:
    Direction direction() const;
    Direction secondary() const;
    int distTo(int2 const &other) const;
    int quadDistTo(int2 const &other) const;
    int2 operator+(int2 const &other) const;
    int2 operator-(int2 const &other) const;
    bool operator==(int2 const &other) const { return x==other.x && y==other.y; }
    bool operator!=(int2 const &other) const { return x!=other.x || y!=other.y; }
    friend std::ostream &operator<<(std::ostream &os, const int2& c);
    friend std::istream &operator>>(std::istream &is, int2& c);

public:
    int x;
    int y;
};

inline int sq(int val) { return val*val; }
template<typename T>
inline void varSwitch(T &a, T &b) { T tmp=a; a=b; b=tmp; }

#endif  /* INT2_H */
/* 
 * @file    main.cpp
 * @author  GholGoth21
 * @date    Créé le 28 février 2015 à 17:23
 */

#include "int2.h"
#include "Snake.h"
#include "Enemy.h"

#include <cstdlib>
#include <iostream>
#include <fstream>

using namespace std;

/*
 * @brief La fonction principale du programme.
 * @param argc Le nombre de paramètres passés en ligne de commandes.
 * @param argv La liste des paramètres passés en ligne de commandes.
 */
int main(int argc, char** argv)
{
    /* Error handling */
    if(argc<3)
    {
        cerr<<"Error : not enough arguments on the command line."<<endl;
        cout<<"F"<<endl;
        return 1;
    }

    /* Init and load */
    int2 prevFood;
    int date = 0;
    Enemy enemy;
    ifstream load("PreviousState.txt");
    if(load)
    {
        load>>date;
        load>>prevFood;
        load>>enemy;
        load.close();
    }
    int2 food(argv[1]);
    Snake me(argv[2]);
    if(me.isStarting())
    {
        date=0;
        if(me.curPos().x<MAPSIZE/2)
            enemy.setPos(int2(MAPSIZE-4,MAPSIZE/2), 0);
        else
            enemy.setPos(int2(3,MAPSIZE/2), 0);
    }
    else if(prevFood!=food && me.curPos()!=prevFood)
    {
        enemy.setPos(prevFood, date);
    }

    /* Moving */
    cout<<me.move(food,date,enemy)<<endl;

    /* Saving */
    ofstream save("PreviousState.txt");
    if(save)
    {
        save<<++date<<endl;
        save<<food<<endl;
        save<<enemy<<endl;
        save.close();
    }
    return 0;
}
# Makefile
HEADERS = $(wildcard $(SRCPATH)/*.h)
SOURCES = $(wildcard $(SRCPATH)/*.cpp)
OBJECTS = $(patsubst $(SRCPATH)/%.cpp,$(BUILDPATH)/%.o,$(SOURCES))
M = Makefile

CFLAGS = -Wall -std=c++11

BINPATH = bin
BUILDPATH = build
SRCPATH = src

ifeq ($(OS),Windows_NT)
EXE = Zen.exe
else
EXE = Zen
endif


$(BINPATH)/$(EXE): $(BINPATH) $(BUILDPATH) $(OBJECTS)
    g++ -o $@ $(OBJECTS)

$(BUILDPATH)/%.o: $(SRCPATH)/%.cpp $(HEADERS) $M
    g++ $(CFLAGS) -o $@ -c $<

$(BINPATH) $(BUILDPATH):
    mkdir $@

clean:
    rm $(OBJECTS)

Oder laden Sie die Zip-Datei herunter: Zen.zip

Ergebnisse

|     Name     |   Master   | Score |
|--------------|------------|-------|
| Zen          | GholGoth21 | 24    |
| SneakySnake  | Cipher     | 10    |
| ViciousViper | Cipher     | 6     |
| CircleOfLife | Manu       | 4     |

Und einige typische Schlachten (ViciousViper vs Zen und SneakySnake vs Zen):

ViciousViper gegen Zen SneakySnake vs Zen

Edit : Ich füge diesen sehr interessanten Kampf gegen CircleOfLife hinzu:

Bildbeschreibung hier eingeben

GholGoth21
quelle
Gute Strategie. Könnten Sie Ihr Projekt irgendwo als Zip hochladen, damit andere es einfacher verwenden können?
Randomra
4

CircleOfLife (Java)

CircleOfLife Manu java CircleOfLife(Kompilieren mit javac CircleOfLife.java)

Läuft in die Mitte und bleibt dort. Ich hoffe, dass einige Einreichungen auf dem Weg zum Essen darauf stoßen werden.

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;  

public class CircleOfLife {
    private static final int UP = 0;
    private static final int DOWN = 1;
    private static final int LEFT = 2;
    private static final int RIGHT = 3;
    private static final String GO_RIGHT = "R";
    private static final String GO_LEFT = "L";
    private static final String GO_FORWARD = "F";
    private static int currentDirection = UP;
    private static List<Point> snakeParts = new ArrayList<>();

    public static void main(String[] args) {
        String[] parts = args[1].split("/");
        for (String part : parts) {
            String[] pos = part.split(",");
            int x = Integer.parseInt(pos[0]);
            int y = Integer.parseInt(pos[1]);
            snakeParts.add(new Point(x,y));
        }
        Point head = snakeParts.get(0);
        Point neck = snakeParts.get(1);
        if (head.y - neck.y == 1) {
            currentDirection = DOWN;
        } else if (head.x - neck.x == -1) {
            currentDirection = LEFT;
        } else if (head.x - neck.x == 1) {
            currentDirection = RIGHT;
        }
        if (isInMiddle(head)) {
            makeCircle();
        } else {
            runToMiddle();
        }
    }

    private static void makeCircle() {
        if (!isInMiddle(snakeParts.get(1))) {
            System.out.println(GO_FORWARD);
            return;
        }
        Point head = snakeParts.get(0);
        Point neck = snakeParts.get(1);
        String output = GO_FORWARD;
        if (head.x == 8 && neck.x == 8) {
            output = currentDirection == UP ? GO_LEFT : GO_RIGHT;
        } else if (head.x == 7 && neck.x == 7) {
            output = currentDirection == UP ? GO_RIGHT : GO_LEFT;           
        } else if (head.y == 8 && neck.y == 8) {
            output = currentDirection == RIGHT ? GO_LEFT : GO_RIGHT;        
        } else if (head.y == 7 && neck.y == 7) {
            output = currentDirection == RIGHT ? GO_RIGHT : GO_LEFT;        
        }
        System.out.println(output);
    }

    private static void runToMiddle() {
        Point head = snakeParts.get(0);
        int dX = 8 - head.x;
        int dY = 8 - head.y;
        String output = GO_FORWARD;

        if (Math.abs(dX) > Math.abs(dY)) {
            switch (currentDirection) {
                case DOWN: output = dX < 0 ? GO_RIGHT : GO_LEFT; break;
                case UP: output = dX < 0 ? GO_LEFT : GO_RIGHT; break;
                case RIGHT: output = dX < 0 ? GO_RIGHT : GO_FORWARD; break;
                case LEFT: output = dX < 0 ? GO_FORWARD : GO_RIGHT; break;
            }
        } else {
            switch (currentDirection) {
                case DOWN: output = dY < 0 ? GO_RIGHT : GO_FORWARD; break;
                case UP: output = dY < 0 ? GO_FORWARD : GO_RIGHT; break;
                case RIGHT: output = dY < 0 ? GO_LEFT : GO_RIGHT; break;
                case LEFT: output = dY < 0 ? GO_RIGHT : GO_LEFT; break;
            }
        }
        System.out.println(output);
    }

    public static boolean isInMiddle(Point snakePart) {
        if ((snakePart.x == 7 || snakePart.x == 8) && 
                (snakePart.y == 7 || snakePart.y == 8)) {
            return true;
        }
        return false;
    }
}
CommonGuy
quelle