ưu hóa nước đi của chính mình để đạt được lợi thế, dẫn đến chiến thắng hoặc ít nhất là đảm bảo không thua.Để phát triển một hệ thống AI có thể chơi cờ caro tốt, các thuật toán tìm kiếm n
Cơ sở lý thuyết
Giới thiệu về lý thuyết trò chơi
Lý thuyết trò chơi, một nhánh của Toán học ứng dụng, nghiên cứu các tình huống chiến thuật nơi các đối thủ lựa chọn hành động để tối đa hóa kết quả Ban đầu phát triển để nghiên cứu hành vi kinh tế, hiện nay lý thuyết này được áp dụng rộng rãi trong nhiều lĩnh vực như Sinh học, Triết học và Chính trị học John von Neumann là người đầu tiên hình thức hóa lý thuyết trò chơi, đặc biệt trong bối cảnh Chiến tranh Lạnh với khái niệm đảm bảo phá hủy lẫn nhau Từ những năm 1970, lý thuyết này cũng được sử dụng trong nghiên cứu hành vi động vật và chọn lọc tự nhiên Các trò chơi như Dilemma của tù nhân cho thấy lợi ích cá nhân có thể gây hại cho tập thể, dẫn đến ứng dụng trong Đạo đức học và triết học Gần đây, lý thuyết trò chơi thu hút sự chú ý của các nhà Khoa học máy tính nhờ vào ứng dụng trong Trí tuệ nhân tạo Ngoài các khía cạnh học thuật, lý thuyết trò chơi còn nổi bật trong văn hóa đại chúng, với John Nash, nhà lý thuyết trò chơi đoạt giải Nobel, được miêu tả trong cuốn hồi ký của Sylvia Nasar và bộ phim "Một tâm hồn đẹp".
Các game show như "Friend or Foe?" và "Survivor" đã áp dụng lý thuyết trò chơi, nghiên cứu quyết định trong môi trường tương tác giữa các đối thủ Khác với lý thuyết quyết định, lý thuyết trò chơi tập trung vào việc lựa chọn hành vi tối ưu, nơi chi phí và lợi ích không cố định mà phụ thuộc vào hành động của các cá nhân khác.
Các loại trò chơi
Trò chơi đối xứng là loại trò chơi mà lợi ích từ việc áp dụng một chiến thuật nhất định chỉ phụ thuộc vào các chiến thuật được sử dụng, không phụ thuộc vào danh tính của người chơi Nếu việc thay đổi người chơi không ảnh hưởng đến lợi ích của chiến thuật, thì trò chơi đó được coi là đối xứng.
Nhiều trò chơi 2×2 được nghiên cứu thường mang tính đối xứng, với những ví dụ tiêu biểu như trò chơi con gà, song đề tù nhân và đi săn nai Ngược lại, các trò chơi bất đối xứng thường có các tập hợp chiến thuật khác nhau được áp dụng bởi hai người chơi.
Trong trò chơi tối hậu thư và trò nhà độc tài, mỗi người chơi có các chiến thuật khác nhau Tuy nhiên, có thể xảy ra tình huống một trò chơi có các chiến thuật giống nhau cho cả hai người chơi nhưng vẫn mang tính bất đối xứng Ví dụ, trò chơi được minh họa bên phải cho thấy sự bất đối xứng mặc dù cả hai người chơi đều sử dụng cùng một tập hợp chiến thuật.
1.2.2 Trò chơi tổng bằng không và trò chơi tổng khác không
Trong trò chơi tổng bằng không, tổng điểm của tất cả người chơi luôn bằng 0, nghĩa là lợi ích của một đấu thủ đồng nghĩa với thiệt hại của người khác Ví dụ điển hình là Poker, nơi điểm số của người thắng chính là số điểm mà người thua mất đi Các trò chơi cổ điển như cờ vây, cờ vua và cờ tướng cũng thuộc loại này Ngược lại, một số trò chơi như bài toán song đề tù nhân có thể có kết quả không tổng bằng 0, vì lợi ích của một bên không nhất thiết phải tương ứng với thiệt hại của bên kia Để chuyển đổi bất kỳ trò chơi nào thành trò chơi tổng bằng không, ta có thể thêm một đấu thủ "bù nhìn" để cân bằng thiệt hại và lợi ích của các đấu thủ khác.
1.2.3 Trò chơi đồng thời và trò chơi tuần tự
Trong trò chơi đồng thời, cả hai đấu thủ thực hiện các nước đi cùng một lúc, tạo ra "hiệu ứng" đồng thời, trong khi ở trò chơi tuần tự, người chơi thứ hai có thể biết một phần thông tin về các nước đi trước đó.
Biểu diễn dạng chuẩn tắc được dùng để biểu diễn các trò chơi đồng thời, còn Biểu diễn dạng mở rộng được dùng cho các trò chơi tuần tự.
1.2.4 Trò chơi thông tin hoàn hảo và Trò chơi có thông tin không hoàn hảo
Các trò chơi thông tin hoàn hảo là một phần quan trọng trong lý thuyết trò chơi, đặc biệt là trong các trò chơi tuần tự Một trò chơi được coi là có thông tin hoàn hảo khi mọi người chơi đều biết tất cả các nước đi của những người chơi khác Trong khi nhiều trò chơi được nghiên cứu là trò chơi thông tin không hoàn hảo, một số trò chơi nổi tiếng như cờ vây và cờ vua lại thuộc loại này Cần phân biệt rõ giữa thông tin hoàn hảo và thông tin đầy đủ; thông tin đầy đủ yêu cầu người chơi biết về chiến lược và kết quả của những người chơi khác, nhưng không nhất thiết phải biết về các hành động cụ thể của họ.
1.2.5 Các trò chơi dài vô tận
Các trò chơi thường được nghiên cứu bởi các kinh tế gia và người chơi thực tế thường kết thúc trong một số bước đi hữu hạn Tuy nhiên, các nhà toán học lý thuyết không bị giới hạn bởi điều này và các nhà lý thuyết tập hợp nghiên cứu những trò chơi có thể kéo dài vô hạn, nơi kết quả thắng thua chỉ được xác định sau khi tất cả các bước đi đã hoàn thành.
Sự chú ý trong trò chơi thường không chỉ xoay quanh cách chơi tốt nhất, mà chủ yếu phụ thuộc vào việc người chơi có chiến thuật chiến thắng hay không Có thể chứng minh rằng, dựa vào tiên đề chọn lựa, tồn tại những trò chơi—dù có thông tin đầy đủ và chỉ có kết quả "thắng" hay "thua"—mà không có chiến thuật nào đảm bảo chiến thắng cho người chơi Sự hiện diện của những chiến thuật như vậy trong các trò chơi được thiết kế thông minh mang lại những kết quả quan trọng trong lý thuyết mô tả tập hợp.
Cơ sở thuật toán
Trong 2 người chơi thì một người gọi là người chơi cực đại (Max) và đối thủ
Cả hai đấu thủ đều nỗ lực thực hiện những nước đi chiến lược nhằm nâng cao điểm số tối đa của mình Người chơi cực tiểu (Min) luôn tìm cách tối ưu hóa kết quả để đạt được điểm tuyệt đối cao nhất có thể.
Max sẽ nỗ lực để nâng cao điểm số của mình và giảm điểm số của đối thủ Ngược lại, người chơi Min sẽ cố gắng làm cho điểm số của mình thấp hơn và đồng thời giảm điểm số của đối thủ.
Giải thuật tìm kiếm Min-Max giúp xác định tất cả các diễn biến tiếp theo của trò chơi đến một tầng nhất định Điểm số ban đầu được gán cho các lá, sau đó thông qua việc đánh giá các nước đi, điểm số được gán cho các tầng trên bằng cách sử dụng thuật toán Min-Max Thuật toán này thực hiện một lát cắt trước và tính toán điểm số dựa trên đó.
Ý tưởng cơ bản của thuật giải Min-Max theo đệ quy
Nếu mức đang xét là người chơi cực tiểu thì áp dụng thuật toán MinMax cho các con của nó.Lưu kết quả là giá trị nhỏ nhất.
Nếu mức đang xét là người chơi cực đại thì áp dụng thuật toán MinMax cho các con của nó.Lưu kết quả là giá trị lớn nhất.
Nếu mức đang xem xét là lá, tức là tầng cuối cùng trong cây tìm kiếm, thì giá trị tĩnh của thế cờ hiện tại sẽ phản ánh tình hình của người chơi tại đó Cần ghi nhớ kết quả này để phục vụ cho các bước tiếp theo trong quá trình phân tích.
Hình 1.1 Sơ đồ thuật toán Minimax
Trên một cây lớn, việc tìm kiếm tất cả các nút là không khả thi, do đó chúng ta chỉ giới hạn ở một số tầng nhất định để mô phỏng gần đúng cây Min-Max chưa biết Trong quá trình này, trọng số của các lá được gán không còn chính xác tuyệt đối mà chỉ là ước lượng Trọng số này được tính toán thông qua hàm lượng giá, do người dùng xây dựng dựa trên kiến thức và kinh nghiệm của họ.
1.3.2 Thuật toán cắt tỉa Alpha-Beta
Cắt tỉa Alpha-beta là phiên bản sửa đổi của thuật toán minimax Đây là kỹ thuật tối ưu hóa cho thuật toán minimax.
Trong thuật toán tìm kiếm minimax, số lượng trạng thái trò chơi cần kiểm tra tăng theo cấp số mũ theo chiều sâu của cây Mặc dù không thể loại bỏ hoàn toàn số mũ này, chúng ta có thể giảm nó xuống một nửa bằng kỹ thuật cắt tỉa Kỹ thuật này cho phép tính toán quyết định minimax mà không cần kiểm tra từng nút của cây trò chơi, thông qua hai tham số ngưỡng Alpha và Beta Do đó, nó được gọi là cắt tỉa alpha-beta, hay còn được biết đến với tên gọi Thuật toán Alpha-Beta.
Cắt tỉa alpha-beta có thể thực hiện ở bất kỳ độ sâu nào trong cây, không chỉ giới hạn ở việc cắt tỉa lá mà còn có thể áp dụng cho toàn bộ cây con.
Hai tham số có thể được định nghĩa như sau:
Alpha: Lựa chọn tốt nhất (giá trị cao nhất) mà chúng tôi tìm thấy cho đến nay tại bất kỳ điểm nào trên đường dẫn của
Maximizer Giá trị ban đầu của alpha là -∞.
Beta: Lựa chọn tốt nhất (giá trị thấp nhất) mà chúng tôi tìm thấy cho đến nay tại bất kỳ điểm nào trên đường đi của
Minimumr Giá trị ban đầu của beta là +∞
Cắt tỉa Alpha-beta theo thuật toán minimax chuẩn mang lại nước đi tương tự như thuật toán gốc, nhưng loại bỏ các nút không ảnh hưởng đến quyết định cuối cùng, giúp tăng tốc độ thực hiện Bằng cách cắt tỉa những nút này, thuật toán trở nên nhanh hơn và hiệu quả hơn trong việc tìm kiếm nước đi tối ưu.
Hình 1.2 Sơ đồ thuật toán Alpha-Beta
Thuật toán heuristic là phương pháp giải quyết vấn đề hiệu quả, thường được áp dụng cho các tình huống phức tạp khi không có thuật toán chính xác khả thi hoặc khi việc sử dụng thuật toán chính xác quá tốn kém về tính toán.
Thuật toán heuristic đóng vai trò quan trọng trong nhiều ngành công nghiệp như vận tải, hậu cần và tài chính Chúng được áp dụng để tối ưu hóa các tuyến giao hàng cho các gói hàng, đồng thời giúp giảm thiểu rủi ro trong đầu tư tài chính.
Thuật toán heuristic có khả năng khám phá các giải pháp khả thi cho vấn đề và đưa ra quyết định sáng suốt dựa trên các quy tắc hoặc heuristic Chúng có thể đơn giản hoặc phức tạp, sử dụng nhiều kỹ thuật khác nhau như leo đồi, ủ mô phỏng và thuật toán di truyền để tìm ra các giải pháp tối ưu cho các vấn đề.
Thuật toán heuristic là công cụ thiết yếu cho doanh nghiệp và ngành công nghiệp trong việc giải quyết nhanh chóng và hiệu quả các vấn đề phức tạp Khi đối mặt với những thách thức ngày càng đa dạng và khó khăn, vai trò của thuật toán heuristic càng trở nên quan trọng trong việc tìm kiếm giải pháp tối ưu giữa hiệu quả và độ chính xác.
Thuật toán heuristic là phương pháp giải quyết vấn đề bằng cách sử dụng các giải pháp gần đúng để tìm ra những giải pháp tối ưu hoặc gần tối ưu cho các vấn đề phức tạp Các thuật toán này hoạt động theo các giai đoạn và trình tự cụ thể.
Giai đoạn 1: Hình thành vấn đề
Trong giai đoạn đầu tiên, việc xác định vấn đề được thực hiện bằng cách xây dựng nó theo các thuật toán heuristic Điều này bao gồm việc xác định tham số đầu vào, mục tiêu đầu ra, ràng buộc và không gian tìm kiếm Mục tiêu là thể hiện vấn đề một cách rõ ràng để có thể tìm kiếm và tối ưu hóa bằng thuật toán.
Giai đoạn 2: Biểu diễn giải pháp
Trong giai đoạn thứ hai, việc chọn một biểu diễn giải pháp phù hợp là rất quan trọng để thể hiện không gian tìm kiếm của vấn đề Tùy thuộc vào bản chất của vấn đề, giải pháp có thể được biểu diễn dưới nhiều hình thức khác nhau như tập hợp giá trị nhị phân, tập hợp số thực, chuỗi bước hoặc cấu trúc cây Biểu diễn này cần phải cho phép thuật toán khám phá không gian tìm kiếm và tạo ra các giải pháp tiềm năng một cách hiệu quả.
Giai đoạn 3: Lựa chọn theo kinh nghiệm
Phân tích bài toán
Giới thiệu bài toán
Hình 2.3 Trò chơi cờ ca rô
Cờ caro, một trong những môn cờ logic lâu đời nhất trên thế giới, đã được phát minh độc lập bởi nhiều nền văn minh khác nhau Xuất hiện lần đầu tiên vào khoảng năm 2000 trước Công Nguyên tại sông Hoàng Hà, Trung Quốc, cờ caro đã thu hút sự chú ý của nhiều nhà khoa học, những người đã tìm thấy bằng chứng về sự phát triển của trò chơi này qua các thời kỳ.
Cờ Caro, một trò chơi có nguồn gốc từ Trung Quốc, đã được du nhập vào Nhật Bản khoảng năm 270 trước Công Nguyên Trò chơi này có liên quan đến môn cờ cổ Wutzu, một phần của di sản văn hóa phong phú của nhân loại Trong bối cảnh lịch sử, cờ Caro cũng phản ánh sự giao thoa văn hóa giữa các nền văn minh, từ Hy Lạp cổ đại cho đến Châu Mỹ trước thời kỳ Colombo.
Gomoku, còn được biết đến với các tên gọi khác như Kakugo, gomoku-narabe và Itsutsu-ishi, là một trò chơi cổ có nguồn gốc từ Nhật Bản Trò chơi này đã được phát hiện từ một di tích có niên đại khoảng 100 sau Công nguyên.
CN là một biến thể của trò Caro, nhanh chóng lan truyền với tên gọi Kakugo (trò 5 quân) Các nhà sử học cho biết, vào thế kỷ 17 và 18, trò chơi này phổ biến với mọi lứa tuổi Năm 1858, sách đầu tiên về Kakugo được xuất bản, và trò chơi này tiếp tục được biết đến với nhiều tên gọi khác nhau.
Gomoku và phát triển cho đến ngày nay thành thể loại phức tạp nhất trong họ hàng đông đúc của nó, là Renju (chuỗi ngọc trai).
Luật chơi của Gomoku cổ như sau:
Bàn cờ 15 x 15, quân đen đi trước.
Ai tạo được 5 quân liền nhau trước thì thắng
Khi trình độ các kỳ thủ Gomoku tăng cao, họ nhận thấy rằng việc chỉ chơi theo cách thông thường sẽ mang lại lợi thế lớn cho bên Đen, dẫn đến ưu thế thắng Một số nhà toán học đã chứng minh rằng trong luật Gomoku trên bàn cờ từ 15x15 trở lên, Đen chắc chắn thắng, và các cách đi cụ thể đã được hệ thống hóa Điều này đã khiến Gomoku rơi vào khủng hoảng, khi khả năng thắng 100% của Đen làm giảm giá trị của trò chơi Nhiều cải tiến đã được đề xuất, trong đó một số nhanh chóng bị bỏ qua, trong khi những cải tiến khác đã tạo ra các biến thể mới cho trò chơi.
Gomoku là một trò chơi chiến lược, và các cải tiến gần đây tập trung vào việc đặt ra những hạn chế cho quân Đen để cân bằng ưu thế của người đi trước Dưới đây là một số biến thể phổ biến của trò chơi này.
1 Gomoku: Hiện nay được chơi chính thức với bàn 13x13
Trong ván cờ này, không có khả năng hòa Nếu Trắng hết đất, thì Trắng sẽ thắng Hiện tại, chưa có chứng minh nào cho thấy Đen chắc chắn sẽ thắng, mặc dù Đen vẫn đang nắm giữ một ưu thế lớn.
2 ProGomoku: Chơi trên bàn 15x15 Nước đầu của Đen đặt sẵn ở trung tâm Nước thứ ba (nước thứ hai của Đen) phải đặt ngoài hình vuông cấm Hình vuông cấm là hình vuông trung tâm kích thước 5x5 Không có hạn chế cho Trắng Đã có chứng minh Đen chắc chắn thắng trong biến thể này.
3 Pente: Biến thể này không còn giống Gomoku Luật bổ sung là có thể ăn quân đối phương Nước ăn quân được thực hiện bằng cách chặn hai đầu một nước hai quân đối phương và ăn hai quân đó Ai tạo được nước năm hoặc ăn được 5 cặp quân trước thì thắng Rất phổ biến ở Mỹ Chơi trên bàn 19x19.
Giao diện và luật chơi
Bài toán trên được thiết kế 2 giao diện với 2 bàn cờ có kích thước khác nhau là 3x3 và 10x10
Bắt đầu: Bàn cờ là lưới vuông 3x3 ô Hai người chơi thay phiên nhau đi Người chơi thứ nhất thường là "X" và người chơi thứ hai là "O".
Đi quân: Trong mỗi lượt, người chơi sẽ đánh dấu một ô trống trên bàn cờ bằng ký hiệu của mình (X hoặc O).
Thắng: Người chơi nào có được 3 ký hiệu của mình trên một hàng, cột hoặc đường chéo sẽ thắng.
Thua: Người thua là người không đạt được 3 ký hiệu liên tiếp và không cản được đối thủ.
Hòa: Nếu tất cả các ô trên bàn cờ đã được điền kín mà không có ai thắng, ván cờ kết thúc với kết quả hòa.
Bắt đầu: Bàn cờ có 100 ô, xếp thành lưới 10x10 Hai người chơi thay phiên nhau đi Một người chơi là "X", và người chơi còn lại là "O".
Đi quân: Trong mỗi lượt, người chơi sẽ đánh dấu một ô trống trên bàn cờ bằng ký hiệu của mình (X hoặc O).
Thắng: Người chơi nào có được 5 ký hiệu của mình trên một hàng, cột hoặc đường chéo sẽ thắng.
Thua: Người thua là người không đạt được 5 ký hiệu liên tiếp và không cản được đối thủ.
Hòa: Nếu tất cả các ô trên bàn cờ đã được điền kín mà không có ai thắng, ván cờ kết thúc với kết quả hòa.
Thuật toán cho AI
Thuật toán tìm kiếm Minimax
Thuật toán Minimax là một công cụ quan trọng trong việc tìm kiếm nước đi tối ưu cho AI trong các trò chơi đối kháng như cờ caro Thuật toán này giúp đánh giá các nước đi, nhằm tối đa hóa điểm số cho AI và đồng thời giảm thiểu khả năng chiến thắng của đối thủ.
def minimax(self, board, depth, is_maximizing):
for i in range(self.BOARD_SIZE):
for j in range(self.BOARD_SIZE):
score = self.minimax(board, depth + 1,
best_score = max(score, best_score)
for i in range(self.BOARD_SIZE):
for j in range(self.BOARD_SIZE):
score = self.minimax(board, depth + 1, True)
best_score = min(score, best_score)
Hàm minimax hoạt động bằng cách nhận các tham số như board, depth và is_maximizing để đánh giá điểm số của các trạng thái bàn cờ dựa trên điều kiện thắng, thua hoặc hòa Khi AI tìm cách tối đa hóa điểm số (is_maximizing=True), hàm sẽ xem xét tất cả các nước đi có thể và chọn nước đi có điểm số cao nhất Ngược lại, nếu is_maximizing là False, hàm sẽ đánh giá nước đi tốt nhất cho người chơi nhằm giảm thiểu điểm số của AI Kết quả từ hàm minimax sẽ cho ra giá trị cao nhất hoặc thấp nhất có thể đạt được từ nước đi hiện tại.
Tìm kiếm nước đi tối ưu cho AI bằng cách áp dụng thuật toán minimax cho từng ô trống trên bảng Sau khi đánh giá, hàm sẽ chọn nước đi có điểm số cao nhất và gán nó cho AI.
for i in range(self.BOARD_SIZE):
for j in range(self.BOARD_SIZE):
score = self.minimax(self.board, 0, False)
self.board[move[0]][move[1]] = self.ai
AI hoạt động bằng cách kiểm tra từng ô trống trên bảng và tạm thời đặt AI vào ô đó Nó sử dụng thuật toán minimax để đánh giá các nước đi, so sánh điểm số của mỗi nước đi với điểm số tốt nhất hiện tại Nếu tìm thấy nước đi có điểm số cao hơn, AI sẽ cập nhật nước đi tốt nhất Cuối cùng, sau khi xác định được nước đi tối ưu, hàm sẽ thực hiện nước đi đó cho AI.
Thuật toán tìm kiếm ưu tiên Heuristic và hàm ưu tiên
Trong bàn cờ 10x10, nhóm em đã quyết định không áp dụng thuật toán tìm kiếm Minimax, mà thay vào đó sử dụng thuật toán Heuristic để đánh giá các nước đi khả thi Phương pháp này giúp chúng em lựa chọn nước đi tốt nhất dựa trên số điểm đánh giá.
AI có thể tiết kiệm tài nguyên tính toán bằng cách sử dụng hàm heuristic và kiểm tra các nước đi ưu tiên, cho phép chọn nước đi mà không cần xây dựng cây tìm kiếm đầy đủ.
Hình 2.6 Minh họa điểm cho bàn cờ
The heuristic evaluation function assesses a game board by calculating potential scoring opportunities for both the AI and human players It begins by counting the potential lines for each player, then iterates through each cell in the board If an empty cell can create three in a row for the AI, a significant score boost of 50 is applied The function returns a multiplied score for the AI if it reaches a threshold of 30, while a score adjustment for the human player is applied if their score exceeds 10 Ultimately, the function calculates and returns a final score by subtracting the human score, adjusted by a factor of 1.5, from the AI score.
Để tính điểm cho cả AI và người chơi, phương thức “count_potential_lines” được gọi Hệ thống kiểm tra từng ô trên bàn cờ; nếu ô trống (board[row][col] == 0) và việc đặt quân của AI vào ô này có thể tạo ra ba quân liên tiếp (creates_three), điểm số của AI sẽ tăng thêm 50 Điểm số cũng được điều chỉnh theo các ngưỡng: nếu điểm của AI đạt 30, điểm sẽ được nhân với 5; nếu điểm của người chơi đạt 10, điểm của họ sẽ bị trừ 3 Cuối cùng, hệ thống trả về điểm tổng hợp, bao gồm điểm của AI và điểm âm của người chơi.
Tính toán điểm cho các chuỗi quân liên tiếp trên bàn cờ cho một người chơi.
def count_potential_lines(self, board, player):
for r in range(self.BOARD_SIZE):
for c in range(self.BOARD_SIZE):
consecutive_score + self.check_direction(board, r, c, d, player)
if self.check_direction(board, r, c, d, self.human) == 10:
consecutive_score += 5 return consecutive_score
Cách thức hoạt động của thuật toán bắt đầu bằng việc khởi tạo một biến “consecutive_score” với giá trị 0 Thuật toán sẽ duyệt qua từng ô trên bàn cờ, và nếu ô đó chứa quân của người chơi (board[r][c] == player), nó sẽ gọi hàm check_direction để xác định điểm số cho chuỗi quân của người chơi trong các hướng khác nhau Ngược lại, nếu ô chứa quân của đối thủ (board[r][c] = self.human), hàm check_direction cũng sẽ được gọi để kiểm tra xem có chuỗi quân liên tiếp nào cần phải được chặn hay không Nếu phát hiện chuỗi quân của đối thủ, biến “consecutive_score” sẽ được tăng lên nhằm ưu tiên cho AI trong việc chặn đối thủ.
Hàm tạo ra 3 nước đi liên tiếp
Xác định xem việc đặt quân vào ô trống có thể tạo ra ba quân liên tiếp hay không.
def creates_three(self, board, row, col, player):
line_positions = [(row + dr * i, col + dc * i) for i in range(4)]
count_player = sum(1 for r, c in line_positions if 0