असममित KOTH: कैच द कैट (पकड़ने वाला धागा)


17

एसिमेट्रिकल कोथ: कैच द कैट

अद्यतन : जीआईएस-फाइलें अद्यतन की जाती हैं (नियंत्रक के रूप में नई उप-जेलों सहित)। यह अब त्रुटियों और अपवादों को पकड़ता है और उन्हें प्रिंट भी करता है।

इस चुनौती में दो धागे शामिल हैं, यह पकड़ने वाला धागा है, बिल्ली का धागा यहां पाया जा सकता है

कंट्रोलर को यहां से डाउनलोड किया जा सकता है

यह एक विषम KOTH है: प्रत्येक सबमिशन एक बिल्ली या एक पकड़ने वाला है । प्रत्येक बिल्ली और पकड़ने वाले की जोड़ी के बीच खेल होते हैं। बिल्लियों और पकड़ने वालों की अलग-अलग रैंकिंग है।

कैचर

एक हेक्सागोनल ग्रिड पर एक बिल्ली है। अपने काम के लिए यह संभव के रूप में तेजी से पकड़ने के लिए है। हर मोड़ पर, आप एक ग्रिड सेल पर पानी की बाल्टी रख सकते हैं ताकि बिल्ली को वहां जाने से रोका जा सके। लेकिन बिल्ली (शायद) उस गूंगे नहीं है, और जब भी आप एक बाल्टी डालते हैं, तो बिल्ली दूसरे ग्रिड सेल में चली जाएगी। चूंकि ग्रिड हेक्सागोनल है, बिल्ली 6 अलग-अलग दिशाओं में जा सकती है। आपका लक्ष्य बिल्ली को पानी की बाल्टियों से घेरना है, जितनी तेज़ी से बेहतर होगा।

बिल्ली

तुम्हें पता है कि पकड़ने वाला तुम्हारे चारों ओर पानी की बाल्टी रखकर तुम्हें पकड़ना चाहता है। बेशक आप बाहर निकलने की कोशिश करते हैं, लेकिन जैसा कि आप एक आलसी बिल्ली हैं (बिल्लियों के रूप में) आप बिल्कुल उस समय एक कदम उठाते हैं। इसका मतलब है कि आप उसी जगह पर नहीं रह सकते हैं, लेकिन आपको आसपास के छह स्थानों में से एक पर जाना होगा। जब भी आप देखते हैं कि पकड़ने वाले ने एक नई पानी की बाल्टी रखी है तो आप दूसरे सेल में जाते हैं। बेशक आप यथासंभव लंबे समय से बचने की कोशिश करते हैं।

ग्रिड

ग्रिड हेक्सागोनल है, लेकिन जैसा कि हमारे पास हेक्सागोनल डेटा संरचना नहीं है, हम एक 11 x 11वर्ग 2 डी सरणी लेते हैं और हेक्सागोनल 'व्यवहार' की नकल करते हैं कि बिल्ली केवल 6 दिशाओं में आगे बढ़ सकती है:

यहाँ छवि विवरण दर्ज करें

टोपोलॉजी टॉरॉयडल है, इसका मतलब है कि यदि आप सरणी के 'सेल' के बाहर कदम रखते हैं, तो आपको बस सरणी के दूसरी तरफ संबंधित सेल में स्थानांतरित किया जाएगा।

खेल

ग्रिड में दी गई स्थिति पर बिल्ली बाहर निकलने लगती है। पकड़ने वाला पहला कदम कर सकता है, फिर बिल्ली और उसका पकड़ने वाला वैकल्पिक तब तक चलता है जब तक बिल्ली को पकड़ा नहीं जाता है। चरणों की संख्या उस गेम का स्कोर है। बिल्ली जितना संभव हो उतना शानदार स्कोर प्राप्त करने की कोशिश करती है, पकड़ने वाला जितना संभव हो उतना कम स्कोर पाने की कोशिश करता है। आपके द्वारा भाग लिए गए सभी खेलों में औसत योग आपके सबमिशन का स्कोर होगा। दो अलग-अलग रैंकिंग हैं, एक बिल्ली के लिए, एक पकड़ने वालों के लिए।

नियंत्रक

दिए गए नियंत्रक को जावा में लिखा गया है। एक कैचर या एक बिल्ली के रूप में आपको प्रत्येक को एक जावा वर्ग को पूरा करना होगा (पहले से ही कुछ आदिम उदाहरण हैं) और इसे playersपैकेज में रखें (और नियंत्रक वर्ग में बिल्लियों / कैचर्स की सूची को अपडेट करें), लेकिन आप भी लिख सकते हैं उस वर्ग के भीतर अतिरिक्त कार्य। नियंत्रक साधारण बिल्लियों / पकड़ने वाले वर्गों के प्रत्येक दो काम के उदाहरणों के साथ आता है।

