วิชาการโดย milo อ่าน 12 นาทีเรียบเรียงโดยมี AI ช่วย

4/9 กับความน่าจะเป็น: คณิตศาสตร์ในเกมที่นักพัฒนาต้องรู้

เลข 4/9 ดูเหมือนจะไม่มีความหมาย แต่ในโลกของการออกแบบเกม มันคือกุญแจที่เปิดประตูสู่ระบบสุ่มที่สมดุลและน่าตื่นเต้น

สารบัญ

เรื่องเล่าจากเซิร์ฟเวอร์ที่ผู้เล่นโกรธ

เมื่อประมาณสองปีก่อน มีเกมมือถือเกมหนึ่งในไทยเปิดตัวบอสตัวใหม่ ดรอปไอเทมหายากที่ผู้เล่นรอคอย ทีมพัฒนาตั้งดรอปเรตไว้ที่ 11% ซึ่งใกล้เคียงกับ 1 ใน 9 ครั้งที่จะได้ของชิ้นนั้น

ผู้เล่นคนหนึ่งฟาร์มบอสไป 50 รอบ ไม่ได้ของสักชิ้น เขาโพสต์ลงโซเชียล กระแสร้อนจัดจนทีมงานต้องออกมาอธิบาย ปรากฏว่าระบบสุ่มใช้แค่ random.random() แบบตรงตัว ไม่มีระบบ pity ไม่มีการปรับสมดุล ผู้เล่นที่โชคไม่อยู่ก็เจอความรู้สึกว่าเกมโกง

เรื่องแบบนี้เกิดขึ้นทุกวันในวงการพัฒนาเกม และจุดเริ่มต้นของการแก้ปัญหาคือการเข้าใจ 4/9, คณิตศาสตร์ในเกม, ความน่าจะเป็น อย่างถ่องแท้

4/9 คืออะไร ในบริบทความน่าจะเป็น

4/9 คือเศษส่วนที่เกิดจากการหาร 4 ด้วย 9 ซึ่งกลายเป็นทศนิยมประมาณ 0.4444 หรือ 44.44%

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

นี่คือปัญหา Monty Hall ฉบับย่อ ความน่าจะเป็นที่ผู้เล่นจะชนะถ้าเปลี่ยนช่องคือ 2/3 แต่ถ้าขยายเป็น 9 ช่อง เปิดเผย 4 ช่องว่าง ความน่าจะเป็นที่จะชนะเมื่อเปลี่ยนช่องจะกลายเป็นเรื่องที่ต้องคำนวณหลายชั้น

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

ทำไม 4/9 ถึงน่าสนใจ

เพราะมันไม่ใช่เลขที่คนทั่วไปนึกถึงเวลาพูดเรื่องความน่าจะเป็น คนมักนึกถึง 1/2, 1/4, 1/100 แต่ในการออกแบบเกม เลขแปลก ๆ แบบนี้ต่างหากที่ทำให้เกมรู้สึก "ยุติธรรมแต่ท้าทาย"

44.44% อยู่ตรงจุดที่ผู้เล่นรู้สึกว่ามีโอกาสพอสมควร แต่ไม่มากจนน่าเบื่อ มันอยู่ในโซนที่จิตวิทยาการเล่นเกมเรียกว่า "near-miss zone" โซนที่ผู้เล่นรู้สึกว่า "ใกล้ได้แล้ว" ทั้งที่จริง ๆ แล้วแต่ละครั้งเป็นอิสระจากกัน

การประยุกต์ใช้คำนวณ Drop Rate ของไอเทมในเกม

มาดูตัวอย่างจริง สมมติเราออกแบบบอสที่ดรอปดาบหายาก ต้องการให้ผู้เล่นได้ดาบประมาณ 1 คันทุก 9 ครั้งที่เล่น นั่นคือดรอปเรต 1/9 หรือประมาณ 11.11%

แต่ถ้าเราต้องการให้มีไอเทมรองลงมาด้วย เช่น เกราะ โล่ และยา โดยให้ดาบเป็นของหายากที่สุด เราอาจออกแบบดรอปเทเบิลแบบนี้

  • ดาบหายาก: 1/9 (11.11%)
  • เกราะ: 2/9 (22.22%)
  • โล่: 2/9 (22.22%)
  • ยา: 4/9 (44.44%)

รวมเป็น 9/9 หรือ 100% สังเกตว่า 4/9 คือสัดส่วนของไอเทมที่พบบ่อยที่สุด ซึ่งทำให้ผู้เล่นรู้สึกว่าฟาร์มแล้วไม่เสียเปล่า ได้อะไรกลับมาตลอด

ปัญหาที่ซ่อนอยู่ในการใช้ความน่าจะเป็นแบบตรงตัว

