2011-11-27 8 views
16

मैं पहले से ही स्टैक ओवरव्लो पर कई टिक टैक पैर विषयों को पढ़ चुका हूं। और मैंने पाया विकिपीडिया पर रणनीति अपनी प्रस्तुति परियोजना के लिए उपयुक्त है:टिक टैक पैर की अंगुली सही एआई एल्गोरिदम: "फोर्क बनाने" चरण में गहराई

एक खिलाड़ी सही टिक टीएसी को पैर की अंगुली खेल सकते हैं अगर वे निम्न तालिका में सर्वोच्च प्राथमिकता के साथ कदम चुनें [3]।

1) विन: यदि आपके पास दो पंक्तियां हैं, तो पंक्ति में तीन प्राप्त करने के लिए तीसरा खेलें।

2) ब्लॉक: यदि प्रतिद्वंद्वी की पंक्ति में दो है, तो को अवरोधित करने के लिए तीसरा खेलें।

3) फोर्क: एक अवसर बनाएं जहां आप दो तरीकों से जीत सकते हैं।

4) ब्लॉक प्रतिद्वंद्वी के कांटा:

विकल्प 1: एक पंक्ति में दो बनाएं क्योंकि यह उन्हें एक कांटा बनाने या जीत में परिणाम नहीं करता है, बचाव में प्रतिद्वंद्वी मजबूर करने के लिए लंबे समय के रूप । उदाहरण के लिए, यदि "एक्स" में एक कोने है, तो "ओ" में केंद्र है, और "एक्स" में विपरीत कोने भी है, "ओ" जीतने के लिए कोने नहीं खेलना चाहिए। अगर वहाँ एक विन्यास जहां प्रतिद्वंद्वी कांटा कर सकते हैं, ब्लॉक कि कांटा है:

विकल्प 2 (। इस परिदृश्य में एक कोने बजाना "एक्स" जीतने के लिए के लिए एक कांटा बनाता है)।

5) केंद्र: केंद्र चलाएं।

6) कॉर्नर के विपरीत: यदि प्रतिद्वंद्वी कोने में है, तो विपरीत कोने खेलें।

7) खाली कॉर्नर: एक खाली कोने खेलें।

8) खाली पक्ष: एक खाली पक्ष चलाएं।

मैंने इन चरणों का पालन किया है, और कंप्यूटर कभी हार नहीं जाता है। हालांकि, जिस तरह से हमला करते हैं वह सही नहीं है। क्योंकि मुझे कोई संकेत नहीं है कि चरण 3 कैसे करें। चरण 3 में मैं यही करता हूं: प्रत्येक सेल को स्कैन करें, जांचें कि उस सेल पर टोकन डालने पर एक कांटा बनाता है, फिर उसे वहां रखें।

private void step3() // Create Fork. 
{ 
    int[] dummyField = (int[])field.Clone(); 
    // Try Level 1 Dummy 
    for (int i = 0; i < 9; i++) 
    { 
     if (dummyField[i] != 0) continue; 
     dummyField[i] = 2; 
     if (countFork(dummyField, 2) >= 2) 
     { 
      nextCell = i; 
      return; 
     } 
     dummyField[i] = 0; 
    } 

} 

कृपया मुझे इस चरण के बारे में कुछ सलाह दें।

EDIT1: गिनती कांटा की गणना होती है कि कितने कांटे कि कंप्यूटर है (कंप्यूटर की टोकन 2 है, तो खिलाड़ी टोकन, 1 है, क्योंकि मैं भी चरण 4 के लिए है कि विधि का इस्तेमाल किया है, इसलिए वहां countFork समारोह में टोकन के लिए एक पैरामीटर है)।

EDIT2: कारण मैं कहता हूं कि यह सही नहीं है (सीपीयू पहले जाता है, और इसकी कोशिकाएं नीली होती हैं, मानव कोशिकाएं लाल होती हैं)। enter image description here जैसा कि आप देख सकते हैं, अगर मैं शीर्ष-पक्ष सेल में डालता हूं, तो कंप्यूटर जीतता है। लेकिन अगर मैं दाएं तरफ सेल डालता हूं, तो यह एक टाई है, हालांकि कंप्यूटर अभी भी जीत सकता है।

EDIT3: पता नहीं क्यों, लेकिन मैंने चरण 3 पर टिप्पणी की, और कंप्यूटर खेलता है ... पूरी तरह से! मैं वास्तव में हैरान हूँ!

