KOTH อสมมาตร: จับแมว (Cat Thread)


14

KOTH อสมมาตร: จับแมว

UPDATE : ไฟล์ gist-update แล้ว (รวมถึง submisisons ใหม่) เนื่องจาก Controller.java ไม่พบข้อยกเว้น (ข้อผิดพลาดเท่านั้น) ตอนนี้มันตรวจจับข้อผิดพลาดและข้อยกเว้นแล้วพิมพ์ออกมา

ความท้าทายนี้ประกอบด้วยสองหัวข้อนี้เป็นหัวข้อแมวด้ายจับที่สามารถพบได้ที่นี่

ควบคุมสามารถดาวน์โหลดได้ที่นี่

นี่คือความไม่สมดุล KOTH: การส่งแต่ละคนเป็นทั้งแมวหรือจับ มีเกมระหว่างแมวและแมวจับแต่ละคู่ แมวและมือปราบมารมีอันดับแยกกัน

สิ่งที่จับ

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

แมว

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

ตะแกรง

กริดนั้นเป็นรูปหกเหลี่ยม แต่เนื่องจากเราไม่มีโครงสร้างข้อมูลแบบหกเหลี่ยมเราจะใช้11 x 11อาร์เรย์ 2d และเลียนแบบ 'พฤติกรรม' หกเหลี่ยมที่แมวสามารถเคลื่อนที่ได้ใน 6 ทิศทาง:

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

โทโพโลยีคือ toroidal ซึ่งหมายความว่าถ้าคุณเหยียบเซลล์ 'นอก' ของอาร์เรย์คุณจะถูกโอนไปยังเซลล์ที่เกี่ยวข้องในอีกด้านหนึ่งของอาร์เรย์

เกม

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

ตัวควบคุม

คอนโทรลเลอร์ที่กำหนดถูกเขียนใน Java ในฐานะที่เป็น catcher หรือ cat คุณแต่ละคนจะต้องใช้คลาส Java (มีตัวอย่างดั้งเดิมอยู่แล้ว) และวางไว้ในplayersแพ็คเกจ (และอัปเดตรายชื่อ cat / catchers ในคลาส Controller) แต่คุณยังสามารถเขียนได้ ฟังก์ชันเพิ่มเติมภายในคลาสนั้น คอนโทรลเลอร์มาพร้อมกับตัวอย่างการทำงานสองอย่างของคลาส cat / catcher แบบง่าย ๆ

เขตข้อมูลนั้นเป็นอาร์เรย์ 2 11 x 11มิติintที่เก็บค่าสถานะปัจจุบันของเซลล์ ถ้ามือถือเป็นที่ว่างเปล่ามันจะมีค่า0ถ้ามีแมวมันมีค่าและถ้ามีถังมี-11

มีฟังก์ชั่นบางอย่างที่คุณสามารถใช้ได้: isValidMove()/ isValidPosition()ใช้สำหรับตรวจสอบว่าการเคลื่อนไหว (cat) / ตำแหน่ง (catcher) ของคุณนั้นถูกต้องหรือไม่

ทุกครั้งที่ถึงตาคุณtakeTurn()จะมีการเรียกฟังก์ชั่นของคุณ อาร์กิวเมนต์ประกอบด้วยสำเนาของกริดปัจจุบันที่มีวิธีการเช่นread(i,j)อ่านเซลล์ที่(i,j)และisValidMove()/ isValidPosition()ตรวจสอบความถูกต้องของคำตอบของคุณ นอกจากนี้ยังจัดการการตัดทอพอโลยีโทโพโลยีซึ่งหมายความว่าแม้ว่ากริดจะมีเพียง 11 x 11 คุณยังสามารถเข้าถึงเซลล์ (-5,13)

วิธีการควรส่งกลับintอาร์เรย์ของสององค์ประกอบซึ่งเป็นตัวแทนของการเคลื่อนไหวที่เป็นไปได้ สำหรับแมวเหล่านี้เป็นซึ่งเป็นตัวแทนของตำแหน่งสัมพัทธ์ของแมวที่อยากจะไปและปราบมารกลับพิกัดที่แน่นอนของที่พวกเขาต้องการที่จะวางถัง{-1,1},{0,1},{-1,0},{1,0},{0,-1},{1,-1}{i,j}

หากวิธีการของคุณสร้างการย้ายที่ไม่ถูกต้องการส่งของคุณจะถูกตัดสิทธิ์ การย้ายนั้นถือว่าไม่ถูกต้องหากที่ปลายทางของคุณเป็นที่เก็บข้อมูลอยู่แล้วหรือการย้ายนั้นไม่ได้รับอนุญาต / ปลายทางนั้นครอบครองอยู่แล้ว (ในฐานะที่เป็นแมว) หรือหากมีการฝากข้อมูล / แมว (เป็นตัวจับ) อยู่แล้ว คุณสามารถตรวจสอบว่าก่อนมือด้วยฟังก์ชั่นที่กำหนด