क्षेत्र एक 11 x 112D- intसरणी है जो कोशिकाओं की वर्तमान स्थिति के मूल्यों को संग्रहीत करता है। यदि कोई कक्ष खाली है, तो उसका मूल्य है 0, यदि कोई बिल्ली है तो उसका मूल्य है -1और यदि एक बाल्टी है तो एक है 1

दिए गए कुछ कार्य हैं जिनका आप उपयोग कर सकते हैं: isValidMove()/ isValidPosition()यह जाँचने के लिए हैं कि आपकी चाल (बिल्ली) / स्थिति (कैचर) वैध है या नहीं।

हर बार जब आपकी बारी है, तो आपका कार्य 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       191674     8      flawr   
StupidFill        214246     9      flawr
Achilles          76820      6      The E
Agamemnon         74844      5      The E
CloseCatcher      54920      4      randomra
ForwordCatcher    94246      7      MegaTom  
Dijkstra          46500      2      TheNumberOne
HexCatcher        48832      3      randomra
ChoiceCatcher     43828      1      randomra

RandCat           77928      7      flawr
StupidRightCat    81794      6      flawr
SpiralCat         93868      5      CoolGuy
StraightCat       82452      9      CoolGuy
FreeCat           106304     3      randomra
RabidCat          77770      8      cain
Dijkstra's Cat    114670     1      TheNumberOne
MaxCat            97768      4      Manu
ChoiceCat         113356     2      randomra

एनिमेशन किस प्रोग्राम को बनाता है?
मेगाटॉम

एनीमेशन बस जीयूआई है (जब नियंत्रक को आपको सेट करना होगा PRINT_STEPS = true, तो फ़ाइल में अधिक विस्तृत सेटिंग्स MyFrame.java)। फिर मैंने इसे लिसेक के साथ रिकॉर्ड किया और इसे जीआईएमपी के साथ संपादित किया । यदि आपके पास और प्रश्न हैं तो बस पूछें!
दोष

यदि आप नियंत्रक में उपयोगकर्ता इनपुट जोड़ते हैं, तो यह GUI और पहले से लिखे गए बॉट के साथ एक अच्छा सॉफ्टवेयर बना सकता है। यह देखना भी दिलचस्प होगा कि मनुष्य विशिष्ट बॉट रणनीतियों का कितना दुरुपयोग / दुरुपयोग कर सकता है।
रैंडम

इसके अलावा, क्या मेरे बॉट पिछले मैच की जानकारी उसी बॉट के खिलाफ बेहतर चाल-क्रम खोजने की कोशिश कर सकते हैं? मुझे लगता है कि नहीं क्योंकि यह बेहतर है कि आप और अधिक राउंड करें। यह भी अनुमान लगाना होगा कि क्या यह एक नए बॉट के खिलाफ खेल रहा है, इसलिए रनिंग ऑर्डर भी मायने रखेगा।
रैंडम

1
बिल्लियों के अंक अन-ऑर्डर क्यों किए जाते हैं?
स्पिकैट्रिक्स

जवाबों:


6

Achilles

Achilles बहुत उज्ज्वल नहीं है, लेकिन वह बेरहमी से कुशल है। पहले वह बोर्ड के चारों ओर लपेट का उपयोग करने से बिल्ली को रोकता है, फिर वह बोर्ड को दो में विभाजित करता है। तब वह बोर्ड के भाग को विभाजित करता रहता है जब तक कि बिल्ली फंस न जाए, तब तक बिल्ली आधा भाग में है।

प्रदर्शन रैंडकैट बनाम अकिलीज़

रंडकट बनाम अचिल

package players;
/**
 * @author The E
 */
import main.*;



public class Achilles implements Catcher
{
    public Achilles() {

    }
    @Override
    public String getName() {

        return "Achilles";
    }

