การต่อสู้กริดเส้นทาง


22

บันทึก:ความท้าทายนี้กำลังจะตายเนื่องจากฉันไม่สามารถติดตั้งภาษาที่จำเป็นในการเรียกใช้การแข่งขัน หากคนอื่นมีเวลาและความสนใจที่จะทำฉันก็จะไม่คัดค้าน

ดูด้านล่างของโพสต์สำหรับกระดานแต้มนำ

นี่เป็นความท้าทายแบบกึ่งร่วมมือกันของกษัตริย์ที่บอตสร้างเส้นทางผ่านกราฟกริดสองมิติ บอทที่ควบคุมโหนดที่มีปริมาณการใช้งานมากที่สุดคือผู้ชนะ อย่างไรก็ตามต้องใช้ทรัพยากรของบอทมากกว่าหนึ่งแห่งในการสร้างเส้นทางเชื่อมต่อดังนั้นบอตจะต้องทำงานร่วมกัน - ในระดับหนึ่ง

เพลย์

ในต่อไปนี้ให้N > 0เป็นจำนวนของบอทในการเล่น

ตาราง

เป็นเกมที่เล่นบนตารางจำนวนเต็มสองมิติขนาดซึ่งล่างซ้ายประสานงานที่ แต่ละประสานงานกับมีขอบขาออกไปยังสามพิกัด, และเหนือที่-coordinates จะถูกนำโมดูโล ซึ่งหมายความว่ากริดล้อมรอบที่ขอบตะวันออกและตะวันตก ทุกด้านล่างประสานงานเป็นแหล่งที่มาและประสานงานด้านบนทุกเป็นอ่างล้างจาน⌊4/3N2⌋ × ⌊4/3N2(0,0)(x,y)0 ≤ y < ⌊4/3N2⌋-1(x-1,y+1)(x,y+1)(x+1,y+1)x⌊4/3N2(x,0)(x,⌊4/3N2⌋-1)

ภาพต่อไปนี้แสดง8 × 8ตาราง

ตาราง 8x8

จุดสุดยอดของกราฟแต่ละคนเป็นอย่างใดอย่างหนึ่งไม่ได้ใช้งาน , การใช้งานหรือเสียเสียทุกจุดเริ่มต้นไม่ได้ใช้งานและสามารถเปิดใช้งานโดยบอทซึ่งจะเป็นเจ้าของของพวกเขา นอกจากนี้บอตสามารถทำลายจุดยอดและไม่สามารถซ่อมแซมได้

เปิดคำสั่งซื้อ

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

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

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

เกมทั้งหมดมีจำนวน 100 รอบและบอทที่มีคะแนนรวมมากที่สุดคือผู้ชนะ ฉันอาจเพิ่มจำนวนนี้ถ้าความแปรปรวนของคะแนนสูงเกินไป

กฎเพิ่มเติม

  • ไม่มีล้อเล่นกับตัวควบคุมหรือการส่งอื่น ๆ
  • ส่งได้มากที่สุดหนึ่งรายการต่อผู้แข่งขัน
  • ไม่มีทรัพยากรภายนอกยกเว้นไฟล์ข้อความส่วนตัวหนึ่งไฟล์ซึ่งจะถูกลบทิ้งในตอนเริ่มเกม
  • อย่าออกแบบบอทของคุณเพื่อเอาชนะหรือสนับสนุนคู่ต่อสู้ที่เฉพาะเจาะจง
  • จัดเตรียมคำสั่งเพื่อคอมไพล์และรันบ็อตของคุณ คอมไพเลอร์ / ล่ามที่สามารถใช้ได้อย่างอิสระสำหรับ Debian Linux นั้นเป็นที่ยอมรับ

ผู้ควบคุม

ตัวควบคุมถูกเขียนในหลาม 3 และสามารถพบได้ใน GitHub ดูไฟล์ README สำหรับคำแนะนำโดยละเอียด นี่คือ API เพื่อให้คุณเริ่มต้น:

  • บ็อตจะเริ่มในตอนต้นของแต่ละรอบและคงอยู่จนกระทั่งจบรอบ การสื่อสารกับคอนโทรลเลอร์ผ่าน STDIN และ STDOUT โดยใช้ข้อความที่ยกเลิกการขึ้นบรรทัดใหม่
  • BEGIN [num-of-bots] [num-of-turns] [side-length] เป็นอินพุตที่จุดเริ่มต้น
  • DESTROY [turn]คืออินพุตที่จุดเริ่มต้นของแต่ละช่วงการทำลาย บอตของคุณจะตอบสนองด้วยVERTEX x,yการเลือกจุดสุดยอดหรือNONEที่จะเลือกจุดสุดยอดหรือ
  • BROKEN [turn] [your-choice] [other-choices]คืออินพุตที่ส่วนท้ายของแต่ละช่วงการทำลาย ลำดับของบ็อตอื่น ๆ จะถูกสุ่มในช่วงเริ่มต้นของแต่ละเกม แต่จะยังคงอยู่ระหว่างนั้น ตัวเลือกจะถูกนำเสนอเป็นx,yหรือNหรือ
  • ACTIVATE [turn]และOWNED [turn] [your-choice] [other-choices]มีค่าเทียบเท่าข้างต้นสำหรับขั้นตอนการเปิดใช้งานและมีความหมายเดียวกัน
  • SCORE [your-score] [other-scores] เป็นอินพุตในตอนท้ายของเกม
  • บอทของคุณมี1 วินาทีในการวิเคราะห์ผลลัพธ์ของเฟสและเลือกจุดสุดยอดถัดไปและ1 วินาทีเพื่อออกหลังจากได้รับคะแนน ฉันจะทดสอบการส่งข้อมูลในแล็ปท็อปที่ค่อนข้างเก่าดังนั้นจึงเป็นการดีกว่าที่จะปล่อยให้ส่วนต่าง ๆ อยู่ที่นี่

โปรดจำไว้ว่าให้ล้างบัฟเฟอร์การส่งออกของคุณ ไม่ทำเช่นนั้นอาจวางคอนโทรลเลอร์ในบางสภาพแวดล้อม

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

