سؤال

أحتاج إلى خريطة نصف قطرها 2 مرسومة من الغرفة الحالية للاعب في الوحل الذي أقوم ببنائه في بايثون (أو أكثر ، إن أمكن).يتم إعداد الغرف كحاويات مع self.exits = {'west':1, 'north':2} حيث المفتاح هو الاتجاه الذي تقع فيه القيمة (إيد من الغرفة المجاورة).ترتبط الغرف بهذه الطريقة فقط.وهناك لاعب مع النفس.موقع 0 يمكن أن اكتب' ن ' وموقعها ، استنادا إلى المتغير أعلاه ، سيكون بعد ذلك 2 ومحتويات تلك الغرفة سيكون إيد اللاعب إلحاق محتوياته.

لذلك ، أود أن يكون الخريطة المعروضة التي تبدو كما يلي ، استنادا إلى المتغير أعلاه ، حيث 'ش' هو الموقع الحالي للاعب..

    [ ]
     |
[ ]-[u]

لقد حققت هذا جزء ، لأن هذا هو مجرد دائرة نصف قطرها 1.هنا هو صغير (تعديل بشكل كبير للنشر هنا) مقتطف من كيف فعلت هذا ، وسترى لماذا أنا نشر ، كما انها رمز الفقراء.

mloc = '[u]'
mn = '   '
mw = '   '
spn= ' '
spw= ' '
for Exit in room.exits.keys():
  if Exit == 'north':
    mn = '[ ]'
    spn = '|'
  if Exit == 'west': 
    mw = '[ ]-'
# player.hear() is our function for printing a line to the player's screen
player.hear('    '+mn)
player.hear('     '+sp)
player.hear(mw+mloc)

في جنوني ، تمكنت من جعل هذا العمل مع جميع الاتجاهات المختلفة 8 (الأقطار ، وليس بما في ذلك أعلى أو لأسفل).ولكن بعد ذلك يجب أن لحلقة الغرف أنا فقط تحليل مع بلدي الأول لحلقة ، ومن ثم رسم تلك ، ومن ثم الفضاء كل ذلك ، ومن ثم تأخذ في الاعتبار تداخل (سب)ارسالا ساحقا مثل '\' أو '|' إذا كان هناك مسارات التي تعبر بعضها البعض.تحولت هذه المهمة الصغيرة الكابوسية على الفور ، وكذلك في 200 خطوط قبل أن يتم ذلك.

عقبة أخرى هي أنه لا يمكنني طباعة سوى سطر بسطر.حتى إذا كانت الخريطة هي 50 حرفا عالية ، لا بد لي من أن يكون player.hear() على 50 خطوط, وأنا لا أعارض.فقط ضع ذلك في الاعتبار قبل نشر إجابة.

أنا أيضا لست صعب الإرضاء بشأن التنسيق.أنا فقط أريد ببساطة 'خريطة في لمحة' لمساعدة اللاعبين أثناء السفر في جميع أنحاء العالم.