การส่งของคุณควรทำงานอย่างรวดเร็วพอสมควร หากวิธีการของคุณใช้เวลานานกว่า 200ms สำหรับแต่ละขั้นตอนมันจะถูกตัดสิทธิ์ด้วย (ยิ่งน้อยกว่า ... )

โปรแกรมได้รับอนุญาตให้จัดเก็บข้อมูลระหว่างขั้นตอน

การส่ง

  • คุณสามารถส่งได้มากเท่าที่คุณต้องการ
  • โปรดอย่าแก้ไขการส่งที่คุณส่งมาอย่างมีนัยสำคัญ
  • โปรดส่งแต่ละคำตอบด้วยคำตอบใหม่
  • การส่งแต่ละครั้งควรมีชื่อที่ไม่ซ้ำกัน
  • การส่งควรประกอบด้วยรหัสของชั้นเรียนของคุณเช่นเดียวกับคำอธิบายที่บอกเราว่าการส่งของคุณทำงานอย่างไร
  • คุณสามารถเขียนบรรทัดสำหรับ<!-- language: lang-java -->ซอร์สโค้ดของคุณเพื่อรับการเน้นไวยากรณ์โดยอัตโนมัติ

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

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

ความท้าทายนี้ได้รับแรงบันดาลใจจากเกมแฟลชเก่า

ขอบคุณ @PhiNotPi สำหรับการทดสอบและให้ข้อเสนอแนะที่สร้างสรรค์

คะแนนปัจจุบัน (100 เกมต่อการจับคู่)

Name              Score      Rank   Author

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

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

1
ฉันคิดว่าความท้าทายแบบนี้คือแท็กตำรวจและโจร
SuperJedi224

4
@flawr ฉันยินดีที่จะขยาย CnR tag ให้กับความท้าทายทั้งหมดที่เกี่ยวข้องกับความท้าทายย่อยสองรายการ (และใช้ทั้งแท็กและ KotH เป็นแท็กในสิ่งนี้) แท็ก CnR wiki ได้รับอิทธิพลจากความท้าทายสองสามอย่างแรกที่เรามีในรูปแบบนั้น (นอกจากนี้คุณยังมีตำรวจและโจรรอบทางที่ผิด;))
มาร์ตินเอนเดอร์

1
อะไรทำให้แมวไม่สามารถนำเข้าmain.ControllerโทรgetCatchers()ออกและจำลอง / ก่อวินาศกรรมคำตอบของมือปราบมารได้โดยtakeTurnวิธีการของพวกเขา
LegionMammal978

12
@ LegionMammal978 กีฬา
Martin Ender

2
@feersum สิ่งนี้ช่วยได้ไหม? (จุดสีดำ (สีฟ้า) เป็นตัวแทนของเซลล์เดียวกัน)
ข้อบกพร่อง

คำตอบ:


5

FreeCat

เลือกการย้ายที่จะให้เส้นทางที่เป็นไปได้มากที่สุดหลังจาก 3 ขั้นตอนถ้าฟิลด์ไม่เปลี่ยน

FreeCat vs Achilles:

FreeCat vs Achilles

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

import java.util.Arrays;

import main.Field;

public class FreeCat implements Cat {

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

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

