การขาดแคลนอาหารใน Snakepit


17

การขาดแคลนอาหารใน Snakepit

เป็นครั้งแรกในรอบ 35 ปีที่ snakepit หมดอาหาร งูที่อาศัยอยู่ในขณะนี้จะต้องต่อสู้กันเพื่อให้สามารถอยู่รอดการขาดแคลนอาหารนี้ มีงูหนึ่งตัวเท่านั้นที่สามารถยืนอยู่บนห่วงโซ่อาหาร


ลีดเดอร์บอร์ด

ไม่ได้อยู่ที่นี่!

อัปเดตล่าสุดเมื่อวันที่ 24 กุมภาพันธ์

ลิงก์ไปยังการสร้างภาพข้อมูลของการแข่งขันครั้งสุดท้าย


ลักษณะ

หากคุณต้องการต่อสู้เพื่อแอปเปิ้ล / เชอร์รี่ / สิ่งที่เหลืออยู่สุดท้ายคุณต้องเตรียมงูในรูปแบบของโปรแกรมที่รับอินพุตที่กำหนดและส่งกลับการเคลื่อนที่ครั้งต่อไป

สิ่งเดียวที่ทำให้คุณไม่ได้อยู่คนเดียวในหลุม งูอีกตัวจะพยายามหาอาหารที่หายากด้วย! แต่มันมืดอยู่ข้างใน Snakepit ดังนั้นคุณจะเห็นได้แค่ตัวคุณและแอปเปิ้ลเท่านั้น การปะทะกับคู่ต่อสู้ของคุณจะส่งผลให้คุณเสียชีวิตเช่นกัดตัวเองหรือกระแทกกำแพง นอกจากนี้เนื่องจากแอปเปิ้ลเป็นของหายากในวันนี้คุณต้องอดอาหารถ้าคู่ต่อสู้ของคุณกินพอถึงความยาว 7

Snakepit เป็นแผนที่สองมิติที่มีความกว้างและความสูง 15 ในขณะที่กระเบื้องชั้นนอกสุดสร้างกำแพงที่ไม่สามารถใช้ได้:

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

พิกัดศูนย์จัดทำดัชนีเพื่อให้จุดที่เป็นจะเป็นx12,2

บอทของคุณจะถูกเรียกด้วยข้อโต้แย้งสองประการ:

  • ที่ตั้งของอาหาร
  • ตำแหน่งของส่วนร่างกายของคุณคั่นด้วย /

จากนั้นควรเขียนหนึ่งในสิ่งต่อไปนี้เพื่อ stdout:

  • L สำหรับไตรมาสที่เหลือเลี้ยวเป็นย้ายต่อไป
  • R สำหรับเลี้ยวขวาหนึ่งในสี่
  • สิ่งอื่นใดสำหรับการเคลื่อนที่ในทิศทางเดียวกัน

ตัวอย่าง:

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

กฎระเบียบ

บอทของคุณได้รับอนุญาตให้:

  • เอาท์พุทอะไรก็ได้เพราะอะไรก็ตามที่เป็นการเคลื่อนไหวที่ถูกต้อง
  • อ่าน / เขียนไฟล์ในไดเรกทอรีของตัวเองซึ่งอยู่ภายใต้. /snakes/ThisIsYourSnake
  • ทำงานบน Ubuntu 14.04 และ Windows 7 (จริง ๆ แล้วต้อง)

บอทของคุณต้องไม่:

  • อ่าน / เขียนไฟล์นอกไดเรกทอรีของตัวเอง
  • ใช้ทรัพยากรภายนอกเช่นอินเทอร์เน็ต
  • มีรันไทม์ที่สูงกว่า 10 วินาทีต่อการดำเนินการ

คุณต้องให้คำตอบของคุณ:

  • รหัสแหล่งที่มาของบอท
  • ชื่อบอท / งู
  • (ชื่อของคุณเอง)
  • คำสั่งให้รันบอทของคุณ

CoolSnake MyOwnName python bot.pyหากคุณต้องการที่จะทำให้ชีวิตง่ายขึ้นโปรดให้สายเช่น