ถ้าเราใช้แค่ random.random() < 0.1111 เพื่อเช็คว่าจะดรอปดาบหรือไม่ จะเกิดปัญหาคือ

  • ผู้เล่นบางคนได้ดาบใน 3 ครั้งแรก รู้สึกเกมง่ายเกินไป
  • ผู้เล่นบางคนฟาร์ม 80 รอบไม่ได้ดาบ รู้สึกเกมโกง
  • ทั้งสองกรณีเป็นเรื่องปกติทางสถิติ แต่ความรู้สึกของผู้เล่นไม่ได้เป็นแบบสถิติ

นี่คือเหตุผลที่เกมใหญ่ ๆ อย่าง Genshin Impact หรือ Honkai: Star Rail ใช้ระบบ pity และ soft pity เข้ามาช่วย ไม่ใช่แค่ความน่าจะเป็นล้วน ๆ

การออกแบบ Drop Rate ที่สมดุล

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

  • ดรอปเรตพื้นฐาน: 1/9
  • หลังฟาร์ม 20 ครั้งไม่ได้ของ เพิ่มโอกาสเป็น 2/9
  • หลังฟาร์ม 40 ครั้งไม่ได้ของ เพิ่มเป็น 4/9
  • หลังฟาร์ม 60 ครั้ง ดรอปการันตี

สังเกตว่า 4/9 กลับมาอีกครั้ง ในจุดที่ผู้เล่นเริ่มรู้สึกหงุดหงิด ระบบเพิ่มโอกาสให้เป็น 44.44% ซึ่งอยู่ในโซนที่ผู้เล่นรู้สึกว่า "ครั้งนี้น่าจะได้แล้ว" แต่ยังมีความตื่นเต้นอยู่

การสร้างระบบสุ่มที่สมดุลด้วย Python

มาลงมือเขียนโค้ดกัน ผมจะสร้างระบบดรอปไอเทมที่ใช้ความน่าจะเป็น 4/9 เป็นฐาน และมีระบบ pity ปรับสมดุล

โครงสร้างพื้นฐาน

import random
from dataclasses import dataclass, field
from typing import Optional

@dataclass
class DropTable:
    items: dict  # {item_name: weight}
    total_weight: int = 0
    
    def __post_init__(self):
        self.total_weight = sum(self.items.values())
    
    def roll(self) -> str:
        r = random.randint(1, self.total_weight)
        cumulative = 0
        for item, weight in self.items.items():
            cumulative += weight
            if r <= cumulative:
                return item
        return list(self.items.keys())[-1]

# ตัวอย่าง: น้ำหนัก 4/9 สำหรับยา, 2/9 สำหรับเกราะและโล่, 1/9 สำหรับดาบ
boss_drop = DropTable({
    "ยาฟื้นพลัง": 4,
    "เกราะเหล็ก": 2,
    "โล่กันดัง": 2,
    "ดาบมังกร": 1,
})

# ทดสอบรอล 10 ครั้ง
for i in range(10):
    print(f"รอบที่ {i+1}: {boss_drop.roll()}")

โค้ดนี้ใช้ระบบน้ำหนัก (weighted random) แทนการเช็คความน่าจะเป็นทีละไอเทม ข้อดีคืออ่านง่าย ปรับง่าย และรวมเป็น 9 ซึ่งสอดคล้องกับโครงสร้าง 4/9 ที่เราวางไว้

เพิ่มระบบ Pity

@dataclass
class PityDropTable:
    base_weights: dict
    pity_threshold: int = 20
    pity_boost: int = 40  # รอบที่เพิ่มโอกาส
    max_pity: int = 60    # รอบการันตี
    rare_item: str = "ดาบมังกร"
    counter: int = 0
    
    def roll(self) -> str:
        self.counter += 1
        
        # ถ้าถึง max pity ดรอปการันตี
        if self.counter >= self.max_pity:
            self.counter = 0
            return self.rare_item
        
        # ปรับน้ำหนักตามจำนวนครั้งที่ไม่ได้ของหายาก
        weights = dict(self.base_weights)
        if self.counter >= self.pity_threshold:
            # เพิ่มน้ำหนักดาบจาก 1 เป็น 2
            weights[self.rare_item] = 2
        if self.counter >= self.pity_boost:
            # เพิ่มน้ำหนักดาบจาก 2 เป็น 4 (กลายเป็น 4/12)
            weights[self.rare_item] = 4
        
        total = sum(weights.values())
        r = random.randint(1, total)
        cumulative = 0
        for item, weight in weights.items():
            cumulative += weight
            if r <= cumulative:
                if item == self.rare_item:
                    self.counter = 0
                return item
        return list(weights.keys())[-1]