شكرا يا رفاق.آمل أن أكون قد قدمت معلومات كافية.اسمحوا لي أن أعرف ، إن لم يكن.(هنا رابط إلى الوحدة النمطية بأكملها (غير المكتملة والرهيبة) التي أشير إليها. Map.py

هل كانت مفيدة؟

المحلول

هذا الرمز في مشكلة خطيرة.لنبدأ التصميم من الصفر.نأمل أن يكون هذا بمثابة درس جيد في كيفية تصميم وبناء الطبقات وهياكل البيانات.

لتبدأ ، يجب عليك تنظيم التعليمات البرمجية الخاصة بك حول Map الطبقة ، والتي تمثل بعد ذلك غرفك كشبكة.لا يجب أن تفكر في" الغرفة 1 " ، "الغرفة 2" ، إلخ (وهو أمر يصعب تتبعه على الخريطة) ، بل فكر في الغرف من حيث الإحداثيات.

الآن ، هناك بعض الميزات المحتملة التي نتجاهلها في البداية ، بما في ذلك رؤية اللاعب للغرف التي زارها فقط ، واللاعب المتبقي في وسط الخريطة ، والمسارات القطرية.إذا كنت تريد لهم يمكنك وضعها في وقت لاحق ، مرة واحدة تعمل الوظائف الأساسية.في الوقت الحالي ، نحن نهدف إلى شيء يشبه هذا قليلا:

[ ]-[u] [ ] [ ]
 |
[ ]-[ ]-[ ] [ ]
     |
[ ]-[ ]-[ ] [ ]
 |
[ ]-[ ]-[ ]-[ ]

أي أننا نمثلها كشبكة حيث ترتبط بعض الغرف والبعض الآخر ليس كذلك.دعونا يكون كل غرفة لديها تنسيق الزوج ، قليلا مثل هذا:

      0   1   2   3
   0 [ ]-[u] [ ] [ ]
      |
   1 [ ]-[ ]-[ ] [ ]
          |
   2 [ ]-[ ]-[ ] [ ]
      |
   3 [ ]-[ ]-[ ]-[ ]

دع س يكون على طول الجزء العلوي و ص يكون على طول الجانب.أعلى اليسار هو (0 ، 0) ، واحد مع [u] في ذلك هو (0 ، 1).

الآن ، ما هي مكونات لدينا Map صف دراسي?

  1. ارتفاع الخريطة:عدد صحيح

  2. عرض الخريطة:عدد صحيح)

  3. لاعب ، لاعب:إحداثيات اللاعب

  4. المسارات الممكنة:قائمة أزواج الغرف التي يمكننا التنقل بينها.سيتم تمثيل الخريطة أعلاه على النحو التالي:

    [((0, 0), (1, 0)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1), (2, 1)),
     ((1, 0), (1, 2)), ((0, 2), (1, 2)), ((1, 2), (2, 2)), ((0, 2), (0, 3)),
     ((0, 3), (1, 3)), ((1, 3), (2, 3)), ((2, 3), (3, 3))]
    

لاحظ أنني أمرت كل زوج بحيث تذهب المجموعة الأكبر أولا (وهذا مهم لاحقا).

والآن بعد أن أصبح لدينا تصميمنا ، دعنا نكتب ذلك Map صف!

يمكنني التفكير في أربع طرق نريدها: print_map, move, ، ومهيئ.إنتيتياليزاشيون بسيط:ما عليك سوى تعيين السمات الأربع التي ذكرناها أعلاه:

class Map:
    def __init__(self, height, width, player_x, player_y, paths):
        self.height = height
        self.width = width
        self.x = player_x
        self.y = player_y
        self.paths = paths

الآن, move هو بسيط جدا.نظرا لاتجاه ن / ه / ق / ث:

    def move(self, direction):
        if direction == "n":
            if ((self.x, self.y - 1), (self.x, self.y)) not in self.paths:
                print "Cannot go north"
            else:
                self.y -= 1

ال move وظيفة ل "الشمال" يتحقق فقط إذا كان هناك مسار إلى الغرفة فوق واحد نحن في.

الآن للجزء الأكثر إثارة للاهتمام:طباعة الخريطة.يمكنك القيام بذلك عن طريق حلقات فوق الصفوف (0 إلى self.height) وعلى الأعمدة (0 إلى self.width). (ملاحظة:لا يمكنك استخدام print في هذه الحالة لأنه يضع تلقائيا سطر جديد أو مسافة بعد السلسلة.بدلا من ذلك نستخدم سيس.(ستدوت).اكتب.

def print_map(self):
    for y in range(0, self.height):
        # print the yth row of rooms
        for x in range(0, self.width):
            if self.x == x and self.y == y:
                sys.stdout.write("[u]")  # this is the player's room
            else:
                sys.stdout.write("[ ]")  # empty room
            # now see whether there's a path to the next room
            if ((x, y), (x + 1, y)) in self.paths:
                sys.stdout.write("-")
            else:
                sys.stdout.write(" ")
        # now that we've written the rooms, draw paths to next row
        print  # newline
        for x in range(0, self.width):
            sys.stdout.write(" ")  # spaces for above room
            if ((x, y), (x, y + 1)) in self.paths:
                sys.stdout.write("|  ")
            else:
                sys.stdout.write("   ")
        print

الآن ، دعونا نضع كل ذلك معا ومحاولة الخروج منها.وهنا رمز:

import sys

class Map:
    def __init__(self, height, width, player_x, player_y, paths):
        self.height = height
        self.width = width
        self.x = player_x
        self.y = player_y
        self.paths = paths

    def move(self, direction):
        if direction == "n":
            if ((self.x, self.y - 1), (self.x, self.y)) not in self.paths:
                print "Cannot go north"
            else:
                self.y -= 1
        if direction == "s":
            if ((self.x, self.y), (self.x, self.y + 1)) not in self.paths:
                print "Cannot go south"
            else:
                self.y += 1
        if direction == "e":
            if ((self.x, self.y), (self.x + 1, self.y)) not in self.paths:
                print "Cannot go east"
            else:
                self.x += 1
        if direction == "w":
            if ((self.x - 1, self.y), (self.x, self.y)) not in self.paths:
                print "Cannot go west"
            else:
                self.x -= 1

    def print_map(self):
        for y in range(0, self.height):
            # print the yth row of rooms
            for x in range(0, self.width):
                if self.x == x and self.y == y:
                    sys.stdout.write("[u]")  # this is the player's room
                else:
                    sys.stdout.write("[ ]")  # empty room
                # now see whether there's a path to the next room
                if ((x, y), (x + 1, y)) in self.paths:
                    sys.stdout.write("-")
                else:
                    sys.stdout.write(" ")
            # now that we've written the rooms, draw paths to next row
            print  # newline
            for x in range(0, self.width):
                sys.stdout.write(" ")  # spaces for above room
                if ((x, y), (x, y + 1)) in self.paths:
                    sys.stdout.write("|  ")
                else:
                    sys.stdout.write("   ")
            print


paths = [((0, 0), (1, 0)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1),
         (2, 1)), ((1, 1), (1, 2)), ((0, 2), (1, 2)), ((1, 2), (2, 2)),
         ((0, 2), (0, 3)), ((0, 3), (1, 3)), ((1, 3), (2, 3)), ((2, 3),
         (3, 3))]
