ฉันควรใช้โครงสร้างข้อมูลใดสำหรับต้นไม้พรสวรรค์ของ Diablo / WoW


23

ฉันกำลังพิจารณาที่จะนำระบบพรสวรรค์ไปใช้กับ RPG ออนไลน์ซึ่งคล้ายกับที่เห็นใน World of Warcraft ซึ่งการได้รับทักษะจะปลดล็อค "ระดับ" ถัดไปที่อยู่ใต้ต้นไม้

ไม่มีใครรู้วิธีที่ดีที่สุดในการใช้โครงสร้างนี้ในฐานข้อมูล / รหัส?

คำตอบ:


13

ใช้โครงสร้างเช่นนี้เพื่อเป็นตัวแทนของต้นไม้ในฐานข้อมูล:

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

และอีกตารางเพื่อแสดงความสามารถที่ได้รับต่อผู้ใช้

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

คุณสามารถตรวจสอบความสามารถในการพึ่งพาความสามารถทางโปรแกรมโดยการสอบถามตารางความสามารถที่สมบูรณ์ คุณสามารถทำเช่นนั้นกับ SQL ได้ แต่จะต้องเลือกย่อยซ้ำหรือแบบสอบถามจำนวนมาก ทำได้ดีกว่าในรหัสของคุณ

หากมีการขึ้นต่อกันหลายอย่างเช่นFire Punchขึ้นกับPunchและImmolationใช้สองตารางเพื่อแสดงกราฟการพึ่งพา:

#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

UserTalentตารางของคุณไม่จำเป็นต้องมีคอลัมน์ autokey userและtalentสามารถเป็นสองคอลัมน์เท่านั้นและคีย์ผสม: จะไม่มีการซ้ำซ้อนและคุณจะไม่ค้นหาidเลย
doppelgreener

ฉันไม่ใช่นักออกแบบฐานข้อมูลและฉันสนใจที่จะได้ยินคำพูดนี้: หากพรสวรรค์ทุกคนมีชื่อที่ไม่ซ้ำกันคุณสามารถที่จะไม่ทำอะไรกับฟิลด์ ID ตัวเลขอื่น ๆ ในการออกแบบตารางนี้และใช้ชื่อเป็นกุญแจ (ด้วย การแก้ไขใด ๆ ที่เรียงซ้อนกัน) มีค่าใช้จ่ายหรือผลประโยชน์ที่สำคัญในการทำเช่นนั้นหรือไม่?
doppelgreener

3
@Jonathan Hobbs: รหัสหลัก autoincrement ดีเสมอสำหรับการลบ / อัปเดตการดำเนินการ มันไม่เคยช้า แต่เร็วกว่า ขนาดแถวก็ไม่ได้เป็นปัญหาที่นี่ เช่นเดียวกันกับกรณีของชื่อผู้มีความสามารถพิเศษ เพื่อประสิทธิภาพที่ดีคุณจะต้องเข้าร่วมตารางกับจำนวนเต็มเฉพาะเท่านั้น ดูen.wikipedia.org/wiki/Database_normalizationฯลฯ
Jonas Bötel

ขอบคุณ ผู้ออกแบบ DB ฉันรู้ว่าครั้งหนึ่งเคยบอกว่า autokeys นั้นชั่วร้ายและควรหลีกเลี่ยง แต่ฉันไม่เคยรู้แน่ชัดว่ามันเป็นอย่างนั้นหรือเพราะอะไร ฉันคิดว่ามันไม่ใช่
doppelgreener

ไม่มีเหตุผลที่แท้จริงในการใช้ฐานข้อมูลเพื่อเก็บข้อมูลนี้เว้นแต่ว่าคุณต้องการฐานข้อมูลสำหรับนักออกแบบเพราะคุณรองรับการแก้ไขแบบหลายผู้ใช้หรือบางอย่าง ไม่เช่นนั้นมันจะเข้าทาง (ฉันจะไม่ใช้คีย์ autoincrement หลักสำหรับเรื่องนี้เพราะคุณเกือบจะต้องการเข้าร่วมในชื่อโลจิคัลที่ตัดสินใจโดยนักออกแบบมากกว่าคีย์ที่ระบุโดย DB)

5

ฉันอยากจะแนะนำให้ใช้ต้นไม้ที่แต่ละโหนดแสดงถึงพรสวรรค์ / ทักษะที่เฉพาะเจาะจง ขึ้นอยู่กับว่าผู้เล่นได้รับพรสวรรค์หรือไม่พรสวรรค์ของเด็กจะได้รับ ตัวอย่างเช่นโครงสร้างข้อมูลต่อไปนี้

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

ในการพิจารณาว่าผู้เล่นคนใดมีความสามารถคุณจะนำพรสวรรค์ที่มีอยู่แล้วเดินลงไปที่กราฟจนกว่าคุณจะไปถึงโหนดพรสวรรค์ที่ได้รับนั้นเป็นเท็จ สิ่งนี้จะเปิดเผยว่าพรสวรรค์ใดบ้างที่มีให้ได้รับ: ความสามารถแรกในแต่ละสาขาลดลงจากความสามารถพิเศษที่ได้รับนั้นเป็นเท็จ


