Làm thế nào một mạch hoặc hệ thống điện (như đá đỏ trong Minecraft) nên được thực hiện


8

Tôi muốn thực hiện một hệ thống năng lượng như hệ thống đá đỏ trong minecraft.

Tôi có n nguồn điện và m cáp. Nếu tôi ngắt kết nối nguồn điện hoặc cáp, mạch sẽ tắt. mô hình hệ thống cáp

Làm cách nào để tránh vòng tròn? Nếu mỗi cáp có trạng thái "bật" cấp nguồn cho các cáp gần đó, tôi có thể tạo các vòng tròn vô hạn nơi không có nguồn điện liên quan (xem hình ảnh). Trang web cộng là nó chạy trong T = m

Tôi có thể gửi nguồn điện thông qua biểu đồ bắt đầu từ mọi nguồn điện và trong mỗi cuộc gọi cập nhật, tôi tắt mọi dây cáp. Vấn đề là nó chạy trong T = n * m.

Có một thực hành tốt nhất? Trong Minecraft hệ thống đá đỏ rất chậm nên tôi nghĩ rằng tôi đã bỏ qua thứ gì đó.

EDIT: Hệ thống sẽ hoạt động mà không có sự phân rã dựa trên khoảng cách.


Điều này phụ thuộc vào mô hình bạn đang cố gắng thực hiện. Ví dụ, một nguồn năng lượng có thể cung cấp x đơn vị năng lượng được tiêu thụ khi sử dụng. Một mô hình khác là nguồn điện của bạn có tiềm năng giới hạn tải mà bạn có thể đặt trên mạch có chức năng miễn là bạn cung cấp năng lượng cho nguồn điện của mình.
dùng3730788

Câu trả lời:


7

Tuyên truyền đệ quy. Ví dụ, bạn có một đèn được kết nối bởi các đối tượng cáp N với pin. Đèn hỏi cáp Nth nếu nó được cấp nguồn (đây là cáp được gắn trực tiếp vào đèn). Cáp Nth sau đó hỏi cáp N-1 nếu nó được cấp nguồn và cứ thế. Mỗi lần một đối tượng được hỏi liệu nó có được cung cấp năng lượng hay không, nó sẽ đặt một lastEvaluatedbiến theo thời gian khung hình hiện tại. Đệ quy chạm đáy trên một nút kết thúc, như pin, hoặc khi nó chạm tới một đối tượng đã được đánh giá khung đó (điều này tránh được đệ quy vô hạn). Những sự lan truyền này chỉ xảy ra khi hệ thống thay đổi. Các thay đổi bao gồm thêm / xóa các bộ phận hoặc công tắc đang được bật.

Không có sự phân rã khoảng cách hoặc hạn chế tương tự với hệ thống này. Tôi đã sử dụng nó để tạo ra một trình mô phỏng cổng logic và nó hoạt động cho các ví dụ logic khác nhau như flip-flop.


Điều này. Thêm vào đó tôi sẽ thêm một tham chiếu đến powersource. Nếu một phần tử bị thay đổi, hãy báo cho nguồn được tham chiếu để cập nhật mạng mà nó đang cấp nguồn. Bằng cách này, bạn không chỉ phải cập nhật khi có gì đó thay đổi, bạn còn biết những yếu tố nào bị ảnh hưởng. Các thay đổi trong mạng của bạn cũng có thể được xác định dễ dàng: một thay đổi có cần đánh giá lại hay không, v.v.
Felsir

@Felsir Bạn có thể làm điều đó, nhưng tôi không khuyên bạn nên làm điều đó. Nó làm tăng sự phức tạp mà không đạt được nhiều. Có thể có nhiều nguồn năng lượng và nhiều bồn cho mỗi nguồn. Sẽ dễ dàng hơn nếu chỉ tin tưởng vào đánh giá, và nó thực sự không quá tốn tài nguyên.
MichaelHouse

Giải pháp thiếu một điều tôi nghĩ: nếu bạn có một dây cáp ở giữa và một đầu có nguồn và đầu kia không chỉ có một người sẽ nhận được sự thay đổi. Về cơ bản, bạn đã tạo một cây với biến "lastEvauluated" bằng cách tước các vòng tròn. Bây giờ sự thay đổi lan truyền lên trên cây nhưng không xuống. Tôi sẽ thử thực hiện bằng cách đẩy các thay đổi xuống sau khi kéo chúng lên.
Benedikt S. Vogler

Tôi đã thêm giải pháp cho câu trả lời của bạn trong một lần chỉnh sửa vì phần bổ sung của tôi vào thuật toán hoạt động.
Benedikt S. Vogler

1
@Benedikt Bạn mô tả hành vi dự kiến. Đó là bởi vì hệ thống của tôi sử dụng đầu vào và đầu ra. Cổng AND và cổng OR không phải là hai chiều (chúng sử dụng thực hiện diode). Vì vậy, nếu tôi muốn năng lượng di chuyển đến một cái gì đó ngoài nút B, tôi sẽ điều khiển một đầu ra theo cách đó. Tôi khuyên bạn nên tạo một câu trả lời mới để mô tả hệ thống hai chiều của bạn.
MichaelHouse