อัปเดต 3/13/2015

ผู้สร้างสันตินั้นเปิดใช้งานแล้วและ Funnelweb ได้รับการอัปเดตด้วย คะแนนเพิ่มขึ้นตามลำดับความสำคัญ ตัวเชื่อมต่อเกินขีด จำกัด เวลาในสองเกม

Funnelweb: 30911
Connector: 18431
Watermelon: 3488
Annoyance: 1552
Explorer: 735
Checkpoint: 720
Random Builder: 535
FaucetBot: 236
Peacemaker: 80

บันทึกที่เต็มไปด้วยกราฟิกศิลปะ ASCII graphical_log.txtสามารถพบได้ในพื้นที่เก็บข้อมูลของตัวควบคุมใน

ข้อสังเกตบางอย่าง:

  • ขั้วต่อสามารถหยุดได้ง่ายมากโดยการทำลายจุดสุดยอดด้านหน้าเดียว ฉันสงสัยว่า Annoyance ทำสิ่งนี้บ่อยครั้ง อย่างไรก็ตามในปัจจุบันมันมีเหตุผลเล็กน้อยเนื่องจากมีเพียงขั้วต่อเท่านั้นที่สามารถสร้างเส้นทางได้
  • แตงโมสามารถได้รับคะแนนที่ดีโดยเพียงแค่เกิดขึ้นบนเส้นทางเชื่อมต่อ (เนื่องจาก DFS มีแนวโน้มที่จะใช้จุดยอด)
  • Explorer ชอบเถาวัลย์เติบโตจากแตงโม
  • Funnelweb ที่อัปเดตได้รับคะแนนที่ดีมากเนื่องจากตัวเชื่อมต่อมักจะสลักลงในครึ่งล่างของตาราง
  • เกมเริ่มค่อนข้างยาวโดยเฉลี่ยแล้วใช้เวลาประมาณ 25 วินาทีในเครื่องของฉัน

1
@ อเล็กซ์ฉันพยายามออกแบบความท้าทายเพื่อที่บอทฆ่าตัวตายจะไม่ทำให้ทุกอย่างยุ่ง บอทที่ออกแบบมาอย่างดีสามแห่งควรจะสามารถสร้างพา ธ ที่ถูกต้องได้หากมันทำงานร่วมกัน
Zgarb

2
@ Zgarb การฆ่าตัวตายไม่ควรทำให้ยุ่งเหยิง แต่บ็อบหมุนรอบสองคนทำงานร่วมกันอาจจะบล็อกทุกเส้นทางทำลายเกม
Geobits

2
@CarpetPython Active nodes ไม่สามารถทำลายได้
Zgarb

1
ดูเหมือนว่าเราไม่น่าจะเห็นเกมที่น่าสนใจใด ๆ กับผู้เล่นและกฏปัจจุบัน ฉันขอแนะนำให้คุณเปลี่ยนกฎเล็กน้อยเพื่อสร้างโอกาสสำหรับเกมที่น่าสนใจ การเปลี่ยนขนาดกริดเป็น 1.5 * N ^ 2 แทนที่จะเป็น 2 * N ^ 2 ควรจะดีและไม่สับสนกับหุ่นยนต์ที่มีอยู่มากเกินไป
Logic Knight อัศวิน

1
@justhalf นั่นเป็นความจริง เกมในบันทึกนั้นเล่นจริงด้วยขนาดกริดที่ลดลงอีก4/3*N^2และแม้ที่นั่นบอทก็มีปัญหาในการสร้างเส้นทางที่ถูกต้อง อย่างไรก็ตามตัวเชื่อมต่อถูกตัดสิทธิ์ชั่วคราวเนื่องจากข้อผิดพลาดและตอนนี้มันได้รับการแก้ไขแล้วฉันคาดหวังว่าเกมจะน่าสนใจยิ่งขึ้น ฉันจะรันอีกชุดในคืนนี้
Zgarb

คำตอบ:


7

ตัวเชื่อมต่อ (Java)

พยายามสร้างเส้นทางที่ตำแหน่งสุ่ม เนื่องจากมันไม่สามารถสร้างเส้นทางด้วยตนเองมันจึงค้นหาเซลล์ที่ใช้งานและใช้มัน เครดิตไปที่ Geobits ซึ่งฉันขโมยรหัสมา นอกจากนี้การส่งนี้ยังไม่เสร็จเนื่องจากเพียงแค่หยุดทำอะไรทันทีที่สร้างเส้นทาง

แก้ไข:หากมีการสร้างพา ธ ตัวเชื่อมต่อจะพยายามสร้างหลายเส้นทางตามเส้นทางที่มีอยู่

