2015-12-30 8 views
7

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

जबकि निशान यादृच्छिक रूप से तय किए जाते हैं, वहां कई नियम हैं कि उन्हें जानवर पर कैसे दिखाना है, उदाहरण के लिए "पेट" क्षेत्र में चिह्नों के ऊपर "पूर्ण शरीर" क्षेत्र में चिह्न चिह्न दिखाते हैं। बेहतर व्याख्या करने के लिए, मैं अब तक परीक्षक की एक छवि संलग्न करेंगे:

enter image description here

तो यह अनियमित रूप से उत्पन्न जानवर पर 5 चिह्नों तोड़ने के लिए, eyeshadow अंकन आंख क्षेत्र के अंतर्गत आता है, undertail पूंछ के अंतर्गत आता है , streaks पूर्ण व्यक्ति से संबंधित है, appaloosa पीछे से संबंधित है, और okapi पैरों से संबंधित है। ऑर्डर अभी अभी जोड़ा गया है क्योंकि स्क्रिप्ट को डेटाबेस और यादृच्छिक रूप से चुने गए चिह्नों के माध्यम से लूप किया गया है, इसलिए ओकेपी (पैरों पर पट्टियां) शीर्ष पर है क्योंकि यह सरणी में आखिरी बार था, और अंतिम जोड़ा गया। लेकिन आदेश नियमों का पालन करते हुए, सरणी में आखिरी वाला होना चाहिए (शरीर भर में क्षैतिज रेखाएं), क्योंकि पूर्ण व्यक्ति चिह्न शीर्ष पर जाते हैं।

यहाँ, कोड चयन चिह्नों है इस Laravel इंजन का उपयोग किया जाता है:

// Determine number of markings 
    $num = mt_rand(1,10); 

    if ($num == 1) { 
     $markingNum = 0; 
    } elseif ($num > 1 && $num < 4) { 
     $markingNum = 1; 
    } elseif ($num > 4 && $num < 6) { 
     $markingNum = 2; 
    } elseif ($num > 6 && $num < 8) { 
     $markingNum = 3; 
    } elseif ($num > 8 && $num < 10) { 
     $markingNum = 4; 
    } else { 
     $markingNum = 5; 
    } 

    // Calculate Marking type and color 
    $markings = array(); 

    if ($markingNum > 0) { 
     for ($m = 0 ; $m < $markingNum; $m++) { 
      // Set color values (pulls from the "pallet" selected earlier in the code, which will determine the range of color that marking can be) 
      if ($m == 1) { 
       $pal = $pallet->marking1; 
      } elseif ($m == 2) { 
       $pal = $pallet->marking2; 
      } elseif ($m == 3) { 
       $pal = $pallet->marking3; 
      } elseif ($m == 4) { 
       $pal = $pallet->marking4; 
      } else { 
       $pal = $pallet->marking5; 
      } 

      // Pull previous marking info 
      if (count($markings) != 0) { 
        $previous = DataMarking::whereIn('name', array_keys($markings))->get(); 

        // This pulls the regions of the current markings in the array so it won't select a region that already has a marking. 
        foreach ($previous as $p) { 
         $regions[$p->region] = $p->name; 
        } 

        // Uncommon marking (10% chance) 
        $r = mt_rand(1, 10); 

        if ($r == 10) { 
         $marking = DataMarking::where('rarity', 1) 
               ->where('public', 1) 
               ->whereNotIn('name', array_keys($markings)) 
               ->whereNotIn('region', array_keys($regions)) 
               ->orderByRaw("RAND()") 
               ->first(); 
        // Common markings 
        } else { 
         $marking = DataMarking::where('rarity', 0) 
               ->where('public', 1) 
               ->whereNotIn('name', array_keys($markings)) 
               ->whereNotIn('region', array_keys($regions)) 
               ->orderByRaw("RAND()") 
               ->first(); 
        } 

        // Colors marking 
        if ($pal == 0) { 
         $markingColor = rand_color(); 
        } else { 
         $range = ColorRange::where('id', $pal)->firstOrFail(); 
         $markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1)); 
        } 

        $markings[$marking->name] = $markingColor; 
       } else { 
       // Uncommon marking (10% chance) 
       $r = mt_rand(1, 10); 

       if ($r == 10) { 
        $marking = DataMarking::where('rarity', 1) 
              ->where('public', 1) 
              ->orderByRaw("RAND()")->first(); 
       // Common marking 
       } else { 
        $marking = DataMarking::where('rarity', 0) 
              ->where('public', 1) 
              ->orderByRaw("RAND()")->first(); 
       } 

       // Colors marking 
       if ($pal == 0) { 
        $markingColor = rand_color(); 
       } else { 
        $range = ColorRange::where('id', $pal)->firstOrFail(); 
        $markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1)); 
       } 

       $markings[$marking->name] = $markingColor; 
      } 
     } 
    } 

