Tôi nên sử dụng cấu trúc dữ liệu nào cho cây tài năng theo kiểu Diablo / WoW?


23

Tôi đang xem xét triển khai hệ thống cây tài năng cho một game nhập vai trực tuyến, tương tự như đã thấy trong World of Warcraft, khi có được một kỹ năng mở ra "cấp bậc" tiếp theo bên dưới nó trong cây.

Có ai biết cách tốt nhất để thực hiện cấu trúc này trong cơ sở dữ liệu / mã không?

Câu trả lời:


13

Sử dụng cấu trúc như thế này để thể hiện một cây trong cơ sở dữ liệu:

#Talent
id  parent  description
1   0       Tackle
2   1       Kick
3   1       Punch
4   3       Fire Punch

Và một bảng khác để thể hiện tài năng có được trên mỗi người dùng

#UserTalent
id  user  talent
1   4     1
2   4     3
3   4     4

Bạn có thể kiểm tra các phụ thuộc tài năng theo chương trình bằng cách truy vấn bảng tài năng hoàn chỉnh và xây dựng một cây được liên kết. Bạn cũng có thể làm điều đó với SQL nhưng nó sẽ yêu cầu các mục con đệ quy hoặc nhiều truy vấn. Tốt hơn làm điều đó trong mã của bạn.

Nếu có nhiều phụ thuộc, ví dụ như Fire Punchphụ thuộc vào PunchAND Immolationsử dụng hai bảng để biểu thị biểu đồ phụ thuộc:

#Talent
id  description
1   Tackle
2   Kick
3   Punch
4   Fire Punch
5   Immolation

#Depedency
id  parent  child
1   0       1
2   0       5
3   1       2
4   1       3
5   3       4
6   5       4

UserTalentBảng của bạn không cần cột autokey. usertalentcó thể là hai cột duy nhất và khóa tổng hợp: chúng sẽ không bao giờ trùng lặp và iddù sao bạn cũng sẽ không bao giờ truy vấn .
doppelgreener

Tôi không phải là nhà thiết kế cơ sở dữ liệu và tôi rất muốn nghe ai đó nói về điều này: Nếu mỗi tài năng có một tên duy nhất, bạn cũng không thể loại bỏ mọi trường ID số khác trong thiết kế bảng này và sử dụng tên làm khóa (với bất kỳ chỉnh sửa xếp tầng)? Sẽ có bất kỳ chi phí hoặc lợi ích đáng kể khi làm như vậy?
doppelgreener

3
@Jonathan Hobbs: Id chính tự động luôn luôn tốt cho các hoạt động xóa / cập nhật. Nó không bao giờ chậm hơn nhưng thường nhanh hơn. Ngoài ra kích thước hàng không phải là mối quan tâm ở đây. Điều tương tự cũng đúng với trường hợp tên tài năng độc đáo. Để có hiệu suất tốt, bạn sẽ chỉ muốn tham gia các bảng của mình trên các số nguyên duy nhất. Xem en.wikipedia.org/wiki/Database_n
normalization,

Cảm ơn. Một nhà thiết kế DB mà tôi biết đã từng nói rằng autokeys là xấu xa và nên tránh, nhưng tôi chưa bao giờ rõ ràng về trường hợp đó hay tại sao. Tôi cho rằng nó không phải.
doppelgreener

Không có lý do thực sự để sử dụng cơ sở dữ liệu để lưu trữ dữ liệu này trừ khi bạn cần cơ sở dữ liệu cho các nhà thiết kế vì bạn hỗ trợ chỉnh sửa nhiều người dùng hoặc một cái gì đó. Nếu không nó sẽ chỉ cản trở. (Tôi cũng sẽ không bao giờ sử dụng khóa tự động chính cho việc này, bởi vì bạn gần như chắc chắn muốn tham gia vào các tên logic do nhà thiết kế quyết định thay vì khóa do DB cung cấp.)

5

Tôi sẽ khuyên bạn nên sử dụng một cây trong đó mỗi nút đại diện cho một tài năng / kỹ năng cụ thể. Dựa trên việc người chơi có kiếm được tài năng hay không, tài năng con của nó có thể kiếm được. Ví dụ cấu trúc dữ liệu sau

class Talent {
    std::vector<Talent*> children;
    bool earned;
};

Để xác định tài năng nào mà người chơi có, bạn lấy tài năng gốc và đi xuống biểu đồ cho đến khi bạn đạt được các nút tài năng nơi kiếm được là sai. Điều này cũng sẽ tiết lộ những tài năng nào có sẵn để có được: tài năng đầu tiên trong mỗi chi nhánh từ tài năng gốc mà kiếm được là sai.