เกณฑ์การให้คะแนน

งูของคุณได้รับคะแนนสำหรับการชนะเกมกับงูอีกตัว เกมชนะในสถานการณ์ต่อไปนี้:

  • คู่ต่อสู้ของคุณปะทะตัวเองคุณหรือกำแพง
  • คุณมาถึงความยาว 7

นอกจากนี้งูทั้งสองยังอดตายหลังจาก 200 รอบ

งูแต่ละตัวจะต่อสู้ 10 แมทช์เพื่อความอยู่รอดของพวกเขากับงูแต่ละตัว


บอทตัวอย่าง

เพียงเพื่อให้ความคิดแก่คุณฉันจะให้งูตัวอย่าง (เข้าร่วม) ทั้งสองนี้:

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

และการแข่งขันของพวกเขา:

ตัวอย่างการจับคู่ 1 ตัวอย่างการจับคู่ 2

ตัวอย่างการจับคู่ 3

โปรแกรมควบคุม

คุณสามารถค้นหาโปรแกรมควบคุมบนGitHubพร้อมกับบอทและบันทึกการแข่งขันที่ผ่านมาทั้งหมด

ที่ต้องการ:

  • Python 2 + ไลบรารีnumpyและpillow(คุณสามารถตรวจสอบได้ว่ามีอยู่python -c "import numpy, PIL"หรือไม่หากมีข้อผิดพลาดจะทำให้โมดูลหายไป)
  • จำเป็นต้องคัดลอกโครงสร้างโฟลเดอร์แบบเต็มเพื่อให้คอนโทรลเลอร์ทำงานได้
  • ลงทะเบียน bot ของคุณใน./snakes/list.txtไฟล์ในรูปแบบของCoolSnake MyOwnName Command To Run My Bot
  • วางบอทของคุณไว้ในไดเรกทอรีที่มีชื่อภายใต้ ./snakes
  • ไม่อนุญาตให้คุณหรือชื่อบอทของคุณไม่มีช่องว่าง!

การใช้งาน:

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

python run.pyจะจัดการแข่งขันโดยบอตทั้งหมดที่ลงทะเบียนใน list.txt และคุณสมบัติมาตรฐาน ตัวเลือกขั้นสูงคือ:

  • -h แสดงข้อความช่วยเหลือ
  • -n int รอบการต่อสู้สำหรับแต่ละคู่ต่อสู้
  • -s int กำหนดขนาดของกริด (ความกว้างและความสูง)
  • -l int กำหนดความยาวที่ต้องการเพื่อชนะ
  • -c int กำหนดขีด จำกัด ของรอบ
  • -gหรือ--no-gifsสร้าง gif ของการแข่งขันไม่ได้

12
ฉันไม่แน่ใจว่าคุณจะได้รับกลยุทธ์การโต้ตอบที่น่าสนใจมากแค่ไหนหากบอทแทบจะไม่มีทางรู้ว่าบอทตัวอื่นอยู่ที่ไหน
Martin Ender

6
เนื่องจากเราถูกจำกัดความยาว <7 แม้จะรู้ว่าคู่ต่อสู้เป็นเรื่องสำคัญสำหรับการหลีกเลี่ยงเท่านั้น คุณไม่นานพอที่จะทำอะไร แต่ง่ายที่สุดในการปิดกั้น ฉันสงสัยว่าการแข่งขันส่วนใหญ่จะลงมากับผู้ที่ใกล้เคียงกับอาหารแต่ละชนิดมากที่สุดเท่าที่มันวางไข่
Geobits

7
ฉันมีแผนที่น่าทึ่งสำหรับวิธีการทำดีจริงๆในเรื่องนี้ จากนั้นฉันก็อ่านกฏเพิ่มเติม หากคุณไม่เห็นงูตัวอื่นของคุณตัวเลือกของคุณคือ "ใช้เส้นทางตรง" หรือ "ใช้เส้นทางที่ยาวกว่า" ไม่น่าสนใจมากหากเป็นเพียงโชคใบ้ที่หลีกเลี่ยงงูตัวอื่น
captncraig