pity_boss = PityDropTable(
    base_weights={
        "ยาฟื้นพลัง": 4,
        "เกราะเหล็ก": 2,
        "โล่กันดัง": 2,
        "ดาบมังกร": 1,
    }
)

# จำลองการฟาร์ม 100 รอบ
results = {}
sword_rounds = []
for i in range(100):
    item = pity_boss.roll()
    results[item] = results.get(item, 0) + 1
    if item == "ดาบมังกร":
        sword_rounds.append(i + 1)

print("ผลลัพธ์ 100 รอบ:", results)
print("ได้ดาบในรอบที่:", sword_rounds)

วิเคราะห์ผลลัพธ์

ลองรันโค้ดด้านบนหลาย ๆ ครั้ง จะพบว่า

  • ผู้เล่นส่วนใหญ่ได้ดาบภายใน 20-40 รอบแรก เพราะ pity เริ่มทำงาน
  • ไม่มีใครฟาร์มเกิน 60 รอบโดยไม่ได้ดาบ เพราะ max pity การันตี
  • สัดส่วนไอเทมอื่น ๆ ยังใกล้เคียง 4/9, 2/9, 2/9 ตามที่ออกแบบ

นี่คือพลังของการผสาน 4/9, คณิตศาสตร์ในเกม, ความน่าจะเป็น เข้ากับการออกแบบระบบ คุณได้ทั้งความสมดุลทางสถิติและความรู้สึกที่ดีของผู้เล่น

มุมมอง: ทำไมนักพัฒนาเกมต้องสนใจเลขแปลก ๆ

หลายคนคิดว่าการออกแบบระบบสุ่มในเกมแค่ใส่เปอร์เซ็นต์แล้วจบ แต่จริง ๆ แล้วทุกเลขที่เราเลือกส่งผลต่อประสบการณ์ผู้เล่น

4/9 ไม่ใช่แค่เลข มันคือการตัดสินใจออกแบบ มันบอกว่าเราต้องการให้ผู้เล่นเจอไอเทมทั่วไปประมาณ 4 ครั้งในทุก 9 ครั้งที่เล่น มันสร้างจังหวะที่ผู้เล่นรู้สึกว่าตัวเองกำลังได้อะไรกลับมา ไม่ใช่ฟาร์มเปล่า ๆ

เลข 4/9 ยังสะท้อนหลักการที่ว่า ในเกมที่ดี ผู้เล่นควรรู้สึกว่า "ความพยายามอยู่กับความสมเหตุสมผล" ไม่ใช่โชคล้วน ไม่ใช่ความพยายามล้วน แต่เป็นจุดผสมที่พอดี

เปรียบเทียบกับเกมจริง

ลองดูเกมดัง ๆ สักสองสามเกม

  • Diablo IV: ใช้ระบบน้ำหนักหลายชั้น ไอเทมต่างกันมีโตเทเบิลแยก สัดส่วนคล้าย 4/9 สำหรับไอเทมทั่วไป
  • Genshin Impact: ดรอปเรตไอเทมหายากเริ่มต่ำ แต่มี soft pity ที่ปรับเพิ่มเหมือนที่เราทำในโค้ด
  • Monster Hunter: ดรอปเรตจากการล่ามอนสเตอร์ใช้ระบบน้ำหนัก บางไอเทมมีน้ำหนัก 4 จาก 9 หรือใกล้เคียง

ทุกเกมใช้หลักการเดียวกัน แต่ต่างกันที่การปรับแต่งตัวเลขให้เข้ากับประสบการณ์ที่ต้องการ

การทดสอบและวัดผล

หลังจากออกแบบระบบสุ่มแล้ว สิ่งสำคัญคือต้องทดสอบ ลองเขียนสคริปต์จำลองผู้เล่น 10,000 คน ฟาร์มบอส 100 รอบ แล้วดูการกระจายของผลลัพธ์

def simulate_players(num_players=10000, num_rounds=100):
    all_sword_counts = []
    all_max_rounds_without_sword = []
    
    for _ in range(num_players):
        pity_boss = PityDropTable(
            base_weights={
                "ยาฟื้นพลัง": 4,
                "เกราะเหล็ก": 2,
                "โล่กันดัง": 2,
                "ดาบมังกร": 1,
            }
        )
        sword_count = 0
        rounds_without = 0
        max_without = 0
        
        for _ in range(num_rounds):
            item = pity_boss.roll()
            if item == "ดาบมังกร":
                sword_count += 1
                max_without = max(max_without, rounds_without)
                rounds_without = 0
            else:
                rounds_without += 1
        max_without = max(max_without, rounds_without)
        
        all_sword_counts.append(sword_count)
        all_max_rounds_without_sword.append(max_without)
    
    avg_swords = sum(all_sword_counts) / len(all_sword_counts)
    worst_case = max(all_max_rounds_without_sword)
    
    print(f"ค่าเฉลี่ยดาบที่ได้ต่อ 100 รอบ: {avg_swords:.2f}")
    print(f"รอบที่ยาวนานที่สุดที่ไม่ได้ดาบ: {worst_case}")
    return all_sword_counts, all_max_rounds_without_sword