    @Override
    public int[] takeTurn(Field f) {
        try{
        if(f.read(0, f.SIZE-1)!=Field.BUCKET)
        {
            //Make the first line

            for(int j = 0; j<f.SIZE; j++)
            {
                if(f.read(0, j) == Field.EMPTY)
                {
                    return new int[]{0,j};
                }
            }
            return WasteGo(f);

        }
        else if (f.read(f.SIZE-1, 0)!=Field.BUCKET)
        {
            //Make the second line
            for(int i = 0; i<f.SIZE; i++)
            {
                if(f.read(i, 0) == Field.EMPTY)
                {
                    return new int[]{i,0};
                }
            }
            //The cat got in the way
            for(int j = 0; j<f.SIZE; j++)
            {
                if(f.read(1, j) == Field.EMPTY)
                {
                    return new int[]{1,j};
                }
            }
            return WasteGo(f);
        }
        else
        {
            return TrapCat(1,1,f.SIZE-1, f.SIZE-1, false, f);

        }
        }
        catch (Exception e)
        {
            return WasteGo(f);
        }
    }
    private int[] TrapCat(int i1, int j1, int i2, int j2, Boolean direction, Field f) {
        for(int a = 0; a<f.SIZE+10; a++)
        {
            if(direction)
            {

                int height = j2-j1+1;
                int row = j1 + height/2;
                for(int i = i1; i<=i2; i++)
                {
                    if(f.read(i, row)==Field.EMPTY)
                    {
                        return new int[]{i,row};
                    }
                }

                    //Done that Row
                    //Find cat
                    if(f.findCat()[1]>row)
                    {
                        //he's above the line
                        j1 = row+1;
                        direction = !direction;
                        //return TrapCat(i1, row+1, i2, j2, !direction, f);
                    }
                    else
                    {
                        //he's below the line
                        j2 = row - 1;
                        direction = !direction;
                        //return TrapCat(i1, j1, i2, row-1, !direction, f);
                    }


            }
            else
            {
                int bredth = i2-i1+1;
                int column = i1 + bredth/2;
                //Continue making the line
                for(int j = j1; j<=j2; j++)
                {
                    if(f.read(column,j)==Field.EMPTY)
                    {
                        return new int[]{column,j};
                    }
                }

                    //Done that Column
                    //Find cat
                    if(f.findCat()[0]>column)
                    {
                        //he's right of the line
                        i1 = column + 1;
                        direction = !direction;
                        //return TrapCat(column+1, j1, i2, j2, !direction, f);
                    }
                    else
                    {
                        //he's left of the line
                        i2 = column -1;
                        direction = !direction;
                        //return TrapCat(i1, j1, column-1, j2, !direction, f);
                    }

            }
        }
        return WasteGo(f);
    }
    private int[] WasteGo(Field f) {
        for (int i = 0; i<f.SIZE;i++)
        {
            for(int j=0;j<f.SIZE;j++)
            {
                if(f.read(i,j)==Field.EMPTY)
                {
                    return new int[]{i,j};
                }
            }
        }
        //Something drastic happened
        return new int[]{0,0};
    }



}

खैर अब यह कौन सा है, अकिलीज़ या हेक्टर? (या एक असामयिक पहचान विकार के साथ किसी को? =)
दोष

@flawr Achilles, lol मैंने नाम को आधे रास्ते से बदल दिया (यह कैच अकिलीज़ और बिल्ली हेक्टर के नाम के लिए अधिक उपयुक्त है) लेकिन जावा को बदलना भूल गया - यह तब होता है जब आप चाय के बाद कार्यक्रम करते हैं :(
euanatt

लेकिन हेक्टर बल्कि एक कुत्ते का नाम होगा =) आपके प्रस्तुत कार्यों के लिए धन्यवाद महान है। मुझे आशा है कि आपको इस बात से कोई आपत्ति नहीं है कि मैं आपके कोड में 'प्रस्तावना' को भी शामिल करता हूँ।
दोष

हां कोई समस्या नहीं। हेक्टर कुत्तों के नाम की तरह आवाज करता है ...
euanjt

मैंने सिर्फ एक सिमुलेशन (प्रत्येक जोड़ी के लिए 10000 खेल) चलाया और बार-बार स्टैकऑवरफ्लोइयर के कारण अकिलीज़ को अयोग्य घोषित कर दिया गया। मुझे लगता है कि पुनरावृत्ति समाप्त नहीं हुई: pastebin.com/9n6SQQnd
त्रुटी

5

अपना पहला नाटक

Agamemnon बिल्लियों को एक ऊर्ध्वाधर रेखा के साथ आधे हिस्से में विभाजित करता है जब तक कि बिल्ली के पास केवल चलने के लिए चौड़ाई 2 की एक पट्टी नहीं होती है, जिस बिंदु पर वह बिल्ली को फंसाता है।

Agamemnon बनाम RandCat:

यहाँ छवि विवरण दर्ज करें

package players;
/**
 * @author The E
 */
