แนวคิด AI ด้วย Python

การค้นหาและ AI สำหรับเกม: A* และ minimax ใน Python

AI แบบดั้งเดิมแก้ปัญหาด้วยการค้นหาในสถานะที่เป็นไปได้ A* หาเส้นทางที่ถูกที่สุดโดยรวมต้นทุนที่เดินมาแล้วกับค่าประมาณต้นทุนที่เหลือ ส่วน minimax เลือกตาเดินในเกมสองผู้เล่นโดยสมมติว่าคู่แข่งเล่นได้ดี

แนวคิดแบบเข้าใจง่าย

AI แบบดั้งเดิมแก้ปัญหาด้วยการค้นหาในสถานะที่เป็นไปได้ A* หาเส้นทางที่ถูกที่สุดโดยรวมต้นทุนที่เดินมาแล้วกับค่าประมาณต้นทุนที่เหลือ ส่วน minimax เลือกตาเดินในเกมสองผู้เล่นโดยสมมติว่าคู่แข่งเล่นได้ดี

หาเส้นทางที่สั้นที่สุดบนตารางด้วยการค้นหา A* และเลือกตาเดินที่ดีที่สุดในเกมด้วย minimax

ประเด็นสำคัญ

  • A* หาเส้นทางที่ดีที่สุดได้เมื่อค่าประมาณ (heuristic) ไม่เคยเกินต้นทุนจริง
  • minimax ค้นในต้นไม้เกมจนถึงความลึกที่กำหนดหรือจนจบเกม
  • การตัดแต่งแบบ alpha-beta ข้ามกิ่งที่ไม่สามารถเปลี่ยนการตัดสินใจได้
  • อัลกอริทึมเชิงพันธุกรรมค้นหาด้วยวิธีต่างออกไป คือวิวัฒนาการประชากรของคำตอบที่เป็นไปได้

ควรใช้เมื่อใด?

  • เข้าใจสิ่งที่เกิดขึ้นภายในโครงข่ายประสาทเทียมและไลบรารี AI
  • เข้าใจแนวคิดก่อนลงมือเขียนเองในโจทย์ที่เกี่ยวข้อง
  • เตรียมตัวสำหรับคอร์สแมชชีนเลิร์นนิง การสัมภาษณ์งาน และโปรเจกต์

ลองดูการทำงานจริง

กด เล่น เพื่อดู A* สำรวจตาราง คลิกที่ช่องเพื่อเพิ่มหรือลบกำแพง ในต้นไม้เกม คลิกที่ใบเพื่อเปลี่ยนคะแนน

โค้ดตัวอย่าง

รันโค้ด →
main.py
import heapq

# A* finds the cheapest path using cost so far + a guess of the cost left.
grid = ["S..#",
        ".#..",
        "...G"]
start, goal = (0, 0), (2, 3)
guess = lambda r, c: abs(r - goal[0]) + abs(c - goal[1])   # Manhattan distance

frontier = [(guess(*start), 0, start, [start])]
seen = set()
while frontier:
    _, cost, (r, c), path = heapq.heappop(frontier)
    if (r, c) == goal:
        print("path:", path, "cost:", cost)
        break
    if (r, c) in seen:
        continue
    seen.add((r, c))
    for dr, dc in ((0, 1), (1, 0), (0, -1), (-1, 0)):
        nr, nc = r + dr, c + dc
        if 0 <= nr < 3 and 0 <= nc < 4 and grid[nr][nc] != "#":
            heapq.heappush(frontier, (cost + 1 + guess(nr, nc), cost + 1, (nr, nc), path + [(nr, nc)]))

# Minimax: the maximizer assumes the opponent always picks the worst for it.
def minimax(node, maximizing):
    if isinstance(node, int):
        return node
    values = [minimax(child, not maximizing) for child in node]
    return max(values) if maximizing else min(values)

tree = [[3, 5], [2, 9], [0, 7]]   # our move, then the opponent's reply
print("best guaranteed score:", minimax(tree, True))

ผลลัพธ์ที่คาดหวัง

path: [(0, 0), (0, 1), (0, 2), (1, 2), (1, 3), (2, 3)] cost: 5
best guaranteed score: 3

หลักการทำงาน

คิวลำดับความสำคัญจะขยายช่องที่มีต้นทุน + ค่าประมาณน้อยที่สุดเสมอ โดยค่าประมาณคือระยะแมนฮัตตันถึงเป้าหมาย A* จึงไปถึง G ใน 5 ก้าวโดยอ้อมกำแพง ส่วน minimax() เลือกค่าสูงสุดในตาของเราและค่าต่ำสุดในตาของคู่แข่ง ตาเดินแรกรับประกันได้ 3 ซึ่งดีที่สุดในบรรดากรณีแย่ที่สุดทั้งสาม

เปลี่ยนค่าและรันโปรแกรมด้วย คอมไพเลอร์ Python ออนไลน์ของ CodeUtility โดยไม่ต้องติดตั้ง Python

แบบฝึกหัด

ลองเปลี่ยน input และทดสอบกรณีขอบก่อนใช้ชุดข้อมูลที่ใหญ่ขึ้น

  1. เปลี่ยนอินพุตหรือน้ำหนัก แล้วลองทายผลลัพธ์ก่อนรัน
  2. พิมพ์ค่าระหว่างทางออกมาเพื่อดูการคำนวณทีละขั้น
  3. แก้โจทย์ที่ลิงก์ไว้ด้านล่างเพื่อเขียนแนวคิดนี้ด้วยตัวเอง
รันใน Python IDE →

ฝึกด้วยโจทย์

ใช้สิ่งที่เรียนในบทนี้แก้ปัญหาจริง ทุกโจทย์รันในเบราว์เซอร์ พร้อมการทดสอบทันทีและรีวิวจาก AI

โจทย์ทั้งหมด