2012-04-27 13 views
5

ठीक है में योजना, इस पर विचार करें:सरणी में मिलान उप-सरणी। योजना

मैं arrays, -1, a और b युक्त एक बड़ा सरणी है।

-1 का मतलब फ़ील्ड रिक्त है:

var board = [ 
    [-1,-1, a], 
    [-1,-1, b], 
    [ b,-1, a] 
] 

अब मैं इस के खिलाफ छोटे सरणियों जाँच करना चाहते हैं:

var solutions = [ 
    [ 
     [1, 1, 1] 
    ], 
    [ 
     [1], 
     [1], 
     [1] 
    ], 
    [ 
     [1], 
     [0,1], 
     [0,0,1] 
    ], 
    [ 
     [0,0,1], 
     [0,1], 
     [1] 
    ] 
] 

board मैच solutions में पैटर्न से अगर एक मौजूदा मूल्य देखने के लिए।


क्या a किसी भी पैटर्न से मेल खाता है?
b किसी भी पैटर्न से मेल खाता है?

var q,w,e,r,t,y; 

q=w=e=r=t=y=0; 

for(; q < 3; q++) { 
    for(; w < 3; w++) { 
     for(; e < SOLUTIONS.length; e++) { 
      .... and so on... 
     } 
    } 
} 

इस उदाहरण मैं टिक टीएसी को पैर की अंगुली का इस्तेमाल किया है में:


आप में से किसी एक पागल नेस्टेड लूप बनाने की तुलना में एक बेहतर तरीका देख सकते हैं।

लेकिन मैं कुछ भी हो सकता था।

+0

मुझे लगता है कि, 'समाधान' पैटर्न में एक टिक-टैक-टो के लिए, आप शून्य से मेल नहीं खाते बल्कि खाली कोशिकाओं को मेल नहीं करना चाहते हैं। – akuhn

+0

तुलनात्मकता को आसान बनाने के लिए आप सरणी को 1 स्तर गहराई में बदलने की कोशिश कर सकते हैं। लेकिन मुझे कोई सरणी उथल-पुथल स्निपेट नहीं पता ... :( – ajax333221

उत्तर

0

बहुत ही रोचक सवाल। +1 :) यहां मेरा लेना है।

पूर्ण समाधान के लिए मेरी पहेली http://jsfiddle.net/BuddhiP/J9bLC/ देखें। मैं यहां मुख्य बिंदुओं को समझाने की कोशिश करूंगा।

मैं इस तरह के बोर्ड से शुरू करता हूं। मैंने -1 के बजाय 0 का उपयोग किया है क्योंकि यह आसान है।

var a = 'a', b = 'b'; 
    var board = [ 
     [a, 0, a], 
     [b, b, b], 
     [a, 0, a] 
     ]; 

मेरी रणनीति सरल है।

  1. जांचें कि पंक्तियों में से कोई भी एक ही खिलाड़ी (ए या बी) है, यदि हमारे पास विजेता है।
  2. वरना, देखें कि क्या किसी भी कॉलम को ही खिलाड़ी
  3. वरना है, की जाँच करें जो तीन जीत मामलों रहे हैं, तो विकर्ण एक खिलाड़ी

है।

सबसे पहले मैंने एक फ़ंक्शन बनाया जो पंक्तियों का सेट ले सकता है (पूर्व: [ए, 0, बी]), और जांचें कि क्या संपूर्ण पंक्ति में एक ही मान है, और यदि वह मान शून्य नहीं है (या -1 मामला)।

checkForWinner = function() { 
    lines = Array.prototype.slice.call(arguments); 
    // Find compact all rows to unique values. 
    var x = _.map(lines, function (l) { 
     return _.uniq(l); 
    }); 
    // Find the rows where all threee fields contained the same value. 
    var y = _.filter(x, function (cl) { 
     return (cl.length == 1 && cl[0] !== 0); 
    }); 
    var w = (y.length > 0) ? y[0] : null; 
    return w; 
}; 