import main.*;



    public class Agamemnon implements Catcher {
        boolean up = true;
        @Override
        public String getName() {
            return "Agamemnon";
        }

        @Override
        public int[] takeTurn(Field f) {
            //First Make Line in column 1
            for(int j = 0; j<f.SIZE; j++)
            {
                if(f.read(0, j)==Field.EMPTY)
                {
                    return new int[]{0,j};
                }
            }
            //Then in column SIZE/2
            for(int j = 0; j<f.SIZE; j++)
            {
                if(f.read(f.SIZE/2, j)==Field.EMPTY)
                {
                    return new int[]{f.SIZE/2,j};
                }
            }
            //Then work out where the cat is
            int left, right;
            int cati = f.findCat()[0];
            if(cati<f.SIZE/2)
            {
                left = 1;
                right = f.SIZE/2-1;
            }
            else
            {
                left = f.SIZE/2+1;
                right = f.SIZE-1;
            }
            while(right-left>1)
            {
                //If the cat is not in a two width column
                //Split the area the cat is in in half
                int middleColumn = (left+right)/2;
                for(int j = 0; j<f.SIZE; j++)
                {
                    if(f.read(middleColumn, j)==Field.EMPTY)
                    {
                        return new int[]{middleColumn,j};
                    }
                }
                //If we got here we had finished that column
                //So update left and/or right
                if(cati<middleColumn)
                {
                    //he's left of the middle Column
                    right = middleColumn - 1;
                }
                else
                {
                    //he's right of the middle Column
                    left = middleColumn+1;
                }
                //Repeat
            }
            //Otherwise try to trap the cat
            //Make a line up and down on the opposite side of the cat
            int catj = f.findCat()[1];
            if(left!=right){
                if(cati==left)
                {
                    if(f.read(right, catj)==Field.EMPTY)
                    {
                        return new int[]{right, catj};
                    }
                    if(f.read(right, catj-1)==Field.EMPTY)
                    {
                        return new int[]{right, catj-1};
                    }
                    if(f.read(right, catj+1)==Field.EMPTY)
                    {
                        return new int[]{right, catj+1};
                    }


                }
                else
                {
                    if(f.read(left, catj)==Field.EMPTY)
                    {
                        return new int[]{left, catj};
                    }
                    if(f.read(left, catj-1)==Field.EMPTY)
                    {
                        return new int[]{left, catj-1};
                    }
                    if(f.read(left, catj+1)==Field.EMPTY)
                    {
                        return new int[]{left, catj+1};
                    }

                }
            }
            //Alternate between above and below
            if(up)
            {
                up = !up;
                if(f.read(cati, catj+1)==Field.EMPTY)
                {

                    return new int[]{cati, catj+1};
                }
            }
            up = !up;
            if(f.read(cati, catj-1)==Field.EMPTY)
            {

                return new int[]{cati, catj-1};
            }
            return WasteGo(f);
        }

        private int[] WasteGo(Field f) {
            for (int i = 0; i<f.SIZE;i++)
            {
                for(int j=0;j<f.SIZE;j++)
                {
                    if(f.read(i,j)==Field.EMPTY)
                    {
                        return new int[]{i,j};
                    }
                }
            }
            //Something drastic happened
            return new int[]{0,0};
        }
    }

यह कैच अचिल्स की तुलना में लगातार बेहतर करता है और मुझे लगता है कि वह एक नया उत्तर देने के लिए पर्याप्त है।


बहुत अच्छा समाधान, मुझे यकीन था कि
अकिलीज़

हाँ, Agamemnon में Achilles की तुलना में बेहतर अंत गेम ट्रैपिंग एल्गोरिदम है, लेकिन मुझे पूरा यकीन है कि कुछ
ट्वीक हैं

@flawr बहुत छोटे ट्विक को कुछ विशेष मामलों में पकड़ने में तेजी लाने के लिए जोड़ा गया है, यह यहां एनीमेशन को प्रभावित नहीं करता है (हालांकि मुझे लगता है कि यह स्पाइरलकैट के एनीमेशन को प्रभावित कर सकता है)
euanjt

सवाल! यदि आप एक पंक्ति को बंद करने वाले हैं, तो क्या होता है, लेकिन बिल्ली अंतिम स्थान पर खड़ी है?
श्री लामा

@ Mr.Llama यह अगली लाइन बनाना शुरू करता है जैसे कि वह लाइन भर गई थी (यानी बिल्ली वास्तव में एक बाल्टी थी) - एक मोड़ का सबसे प्रभावी उपयोग नहीं होता है, लेकिन बहुत कम ही ऐसा होता है कि यह वास्तव में मायने नहीं रखता है- बिल्ली को अपने अगले मोड़ पर दूर जाना है ताकि मैं अपनी बाल्टी वहां
रख सकूं

5

HexCatcher

यदि कैचर को 3 इकाइयों पक्षों के साथ एक बड़े षट्भुज के अंदर बिल्ली मिल सकती है जहां हेक्सागोन के कोनों पर पहले से ही बाल्टियों का कब्जा है, तो पकड़ने वाला इस क्षेत्र में बिल्ली को रख सकता है और उसे पकड़ सकता है। षट्भुज इस तरह दिखता है:

यहाँ छवि विवरण दर्ज करें

यह वही है जो HexCatcher प्राप्त करने की कोशिश करता है। यह मानसिक रूप से इन बड़े हेक्सागोन्स के साथ क्षेत्र को टाइल करता है कि प्रत्येक कोने की सेल 3 बड़े हेक्सागोन्स का हिस्सा है।

अगर बिल्ली के बगल में दो कोनों को जोड़कर बिल्ली को वर्तमान क्षेत्र में रखने का मौका है, तो बॉट ऐसा करेगा। (छवि में अगर बिल्ली 7,5 पर है, तो हम 7,6 चुनते हैं, भले ही केवल 6,6 और 8,5 कोशिकाओं पर अभी तक कब्जा हो।)

यदि पिछली कोई विकल्प नहीं है, तो हम एक कोने में खेलने का विकल्प चुनते हैं जो उस क्षेत्र का एक हिस्सा है जहां बिल्ली है। यदि इस तरह के सभी कोनों को पहले से ही चुना गया है (जैसे छवि में) तो हम बिल्ली के बगल में एक सेल चुनते हैं।

कई छोटे सुधार संभव हैं जैसे कि रैप-अराउंड को बेहतर तरीके से संभालना (वहां की टाइलिंग टूटना) या अंतिम जोड़ी को बेहतर तरीके से चलाना। मैं इनमें से कुछ कर सकता हूं। यदि इसकी अनुमति नहीं है, तो मैं इसे दिलचस्पी रखने वाले लोगों के लिए (प्रतियोगिता के बाहर) जोड़ दूंगा।

डिकोस्ट्रैसकैट बनाम हेक्सकैचर:

यहाँ छवि विवरण दर्ज करें

package players;
/**
 * @author randomra
 */
import main.Field;

public class HexCatcher implements Catcher {
    public String getName() {
        return "HexCatcher";
    }

    final int[][] o = { { -1, 1 }, { 0, 1 }, { -1, 0 }, { 1, 0 }, { 0, -1 },
            { 1, -1 } };// all valid moves
    final int[][] t = { { -2, 2 }, { 0, 2 }, { -2, 0 }, { 2, 0 }, { 0, -2 },
            { 2, -2 } };// all valid double moves in one direction
    final int[][] h = { { -1, 2 }, { -2, 1 }, { -1, -1 }, { 1, -2 }, { 2, -1 },
            { 1, 1 } };// all valid moves in not one direction
    int opp = 0;

    public int[] takeTurn(Field f) {
        int[] p = f.findCat();
        // center of the hexagon the cat is in
        int[] c = { ((int) p[0] / 3) * 3 + 1, ((int) p[1] / 3) * 3 + 1 };
        // change priority of catching direction at every turn
        opp = 1 - opp;

        // check missing corner piece next to cat
        for (int i = 0; i < 6; i++) {
            int ind = (i + opp * 3) % 6;
            boolean close = false;
            for (int k = 0; k < 6; k++) {
                if (c[0] + h[ind][0] == p[0] + o[k][0]
                        && c[1] + h[ind][1] == p[1] + o[k][1]) {
                    close = true;
                }
            }
            if (f.read(c[0] + h[ind][0], c[1] + h[ind][1]) == 0 && close) {
                return new int[] { c[0] + h[ind][0], c[1] + h[ind][1] };
            }
        }
        // cut off escape route if needed
        for (int i = 0; i < 6; i++) {
            int ind = (i + opp * 3) % 6;
            if (f.read(c[0] + o[ind][0], c[1] + o[ind][1]) == -1
                    && f.read(c[0] + t[ind][0], c[1] + t[ind][1]) == 0) {
                return new int[] { c[0] + t[ind][0], c[1] + t[ind][1] };
            }
        }
        // check any missing corner piece in the area
        for (int i = 0; i < 6; i++) {
            int ind = (i + opp * 3) % 6;
            if (f.read(c[0] + h[ind][0], c[1] + h[ind][1]) == 0) {
                return new int[] { c[0] + h[ind][0], c[1] + h[ind][1] };
            }
        }
        // choose an empty cell next to the cat
        for (int i = 0; i < 6; i++) {
            int ind = (i + opp * 3) % 6;
            if (f.read(p[0] + o[ind][0], p[1] + o[ind][1]) == 0) {
                return new int[] { p[0] + o[ind][0], p[1] + o[ind][1] };
            }
        }
        return null;
    }
}

3

CloseCatcher

उन पदों में से एक को चुनता है जहां बिल्ली अगले चरण में कदम रख सकती है। यह एक का चयन करता है जो बिल्ली के लिए 3 चरणों के बाद सबसे अधिक संभव पथ देगा यदि यह वहां चलेगा और क्षेत्र नहीं बदलेगा।