मैं समझ मैं जटिल बयान करता है, तो बहुत से ऐसा कर सकते हैं, लेकिन यह सिर्फ एक सुंदर की तरह प्रतीत नहीं होता मेरे लिए समाधान इसके अलावा, एक अपवाद भी है: 'ग्रेडिएंट', एक पूर्ण व्यक्ति अंकन, सबकुछ नीचे जाता है भले ही यह एक पूर्ण शरीर अंकन हो। हालांकि, इस तरह के अपवाद के साथ अब तक यह एकमात्र अंकन है।

मैंने PHP द्वारा प्रदान किए गए विभिन्न sort फ़ंक्शंस का उपयोग करने का प्रयास किया है लेकिन मुझे बहुत भाग्य नहीं है। uksort सबसे अधिक आशाजनक प्रतीत होता है, लेकिन चूंकि हम उस डेटाबेस में मौजूद हैं जो डेटाबेस में मौजूद है और सरणी में नहीं है, हम सॉर्टिंग कर रहे हैं (कल्पना फ़ंक्शन को मार्किंग => रंग सरणी प्रारूप को खिलाया जाना चाहिए), यह काम करना मुश्किल साबित हो रहा है।

टीएल; डॉ: मुझे एक सरणी को फिर से व्यवस्थित करने की आवश्यकता है कि कुंजी के लिए डीबी में मौजूद मानों के आधार पर अनिश्चित मात्रा में डेटा (चिह्नों के लिए क्षेत्र)। इसे पूरा करने का सबसे शानदार तरीका क्या है?

+0

मुझे कुत्ते के साथ छवि पसंद है, भले ही यह एक अजीब दिखने वाला कुत्ता हो। – Phiter

+0

हाहा! यह एक अजीब कुत्ता है, है ना? –

+0

ऐसा लगता है कि आपको अपनी 'डेटामार्किंग' तालिका में 'z-index' (int) कॉलम चाहिए। यह संपत्ति गहराई के रूप में कार्य करती है। तो 'eyeshadow'' z-index' 1 हो सकता है, उदाहरण के लिए, और 'streaks'' z-index' हो सकता है 5. 'z-index' जितना अधिक होगा, बाद में अंकन खींचा जाएगा, जिसके परिणामस्वरूप बाकी सब कुछ के ऊपर 'streaks' खींचा जा रहा है। चिह्नों की अपनी सरणी को पुनर्प्राप्त करने के बाद, इसे आरोही क्रम में 'z-index' द्वारा ऑर्डर करें। फिर इसके माध्यम से लूप और सभी निशान खींचें। – Alexander

उत्तर

4

कर रहे हैं यहाँ में खो दिया जाएगा अपने कोड के लिए कुछ अनुकूलन कर रहे हैं, वहाँ का वर्णन करने के लिए क्या किया गया था इनलाइन टिप्पणी कर रहे हैं। यह स्पष्ट रूप से समाप्त नहीं हुआ है क्योंकि कुछ चीजें हैं मार्किन ने अपने जवाब में बताया कि बेहतर होगा।