import java.awt.Point;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Connector {
    private static final int INACTIVE = 0;
    private static final int ACTIVE   = 1;
    private static final int BROKEN   = 2;
    private static final int MINE     = 3;

    private int size = 0;
    private int[][] grid = new int[size][size];
    private Point previousCell = null;
    private final List<Point> path = new ArrayList<>();

    public static void main(String[] args) {
        new Connector().start();
    }

    private void start() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while(true) {
            try {
                String input = reader.readLine();
                act(input);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
    }

    private void act(String input) throws Exception {
        String[] msg = input.split(" ");
        String output = "";
        int turn;
        switch(msg[0]){
        case "BEGIN":
            size = Integer.parseInt(msg[3]);
            grid = new int[size][size];
            break;
        case "DESTROY":
            output = "NONE";
            break;
        case "BROKEN":
            update(msg, true);
            break;
        case "ACTIVATE":
            turn = Integer.parseInt(msg[1]);
            output = activate(turn);
            break;
        case "OWNED":
            update(msg, false);
            break;
        case "SCORE":
            System.exit(0);
            break;
        }
        if (output.length() > 0) {
            System.out.println(output);
        }
    }

    private String activate(int turn) {
        if (turn == 0) {
            Random r = new Random();
            previousCell = new Point(r.nextInt(size), 0);
            return "VERTEX " + previousCell.x + "," + 0;
        }
        Point lastCell = findLastPathCell(previousCell.x, previousCell.y);
        if (lastCell.y == size-1) {
            //path is done
            Point extendingPathPoint = findExtendingPathPoint();
            if (extendingPathPoint == null) {
                return "NONE";
            }
            return "VERTEX " + extendingPathPoint.x + "," + extendingPathPoint.y;
        } else {
            int x = findBestX(lastCell.x, lastCell.y);
            return "VERTEX " + x + "," + (lastCell.y + 1);
        }
    }

    private int findBestX(int x, int y) {
        int bestScore = Integer.MIN_VALUE;
        int bestX = 0;
        for (int i = -1; i <= 1; i++) {
            int newY = y + 1;
            int newX = (x + i + size) % size;
            int score = calcCellScore(newX, newY, 10);
            if (score > bestScore) {
                bestScore = score;
                bestX = newX;
            } else if (score == bestScore && Math.random() < 0.3) {
                bestX = newX;
            }
        }
        return bestX;
    }

    private int calcCellScore(int x, int y, int depth) {
        int newY = y + 1;
        if (depth < 0) {
            return 1;
        }
        if (newY >= size)
            return 100;
        int cellScore = 0;
        for (int i = -1; i <= 1; i++) {
            int newX = (x + i + size) % size;
            if (grid[newX][newY] == ACTIVE || grid[newX][newY] == MINE) {
                cellScore += 5;
            } else if (grid[newX][newY] == INACTIVE) {
                cellScore += 1;             
            } else {
                cellScore -= 2;
            }
            cellScore += calcCellScore(newX, newY, depth -1);
        }
        return cellScore;
    }

    private Point findLastPathCell(int x, int y) {
        Point thisCell = new Point(x,y);
        int newY = y + 1;
        if (newY >= size) {
            return thisCell;
        }
        List<Point> endCells = new ArrayList<>();
        endCells.add(thisCell);
        path.add(thisCell);
        for (int i = -1; i <= 1; i++) {
            int newX = (x + i + size) % size;
            if (grid[newX][newY] == ACTIVE || grid[newX][newY] == MINE) {
                endCells.add(findLastPathCell(newX, newY));
            }
        }
        int bestY = -1;
        Point bestPoint = null;
        for (Point p : endCells) {
            if (p.y > bestY) {
                bestY = p.y;
                bestPoint = p;
            }
        }
        return bestPoint;
    }

    private Point findExtendingPathPoint() {
        if (path.size() == 0)
            return null;
        Random rand = new Random();
        for (int i = 0; i < size; i++) {
            Point cell = path.get(rand.nextInt(path.size()));
            for (int j = -1; j <= 1; j += 2) {
                Point newCellX = new Point((cell.x + j + size) % size, cell.y);
                if (grid[newCellX.x][newCellX.y] == INACTIVE)
                    return newCellX;

                Point newCellY = new Point(cell.x, cell.y + j);
                if (cell.y < 0 || cell.y >= size)
                    continue;
                if (grid[newCellY.x][newCellY.y] == INACTIVE)
                    return newCellY;
            }
        }
        return null;
    }

    private void update(String[] args, boolean destroyPhase) {
        for(int i = 2; i < args.length; i++) {
            String[] tokens = args[i].split(",");
            if(tokens.length > 1){
                int x = Integer.parseInt(tokens[0]);
                int y = Integer.parseInt(tokens[1]);
                if (grid[x][y] == INACTIVE) {
                    if (destroyPhase) {
                        grid[x][y] = BROKEN;
                    } else if (i == 2) {
                        grid[x][y] = MINE;
                        path.add(new Point(x,y));
                        previousCell = new Point(x,y);
                    } else {
                        grid[x][y] = ACTIVE;
                    }
                }
            }
        }
    }
}

@Zgarb ขออภัยฉันสร้างข้อผิดพลาดขณะแก้ไขอีกอัน ใช้งานได้แล้ววันนี้
CommonGuy

@Manu มันเป็นเรื่องดีที่คุณจะกลับมาในเกม มีผู้โกงจำนวนมากและผู้สร้างไม่เพียงพอ เมื่อใช้การเชื่อมต่อเกมอาจน่าสนใจยิ่งขึ้น (มากกว่า 1 เกมใน 100 คะแนนด้วย)
Logic Knight

ตัวเชื่อมต่อใช้เวลา 28 วินาทีเพื่อตอบสนองในหนึ่งในเกมล่าสุด (ดูบันทึก) ดูเหมือนว่ามันวิ่งเข้าไปในแตงโมและมีเวลายากที่จะตัดสินใจว่าจะไปที่ไหนต่อไป
Zgarb

ฉันรันเกมบางเกมอีกครั้งพร้อมกับ Peacemaker ที่ปรับปรุงแล้วและตัวเชื่อมต่อเกิดข้อผิดพลาด: java.lang.ArrayIndexOutOfBoundsException: -1 at Connector.findExtendingPathPoint(Connector.java:166).
Zgarb

7

Funnelweb, Python 2

รุ่น 1.2 - รหัสการเข้าร่วมที่ดีขึ้นเพิ่มภาพเคลื่อนไหวใหม่

ตั้งชื่อตามสไปเดอร์ที่เป็นมิตรน้อยของออสเตรเลีย บอทตัวแรกสร้างรังรูปกรวยในแถวบนสุดจากนั้นล่อบ็อตอื่น ๆ ให้เข้าสู่เส้นทางการสร้างเพื่อรับส่งข้อมูลไปยังรัง

นี่คือภาพเคลื่อนไหวใหม่ของเกม 6 bot บนกระดาน 4 / 3N ^ 2 ที่แสดง funnelweb และบอทที่ง่ายขึ้น:

bots6.gif

รหัส Python ของช่องทาง:

from random import *
import sys
ME = 0
def pt(x,y): return '%u,%u' % (x % side_len, y)

while True:
    msg = raw_input().split()

    if msg[0] == 'BEGIN':
        turn = 0
        numbots, turns, side_len = map(int, msg[1:])
        R = range(side_len)
        top = side_len - 1
        grid = dict((pt(x, y), []) for x in R for y in R)
        mynodes = set()
        deadnodes = set()
        freenodes = set(grid.keys())
        mycol = choice(R)
        extra = sample([pt(x,top) for x in R], side_len)
        path = [(mycol, y) for y in range(top, top - side_len/6, -1)]
        moves = []
        fence = []
        for x,y in path:
            moves.append( [pt(x,y), pt(x+1,y), pt(x-1,y)] )
            fence.extend( [pt(x+1,y), pt(x-1,y)] )
        for dx in range(2, side_len):
            fence.extend( [pt(x+dx,y), pt(x-dx,y)] )
        for x,y in [(mycol, y) for y in 
                range(top - side_len/6, top - 3*side_len/4, -1)]:
            moves.append( [pt(x,y), pt(x+1,y), pt(x-1,y)] )

    elif msg[0] == 'DESTROY':
        target = 'NONE'
        while fence:
            loc = fence.pop(0)
            if loc in freenodes:
                target = 'VERTEX ' + loc
                break
        print target
        sys.stdout.flush()

    elif msg[0] == 'BROKEN':
        for rid, loc in enumerate(msg[2:]):
            if loc != 'N':
                grid[loc] = None
                deadnodes.add(loc)
                freenodes.discard(loc)
                if loc in extra: extra.remove(loc)

    elif msg[0] == 'ACTIVATE':
        target = 'NONE'
        while moves:
            loclist = moves.pop(0)
            goodlocs = [loc for loc in loclist if loc in freenodes]
            if goodlocs:
                target = 'VERTEX ' + goodlocs[0]
                break
        if target == 'NONE':
            if extra:
                target = 'VERTEX ' + extra.pop(0)
            else:
                target = 'VERTEX ' + pt(choice(R), choice(R))
        print target
        sys.stdout.flush()

    elif msg[0] == 'OWNED':
        for rid, loc in enumerate(msg[2:]):
            if loc != 'N':
                grid[loc].append(rid)
                if rid == ME:
                    mynodes.add(loc)
                freenodes.discard(loc)
                if loc in extra: extra.remove(loc)
        turn += 1

    elif msg[0] == 'SCORE':
        break

python funnelweb.pyแมงมุมจะดำเนินการกับ


เปลี่ยนอัลกอริทึมและทดสอบแล้ว มันควรจะทำงานตอนนี้
Logic Knight อัศวิน

ใช้งานได้ดีตอนนี้!
Zgarb

6

ด่าน, ชวา

บอทนี้พยายามสร้างจุดตรวจเพื่อให้เส้นทางที่ถูกต้องผ่านจุดหนึ่งของฉัน เนื่องจากมีการหมุนN 2 ครั้งและกระดานมี 2N 2ข้ามฉันสามารถเปิดใช้งาน / ทำลายทุก ๆ โหนดบนเส้นแนวนอนเดียว (สมมติว่าฉันอยู่ที่นั่นก่อน) ทำสิ่งนี้ในรูปแบบสลับ ( xถูกทำลายoเป็นของฉัน):

xoxoxoxoxoxox...

หากคุณต้องการสร้างเส้นทางคุณต้องผ่านจุดตรวจของฉัน :)

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