कोड मेरी कैट प्रविष्टि, FreeCat के लगभग समान है , जो बहुत ही समान तरीके से दिशा चुनता है।

SpiralCat बनाम CloseCatcher:

स्पिरालकैट बनाम क्लोजचैकर

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

import main.Field;
import java.util.Arrays;

public class CloseCatcher implements Catcher {
    public String getName() {
        return "CloseCatcher";
    }

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

    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;
            }
        }
        int[] bestPos = { pos[0] + bestMove[0], pos[1] + bestMove[1] };
        return bestPos;
    }

    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;
    }

}

अच्छा 1। CloseCatcher आसानी से कब्जा StraightCat
Spikatrix

3

डिज्कस्ट्रा

वह बिल्लियों को बहुत पसंद नहीं करता (:v{ >

FreeCat बनाम दिज्क्स्त्र (अद्यतन की आवश्यकता) :

यहाँ छवि विवरण दर्ज करें

package players;

import main.Controller;
import main.Field;

import java.util.*;

/**
 * @author TheNumberOne
 *
 * Catches the cat.
 */

public class Dijkstra implements Catcher{

    private static final int[][][] CACHE;

    static {
        CACHE = new int[Controller.FIELD_SIZE][Controller.FIELD_SIZE][2];
        for (int x = 0; x < Controller.FIELD_SIZE; x++){
            for (int y = 0; y < Controller.FIELD_SIZE; y++){
                CACHE[x][y] = new int[]{x,y};
            }
        }
    }

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

    @Override
    public int[] takeTurn(Field f) {
        long startTime = System.nanoTime();

        final int[] theCat = f.findCat();
        int[] bestMove = {-1,1};
        int[] bestOpenness = {Integer.MAX_VALUE, 0};
        List<int[]> possiblePositions = new ArrayList<>();
        for (int x = 0; x < 11; x++){
            for (int y = 0; y < 11; y++){
                int[] pos = {x,y};
                if (f.isValidPosition(pos)){
                    possiblePositions.add(pos);
                }
            }
        }
        Collections.sort(possiblePositions, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return distance(o1, theCat) - distance(o2, theCat);
            }
        });
        for (int i = 0; i < possiblePositions.size() && System.nanoTime() - startTime < Controller.MAX_TURN_TIME/2; i++){
            int[] pos = possiblePositions.get(i);
            int before = f.field[pos[0]][pos[1]];
            f.placeBucket(pos);
            int[] openness = openness(theCat, f, true);
            if (openness[0] < bestOpenness[0] ||
                    (openness[0] == bestOpenness[0] &&
                            (openness[1] > bestOpenness[1])
                    )
                    ){
                bestOpenness = openness;
                bestMove = pos;
            }
            f.field[pos[0]][pos[1]] = before;
        }
        return bestMove;
    }


    /**
     *
     * @param pos The pos to calculate the openness of.
     * @param f The field to use.
     * @return Two integers. The first integer represents the number of reachable hexagons.
     * The second integer represents how strung out the squares are relative to the pos.
     */
    public static int[] openness(int[] pos, Field f, boolean catZeroWeight){
        Map<int[], Integer> lengths = new HashMap<>();
        PriorityQueue<int[]> open = new PriorityQueue<>(10,new Comparator<int[]>() {
            Map<int[], Integer> lengths;
            @Override
            public int compare(int[] o1, int[] o2) {
                return lengths.get(o1) - lengths.get(o2);
            }
            public Comparator<int[]> init(Map<int[], Integer> lengths){
                this.lengths = lengths;
                return this;
            }
        }.init(lengths));
        Set<int[]> closed = new HashSet<>();
        lengths.put(pos, catZeroWeight ? 0 : 6 - pointsAround(pos, f).size());
        open.add(pos);
        while (open.size() > 0){
            int[] top = open.remove();
            if (closed.contains(top)){
                continue;
            }
            closed.add(top);
            int l = lengths.get(top);
            List<int[]> pointsAround = pointsAround(top, f);

            for (ListIterator<int[]> iter = pointsAround.listIterator(); iter.hasNext();){
                int[] point = iter.next();
                if (closed.contains(point)){
                    iter.remove();
                }
            }

            for (int[] p : pointsAround){
                int length = l + 7 - pointsAround(p, f).size();
                if (lengths.containsKey(p)){
                    length = Math.min(length, lengths.get(p));
                }
                lengths.put(p, length);
                open.add(p);
            }
        }
        int sum = 0;
        for (int integer : lengths.values()){
            sum += integer;
        }
        return new int[]{lengths.size(),sum};
    }

    public static int distance(int[] p1, int[] p2){
        p2 = Arrays.copyOf(p2, 2);
        while (p2[0] < p1[0]){
            p2[0] += 11;
        }
        while (p2[1] < p2[0]){
            p2[1] += 11;
        }
        int lowestDistance = 0;
        for (int dx = 0; dx == 0; dx -= 11){
            for (int dy = 0; dy == 0; dy -= 11){
                lowestDistance = Math.min(lowestDistance,Math.min(Math.abs(p1[0]-p2[0]-dx),Math.min(Math.abs(p1[1]-p2[1]-dy),Math.abs(p1[0]+p1[1]-p2[0]-dx-p2[1]-dy))));
            }
        }
        return Math.min(Math.abs(p1[0]-p2[0]),Math.min(Math.abs(p1[1]-p2[1]),Math.abs(p1[0]+p1[1]-p2[0]-p2[1])));
    }

    public static int[] normalize(int[] p){
        return CACHE[(p[0]%11+11)%11][(p[1]%11+11)%11];
    }

    public static List<int[]> pointsAround(int[] p, Field f){
        int[] cat = f.findCat();
        List<int[]> locations = new ArrayList<>();
        for (int[] move : possibleMoves){
            int[] location = normalize(new int[]{p[0]+move[0], p[1] + move[1]});
            if (f.isValidPosition(location) || Arrays.equals(cat, location)){
                locations.add(location);
            }
        }
        return locations;
    }
}