คุณมีตัวชี้ไปยังอาร์เรย์ดั้งเดิมและขนาดหรือไม่ ล้มเหลว - ใช้ตัวชี้การปรับขนาดด้วยตัวเอง
DeadMG

อ๊ะ ... การรวมกันของ C / C ++ และข้อผิดพลาด ฉันได้อัพเดตคำตอบแล้ว ขอบคุณสำหรับหัวขึ้น.
ผี

@DeadMG: คุณหมายถึงอะไรโดย 'self-owning self-sizing'? คุณหมายถึงบางอย่างเช่นเวกเตอร์ด้านบนหรือคุณกำลังคิดอย่างอื่นอยู่หรือไม่?
Kylotan

Boost ptr_vectorอาจดีกว่านี้
Zan Lynx

5
โครงสร้างต้นไม้ควรแยกจากกันโดยสิ้นเชิงว่าผู้เล่นได้รับมาหรือไม่ข้อมูลในอดีตนั้นเป็นข้อมูลสแตติกที่นักออกแบบสร้างขึ้นและข้อมูลหลังนั้นเป็นข้อมูลต่อผู้เล่นที่เก็บไว้ในเกมหรือ DB

1

ในเกมของฉันฉันทำแบบนี้:

ฐานข้อมูล:

Reference_talent : มี ID, ชื่อ, เอฟเฟกต์และอื่น ๆ ที่ไม่ซ้ำกัน

พรสวรรค์ : id, playerid <- มีความสามารถทั้งหมดที่ผู้เล่นได้ "เรียนรู้"

Ingame: (บนเซิร์ฟเวอร์)

ฉันโหลด Reference_talents ทั้งหมดในแผนที่ 'คงที่' (อ่านอย่างเดียว) std :: map เพื่อให้ฉันสามารถเข้าถึงได้อย่างง่ายดายโดยใช้ ID ของพวกเขา

เมื่อลูกค้าตรวจสอบผู้เล่นฉันจะได้รับความสามารถทั้งหมดจากฐานข้อมูลและแบ่งปันพวกเขาใน std :: vector เพื่อที่เมื่อฉันต้องการคำนวณลักษณะอื่น ๆ ฉันมีพวกเขาใน RAM ฉันยังส่งพรสวรรค์ไปยังลูกค้าด้วย

นั่นคือเกี่ยวกับมัน (ยกเว้นบันทึกความสามารถใหม่ของหลักสูตรซึ่งเป็นเพียง 'INSERT' ในตาราง 'พรสวรรค์' + ข้อความถึงลูกค้า)


0

วิธีการเชิงสัมพันธ์

คุณอธิบายว่ามันเป็นความสัมพันธ์ระหว่างตัวปลดล็อคและปลดล็อคคล้ายกับในบทช่วยสอนนี้นี้ ฉันขอแนะนำให้เรียนรู้เพิ่มเติมเกี่ยวกับพีชคณิตเชิงสัมพันธ์และฐานข้อมูล พวกเขาเป็นวิธีที่ดีในการสร้างแบบจำลองข้อมูล หากคุณเรียนรู้วิธีสอบถามข้อมูลจากฐานข้อมูลคุณสามารถสร้างแบบจำลองข้อมูลได้ค่อนข้างง่าย

ฉันไม่รู้ว่าคุณรู้เรื่องแบบจำลองความสัมพันธ์มากแค่ไหน บทช่วยสอนนั้นจะช่วยคุณได้

ทางออกหนึ่ง

ฉันคิดว่า WoW ทำงานเหมือนในความเป็นจริง (ehm)

  • พรสวรรค์ปลดล็อคพรสวรรค์ (อื่น ๆ ) หลายอย่าง
  • พรสวรรค์ถูกปลดล็อคโดยพรสวรรค์ (อีกหลายคน)

มันคือความสัมพันธ์ N: N ซึ่งหมายถึงคุณต้องการ "คนกลาง" ความสัมพันธ์ใหม่ระหว่างสองความสามารถ:

(talent who unlocks id, talent who is unlocked)

วิธีนี้คุณสามารถมีพรสวรรค์ปลดล็อค B, C และ D ((A, B), (A, C), (A, D)) และพรสวรรค์ Y ปลดล็อคโดย X, Z และ W ((X, Y), ( Z, Y), (W, Y)) ในภาษาที่จำเป็น / ขั้นตอน / เชิงวัตถุคุณจะทำมันเป็นรายการ / อาร์เรย์ของคู่เช่น:

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

ดังนั้นสำหรับตัวอย่าง "โลกแห่งความจริง" คุณสามารถมี:

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

และหมายความว่าคุณจะได้รับ "การกระโดดสูงสูง" หลังจากที่คุณมีความสามารถ "วิ่งเร็ว" และ "ลูกแรงต้านแรงโน้มถ่วง"

ทางออกอื่น ๆ

ฉันไม่ได้เล่น Diablo เมื่อเร็ว ๆ นี้ แต่อาจเป็นไปได้ว่ามันมีเพียง:

  • ความสามารถพิเศษปลดล็อคความสามารถพิเศษอื่น ๆ
  • พรสวรรค์ถูกปลดล็อคเพียงหนึ่งพรสวรรค์

มันคือ 1: ความสัมพันธ์ N:

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

ชอบ:

 var Talent[8] = { "name": "superpower", "unlocked by": "being Clark Kent"};
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.