// Determine number of markings 
    $num = mt_rand(1,10); 

    // Removed redundent $num > X as the conditions were already meet that it was > X by the previous if statement 
    if ($num == 1) { 
     $markingNum = 0; 
    } else if ($num < 4) { 
     $markingNum = 1; 
    } else if ($num < 6) { 
     $markingNum = 2; 
    } else if ($num < 8) { 
     $markingNum = 3; 
    } else if ($num < 10) { 
     $markingNum = 4; 
    } else { 
     $markingNum = 5; 
    } 

    // Calculate Marking type and color 
    $markings = array(); 

    if ($markingNum > 0) { 
     for ($m = 1 ; $m <= $markingNum; $m++) { // incrimented to 1 and <= so we can dynamically select elements 
      // Set color values (pulls from the "pallet" selected earlier in the code, which will determine the range of color that marking can be) 
      $pal = $pallet->{'marking' . $m}; // Removed if/else and replaced with a dynamic variable 


      // Uncommon marking (10% chance) 
      $r = mt_rand(1, 10); 

      // removed duplicate database selections for a simple $rarity variable that accomplishes the same task 
      if ($r == 10) { 
       $rarity = 1; 
      } else { 
       $rarity = 0; 
      } 

      $marking = DataMarking::where('rarity', $rarity) 
            ->where('public', 1) 
            ->whereNotIn('name', array_keys($markings)) 
            ->whereNotIn('region', $regions) 
            ->orderByRaw("RAND()") 
            ->first(); 

      // Colors marking 
      if ($pal == 0) { 
       $markingColor = rand_color(); 
      } else { 
       $range = ColorRange::where('id', $pal)->firstOrFail(); 
       $markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1)); 
      } 

      $markings[$marking->name] = $marking; // adds all of the marking data, this is where you could have a z-index in the database 
      $markings[$marking->name] = $markingColor; // add your color to your marking data 
      $regions[] = $marking->region; 

     } 
    } 
2

मैं आपके प्रश्न का उत्तर नहीं दूंगा, लेकिन आपके कोड को देखकर सुधार के लिए बहुत सी जगह है।

इस पर विचार करें:

if ($m == 1) {  
    $pal = $pallet->marking1; 
} elseif ($m == 2) { 
    $pal = $pallet->marking2; 
} elseif ($m == 3) { 
    $pal = $pallet->marking3; 
} elseif ($m == 4) { 
    $pal = $pallet->marking4; 
} else { 
    $pal = $pallet->marking5; 
} 

यह बहुत सरल कुछ के लिए बदला जा सकता है:

$pa1 = (in_array($m,range(1,4))) ? $pallet->marking{$m} : $pallet->marking5; 

एक ही के लिए:

$marking = DataMarking::where('rarity', ($r == 10) ? 1 : 0) 
         ->where('public', 1) 
         ->whereNotIn('name', array_keys($markings)) 
         ->whereNotIn('region', array_keys($regions)) 
         ->orderByRaw("RAND()") 
         ->first(); 
:

if ($r == 10) { 

    $marking = DataMarking::where('rarity', 1) 
          ->where('public', 1) 
          ->whereNotIn('name', array_keys($markings)) 
          ->whereNotIn('region', array_keys($regions)) 
          ->orderByRaw("RAND()") 
          ->first(); 
// Common markings 
} else { 
    $marking = DataMarking::where('rarity', 0) 
          ->where('public', 1) 
          ->whereNotIn('name', array_keys($markings)) 
          ->whereNotIn('region', array_keys($regions)) 
          ->orderByRaw("RAND()") 
          ->first(); 
} 

अगर फिर से लिखा जा सकता है

बेशक ORDER BY RAND() में प्रदर्शन कारणों से सबसे अच्छा समाधान नहीं हो सकता है।

आप वास्तव में अपने कोड और दोहराव की राशि के बारे में ध्यान देना चाहिए या आप जल्दी ही तुम क्या

+0

युक्तियों के लिए बहुत बहुत धन्यवाद! –

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