หากหนึ่งในช่องว่างในบรรทัดถูกบล็อก / อ้างสิทธิ์แล้วฉันแค่ค้นหาจุดที่อยู่ใกล้เคียงที่ฉันสามารถใช้ได้ (โดยเฉพาะอย่างยิ่งในxบรรทัดเดียวกัน


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Checkpoint {
    public static void main(String[] args) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while(true)
            try {
                String input = reader.readLine();
                act(input);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
    }

    static void act(String input) throws Exception{
        String[] msg = input.split(" ");
        String output = "";
        int turn;
        boolean found = false;
        switch(msg[0]){
        case "BEGIN":
            size = Integer.parseInt(msg[3]);
            grid = new int[size][size];
            target = size/2;
            break;
        case "DESTROY":
            turn = Integer.parseInt(msg[1]);
            for(int x=0;x<size;x+=2)
                for(int y=0;y<size&&!found;y++)
                    if(grid[(x+turn*2)%size][(y+target)%size]==INACTIVE){
                        output = "VERTEX " + ((x+turn*2)%size) + "," + ((y+target)%size);
                        found = true;
                    }
            if(output.length() < 1)
                output = "NONE";
            break;
        case "BROKEN":
            for(int i=2;i<msg.length;i++){
                String[] tokens = msg[i].split(",");
                if(tokens.length>1){
                    int x = Integer.parseInt(tokens[0]);
                    int y = Integer.parseInt(tokens[1]);                    
                    if(grid[x][y]==INACTIVE)
                        grid[x][y] = BROKEN;
                }
            }
            break;
        case "ACTIVATE":
            turn = Integer.parseInt(msg[1]);
            for(int x=1;x<size;x+=2)
                for(int y=0;y<size&&!found;y++)
                    if(grid[(x+turn*2)%size][(y+target)%size]==INACTIVE){
                        output = "VERTEX " + ((x+turn*2)%size) + "," + ((y+target)%size);
                        found = true;
                    }
            if(output.length() < 1)
                output = "NONE";
            break;
        case "OWNED":
            for(int i=2;i<msg.length;i++){
                String[] tokens = msg[i].split(",");
                if(tokens.length>1){
                    int x = Integer.parseInt(tokens[0]);
                    int y = Integer.parseInt(tokens[1]);
                    if(i==2){
                        if(grid[x][y]==INACTIVE)
                            grid[x][y] = MINE;
                    }else{
                        if(grid[x][y]==INACTIVE)
                            grid[x][y]=ACTIVE;
                    }
                }
            }
            break;
        case "SCORE":
            System.exit(0);
            break;
        }
        if(output.length()>0)
            System.out.println(output);
    }

    static int size = 2;
    static int target = size/2;
    static int[][] grid = new int[size][size];

    static final int INACTIVE = 0;
    static final int ACTIVE   = 1;
    static final int BROKEN   = 2;
    static final int MINE     = 3;
}

javac Checkpoint.javaเพื่อรวบรวมมัน ในการวิ่ง, java Checkpoint. คุณจะต้องการเพิ่ม / เปลี่ยนเส้นทางเพื่อแสดงว่าอยู่ที่ไหน


5

แตงโมชวา

พยายามวาดแตงโมบนกริด

import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Watermelon {

    private static int numberOfBots;
    private static int numberOfTurns;
    private static int sideLength;

    private static int turn = 0;

    private static int[][] theGrid;

    private static final int INACTIVE = -2;
    private static final int BROKEN   = -1;
    private static final int MINE     =  0;
    private static final int ACTIVE   =  1;

    private static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    private static PrintStream out = System.out;

    public static void main(String[] args) throws IOException {
        while (true){
            String[] input = in.readLine().trim().split(" ");
            String instruction = input[0];
            switch (instruction){
                case "BEGIN":
                    begin(input);
                    break;
                case "DESTROY":
                    destroy(input);
                    break;
                case "BROKEN":
                    broken(input);
                    break;
                case "ACTIVATE":
                    activate(input);
                    break;
                case "OWNED":
                    owned(input);
                    break;
                default:
                    return;
            }
            out.flush();
        }
    }

    private static void begin(String[] input) {
        numberOfBots = Integer.parseInt(input[1]);
        numberOfTurns = Integer.parseInt(input[2]);
        sideLength = Integer.parseInt(input[3]);
        theGrid = new int[sideLength][sideLength];
        for (int x = 0; x < sideLength; x++){
            for (int y = 0; y < sideLength; y++){
                theGrid[x][y] = INACTIVE;
            }
        }
    }

    private static void owned(String[] input) {
        turn = Integer.parseInt(input[1]);
        for (int i = input.length - 1; i >= 2; i--){
            if (input[i].equals("N")){
                continue;
            }
            String[] coordinates = input[i].split(",");
            int x = Integer.parseInt(coordinates[0]);
            int y = Integer.parseInt(coordinates[1]);
            int player = i - 2;
            if (player == 0){
                theGrid[x][y] = MINE;
            } else {
                theGrid[x][y] = ACTIVE;
            }
        }
    }

    private static void activate(String[] input) {
        turn = Integer.parseInt(input[1]);
        double[][] values = new double[sideLength][sideLength];
        List<Point> pointList = new ArrayList<>();
        for (int x = 0; x < sideLength; x++){
            for (int y = 0; y < sideLength; y++){
                if (theGrid[x][y] == MINE || theGrid[x][y] == ACTIVE){
                    for (int x1 = 0; x1 < sideLength; x1++){
                        for (int y1 = 0; y1 < sideLength; y1++){
                            double distance = Math.pow(x - x1, 2) + Math.pow(y - y1, 2);
                            values[x1][y1] += 1 / (distance + 1);
                        }
                    }
                }
                pointList.add(new Point(x, y));
            }
        }
        pointList.sort(Comparator.comparingDouble((Point a) -> values[a.x][a.y]).reversed());
        for (Point point : pointList){
            if (theGrid[point.x][point.y] == INACTIVE){
                out.println("VERTEX " + point.x + "," + point.y);
                return;
            }
        }
        out.println("NONE");
    }

    private static void broken(String[] input) {
        turn = Integer.parseInt(input[1]);
        for (int i = 2; i < input.length; i++){
            if (input[i].equals("N")){
                continue;
            }
            String[] coordinates = input[i].split(",");
            int x = Integer.parseInt(coordinates[0]);
            int y = Integer.parseInt(coordinates[1]);
            theGrid[x][y] = BROKEN;
        }
    }

    private static void destroy(String[] input) {
        turn = Integer.parseInt(input[1]);
        double[][] values = new double[sideLength][sideLength];
        List<Point> pointList = new ArrayList<>();
        for (int x = 0; x < sideLength; x++){
            for (int y = 0; y < sideLength; y++){
                if (theGrid[x][y] == MINE){
                    for (int x1 = 0; x1 < sideLength; x1++){
                        for (int y1 = 0; y1 < sideLength; y1++){
                            double distance = Math.pow(x - x1, 2) + Math.pow(y - y1, 2);
                            values[x1][y1] -= 1 / (distance + 1);
                        }
                    }
                }
                if (theGrid[x][y] == ACTIVE){
                    for (int x1 = 0; x1 < sideLength; x1++){
                        for (int y1 = 0; y1 < sideLength; y1++){
                            double distance = Math.pow(x - x1, 2) + Math.pow(y - y1, 2);
                            values[x1][y1] += 1 / (distance + 1) / (numberOfBots - 1);
                        }
                    }
                }
                pointList.add(new Point(x, y));
            }
        }
        pointList.sort(Comparator.comparingDouble((Point a) -> values[a.x][a.y]).reversed());
        for (Point point : pointList){
            if (theGrid[point.x][point.y] == INACTIVE){
                out.println("VERTEX " + point.x + "," + point.y);
                return;
            }
        }
        out.println("NONE");
    }
}

5

FaucetBot (ใน R)

สร้างคอขวดในบรรทัดที่สองและเปิดใช้งานโหนดบนเส้นทางด้านหลัง

infile <- file("stdin")
open(infile)
repeat{
    input <- readLines(infile,1)
    args <- strsplit(input," ")[[1]]
    if(args[1]=="BEGIN"){
        L <- as.integer(args[4])
        M <- N <- matrix(0,nrow=L,ncol=L)
        x0 <- sample(2:(L-1),1)
        }
    if(args[1]=="DESTROY"){
        if(args[2]==0){
            X <- x0
            Y <- 2
            }else{
                free <- which(M[,2] == 0)
                mine <- which(N[,2] == 1)
                X <- free[which.min(abs(free-mine))]
                Y <- 2
                }
        if(length(X)){cat(sprintf("VERTEX %s,%s\n",X-1,Y-1))}else{cat("NONE\n")}
        flush(stdout())
        }
    if(args[1]=="BROKEN"){
        b <- strsplit(args[args!="N"][-(1:2)],",")
        o <- strsplit(args[3],",")[[1]]
        b <- lapply(b,as.integer)
        if(o[1]!="N") N[as.integer(o[1])+1,as.integer(o[2])+1] <- -1
        for(i in seq_along(b)){M[b[[i]][1]+1,b[[i]][2]+1] <- -1}
        }
    if(args[1]=="ACTIVATE"){
        if(args[2]==0){
            broken <- which(M[,2] == -1)
            free <- which(M[,2] == 0)
            X <- free[which.min(abs(broken-free))]
            Y <- 2
            }else{
                y <- 3
                X <- NULL
                while(length(X)<1){
                    lastrow <- which(N[,y-1]==1)
                    newrow <- unlist(sapply(lastrow,function(x)which(M[,y]==0 & abs((1:L)-x)<2)))
                    if(length(newrow)){
                        X <- sample(newrow,1)
                        Y <- y
                        }
                    y <- y+1
                    if(y>L){X <- x0; Y <- 1}
                    }
                }
        cat(sprintf("VERTEX %s,%s\n",X-1,Y-1))
        flush(stdout())
        }
    if(args[1]=="OWNED"){
        b <- strsplit(args[args!="N"][-(1:2)],",")
        o <- strsplit(args[3],",")[[1]]
        b <- lapply(b,as.integer)
        if(o[1]!="N") N[as.integer(o[1])+1,as.integer(o[2])+1] <- 1
        for(i in seq_along(b)){M[b[[i]][1]+1,b[[i]][2]+1] <- 1}
        }
    if(args[1]=="SCORE") q(save="no")
    }

หากฉันไม่ได้ล้มเหลวการกำหนดค่าสุดท้ายควรเป็นดังนี้:

........    .a..aa..
..aaa...    ..aaa...
.xxaxx..    xxxaxxx.    etc.
........    ........

Rscript FaucetBot.Rคำสั่ง


5

ผู้สร้างสันติภาพ, Java

ขึ้นอยู่กับรหัสของมนู

เขต Peace ขัดแย้งค้นหา (เช่นความเข้มข้นสุดยอด BROKEN หรือ ACTIVE) และเปิดใช้งานจุดสุดยอดแบบสุ่มที่ใกล้เคียง

import java.awt.Point;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;

public class Peacemaker {
    private static final int INACTIVE = 0;
    private static final int ACTIVE   = 1;
    private static final int BROKEN   = 2;
    private static final int MINE     = 3;

    private int size = 0;
    private int[][] grid = new int[size][size];
    private int startingPoint = 0;

    public static void main(String[] args) {
        new Peacemaker().start();
    }

    private void start() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while(true) {
            try {
                String input = reader.readLine();
                act(input);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
    }

    private void act(String input) throws Exception {
        String[] msg = input.split(" ");
        String output = "";
        int turn;
        switch(msg[0]){
        case "BEGIN":
            size = Integer.parseInt(msg[3]);
            grid = new int[size][size];
            break;
        case "DESTROY":
            output = "NONE";
            break;
        case "BROKEN":
            update(msg, true);
            break;
        case "ACTIVATE":
            turn = Integer.parseInt(msg[1]);
            output = activate(turn);
            break;
        case "OWNED":
            update(msg, false);
            break;
        case "SCORE":
            System.exit(0);
            break;
        }
        if (output.length() > 0) {
            System.out.println(output);
        }
    }

    private String activate(int turn) {
        Random r = new Random();
        if (turn == 0) {
            startingPoint = r.nextInt(size);
            return "VERTEX " + startingPoint + "," + 0;
        } else {

            Point point = searchConflicts();

            int posX = point.x;
            int posY = point.y;

            while (grid[posX][posY] != INACTIVE) {
                 int previousX = (posX - 1 < 0 ? size - 1 : posX - 1);
                 int nextX = (posX + 1 > size - 1 ? 0 : posX + 1);
                 int previousY = (posY - 1 < 0 ? size - 1 : posY - 1);
                 int nextY = (posY + 1 > size - 1 ? 0 : posY + 1);

                 int choice = r.nextInt(4);
                 switch (choice) {
                     case 0: posX = previousX; break;
                     case 1: posX = nextX; break;
                     case 2: posY = previousY; break;
                     case 3: posY = nextY; break;
                 }
            }

            return "VERTEX " + posX + "," + posY;
        }
    }

    private Point searchConflicts() {

        int previousCellScore = 0;
        int cellX = 0;
        int cellY = 0;
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j ++) {
                if (previousCellScore < adjacentCellsScore(i, j)) {
                    cellX = i; cellY = j;
                    previousCellScore = adjacentCellsScore(i, j);
                }
            }
        }
        return new Point(cellX, cellY);
    }

    /*  Format of adjacent cells :
     * 
     *   0 1 2
     *   3 . 4
     *   5 6 7
     */
    private int adjacentCellsScore(int x, int y) {

        int[] scores = new int[8];

        int previousX = (x - 1 < 0 ? size - 1 : x - 1);
        int nextX = (x + 1 > size - 1 ? 0 : x + 1);
        int previousY = (y - 1 < 0 ? size - 1 : y - 1);
        int nextY = (y + 1 > size - 1 ? 0 : y + 1);

        scores[0] = calcScore(previousX, nextY);
        scores[1] = calcScore(x, nextY);
        scores[2] = calcScore(nextX, nextY);
        scores[3] = calcScore(previousX, y);
        scores[4] = calcScore(nextX, y);
        scores[5] = calcScore(previousX, previousY);
        scores[6] = calcScore(x, previousY);
        scores[7] = calcScore(nextX, previousY);

        return IntStream.of(scores).reduce(0, (a, b) -> a + b);
    }

    private int calcScore(int x, int y) {
        int activeScore = 2;
        int mineScore = 1;
        int inactiveScore = 0;
        int brokenScore = 3;

        if (grid[x][y] == ACTIVE) 
            return activeScore;
        else if (grid[x][y] == MINE)
            return mineScore;
        else if (grid[x][y] == INACTIVE) 
            return inactiveScore;
        else if (grid[x][y] == BROKEN) 
            return brokenScore;
        else
            return 0;
    }


    private void update(String[] args, boolean destroyPhase) {
        for(int i = 2; i < args.length; i++) {
            String[] tokens = args[i].split(",");
            if(tokens.length > 1){
                int x = Integer.parseInt(tokens[0]);
                int y = Integer.parseInt(tokens[1]);
                if (grid[x][y] == INACTIVE) {
                    if (destroyPhase) {
                        grid[x][y] = BROKEN;
                    } else if (i == 2) {
                        grid[x][y] = MINE;
                    } else {
                        grid[x][y] = ACTIVE;
                    }
                }
            }
        }
    }       
}