private int countFork(int[] field, int token) 
{ 
    int result = 0; 

    // Vertical 
    int cpuTokenCount; 
    int spareCell; 
    for (int x = 0; x < 3; x++) 
    { 
     cpuTokenCount = 0; 
     spareCell = -1; 
     for (int y = 0; y < 3; y++) 
     { 
      if (field[getNumberFromXY(x, y)] == token) 
       cpuTokenCount++; 
      else if (field[getNumberFromXY(x, y)] == 0) 
       spareCell = getNumberFromXY(x, y); 
     } 
     if (cpuTokenCount == 2 && spareCell != -1) result++; 
    } 

    // Horizontal 
    for (int y = 0; y < 3; y++) 
    { 
     cpuTokenCount = 0; 
     spareCell = -1; 
     for (int x = 0; x < 3; x++) 
     { 
      if (field[getNumberFromXY(x, y)] == token) 
       cpuTokenCount++; 
      else if (field[getNumberFromXY(x, y)] == 0) 
       spareCell = getNumberFromXY(x, y); 
     } 
     if (cpuTokenCount == 2 && spareCell != -1) result++; 
    } 

    // Top-Left To Lower-Right Diagonal 
    cpuTokenCount = 0; 
    spareCell = -1; 
    for (int i = 0; i < 3; i++) 
    { 
     if (field[getNumberFromXY(i, i)] == token) 
      cpuTokenCount++; 
     else if (field[getNumberFromXY(i, i)] == 0) 
      spareCell = getNumberFromXY(i, i); 
    } 
    if (cpuTokenCount == 2 && spareCell != -1) result++; 

    // Top-Right To Lower-Left Diagonal 
    cpuTokenCount = 0; 
    spareCell = -1; 
    for (int i = 0; i < 3; i++) 
    { 
     if (field[getNumberFromXY(2 - i, i)] == token) 
      cpuTokenCount++; 
     else if (field[getNumberFromXY(2 - i, i)] == 0) 
      spareCell = getNumberFromXY(2 - i, i); 
    } 
    if (cpuTokenCount == 2 && spareCell != -1) result++; 

    return result; 
} 

: यहाँ मेरी countFork समारोह (मैं बंदरगाह के लिए ऐलिस, जो 2-आयाम सरणी का समर्थन नहीं करता के लिए इस कोड की जरूरत है, तो मैं getNumberFromXY का उपयोग 1-आयाम में 2-आयाम सरणी परिवर्तित करने के लिए) है EDIT4: सैंडो के अनुसार बग फिक्स किया गया, और EDIT 3 पर कोड अपडेट किया गया, अब यह पूरी तरह से काम करता है!

+1

उचित लग रहा है। आपको क्या लगता है कि यह काम नहीं करता है? 'CountFork' के लिए दूसरा पैरामीटर क्या है? –

+0

@MatthewStrawbridge आपके सवालों के जवाब देने के लिए संपादित किया गया। जवाब देने के लिए धन्यवाद। –

+0

शून्य खिलाड़ी है, या शून्य अप्रयुक्त है? – soandos

उत्तर

8

मुझे यकीन नहीं है कि यह करने का सबसे शानदार तरीका है, लेकिन यहां कांटे को देखने का एक दो कदम है।

यदि कंप्यूटर अगली बारी नहीं जीत सकता है, और यह पहली या दूसरी बारी नहीं है, तो एक कांटा संभव हो सकता है (यह एक कांटा के लिए सेटअप बनाने के साथ सौदा नहीं करता है, केवल एक कांटा ढूंढ रहा है)।

खाली होने वाली प्रत्येक कोशिका के लिए, इसे भरें, फिर अपना चरण 1 फ़ंक्शन चलाएं (देखें कि पंक्ति में दो हैं या नहीं)। यदि यह दो स्थानों को पाता है, बधाई हो, तो आपके पास कांटा है। यदि नहीं, तो आप नहीं करते हैं।

+0

इस तरह मैं अपने कोड में कर रहा हूं! फ़ंक्शन 'countFork' यह मानना ​​है कि अगर मैं किसी सेल पर टोकन डालता हूं तो जीतने के कितने तरीके हैं। परिणाम, हालांकि, जैसा कि मैंने संपादन 3 में देखा है, यदि कोई चरण 3 नहीं है तो यह बेहतर होगा! –

+0

तो इस प्रक्रिया में आपके कोड में एक बग है, या आप एक अलग तरीके की तलाश में हैं? – soandos

+0

मैं कुछ भी स्वीकार करूंगा जो कंप्यूटर को बेहतर खेलता है। मैंने अपना countFork फ़ंक्शन पोस्ट किया है, ताकि आप जांच सकें कि कोई बग है या नहीं। –

संबंधित मुद्दे