कैसे वह बिल्ली को पकड़ने की कोशिश करता है:

वह बोर्ड के सभी वर्गों का विश्लेषण करता है और उस वर्ग को खोजने की कोशिश करता है जो बोर्ड के खुलेपन को कम करता है, और अधिकतम यह बताता है कि बोर्ड कितना घुसा हुआ है; बिल्ली के संबंध में। एक बोर्ड के खुलेपन और कठोरता की गणना उसके प्रसिद्ध एल्गोरिदम के एक संशोधन का उपयोग करके की जाती है

खुलापन:

किसी स्थिति के सापेक्ष एक बोर्ड का खुलापन उस स्थिति से पहुंच योग्य स्थानों की संख्या है।

Stringiness:

किसी स्थिति के सापेक्ष एक बोर्ड की कठोरता, पहुंच योग्य स्थिति और स्थिति के बीच की दूरी का योग है।

अंतिम अद्यतन के साथ:

अब, वह FreeCat और अपनी बिल्ली सभी बिल्लियों को पकड़ने में बहुत बेहतर है। दुर्भाग्य से, वह पागल असहयोगी बिल्लियों को पकड़ने में बहुत खराब है। अगर बिल्ली पागल में से एक है और फिर क्लैचर के रूप में काम कर रही है, तो यह पता लगाकर सुधार किया जा सकता है।

त्रुटि निवारण संपन्न।


यह पुष्टि कर सकता है कि यह अब तक काम करता है, लेकिन अब तक सबसे धीमा लेकिन सबसे अच्छा में से एक जो मुझे लगता है। केवल 4406 चालों के कुल योग करते हुए RandCat के खिलाफ 100 मैचों के लिए 134 सेकंड की आवश्यकता है! मुझे लगता है कि मुझे अगले एक दिन में अपने पीसी को रात भर चलने देना है ... क्या आप हमें बता सकते हैं कि यह कैसे काम करता है?
दोष

@flawr ने एक विवरण जोड़ा।
TheNumberOne

फिर भी मेरे लिए काम नहीं करता है। मुझे एक त्रुटि देता है: error: cannot infer type arguments for PriorityQueue<>इस लाइन पर PriorityQueue<int[]> open = new PriorityQueue<>(new Comparator<int[]>() {
स्पिकैट्रिक्स

@CoolGuy आप जावा 6 का उपयोग कर रहे हैं? मुझे लगता है कि आपको अपने JDK को अपडेट करने की आवश्यकता है।
TheNumberOne

@CoolGuy आप int[]बाद में दो खाली हीरे के बीच भी रख सकते हैं PriorityQueue
TheNumberOne

2

ForwordCatcher

बिल्ली के सामने एक बाल्टी रखते हैं, या अगर वह ले जाता है, तो पीछे की जगहें।

RabidCat बनाम ForwordCatcher:

RabidCat बनाम ForwordCatcher:

package players;

import main.Field;
import java.util.Arrays;

public class ForwordCatcher implements Catcher {
    public String getName() {
        return "ForwordCatcher";
    }

    private int[] lastPos = {0,0};

    public int[] takeTurn(Field f) {
        int[] temp = lastPos;
        int[] pos = f.findCat();
        lastPos = pos;
        int[] Move = {pos[0]*2-temp[0], pos[1]*2-temp[1]};
        if(f.isValidPosition(Move)){return Move;}
        if(f.isValidPosition(temp)){return temp;}
        Move[0] = pos[0];Move[1] = pos[1]+1;
        return Move;
    }
}

1
काफी कुछ त्रुटियां हैं, जो मुझे इस धारणा की ओर ले जाती हैं कि आपने अपने कार्यक्रम का परीक्षण नहीं किया। कृपया उन्हें ठीक करें ...
निर्दोष

@flawr तय त्रुटियों के बारे में खेद है। मैंने इसका परीक्षण नहीं किया और मेरा जावा अच्छा नहीं है।
मेगाटॉम

अच्छा, अब तक सब कुछ स्मूथली चलता है, लेकिन मैं अभी भी अनिश्चित हूं कि क्या यह हमेशा वैध चालें पैदा करेगा =)
त्रुटी

1
@flawr एक बिल्ली के पीछे की जगह हमेशा पकड़ने वाले के लिए खाली होगी :)
TheNumberOne

