首页 > 解决方案 > 如何在跨平台的控制台中显示等宽字体(或恒定距离)?

问题描述

我正在开发包含 Metro 表达的 CLI 游戏。我想像这样在控制台上显示,我在 Windows 上做到了。该代码将 XML(XY 位置数据)转换为包含 Station 标志的链接:

class Metro():
    def __init__(self, data_root):
        # data_root는 xml을 파싱한 루트 요소이다.
        self.data_root = data_root

        # self.stations_dic 딕셔너리에 '인덱스 번호 : 각 요소' 구조를 넣는다.

        self.stations_dic = {}

        for element in self.data_root.findall('station'):
            station = Station(element)
            self.stations_dic[int(element.attrib['index_number'])] = station

        # 아래 코드에서는 2차원 배열로 맵을 작성한다.
        # self.metro_map[x좌표][y좌표] 는 'station' Element를 반환한다.

        x_list = []
        y_list = []

        for key in self.stations_dic.keys():
            locate = self.stations_dic[key].location
            x_list.append(locate[0])
            y_list.append(locate[1])

        self.max_x = max(x_list)
        self.max_y = max(y_list)

        self.symbol_map = [[None]*(self.max_y + 1) for i in range(self.max_x + 1)]

        for key in self.stations_dic.keys():
            locate = self.stations_dic[key].location
            self.symbol_map[locate[0]][locate[1]] = self.stations_dic[key]
            for near_i in self.stations_dic[key].near_number_list:
                symbol = self.stations_dic[key] * self.stations_dic[near_i]
                if symbol != None:
                    sy_locate = symbol.locate
                self.symbol_map[sy_locate[0]][sy_locate[1]] = symbol

        # self.metro_map은 바뀌지 않고 불러와 설정한 대로 불변이어야 한다.

    def etro_display(self, current_location):
        # 이 파일을 import하고 m = Metro(인자)로 선언한 뒤
        # m.etro_display(location) 형태로 사용한다.
        from colorama import init, Fore, Back, Style
        init()

        c = {1 : Fore.RED,
             2 : Fore.GREEN,
             3 : Fore.YELLOW,
             4 : Fore.BLUE,
             5 : Fore.MAGENTA,
             6 : Fore.WHITE,
             7 : Fore.CYAN}

        # 노선도를 출력하는 부분이다.

        for y in range(0, self.max_y + 1):
            for x in range(0, self.max_x + 1):
                if [x, y] == current_location:
                    print(Style.RESET_ALL + Fore.WHITE + Back.BLACK + '●', end='')
                else:
                    try:
                        if isinstance(self.symbol_map[x][y].line, int) == True:
                            print(Style.RESET_ALL + c[self.symbol_map[x][y].line] + Back.BLACK + self.symbol_map[x][y].symbol, end='')
                        else:
                            print(Style.RESET_ALL + Fore.WHITE + Back.BLACK + self.symbol_map[x][y].symbol, end='')
                    except:
                        # 실행에 실패할 경우는 주로 symbol 애트리뷰트를 Nonetype 객체에서
                        # 획득 불가능할 때이므로 공백을 출력한다
                        print(Style.DIM + Back.BLACK + Fore.WHITE + ' ', end='')
            print('\n', end='')
        print(Style.RESET_ALL, end='')

class Station():
    def __init__(self, element):
        self.element = element
        self.symbol = '○' # 동그라미 기호다.

        self.index = int(element.attrib['index_number'])
        self.name_korean = element.findtext('name[@language="korean"]')

        # 좌표를 설정한다.
        location_str = element.findtext('location')
        location_list = location_str.split(", ")
        self.location = list(map(int, location_list))

        line_str_list = element.findtext('line').split(", ")
        self.line = list(map(int, line_str_list))

        if element.findtext('transfer') == 'True': self.transfer = True
        elif element.findtext('transfer') == 'False': self.transfer = False
        else: self.transfer = None

        if self.transfer == True: self.symbol = '◎'

        near_str_list = element.findtext('near_number').split(", ")
        self.near_number_list = list(map(int, near_str_list))
        self.near_direct_list = element.findtext('near_direct').split(", ")

        self.facilities = element.findtext('facilities').split(",")

    def __mul__(self, other):
        #
        # 곱연산이 아니다!!!
        #
        # couples_list에 들어 있는 짝의 리스트에
        # 두 인스턴스의 해당하는 방향값이 모두 들어있을 경우:
        # 즉 서로에서 가리킨 방향이 일치할 경우 해당 통로의
        # 좌표값과 모양을 반환한다.
        couples_list = [['N', 'S'],
                        ['W', 'E'],
                        ['NW', 'ES'],
                        ['NE', 'WS'],
                        ['WN', 'SE'],
                        ['EN', 'SW']]

        direction_list = ['┃', '━', '┓', '┏', '┗', '┛']

        first_i = self.index
        second_i = other.index

        first_locate = self.location
        second_locate = other.location

        first_near_n = self.near_number_list
        first_near_d = self.near_direct_list
        second_near_n = other.near_number_list
        second_near_d = other.near_direct_list

        if first_i in second_near_n and second_i in first_near_n:
            pass
        else:
            print(first_i, second_i)
            print(second_near_n, first_near_n)
            print('ERROR 숫자가 일치하지 않음')
            return None

        first_to_second_d = first_near_d[first_near_n.index(second_i)]
        second_to_first_d = second_near_d[second_near_n.index(first_i)]

        first_transfer = self.transfer
        second_transfer = other.transfer

        first_line = self.line
        second_line = other.line

        result_location = [0, 0]

        # 좌표 정보를 결정한다.
        if first_to_second_d[0] == 'N':
            result_location = [first_locate[0], first_locate[1] - 1]
        elif first_to_second_d[0] == 'S':
            result_location = [first_locate[0], first_locate[1] + 1]
        elif first_to_second_d[0] == 'W':
            result_location = [first_locate[0] - 1, first_locate[1]]
        elif first_to_second_d[0] == 'E':
            result_location = [first_locate[0] + 1, first_locate[1]]

        # 노선 정보를 결정한다.
        if first_transfer == False and second_transfer == False:
            if first_line[0] == second_line[0]:
                result_line = first_line[0]
        elif first_transfer == False and second_transfer == True:
            if first_line[0] in second_line:
                result_line = first_line[0]
        elif first_transfer == True and second_transfer == False:
            if second_line[0] in first_line:
                result_line = second_line[0]
        elif first_transfer == True and second_transfer == True:
            for line in first_line:
                if line in second_line:
                    result_line = line
        else:
            print('노선 정보 에러')
            return None      

        pass_to = False
        result_direction = ''

        # 방향을 설정한다.
        for couple in couples_list:
            if first_to_second_d in couple and second_to_first_d in couple:
                result_direction = direction_list[couples_list.index(couple)]
                pass_to = True

        if pass_to == True:
            # 반환
            return Symbol(result_location, result_direction, result_line)
        else:
            print(self.index, other.index)
            return None

class Symbol():
    def __init__(self, locate, symbol, line):
        self.locate = [locate[0], locate[1]]
        self.symbol = symbol
        self.line = line

但是,当我在 Lubuntu Linux 上测试我的代码时,它崩溃了。

好吧,我的意思是显示器不是很好看:

我可以表示间隔(常规距离)标志以在跨平台上显示地图吗?

标签: pythonpython-3.6

解决方案


推荐阅读