1. 程式人生 > >流水線合成材料依賴表的生成演算法

流水線合成材料依賴表的生成演算法

前不久玩了一個燒腦的遊戲"異星工廠",就是開局一農民,然後通過建造自動化的流水線,最後合成宇宙飛船飛回故鄉的故事.其中自動化的流水線需要玩家自己規劃,比如這樣的:

下面的這個是遊戲中的一個物品"電力機械臂"的合成配方:

可以看到,這裡合成一個"電力機械臂",需要"齒輪","鐵板","電路板"這三種材料,而鐵板又是由鐵礦直接加工而成的,但是電路板的合成就很複雜了.

縱使有一本手冊大全,也是無法對遊戲提供幫助的,看下游戲開局地圖:

礦產的位置很固定,因此無法對生產線的規劃起到作用.

但是,如果能從原材料出發,逐漸合成愈加複雜的物品,直至最後的宇宙飛船,這樣就對流水線的規劃有了一定的參考作用,而這個演算法也是解決這個問題的.

輸入:

產品,原料1,原料2....

(輸入資料為無限可列個,如果沒有原料,則表示產品為可以直接獲得的,無需合成)

輸出:

從原材料出發,直至合成所有的物品的依賴圖

下面是我做的一個例子:

輸入:

iron_ore, #這裡iron_ore為鐵礦,是可以從遊戲地圖上直接獲得的,無需材料合成
copper_ore,
copper_cable,copper_plate #這裡銅線copper_cable,需要銅板copper_plate合成,而銅板是由下面的那個公式合成來的
copper_plate,copper_ore
iron_plate,iron_ore
electronic_circuit,iron_plate,copper_plate
iron_gear_wheel,iron_plate
inserter,electronic_circuit,iron_gear_wheel,iron_plate
science_pack_1,copper_plate,iron_gear_wheel
transport_belt,iron_plate,iron_gear_wheel

輸出:

類似這樣的圖:

從左下角的iron_ore(鐵礦)與copper_ore(銅礦),逐漸向右上方依次合成,直至合成全部產品.

程式碼:

import matplotlib.pyplot as plt

file = open("connections.txt", 'r')#這裡的connections.txt就是一個文字,文字內容為上面輸入的資料
# 原材料,用於記錄原料與遍歷結束後的繪圖,不同層級用"##"分割
raw_material = []
# 待篩選的產品
products = []
# 繪圖中的直線記錄列表
line_plot = []
# 記錄每一層的個數
each_level_num = []

num_in_this_level = 0
for line in file:
    line = str(line).strip("\n").split(",")
    line = [i for i in line if i]
    print(line)
    if len(line) == 1:
        raw_material.append(",".join(line))
        num_in_this_level += 1
    else:
        products.append(line)
file.close()
raw_material.append("###")
each_level_num.append(num_in_this_level)
while len(products):
    num_in_this_level = 0
    # pro:每一個待篩選產品,list
    for pro in products:
        # module:待篩選產品的元件,str
        module_in_num = 0
        for module in pro[1:]:
            module = module.replace(" ", '')
            if module in raw_material:
                module_in_num += 1
            else:
                break
            if module_in_num == len(pro) - 1:
                raw_material.append(pro[0])
                num_in_this_level += 1
                products.remove(pro)
                # 開始記錄繪圖的直線指向座標
                line = []
                for module in pro[1:]:
                    target = raw_material.index(module)
                    line.append(target)
                line_plot.append(line)
    raw_material.append("###")
    each_level_num.append(int(num_in_this_level))

# raw_material生成結束,開始繪圖
# 當前層數
level = 0
# 當前層中的位置
num_in_this_level = 0
# line_plot中應該繪製的下標
plt_num = 0
for material in raw_material:
    if material == "###":
        level += 1
        num_in_this_level = 0
        continue
    plt.text(level * 10, 10 * num_in_this_level + (level + 1) * 7, material)
    # print("描點" + material, level * 10, 10 * num_in_this_level + (level + 1) * 7)
    if level > 0:
        # 開始繪圖
        targets = line_plot[plt_num]
        plt_num += 1
        # target為每一個需要相連的下標
        for target in targets:
            # target_level為目標層級
            target_level = 0
            for level_num in each_level_num:
                if target > level_num:
                    target -= level_num
                    target -= 1
                    target_level += 1
                else:
                    plt.plot([target_level * 10, level * 10],
                             [target * 10 + (target_level + 1) * 7, 10 * num_in_this_level + 7 * (level + 1)])
                    # print("劃線")
                    # print([target_level * 5, target * 10 + (target_level + 1) * 7],
                    #       [level * 10, 10 * num_in_this_level + 7 * (level + 1)])
                    break
    num_in_this_level += 1
plt.show()

這裡通過matplotlib.pyplot來繪圖.