@Zgarb ขอบคุณฉันควรจะแก้ไขปัญหานี้ได้แล้ว
Thrax

ผู้สร้างสันติทำงานในตอนนี้และรวมอยู่ในกระดานผู้นำ อย่างไรก็ตามดูเหมือนจะไม่ได้ทำอะไรมากมายดังนั้นอาจมีข้อผิดพลาดบางอย่างเหลืออยู่
Zgarb

ที่จริงแล้วเมื่อดูที่รหัสของคุณฉันคิดว่าปัญหาอยู่ในwhileลูปของactivateวิธีการ คุณหยุดการค้นหาเมื่อคุณพบจุดสุดยอดที่ไม่ใช่ของคุณและไม่เสียหาย - แต่อาจเป็นของบุคคลอื่นดังนั้นคุณจึงไม่สามารถเปิดใช้งานได้
Zgarb

@Zgarb ฉันอ่านรายละเอียดผิดและคิดว่าผู้เล่นหลายคนสามารถเปิดใช้งานจุดสุดยอดเดียวกันได้ทุกเวลา ฉันเดาว่าฉันต้องเปลี่ยนการค้นหาและมองหาจุดสุดยอดที่ไม่ทำงานเท่านั้น
Thrax

2

ตัวสร้างแบบสุ่ม Python 3

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