यहाँ मैं एक पंक्ति में अद्वितीय मान लेते हैं, और अगर मैं केवल एक अनूठा मूल्य जो शून्य नहीं है पा सकते हैं, वह विजेता है।

यदि पंक्तियों में कोई विजेता नहीं है, तो मैं कॉलम की जांच करता हूं। मेरे कोड का पुन: उपयोग करने के लिए, मैं कॉलम को पंक्तियों में बदलने के लिए _.zip() विधि का उपयोग करता हूं और उसके बाद उपरोक्त एक ही फ़ंक्शन का उपयोग यह जांचने के लिए करता हूं कि हमारे पास विजेता है या नहीं।

var board2 = _.zip.apply(this, board); 
winner = checkForWinner.apply(this, board2); 

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

extractDiagonals = function (b) { 
    var d1 = _.map(b, function (line, index) { 
     return line[index]; 
    }); 
    var d2 = _.map(b, function (line, index) { 
     return line[line.length - index - 1]; 
    }); 
    return [d1, d2]; 
}; 

अंत में यह वह जगह है जहाँ मैं वास्तव में एक विजेता के लिए बोर्ड की जाँच करें:

// Check rows 
winner = checkForWinner.apply(this, board); 
if (!winner) { 
    var board2 = _.zip.apply(this, board); 

    // Check columns, now in rows 
    winner = checkForWinner.apply(this, board2); 
    if (!winner) { 
     var diags = extractDiagonals(board); 
     // Check for the diagonals now in two rows. 
     winner = checkForWinner.apply(this, diags); 
    } 
} 

अगर आप में से किसी क्यों मैं के बजाय लागू() विधि का उपयोग सीधे फ़ंक्शन कॉल, कारण लागू है () आपको किसी फ़ंक्शन में तर्कों की सूची के रूप में सरणी तत्वों को पारित करने की अनुमति देता है।

मेरा मानना ​​है कि यह 4x4 या उच्चतर मैट्रिक्स के लिए भी काम करना चाहिए, हालांकि मैंने उनका परीक्षण नहीं किया था।

मेरे पास समाधान का परीक्षण करने के लिए बहुत कम समय था, इसलिए अगर आपको कोई त्रुटि मिलती है तो कृपया मुझे बताएं।

+0

हार्डवायरिंग टिक-टैक-टो के लिए डाउनवोट लेकिन किसी भी बोर्ड के खिलाफ किसी भी पैटर्न से मेल खाने के ओपी के सामान्य प्रश्न को संबोधित नहीं करते हैं। – akuhn

+0

हम्म .. वास्तव में? :) ओपी लगता है कि मैंने उसका उत्तर दिया ठीक से सवाल करें। किसी भी ** बोर्ड पर ** ** ** ** मिलान ** ** ** ** इस मंच में उत्तरदायी नहीं होगा, इसके लिए आपको इसके लिए एक पुस्तक की आवश्यकता होगी। ओपी किसी भी आकार बोर्ड पर एक टिक-टैक-टो फैशन पैटर्न मिलान (पंक्ति/कॉलम/डायग में एक एकल मूल्य) चाहता था, जो यह समाधान पूरी तरह से संभालने में सक्षम है, और यह अधिक सरल तरीके से करता है। – BuddhiP

0

नहीं, आप केवल क्या ज़रूरत है तीन नेस्टेड छोरों: पाश करने के लिए अपने पैटर्न से अधिक पाश करने के लिए एक, और दो अपने दो आयामी खेल मैदान:

function checkPatterns(patterns, player, field) { 
    pattern: for (var p=0; p<patterns.length; p++) { 
     for (var i=0; i<patterns[p].length; i++) 
      for (var j=0; j<patterns[p][i].length; j++) 
       if (patterns[p][i][j] && player !== field[i][j]) 
        continue pattern; 
     // else we've matched all 
     return p; 
    } 
    // else none was found 
    return -1; 
} 
function getSolution(player) 
    return SOLUTIONS[checkPatterns(SOLUTIONS, player, currentBOARD)] || null; 
} 