8
ฉันไม่คิดว่าพวกคุณจะคิดอย่างนี้ เมื่อศัตรูของคุณใช้แอปเปิ้ลคุณรู้ว่าเขาอยู่ที่ไหน จากนั้นคุณสามารถทำนายเส้นทางที่เขาจะนำไปสู่แอปเปิ้ลปัจจุบัน คุณอาจเข้าใจว่าคุณสามารถเข้าถึงมันได้โดยไม่เกิดการชนหรือคุณอาจวางกับดักโดยการลากหางของคุณข้ามเส้นทางที่น่าจะเป็น คุณสามารถประเมินกลยุทธ์ของเขาโดยใช้เวลานานกว่าที่เขาจะได้แอปเปิ้ลหรือเมื่อเขาชนกับหางของคุณในเกมก่อนหน้า และแน่นอนเขารู้ว่าคุณรู้ว่าเขารู้ ... ฯลฯ ปริศนาตัวเลขยอดเยี่ยม +1
Logic Knight อัศวิน

4
ฉันกำลังคิดเกี่ยวกับการสร้างทัวร์นาเมนต์ที่แยกจากกันโดยให้ความสำคัญกับเกมต้นฉบับมากขึ้นและสิ่งต่าง ๆ เช่นการเห็นคู่ต่อสู้ของคุณขีดจำกัดความยาวที่เพิ่มขึ้น ฯลฯ ใครที่สนใจ?
ลับ

คำตอบ:


6

เซน - C ++ป้อนคำอธิบายรูปภาพที่นี่

นี้Codémonไม่อยู่ที่นี่จะกิน แต่ที่จะต่อสู้ เขารู้ว่าศัตรูที่ตายแล้วจะไม่ขโมยแอปเปิ้ลของเขา


Name| Author |Launch with

Zen GholGoth21 Zen.exe


กลยุทธ์

ทุกคน (ยกเว้น CircleOfLife) รีบไปที่แอปเปิ้ล แต่ไม่ใช่ Zen ไม่ใช่ทุกครั้ง ถ้าศัตรูสามารถไปถึงอาหารต่อหน้าเขาได้เขาก็รอที่จุดศูนย์กลาง (อะไรนะ แต่คุณกำลังทำอะไรที่นี่ CircleOfLife?) อื่นเซนไปที่แอปเปิ้ลและหันไปรอบ ๆ ในขณะที่รอสิ่งที่เกิดขึ้น ในความเป็นจริงเขาใช้แอปเปิ้ลเป็นเหยื่อล่อ

ฉันไม่ได้เข้ารหัสอะไรกับกลยุทธ์ที่อยากรู้อยากเห็นของ CircleOfLife เพราะเขาสามารถชนะได้ด้วยโชคที่ดี

รหัส

นี่คือรหัสที่สมบูรณ์ของโครงการ C ++ ตัดไฟล์ต้นฉบับ 11 ไฟล์และ Makefile และคอมไพล์ด้วยmake

$ 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)

หรือดาวน์โหลดไฟล์ zip: Zen.zip

ผล

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

และการต่อสู้ทั่วไปบางอย่าง (ViciousViper vs Zen และ SneakySnake vs Zen):

ViciousViper vs Zen SneakySnake vs Zen

แก้ไข : ฉันเพิ่มการต่อสู้ที่น่าสนใจนี้กับ CircleOfLife:

ป้อนคำอธิบายรูปภาพที่นี่


กลยุทธ์ที่ดี คุณช่วยอัปโหลดโปรเจคของคุณที่ซิปเพื่อให้คนอื่นใช้ง่ายขึ้นได้ไหม?
randomra

4

CircleOfLife (Java)

CircleOfLife Manu java CircleOfLife(คอมไพล์ด้วยjavac CircleOfLife.java)

วิ่งไปตรงกลางและอยู่ตรงนั้น ฉันหวังว่าผลงานบางชิ้นจะส่งผลกระทบต่ออาหารของพวกเขา

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;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.