    public int[] takeTurn(Field f) {

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

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

3

แมวของ Dijkstra

เขาเรียนรู้และใช้อัลกอริทึมต้นแบบของเจ้านายของเขา โปรดทราบว่าเขาขึ้นอยู่กับวิธีการบางอย่างในชั้นเรียนที่เกี่ยวข้องของเขา

Cat vs Hexcatcher ของ Dijkstra (ต้องอัพเดต):

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

package players;

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

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

public class DijkstrasCat implements Cat{

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

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

เขาทำงานอย่างไร:

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

พร้อมอัปเดต:

ตอนนี้เขาหลีกเลี่ยงรูปทรงเรขาคณิตแปลก ๆ ที่ถังน้ำบางครั้งก่อตัว


3

MaxCat

ฉันพยายามใช้อัลกอริทึม Minimax อย่างไรก็ตามมันทำงานได้ไม่ดีนักเนื่องจากมีเวลา จำกัด แก้ไข:ตอนนี้ใช้มัลติเธรด แต่ (อย่างน้อยในคอมพิวเตอร์ของฉัน) ฉันไม่สามารถตั้งค่าความลึกได้สูงขึ้น มิฉะนั้นหมดเวลาเกิดขึ้น ใช้พีซีที่มี 6 คอร์ขึ้นไปการส่งนี้จะดีกว่า :)

MaxCat vs Dijkstra:

MaxCat กับ Dijkstra

package players;

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

import main.Field;

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

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

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

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

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

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

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

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

จริงๆแล้วคุณสามารถสร้างตัวสร้างของFieldสาธารณะ ฉันขอโทษฉันยังไม่ได้อัปเดตไฟล์ แต่เราพูดถึงเรื่องนี้ก่อนหน้านี้!
ข้อบกพร่อง

@ flawr โอ้เยี่ยมมากขอบคุณ!
CommonGuy

2

SpiralCat

เคลื่อนที่ในลักษณะที่เป็นเกลียว มัน

  • พยายามย้ายไปที่วงกลมบนซ้าย
  • หากเป็นไปไม่ได้พยายามย้ายไปที่วงกลมด้านบนขวา
  • หากเป็นไปไม่ได้พยายามย้ายไปที่วงกลมด้านขวา
  • หากไม่สามารถทำได้พยายามย้ายไปที่วงกลมด้านล่างขวา
  • หากไม่สามารถทำได้พยายามย้ายไปที่วงกลมด้านล่างซ้าย

SpiralCat vs Agamemnon:

SpiralCat vs Agamemnon

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

import main.Field;

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

คุณรู้หรือไม่ว่าคุณพบข้อบกพร่องอะไรบ้าง? สิ่งเดียวที่ฉันต้องการเปลี่ยนจะได้รับการแก้ไขturns[i]ไปturns[i%6]ในการสั่งซื้อเพื่อหลีกเลี่ยงการออกจากขอบเขต (ซึ่งไม่ควรเกิดขึ้นใน stuation นี้)
ข้อบกพร่อง

@ flawr, ประณาม เลือกคำไม่ดี ฉันหมายความว่าแมวตัวนี้ไม่ฉลาดมาก ในบางครั้งแมวตัวนี้เพียงสลับระหว่างวงกลมด้านบนซ้ายและวงกลมด้านล่างขวาแม้ว่าจะมีทางออก ...
Spikatrix

@flawr ฉันต้องใช้งานturns[i%6]หรือไม่ ฉันหมายความว่าtakeTurnจะไม่ถูกเรียกถ้าแมวถูกบล็อกใช่มั้ย
Spikatrix

ไม่ฉันคิดว่าคุณหมายถึงคุณพบข้อผิดพลาดในโปรแกรมดังนั้นฉันจึงค้นหาสาเหตุที่เป็นไปได้ แต่คุณมีสิทธิอย่างเห็นได้ชัด (ถ้าทุกอย่างเป็นที่ถูกต้อง) i>=6ไม่ควรเกิดขึ้น
ข้อบกพร่อง

2

RabidCat

RabidCat มีอาการกลัวน้ำดังนั้นเขากลัวถังน้ำ เขาพบคนที่ใกล้ที่สุดและวิ่งไปในทิศทางตรงกันข้าม

RabidCat vs ForwordCatcher:

rabidcat_vs_forwordcatcher

package players;

import java.util.Random;

import main.Field;

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

public class RabidCat implements Cat {

public RabidCat() {
}

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

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

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

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

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

}

ว้าวรับความอัปยศโดย CloseCatcher จริง ๆ
Cain

2

ChoiceCat

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

ChoiceCat ดูเหมือนจะทำคะแนนได้ดีกว่าแมวปัจจุบัน

ChoiceCat vs ChoiceCatcher:

ChoiceCat vs ChoiceCatcher

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

import main.Field;

public class ChoiceCat implements Cat {

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

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

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

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

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

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

    public int[] takeTurn(Field f) {

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

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

        Values v = new Values(f.SIZE);

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

        return -v.read(pos);
    }

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

1

StupidRightCat

นี่เป็นเพียงการทดสอบคอนโทรลเลอร์ แมวเคลื่อนไปทางขวาเมื่อใดก็ตามที่เป็นไปได้มิฉะนั้นจะเคลื่อนที่ในทิศทางที่สุ่ม

package players;

import main.Field;

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

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

1

RandCat

นี่เป็นเพียงการทดสอบคอนโทรลเลอร์ แมวเพิ่งย้ายแบบสุ่ม

package players;

import main.Field;

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

1

StraightCat

แมวตัวนี้เคลื่อนตรง

ในตอนเริ่มต้นมันจะเลือกทิศทางแบบสุ่มและเคลื่อนที่ต่อไปในทิศทางนี้จนกว่าจะไม่สามารถทำได้ในกรณีนี้มันจะเปลี่ยนทิศทางในลักษณะตามเข็มนาฬิกาไปยังทิศทางที่ถูกต้องถัดไปและทำซ้ำกระบวนการนี้

StraightCat vs Agamemnon:

StraightCat vs Agamemnon

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

import main.Field;

public class StraightCat implements Cat{

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

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

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

        while(true)
        {
            if(f.isValidMove(move))
                break;
            i = (i+1)%6;
            lastDirection = i;
            move = turns[i];
        }
        return move;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.