simulate_players()

ถ้าค่าเฉลี่ยดาบต่อ 100 รอบอยู่ประมาณ 12-18 เครื่อง และรอบที่ยาวนานที่สุดไม่เกิน 60 แสดงว่าระบบสมดุลพอสมควร ถ้าเลขเพี้ยนมาก ให้กลับไปปรับน้ำหนักหรือ pity threshold

ข้อควรระวังในการออกแบบระบบสุ่ม

1. อย่าใช้ random.random() อย่างเดียว

random.random() เป็น pseudorandom ที่เพียงพอสำหรับเกมทั่วไป แต่ถ้าเกมมีระบบเศรษฐกิจ เช่น การซื้อขายไอเทมระหว่างผู้เล่น ควรใช้ secrets module หรือระบบสุ่มที่ปลอดภัยกว่า

2. ระวังการสะสมความน่าจะเป็น

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

# โอกาสไม่ได้ดาบเลยใน 9 ครั้ง
p_no_sword = (8/9) ** 9
print(f"โอกาสไม่ได้ดาบเลยใน 9 ครั้ง: {p_no_sword:.4f}")
print(f"โอกาสได้อย่างน้อย 1 ดาบใน 9 ครั้ง: {1 - p_no_sword:.4f}")

ผลลัพธ์คือโอกาสได้อย่างน้อย 1 ดาบใน 9 ครั้งคือประมาณ 65.5% ไม่ใช่ 100% อย่างที่ผู้เล่นเข้าใจ นี่คือช่องว่างระหว่างความรู้สึกและความจริงทางคณิตศาสตร์

3. บันทึกข้อมูลทุกอย่าง

ทุกครั้งที่ผู้เล่นรอลดรอป บันทึกลง log ว่าได้อะไร รอบที่เท่าไหร่ แล้วเก็บไว้วิเคราะห์ ถ้ามีผู้เล่นมากร้องเรียนว่า "ฟาร์ม 100 รอบไม่ได้ของ" คุณมีข้อมูลจริงไว้ตรวจสอบ

สรุป: 4/9 สอนอะไรเรา

4/9 ไม่ใช่แค่เลข มันคือปรัชญาการออกแบบเกมที่บอกว่า

  • ผู้เล่นควรรู้สึกว่าได้อะไรกลับมาบ่อยพอสมควร (4 ใน 9)
  • แต่ของหายากต้องหายากจริง ๆ (1 ใน 9)
  • และระบบต้องมีกลไกปรับสมดุลเมื่อโชคไม่อยู่ข้างผู้เล่น

การเข้าใจ 4/9, คณิตศาสตร์ในเกม, ความน่าจะเป็น ไม่ใช่แค่เรื่องของนักคณิตศาสตร์ มันคือเครื่องมือของนักพัฒนาเกมที่อยากสร้างประสบการณ์ที่ผู้เล่นรู้สึกยุติธรรม ท้าทาย และอยากกลับมาเล่นต่อ

ถ้าคุณกำลังพัฒนาเกม ลองนึกถึงเลข 4/9 ครั้งต่อไปที่ตั้งดรอปเรต มันอาจเปลี่ยนวิธีที่คุณออกแบบระบบสุ่มได้มากกว่าที่คิด


คุณเคยเจอปัญหาระบบสุ่มในเกมที่รู้สึกไม่ยุติธรรมไหม หรือเคยออกแบบระบบดรอปเรตแล้วเจอปัญหาผู้เล่นร้องเรียน แชร์ประสบการณ์มาคุยกันได้ในคอมเมนต์ และถ้าอยากลองโค้ดด้านบนจริง ๆ ก๊อปปี้ไปรันในเครื่องได้เลย แล้วมาบอกกันว่าผลออกมาเป็นยังไง

เนื้อหาที่จัดทำโดยมี AI ช่วยจะมีป้ายกำกับ "เรียบเรียงโดยมี AI ช่วย" เพื่อให้คุณทราบอย่างชัดเจน เราถือว่าความโปร่งใสเรื่องการใช้ AI เป็นสิ่งสำคัญต่อความไว้วางใจของผู้อ่าน

พบข้อมูลที่ไม่ถูกต้องหรือคลาดเคลื่อน?เข้าสู่ระบบเพื่อทักท้วง
บทความนี้เป็นอย่างไร?

ยังไม่มีความคิดเห็น — มาเป็นคนแรกกันเถอะ!