Bạn đã có một con trỏ đến một mảng gốc và kích thước? Không sử dụng con trỏ tự kích thước tự sở hữu.
DeadMG

Rất tiếc ... hỗn hợp C / C ++ và một lỗi. Tôi đã cập nhật câu trả lời của tôi. Cảm ơn cho những người đứng đầu lên.
ma

@DeadMG: chính xác ý bạn là gì khi 'tự sở hữu bản thân'? Bạn đang đề cập đến một cái gì đó giống như vector ở trên, hoặc bạn đang nghĩ về cái gì khác?
Kylotan

Boost ptr_vectorcó thể còn tốt hơn nữa.
Zan Lynx

5
Cấu trúc cây phải hoàn toàn tách biệt với việc người chơi đã kiếm được nó, trước đây là dữ liệu tĩnh được tạo bởi các nhà thiết kế và sau đó là dữ liệu trên mỗi người chơi được lưu trữ trong trò chơi lưu hoặc DB.

1

Trong trò chơi của tôi, tôi làm như thế này:

Cơ sở dữ liệu:

Reference_talent : chứa một ID duy nhất, tên, hiệu ứng, v.v.

tài năng : id, playerid <- chứa tất cả tài năng người chơi đã "học".

Ingame: (trên máy chủ)

Tôi tải lên tất cả các tham chiếu trong một 'tĩnh' (chỉ đọc) std :: map để tôi có thể truy cập chúng dễ dàng bằng id của họ.

Khi một khách hàng kiểm tra một người chơi, tôi nhận được tất cả các tài năng từ cơ sở dữ liệu và lưu trữ chúng trong một std :: vector để khi tôi cần tính toán các đặc điểm, v.v. Tôi có chúng trong RAM. Tôi cũng gửi đi những tài năng cho khách hàng.

Đó là về điều đó (ngoại trừ việc tiết kiệm những tài năng mới tất nhiên chỉ là một 'CHERTN' trong bảng 'tài năng' + một thông điệp cho khách hàng).


0

Phương pháp quan hệ

Bạn mô tả nó như là mối quan hệ giữa các trình mở khóa và mở khóa tương tự như trong hướng dẫn này . Tôi đề nghị tìm hiểu thêm về đại số quan hệ và cơ sở dữ liệu. Họ là cách tốt đẹp để mô hình dữ liệu. Nếu bạn học cách truy vấn thông tin từ cơ sở dữ liệu Bạn có thể mô hình hóa dữ liệu khá dễ dàng.

Tôi không biết bạn biết bao nhiêu về mô hình quan hệ. Hướng dẫn đó sẽ giúp bạn với nó.

Một cách giải quyết

Tôi cho rằng WoW hoạt động như trong thực tế (ehm), rằng nó là

  • tài năng mở ra một số tài năng (khác)
  • tài năng được mở khóa bởi một số tài năng (khác).

Đó là mối quan hệ N: N, ngụ ý Bạn cần "người trung gian" một mối quan hệ mới giữa hai tài năng:

(talent who unlocks id, talent who is unlocked)

Bằng cách này, bạn có thể có tài năng A mở khóa B, C và D ((A, B), (A, C), (A, D)) và tài năng Y được mở khóa bởi X, Z và W ((X, Y), ( Z, Y), (W, Y)). Trong ngôn ngữ mệnh lệnh / thủ tục / hướng đối tượng Bạn sẽ thực hiện dưới dạng danh sách / mảng các cặp như ở đó:

var unlocks_unlocked = [[A, B],[A,C],[A,D],[X,Y],[Z,Y],[W,Y]];

Vì vậy, ví dụ "thế giới thực" Bạn có thể có:

... ["running fast", "jumping superhigh"], ["antigravity's child", "jumping superhigh"]

và nó có nghĩa là "nhảy siêu cao" có được sau khi bạn có tài năng "chạy nhanh" và "chống trẻ em".

Giải pháp khác

Gần đây tôi chưa chơi Diablo nhưng có thể là nó chỉ có:

  • tài năng mở ra một số tài năng khác
  • tài năng được mở khóa chỉ bằng một tài năng.

Đó là mối quan hệ 1: N:

 You put "is unlocked by this talent's id" variable into talent's structure

như:

 var Talent[8] = { "name": "superpower", "unlocked by": "being Clark Kent"};
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.