m = Map(4, 4, 0, 0, paths)

while True:
    m.print_map()
    direction = raw_input("What direction do you want to move? [n/e/s/w] ")
    m.move(direction)

لاحظ أنني أضفت قسما في الأسفل يقوم بإنشاء خريطة ويسمح للاعب بالتحرك حولها.وإليك كيف يبدو عندما يعمل:

Davids-MacBook-Air:test dgrtwo$ python Map.py 
[u]-[ ] [ ] [ ] 
     |          
[ ] [ ]-[ ] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

What direction do you want to move? [n/e/s/w] e
[ ]-[u] [ ] [ ] 
     |          
[ ] [ ]-[ ] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

What direction do you want to move? [n/e/s/w] s
[ ]-[ ] [ ] [ ] 
     |          
[ ] [u]-[ ] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

What direction do you want to move? [n/e/s/w] w
Cannot go west
[ ]-[ ] [ ] [ ] 
     |          
[ ] [u]-[ ] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

What direction do you want to move? [n/e/s/w] e
[ ]-[ ] [ ] [ ] 
     |          
[ ] [ ]-[u] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

هناك العديد من التحسينات التي يمكن إجراؤها على هذا الرمز (على وجه الخصوص ، move الطريقة متكررة) ، لكنها بداية جيدة.حاول جعل الخريطة 20/20 وسترى أنها تتوسع على ما يرام.

إيتا:وأود أن أشير إلى أن print_map يمكن إعادة كتابتها في شكل أقصر بكثير كشيء مثل:

def print_map(self):
    for y in range(0, self.height):
        print "".join(["[%s]%s" %
                    ("u" if self.x == x and self.y == y else " ",
                     "-" if ((x, y), (x + 1, y)) in self.paths else " ")
                        for x in range(0, self.width)])
        print " " + "   ".join(["|" if ((x, y), (x, y + 1)) in self.paths
                              else " " for x in range(0, self.width)])

لكن هذا أكثر كثافة قليلا.

نصائح أخرى

فعلت هذا كتمرين حيث الغرف والشبكة "طباعة أنفسهم".أضيف هذا إلى المناقشة لأنه قد يكون من الأسهل تنفيذه بشبكة أكبر في نهاية المطاف.

خريطة أسي

+++++++++++++++
+++++++++++++++
+++++++++++++++
++++++   ++++++
++++++ 2 ++++++
++++++/| ++++++
+++  / | ++++++
+++ 3--1 ++++++
+++     \++++++
+++++++++\  +++
+++++++++ 4 +++
+++++++++   +++
+++++++++++++++
+++++++++++++++
+++++++++++++++

كل خلية في هذه الشبكة هي ثلاثة من ثلاثة مجموعة من علامات'+'.يتم تنفيذ أربع غرف بقيمة معرف من 1 إلى 4.يتم تمثيل الاتصالات بين الغرف على شكل خطوط مائلة وخطوط مائلة للخلف وأنابيب.