ठीक है, आप खिलाड़ियों के लिए एक चौथा पाश आवश्यकता हो सकती है (players.any(getSolution)), लेकिन यह इसे कोई पागल नहीं बनाता है और केवल दो खिलाड़ियों के लिए भी रेखांकित किया जा सकता है।

हालांकि, यह "पैटर्न सरणियों" तैयार करने के लिए खुद को पैटर्न के लिए एल्गोरिदम के निर्माण के लिए की तुलना में आसान हो सकता है:

function hasWon(player, field) { 
    vert: for (var i=0; i<field.length; i++) { 
     for (var j=0; j<field[i].length; j++) 
      if (field[i][j] !== player) 
       continue vert; 
     return "vertical"; 
    } 
    hor: for (var j=0; j<field[0].length; j++) { 
     for (var i=0; i<field.length; i++) 
      if (field[i][j] !== player) 
       continue hor; 
     return "horizontal"; 
    } 
    for (var i=0, l=true, r=true, l=field.length; i<l; i++) { 
     l == l && field[i][i] === player; 
     r == r && field[l-i-1][l-i-1] === player; 
    } 
    if (l || r) 
     return "diagonal"; 
    return null; 
} 
3

आप क्या कर सकते गति के लिए पैटर्न को संकलित करने के लिए है। वैसे ही वही भाषाएं नियमित अभिव्यक्तियों को गति के लिए संकलित करने की अनुमति देती हैं।

function compile(pattern) { 
    var code = "matcher = function(a) { return " 
    var first = null 
    for (var n = 0; n < pattern.length; n++) { 
     for (var m = 0; m < pattern[n].length; m++) { 
      if (pattern[n][m] == 0) continue 
      var nm = "["+n+"]["+m+"]" 
      if (first == null) { 
       code += "a" + nm + " != -1"; 
       first = " && a" + nm + " == " 
      } 
      code += first + "a" + nm 
     } 
    } 
    code += "; }"; 
    eval(code); 
    return matcher 
} 

तो यह क्या कर रहा है?

उदाहरण

compile([[1],[0,1],[0,0,1]]).toString() 

के लिए आप इसे कैसे प्रयोग करते हैं तो निम्नलिखित समारोह

"function (a) { return a[0][0] != -1 && a[0][0] == a[0][0] && a[0][0] == a[1][1] && a[0][0] == a[2][2]; }" 

पैदा करेगा?

मिलान करने के लिए अपने बोर्ड पर पदों के लिए इसका इस्तेमाल के रूप में

var patterns = solutions.collect(function(each) { return compile(each); }) 
var matches = patterns.any(function(each) { return each(board); }) 

 

एनबी, इस प्रकार आखिरी ऊपर कतरना आप कई लोकप्रिय उच्च क्रम प्रोग्रामिंग पुस्तकालयों में से एक का उपयोग कर रहे हो जाती है, उदाहरण के लिए lodash, collect और any सरणी प्रोटोटाइप पर फ़ंक्शन प्रदान करने के लिए, यदि इसके बजाय लूप के लिए सादे पुराने का उपयोग नहीं किया जाता है।

0

आप एक स्ट्रिंग होना करने के लिए अपने बोर्ड हो सकता है:

var board = 
    "-1,-1,a, 
    -1,-1,b, 
    b,-1,a" 

और अपने समाधान तो तार की एक सरणी (बोर्ड के समान)

var solutions = [ 
    "1,1,1, 
    0,0,0, 
    0,0,0" 
    , 
    "1,0,0, 
    0,1,0, 
    0,0,1" 

]

हो सकता है तुलना के लिए, -1 और बी को 0s के साथ प्रतिस्थापित करें और 1s के साथ बस स्ट्रिंग्स

की तुलना करें

यह एक और लूप

+0