2

Trong minecraft có một phân rã dựa trên khoảng cách với khoảng cách phân rã rất ngắn (phạm vi 16 khối).

Những gì bạn cần nó là một bài kiểm tra kết nối giữa các biểu đồ .

Một cách để làm điều đó sẽ được lặp đi lặp lại mỗi cạnh và kết hợp các nút được kết nối và thành một nút duy nhất. Sau khi tất cả các cạnh đã biến mất, bạn sẽ kết thúc với một nút cho mỗi mạng. Sau đó gửi sức mạnh là chuyện nhỏ.


Việc lưu một sơ đồ con trong một nút có vẻ rất thông minh, tuy nhiên tôi phải suy nghĩ một chút về việc triển khai cụ thể vì câu trả lời này cảm thấy hơi mơ hồ khi chỉ đề cập đến "kiểm tra kết nối giữa các biểu đồ" có vẻ là một phần khá quan trọng của giải pháp này.
Benedikt S. Vogler

thực sự mô tả đó là một biến thể trên thuật toán của Karger để tìm kiếm các vết cắt nhỏ. Nhưng thay vào đó, bạn tiếp tục cho đến khi không có nhiều cạnh để ký hợp đồng.
ratchet freak

1

Một khối được cấp nguồn có một số kết nối đầu vào / đầu ra, nhưng tại điểm bắt đầu, chúng tôi không biết bất cứ khi nào nó là đầu vào hoặc đầu ra.

Mỗi khối có một "Điện áp" là năng lượng truyền đến nó trừ đi phần bị mất / sử dụng.

Một khối được cấp nguồn sẽ cung cấp năng lượng cho tất cả các khối xung quanh và mỗi khối sẽ lấy điện áp cao hơn từ các khối xung quanh. Bạn cũng có thể làm phức tạp hệ thống bằng cách xác định cường độ, nhưng tôi sẽ chỉ sử dụng điện áp cho đơn giản.

Mỗi khi thay đổi được thực hiện đối với mạch, bằng cách thêm / xóa các khối hoặc bằng chính mạch đó, thay đổi cần được truyền đến tất cả các mạch cho đến khi ổn định.

Tôi sẽ đề nghị bạn thiết kế một giao diện cho bất kỳ đối tượng được hỗ trợ (khối trong MC):

class PowerInterface
{
protected:
    std::vector<shared_ptr<PowerInterface>> sibling;

    double energy=0;
    bool   isActive = false;

    virtual void propagate(double inEnergy) = 0;

    virtual void addSibling(shared_ptr<PowerInterface> newSibling) = 0;
    virtual void removeSibling( shared_ptr<PowerInterface> remSibling) =0;
};

Vì vậy, giả sử bạn triển khai addSibling và removeSibling, phần quan trọng nhất là hàm tuyên truyền:

void PoweredCube::propagate( double inEnergy ) 
{
    // Define the behaviour
    energy = inEnergy-1.0; // Normal device
    energy = inEnergy-0.1; // Normal cable
    energy = 10.0;         // Normal source of power.

    if (energy<0.0)
    { 
        energy = 0.0;
        isActive = false;
        // No energy, so do not propagate anymore
        return;
    }
    isActive = true;

    // Propagate
    for (auto &s: sibling)
    {
        // Only propagate to sibling with less energy. 
        if (energy > s->energy) s->propagate( energy);
    }
}

Là một giải pháp đệ quy, mỗi khối nên giảm một chút năng lượng, không bao giờ tăng nó. Nguồn năng lượng có thể đặt giá trị cố định, nhưng không bao giờ tăng dựa trên đầu vào. Đó không phải là một vấn đề vì tất cả hệ thống "thực" đều hoạt động theo cách này.


Nhưng với giải pháp này, mỗi vòng lặp cần các cuộc gọi "n = 1 / giảm" trước khi tắt. Đây không phải là một chút tốn kém?
Benedikt S. Vogler

Không, bạn chỉ cập nhật các thay đổi: khi bạn tạo / xóa / chỉnh sửa một khối hoặc khi một khối tạo ra thay đổi hoạt động. Nếu bạn xem mã, hầu hết các thay đổi sẽ chỉ lan truyền một vài khối. Dĩ nhiên, bạn có thể đơn giản hóa biểu đồ như @ BenediktS.Vogler nói, nhưng IMHO, nó sẽ khá nhanh rồi. Cho phép 1000 khối hoạt động trong vùng hoạt động, đây đã là một cơ chế rất lớn. Ngay cả trong trường hợp xấu nhất của bản cập nhật đầy đủ, nó chỉ là một vài thao tác * 1000, ngắn. Thông thường chỉ có một vài khối được cập nhật
Adrian Maire
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.