import random as r

while True:
    msg = input().split()
    if msg[0] == "BEGIN":
        side_len = int(msg[3])
    elif msg[0] == "DESTROY":
        print("NONE")
    elif msg[0] == "ACTIVATE":
        print("VERTEX %d,%d"%(r.randrange(side_len), r.randrange(side_len)), flush=True)
    elif msg[0] == "SCORE":
        break

รันด้วยคำสั่ง

python3 random_builder.py

คุณอาจต้องเปลี่ยนpython3โดยpythonขึ้นอยู่กับการติดตั้ง Python ของคุณ หากต้องการทำสิ่งนี้เพียงแก้ไขbots.txtไฟล์ ฉันอัพเดตคอนโทรลเลอร์แล้วและไม่จำเป็นต้องยุ่งกับพา ธ ไฟล์อีกต่อไป


ตั้งแต่ของคุณโดยใช้หลาม 3 แทนของsys.stdout.flush()คุณก็สามารถทำได้เป็นอาร์กิวเมนต์ไปยังflush=True print
matsjoyce

@ matsjoyce ขอบคุณฉันไม่รู้เหมือนกัน ฉันจะแก้ไขเวอร์ชันที่เก็บในภายหลัง
Zgarb

2

Explorer, Python 3

กลยุทธ์การเปิดใช้งาน:

สร้างแผนที่ความร้อนขึ้นอยู่กับสถานะของทุก ๆ โหนด (แอ็คทีฟ / ไม่แอ็คทีฟ / แตก) และเลือกโหนดที่จะมีค่าความร้อนที่ใหญ่ที่สุดต่อคนถ้ามันจะเลือกอันนั้น

กลยุทธ์การทำลายล้าง:

ไม่ทำลายอะไรเลยเพราะมันไม่ได้ช่วยบอทมากนัก

import sys

class bd:

    def __init__(s, l):

        s.l=l
        s.b=[]
        s.v=[]
        s.m=[]
        s.bm=[]
        s.utd=False #up_to_date
        s.bmc=1

        for i in range(s.l):
            s.b+=[[]]
            s.v+=[[]]
            s.m+=[[]]
            s.bm+=[[]]
            for k in range(s.l):
                s.b[i]+=[0]
                s.v[i]+=[0]
                s.m[i]+=[0]
                s.bm[i]+=[s.bmc]

    def update(s):
        s.utd=True

        vu=[]
        vd=[]
        for i in range(s.l):
            vu+=[[]]
            vd+=[[]]
            for k in range(s.l):
                vu[i]+=[1]
                vd[i]+=[1]

        #spread up
        for i in range(s.l):
            vu[i][0]*=s.bm[i][0]

        for k in range(1,s.l):
            for i in range(s.l):
                sumv=vu[(i-1)%s.l][k-1]+vu[(i)%s.l][k-1]+vu[(i+1)%s.l][k-1]  
                vu[i][k]*=sumv*s.bm[i][k]/3

        #spread down
        t=s.l-1
        for i in range(s.l):
            vd[i][t]*=s.bm[i][t]

        for k in range(s.l-2,-1,-1):
            for i in range(s.l):
                sumv=vd[(i-1)%s.l][k+1]+vd[(i)%s.l][k+1]+vd[(i+1)%s.l][k+1]  
                vd[i][k]*=sumv*s.bm[i][k]/3

        #mult
        for i in range(s.l):
            for k in range(s.l):
                if s.b[i][k]==-1 or s.m[i][k]==1:
                    s.v[i][k]=float(-1)
                else:
                    s.v[i][k]=vu[i][k]*vd[i][k]/(s.b[i][k]+1)

    def add_act(s,al):
        s.utd=False

        for ind, ap in enumerate(al):
            i,k=ap
            s.b[i][k]+=1            
            s.bm[i][k]=2*s.bmc            
            #doesn't work alone WHY???
            if ind==0: s.m[i][k]=1

    def add_ina(s,il):
        s.utd=False

        for ind, ip in enumerate(il):
            i,k=ip
            s.b[i][k]=-1
            s.bm[i][k]=0                    

    def get_newact(s):
        s.update()
        vm=-28
        pm=None
        for i in range(s.l):
            for k in range(s.l):
                if s.v[i][k]>vm:
                    vm=s.v[i][k]
                    pm=(i,k)
        #doesn't work alone WHY???
        s.m[pm[0]][pm[1]]=1
        return pm


b=None