यह मेरा पहला तूफान था, लेकिन इसका मतलब है कि आपको प्रत्येक पंक्ति के लिए पैटर्न को परिभाषित करने की आवश्यकता है। यदि मध्य पंक्ति 1,1 है तो आपका समाधान मेल नहीं खाता है, 1 जब तक कि आप मैच में 0,0,0,1,1,1,0,0,0 भी जोड़ते हैं। यह 3x फ़ील्ड के लिए काम करेगा, लेकिन 9x 9 तक बढ़ने से बहुत सारे समाधान मिलेंगे। आपको भी बनाने की ज़रूरत है प्रतिस्थापन करने के लिए प्रत्येक चेक के लिए प्लेफील्ड की एक प्रति और चूंकि जावास्क्रिप्ट सरणी के संदर्भ बनाता है, इसलिए आपको प्रत्येक चेक के लिए सरणी क्लोन करने की आवश्यकता होती है, इस प्रकार एक नई सरणी बनाने के लिए सभी पंक्तियों और कोल्स को ढीला करना (या c = board.splice का उपयोग करना (0) पठनीयता के लिए, गति नहीं) –

0

के अंदर 10 अलग-अलग लूप होने से बहुत तेज़ है, आपको हमेशा इसे सभी को जाने के लिए लूप की आवश्यकता होगी। आप इसे पढ़ने और अधिक लचीला बनाने में आसान बना सकते हैं। नीचे दिया गया कोड 1 और उसके बाद बड़ी संख्या में पंक्तियों/कोलों के लिए काम करेगा और 2 खिलाड़ियों के लिए एक सरल समायोजन के साथ भी काम करेगा।

var board1 = [ 
[-1,-1, 'a'], 
[-1,-1, 'b'], 
['b',-1, 'a'] 
]; 
var board2 = [ 
['a','a', 'a'], 
[-1,-1, 'b'], 
['b',-1, 'a'] 
]; 
var board3 = [ 
[-1,'b', 'a'], 
[-1,'b', 'b'], 
['b','b', 'a'] 
]; 
var board4 = [ 
['a',-1, 'a'], 
[-1,'a', 'b'], 
['b',-1, 'a'] 
]; 

var solutions = [ 
[ 
    [1, 1, 1] 
], 
[ 
    [1], 
    [1], 
    [1] 
], 
[ 
    [1], 
    [0,1], 
    [0,0,1] 
], 
[ 
    [0,0,1], 
    [0,1], 
    [1] 
] 
]; 

function checkForWinner(playfield) { 
    var sl = solutions.length; //solutions 
    var bl = playfield.length; //board length 
    var bw = playfield[0].length; //board width 
    while(sl--) { 
     //foreach solution 
     var l = solutions[sl].length; 

     if (l==1) { 
      //horizontal 
      //loop trough board length to find a match 
      var tl = bl; 
      while(tl--) { 
       var pat = playfield[tl].join('') 
       var r = checkRow(pat) 
       if (r!==false) 
        return r; 
      } 
     } else { 
      //vertical or diagonal 
      var l1 = solutions[sl][0].length; 
      var l2 = solutions[sl][1].length; 

      if (l1==l2) { 
       //vertical     
       var tw = bw; 
       while (tw--) { 
        //loop for each column 
        var pat = ""; 
        var tl = l; 
        while(tl--) { 
         //loop for vertical 
         pat += playfield[tl][tw]; 
        } 

        var r = checkRow(pat) 
        if (r!==false) 
         return r; 
       } 

      } else { 
       //diagonal 
       var pat = ""; 
       while(l--) { 
        //loop for vertical 
        var tw = solutions[sl][l].length; 
        while (tw--) { 
         //loop for horizontal      
         if (solutions[sl][l][tw]!=0) 
          pat += playfield[l][tw]; 
        } 
       } 

       var r = checkRow(pat) 
       if (r!==false) 
        return r; 
      } 
     } 
    } 
    return 'no winner'; 
} 

function checkRow(pat) { 
    if (!(pat.indexOf('a')>=0 || pat.indexOf('-1')>=0)) { 
     //only b on row. player B won 
     return 'B'; 
    } 

    if (!(pat.indexOf('b')>=0 || pat.indexOf('-1')>=0)) { 
     //only a on row. player A won 
     return 'A'; 
    } 

    return false; 
} 

console.log(checkForWinner(board1)); 
console.log(checkForWinner(board2)); 
console.log(checkForWinner(board3)); 
console.log(checkForWinner(board4));