الرمز

class Room(object):
    def __init__(self, id, loc, exits):
        self.id = id # unique identifier, may be a name
        self.row = loc[0] # loc is tuple of (row, col)
        self.col = loc[1] 
        # exits is a list where 'X' means no exit and 
        # any other value is id of destination
        self.exits = exits 

    def __str__(self):
        directions = '\\|/- -/|\\'
        room = [ e if e == 'X' else ' ' for e in self.exits ]
        for idx in range(len(room)):
            if room[idx] == ' ':
                room[idx] = directions[idx]
            if room[idx] == 'X':
                room[idx] = ' '
        room[4] = self.id[0] # only print first char of id
        return ''.join(room)

class Map(object):
    def __init__(self, rows, cols, rooms):
        self.rows = rows
        self.cols = cols
        self.rooms = rooms

    def __str__(self):
        world = []
        for i in range(self.rows * 3):
            world.append( ['+++'] * self.cols )
        for room in self.rooms:
            ascii = str(room)
            x = room.col
            y = room.row
            for idx in range(0, 3):
                cell = ascii[idx*3:idx*3+3]
                world[y*3+idx][x] = cell
        return '\n'.join( [ ''.join(row) for row in world ] )


if __name__ == '__main__':
    # set up four rooms
    # each room has unique id (string of any length) and coordinates
    # it also has a set of 8 possible exits, represented as a list where
    # 'X' means exit is blocked and valid exits contain the id of the target room
    r1 = Room(id='1', loc=(2,2), exits=['X','2','X',
                                        '3',' ','X',
                                        'X','X','4',])
    r2 = Room(id='2', loc=(1,2), exits=['X','X','X',
                                        'X',' ','X',
                                        '3','1','X',])
    r3 = Room(id='3', loc=(2,1), exits=['X','X','2',
                                        'X',' ','1',
                                        'X','X','X',])
    r4 = Room(id='4', loc=(3,3), exits=['1','X','X',
                                        'X',' ','X',
                                        'X','X','X',])
    # initialize Map with a list of these four rooms
    map = Map(rows = 5, cols=5, rooms=[r1, r2, r3, r4])
    print map

لم يتم تنفيذ الروتين المتحرك ، ولكي يعمل هذا التمثيل ، ستظهر فقط معرفات الأحرف الفردية بشكل جيد.

مزايا هذا النظام:

  • من السهل إضافة غرف وإزالتها
  • تعريف الغرفة قابل للقراءة من قبل الإنسان
  • وظائف الإخراج الزائد __str__ وبالتالي فإن الغرف والشبكة "تطبع نفسها" وقد يكون هذا مفيدا لتصحيح الأخطاء في المستقبل أو التكيف مع التنسيقات المستقبلية على سبيل المثال.كخلايا في جدول هتمل.

تتمتع الخرائط القائمة على الإحداثيات بالكثير من المزايا ، ولكن بالنظر إلى أن العديد من الطين عالي الجودة يستخدم عالما تقليديا قائما على الغرف ، وأن الناس صنعوا آلات لصناعة السيارات للعديد من عملاء الطين والطين ، فليس من المستبعد عمل خريطة تلقائية للطين بدون إحداثيات.سيكون عليك فقط التعامل مع النزاعات على أساس كل حالة على حدة.

ومع ذلك ، لا يزال بإمكانك استخدام الإجابة بواسطة @ديفيد روبنسون.ما تريد القيام به هو الحفاظ على مصغره تركز تقريبا على لاعب وتحديثه ديناميكيا باستخدام بيانات الخروج.لا تحاول الاحتفاظ بخريطة للمنطقة بأكملها مخزنة;من خلال التحديث الديناميكي ، ستتجنب بعض التعارضات الجغرافية.

لكتابة الخريطة إلى عميل الطين ، كل ما عليك القيام به هو كتابة خط الخريطة الخاص بك متباعدة بشكل صحيح وإنهائه مع خط جديد.يمكنك وضع جميع خطوط الخريطة في قائمة بحيث يتم إرسالها كمجموعة واحدة من الخطوط (لا تريد إدراج بعض الأسطر الأخرى بين أسطر الخريطة على سبيل المثال عندما يتم إرسالها إلى المقبس) ، وسوف يقوم أي عميل الطين بطباعتها بشكل صحيح (مع خط أحادي المسافة بالطبع).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top