2010-03-03 45 views
10

में आसन्न कोशिकाओं को खोजने का पाइथोनिक और कुशल तरीका मैं पायथन/ओपनजीएल का उपयोग कर पाइथन में एक टाइल आधारित ऐप का निर्माण कर रहा हूं जिसमें मुझे किसी दिए गए सेल के लिए आसन्न कोशिकाओं को ढूंढना होगा। मैं एक कार्टेसियन ग्रिड के एक चतुर्भुज में काम कर रहा हूँ। प्रत्येक सेल में एक एक्स और वाई मान होता है जो ग्रिड (x_coord और y_coord) में इसकी स्थिति दर्शाता है। ये पिक्सेल मान नहीं बल्कि ग्रिड स्थितियां हैं। मैं आसन्न कोशिकाओं को पाने के लिए एक कुशल तरीका तलाश रहा हूँ। यह शायद होगाग्रिड

def get_adjacent_cells(self, cell): 
    result = [] 
    x_coord = cell.x_coord 
    y_coord = cell.y_coord 
    for c in grid.cells: 
      if c.x_coord == x_coord and c.y_coord == y_coord: # right 
       result.append(c) 
      if c.x_coord == x_coord - 1 and c.y_coord == y_coord + 1: # lower right 
       result.append(c) 
      if c.x_coord == x_coord - 1 and c.y_coord == y_coord: # below 
       result.append(c) 
      if c.x_coord == x_coord - 1 and c.y_coord == y_coord - 1: lower left 
       result.append(c) 
      if c.x_coord == x_coord and c.y_coord == y_coord - 1: right 
       result.append(c) 
      // -- similar conditional for remaining cells 

: अधिकतम वहाँ आठ संभव सन्निकट कक्षों, लेकिन ग्रिड की सीमा की वजह से वहाँ एक सरल अभी तक शायद अक्षम दृष्टिकोण के लिए के रूप में कुछ 3. के रूप में छद्म कोड हो सकता है कुछ इस तरह दिखता काम ठीक है, हालांकि यह संभावना है कि इस कोड को प्रत्येक फ्रेम को चलाने की आवश्यकता होगी और एक बड़े ग्रिड में यह प्रदर्शन को प्रभावित कर सकता है। अधिक सुव्यवस्थित और कम सीपीयू गहन दृष्टिकोण के लिए कोई विचार? या, क्या मुझे बस इस दृष्टिकोण के साथ रोल करना चाहिए?

अग्रिम धन्यवाद।

+0

विशेषण 'पायथनस्क्यू' नहीं है? :-) – Simon

+0

यदि आप ऐसा करने के अपने तरीके से रहना चाहते हैं, तो मैं कम से कम एक काउंटर बनाउंगा कि परिणामस्वरूप कितने परिणाम दिए गए हैं। जब यह 8 तक पहुंचता है, तो लूप से बाहर निकल जाता है। साथ ही, केवल एक सेल संलग्न करते समय यह जांचें कि यह 8 के बराबर है या नहीं। –

उत्तर

7

यह स्पष्ट नहीं था कि एक्स और वाई निर्देशांक की तुलना में कोशिकाओं में अन्य जानकारी थी। किसी भी मामले में, मुझे लगता है कि इसे तेजी से बनाने के लिए डेटा संरचनाओं में बदलाव की आवश्यकता है।

मुझे लगता है कि कोशिकाओं में अतिरिक्त जानकारी है और grid.cells को एक शब्दकोश के रूप में समन्वय के tuples के साथ एक शब्दकोश के रूप में बनाया गया है। यदि कोशिकाओं में केवल समन्वय जानकारी है तो एक ही चीज को grid.cells के साथ एक सेट के रूप में किया जा सकता है।

def get_adjacent_cells(self, x_coord, y_coord): 
    result = {} 
    for x,y in [(x_coord+i,y_coord+j) for i in (-1,0,1) for j in (-1,0,1) if i != 0 or j != 0]: 
     if (x,y) in grid.cells: 
      result[(x,y)] = grid.cells[(x,y)] 

क्या आप डेटा के साथ क्या करना चाहते हैं पर निर्भर करता है, तो आप एक dict परिणाम बनाने के लिए नहीं चाहते हो सकता है, लेकिन उम्मीद है कि आपको अंदाजा हो। यह आपके कोड से बहुत तेज़ होना चाहिए क्योंकि आपका कोड grid.cells में प्रत्येक सेल पर 8 चेक बना रहा है।

+0

यह दृष्टिकोण सबसे तेज़ लगता है क्योंकि इसमें प्रत्येक सेल पर पुनरावृत्ति शामिल नहीं है। कुंजी के रूप में tuples का उपयोग करना एक अच्छा विकल्प है। धन्यवाद – JeremyFromEarth

2

खैर, यह किसी भी प्रदर्शन में मदद मिलेगी, लेकिन आप कह

if abs(c.x_coord - x_coord) == 1 or abs(c.y_coord - y_coord) == 1: 
    result.append(c) 

प्रदर्शन को प्रभावित करने के लिए, अपने ग्रिड कोशिकाएं पता होना चाहिए जो अपने पड़ोसी हैं द्वारा कोड दोहराव से बचने कर सकते हैं, या तो c.neighbors की तरह एक विशेषता के माध्यम से, या एक अंतर्निहित संरचना के माध्यम से, सूचियों की एक सूची की तरह, तो आप समन्वय द्वारा उपयोग कर सकते हैं।

grid = [[a,b,c], 
     [d,e,f], 
     [g,h,i]] 

फिर आप सूची सूचकांक का उपयोग करके पड़ोसी की जांच कर सकते हैं।

1

यह संभवतः पड़ोसियों को देखने का सबसे प्रभावी तरीका है यदि ग्रिडकल्स को एक सेट के रूप में कार्यान्वित किया गया है (हालांकि पहले कथन में कोई गलती है - आपको x_coord के बजाय x_coord + 1 के समानता के लिए परीक्षण करने की आवश्यकता है)।

हालांकि, सूचियों की सूची के रूप में grid.cells को लागू करने से आप पंक्तियों और कॉलम संख्या से अलग-अलग कक्षों को संदर्भित कर सकते हैं। यह आपको पंक्तियों और स्तंभों की कुल संख्या को मापने की अनुमति भी देगा। get_adjacent_cells पहले यह जांच कर काम कर सकते हैं कि कौन से किनारों पर मौजूदा सेल सीमा है, और फिर पड़ोसी को अन्य सभी दिशाओं में देखकर और परिणाम सूची में जोड़ना।

8

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

आप अपने सूचकांक द्वारा रैंडम एक्सेस कर सकते हैं, तो मैं निम्नलिखित की तरह कुछ सुझाव देते हैं:

adjacency = [(i,j) for i in (-1,0,1) for j in (-1,0,1) if not (i == j == 0)] #the adjacency matrix 

def get_adjacent_cells(self, cell): 
    x_coord = cell.x_coord 
    y_coord = cell.y_coord 
    for dx, dy in adjacency: 
      if 0 <= (x_coord + dx) < max_x and 0 <= y_coord + dy < max_y: #boundaries check 
#yielding is usually faster than constructing a list and returning it if you're just using it once 
       yield grid[x_coord + dx, y_coord + dy] 

max_x और max_y ग्रिड के आकार होना चाहिए रहे हैं, और grid.__getitem__ एक टपल स्वीकार करने के लिए माना जाता है निर्देशांक के साथ और उस स्थिति में सेल वापस।

0

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

if abs(c.x_coord -_coord +c.y_coord-y_coord) == 1 
    print "they are adjacent!"