while True:
    inp=input()
    msg = inp.split()
    if msg[0] == "BEGIN":        
        b = bd(int(msg[3]))
    elif msg[0] == "DESTROY":
        print("NONE")
    elif msg[0] == "BROKEN":
        pl=[]
        for m in msg[2:]:
            if m!='N':
                pl+=[tuple(map(int,m.split(',')))]
        b.add_ina(pl)
    elif msg[0] == "ACTIVATE":
        at=b.get_newact()
        print("VERTEX %d,%d"%(at[0], at[1]))
    elif msg[0] == "OWNED":
        pl=[]
        for m in msg[2:]:
            if m!='N':
                pl+=[tuple(map(int,m.split(',')))]        
        b.add_act(pl)
    elif msg[0] == "SCORE":
        break       

    sys.stdout.flush()

1

น่ารำคาญทุบตี

#!/bin/bash

declare -A avail
broken=
owned=

while read c p
    case "$c" in
        ACTIVATE|BROKEN) v=broken;;
        *) v=owned
    esac
    case "$c" in
        BEGIN)
            read b t n <<<"$p"
            list=$(
                eval "echo {0..$((n-1))},{0..$((n-1))}\$'\\n'" |
                shuf
            )
            for i in $list; do
                avail[$i]=1
            done;;
        DESTROY|ACTIVATE)
            for t in $(
                for i in ${!v}; do
                    [ "$i" != N ] &&
                    if [ "$c" = ACTIVATE ]; then
                        echo $(((${i%,*}+2)%n)),${i#*,}
                        echo $(((${i%,*}-2+n)%n)),${i#*,}
                    else
                        echo ${i%,*},$(((${i#*,}+1)%n))
                        echo ${i%,*},$(((${i#*,}-1+n)%n))
                    fi
                done |
                shuf
            ) $list; do
                [ "${avail[$t]}" ] && echo VERTEX $t && break
            done ||
            echo NONE;;
        BROKEN|OWNED)
            read x m $v <<<"$p";
            for i in $m ${!v}; do
                unset avail[$i]
            done;;
        SCORE)! :
    esac
do :;done

พยายามทำให้ผลลัพธ์ดูน่าสนใจยิ่งขึ้น

bash annoyance.shทำงานด้วย


1
บอตของคุณพิมพ์อินพุตทั้งหมดไปยัง STDERR มันไม่ได้ถูกห้ามหรืออะไร แต่เป็นเรื่องน่ารำคาญ
Zgarb

@Zgarb ขออภัยฉันวางเวอร์ชันผิด คงที่
jimmy23013

1

ชายกลาง

ฉันเห็นว่าบอทบางตัวสร้างขึ้นจากด้านบนและบางส่วนมาจากด้านล่าง นี่เป็นครั้งแรก (ฉันคิดว่า) ที่จะเริ่มต้นในกลางและทำงานขึ้นและลง

(มันไม่ได้ทดสอบกับคอนโทรลเลอร์ดังนั้นถ้าปริมาณไม่ทำงานแจ้งให้เราทราบ)

class Node

  def self.set_size s
    @@grid = Array.new(s,Array.new(s,0))
  end

  def initialize x,y
    @x=x
    @y=y
  end

  def offset dx,dy
    return Node.new @x+dx,@y+dy
  end

  def state
    return -1 if @x<0 || @y<0 || @x>=@@grid.length || @y>=@@grid.length
    @@grid[@x][@y]
  end

  def state= n
    return -1 if @x<0 || @y<0 || @x>=@@grid.length || @y>=@@grid.length
     @@grid[@x][@y]=n
  end

  def active?
    state > 0
  end

  def open?
    state == 0
  end
  attr_reader :x,:y

  def to_s
    "VERTEX #{@x},#{@y}"
  end


  def scan_down
    ans = nil
    [0,-1,1].each do|offset|
      n = Node.new @x+offset,@y-1
      ans = (ans||n) if n.open?
      ans = (n.scan_down||ans) if n.active?
    end
    return ans
  end

  def scan_up
    ans = nil
    [0,-1,1].each do|offset|
      n = Node.new @x+offset,@y+1
      ans = (ans||n) if n.open?
      ans = (n.scan_up||ans) if n.active?
    end
    return ans
  end

end

input = gets.split
input.shift

BotCount = input.shift.to_i
Turns = input.shift.to_i
GridSize = input.shift.to_i

Node.set_size GridSize

midRow = GridSize/2

toDestroy = (0...GridSize).map{|i|Node.new i,midRow}
toDestroy.reject!{|n| n.x==midRow}

chain = []
Turns.times do
  gets;
  toDestroy.each{|x|
    if x.active?
      toDestroy.push x.offset 0,1
      toDestroy.push x.offset 1,1
      toDestroy.push x.offset -1,1
    end
  }
  toDestroy.reject!{|x|!x.open?}
  puts toDestroy.sample
  input = gets.split
  input.shift;input.shift
  input.each{|str|
    a,b = str.split ','
    (Node.new a.to_i,b.to_i).state=1
  }
  gets;

  if chain.length == 0
    n = Node.new midRow,midRow
    until n.open?
      n = Node.new n.x+1,midRow
    end
    puts chain[0]=n
  elsif rand>0.5
    n=nil
    loop do
      h=chain[0]
      n = h.scan_down
     break if !n
      chain.shift
    end
    h.unshift n
    puts n
  else
    loop do
      h=chain[-1]
      n = h.scan_up
      h.pop if !n
      brake if n
    end
    chain.push n
    puts n
  end

  input = gets.split
  input.shift;input.shift
  input.each{|str|
    a,b = str.split ','
    (Node.new a,b).state=-1
  }

end
gets
exit

ขอบคุณสำหรับการส่ง! น่าเสียดายที่ความท้าทายนี้หยุดชะงักไปเกือบครึ่งปีและตอนนี้ฉันไม่สามารถใช้งานบอทส่วนใหญ่ได้เนื่องจากฉันไม่สามารถเข้าถึงคอมพิวเตอร์ที่ฉันสามารถติดตั้งภาษาได้
Zgarb

1
@Zgarb ฉันเข้าใจ บางทีสักวันหนึ่งผมจะตอบความท้าทายในกรอบเวลาที่เหมาะสม ...
MegaTom
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.