2

ChoiceCatcher

मेरी चॉइसकट प्रविष्टि के रूप में उसी स्कोरिंग तंत्र का उपयोग करता है । थोड़ा संशोधन है जो पहले कुछ चरणों में प्रासंगिक कोशिकाओं को चुनने में मदद करता है क्योंकि च्वाइसकैट पहले कुछ बाल्टियों के बारे में परवाह नहीं करता है क्योंकि यह उन्हें खतरे के रूप में नहीं देखता है।

चॉइस कैचर मौजूदा कैचर्स की तुलना में काफी बेहतर स्कोर करता है।

च्वाइसकैट बनाम च्वाइसकैचर:

च्वाइसकैट बनाम च्वाइसकैचर

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

import main.Field;

public class ChoiceCatcher implements Catcher {

    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 "ChoiceCatcher";
    }

    @Override
    public int[] takeTurn(Field f) {
        int[] bestPos = null;
        double bestPosValue = Double.MAX_VALUE;
        for (int i = 0; i < f.SIZE; i++) {
            for (int j = 0; j < f.SIZE; j++) {
                if (f.read(i, j) == Field.EMPTY) {
                    Field myField = new Field(f);
                    myField.placeBucket(new int[] { i, j });
                    double posValue = catTurnValue(myField);
                    if (posValue < bestPosValue) {
                        bestPosValue = posValue;
                        bestPos = new int[] { i, j };
                    }
                }
            }
        }
        return bestPos;
    }

    private double catTurnValue(Field f) {

        int[] pos = f.findCat();
        double[] values = new double[6];
        int count=0;
        for (int[] t : turns) {
            int[] currPos = { pos[0] + t[0], pos[1] + t[1] };
            double moveValue = movePosValue(currPos, f);
            values[count++]=moveValue;
        }
        Arrays.sort(values);
        return values[5];
    }

    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;
        int maxRoutes = 2;
        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, maxRoutes); i++) {
            fp *= product[5 - i];
        }
        double fp2 = 1;
        for (int i = 0; i < Math.min(count, 6); i++) {
            fp2 *= product[5 - i];
        }
        double retValue = Math.min(count, maxRoutes) + fp;
        double retValue2 = Math.min(count, 6) + fp2;
        return -retValue - retValue2 / 1000000;
    }

}

1

RandCatcher

यह केवल नियंत्रक के परीक्षण के लिए बनाया गया था और बस बेतरतीब ढंग से बाल्टी (बहुत ही अक्षम रूप से) रखता है।

package players;

import main.Field;

public class RandCatcher implements Catcher {
    public String getName(){
        return "RandCatcher";
    }
    public int[] takeTurn(Field f){
        int[] pos = {0,0};
        do {
            pos[0] = (int) (Math.random()*f.SIZE);
            pos[1] = (int) (Math.random()*f.SIZE);
        } while( f.isValidPosition(pos)==false );
        return pos;
    }

}

1

StupidFillCatcher

यह सिर्फ नियंत्रक परीक्षण के लिए बनाया गया था। यह सिर्फ कॉलम द्वारा कॉलम को भरता है जब तक बिल्ली को पकड़ा नहीं जाता है।

package players;

import main.Field;

public class StupidFillCatcher implements Catcher {
    public String getName(){
        return "StupidFillCatcher";
    }
    public int[] takeTurn(Field f){
        for(int i=0; i < f.SIZE; i++){
            for(int j=0; j < f.SIZE; j++){
                if(f.isValidPosition(new int[] {i,j})){
                    return new int[] {i,j};
                }
            }
        }
        return new int[] {0,0};
    }

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.