首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ChatGPT与我们玩游戏_五子棋

ChatGPT与我们玩游戏_五子棋

作者头像
顾翔
发布2025-02-12 15:18:19
发布2025-02-12 15:18:19
34800
代码可运行
举报
运行总次数:0
代码可运行

第一次询问

以图形方式给出五子棋的python程序

第一次回答

要以图形方式实现五子棋(Gomoku)游戏,我们可以使用 tkinter 库来创建一个简单的图形用户界面(GUI)。下面是一个示例程序,展示如何实现这一点。

代码语言:javascript
代码运行次数:0
运行
复制
import tkinter as tk
from tkinter import messagebox
           
class Gomoku:
    def __init__(self, master):
        self.master = master
        self.master.title("五子棋")
        self.size = 15
        self.board = [['' for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'X'
        self.buttons = [[None for _ in range(self.size)] for _ in range(self.size)]
        self.create_board()
           
    def create_board(self):
        for row in range(self.size):
            for col in range(self.size):    
                button = tk.Button(self.master, text='', width=4, height=2,
                                   command=lambda r=row, c=col: self.make_move(r, c))
                button.grid(row=row, column=col)
                self.buttons[row][col] = button
           
    def make_move(self, row, col):
        if self.board[row][col] == '':
            self.board[row][col] = self.current_player
            self.buttons[row][col].config(text=self.current_player)
            if self.check_winner(row, col):
                messagebox.showinfo("游戏结束", f"玩家 {self.current_player} 胜利!")
                self.reset_game()
            else:
                self.current_player = 'O' if self.current_player == 'X' else 'X'
           
    def check_winner(self, row, col):
        # 检查是否有五子连珠
        return (self.check_direction(row, col, 1, 0) or  # 水平
                self.check_direction(row, col, 0, 1) or  # 垂直
                self.check_direction(row, col, 1, 1) or  # 右下对角线    
                self.check_direction(row, col, 1, -1))   # 左下对角线
           
    def check_direction(self, row, col, delta_row, delta_col):
        count = 1
        count += self.count_in_direction(row, col, delta_row, delta_col)
        count += self.count_in_direction(row, col, -delta_row, -delta_col)
        print(count)
        return count >= 5  # 检查是否有五个相同的棋子连成一线
           
    def count_in_direction(self, row, col, delta_row, delta_col):
        count = 0
        while 0 <= row < self.size and 0 <= col < self.size and self.board[row][col] == self.current_player:
            count += 1
            row += delta_row
            col += delta_col
        return count
           
    def reset_game(self):
        self.board = [['' for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'X'
        for row in range(self.size):    
            for col in range(self.size):
                self.buttons[row][col].config(text='')
           
if __name__ == "__main__":
    root = tk.Tk()
    game = Gomoku(root)
    root.mainloop()

代码说明

初始化:Gomoku 类初始化游戏窗口和棋盘。棋盘为 15x15 的二维列表。

创建棋盘:create_board() 方法创建按钮作为棋盘的每个格子,点击按钮会调用 make_move() 方法。

落子:make_move(row, col) 方法处理玩家的落子,更新棋盘状态并检查是否有玩家胜利。

胜利检查:check_winner(row, col) 方法检查当前玩家是否胜利,调用 check_direction() 方法检查四个方向。

重置游戏:reset_game() 方法重置棋盘和当前玩家。

运行代码

将上述代码复制到Python环境中运行,确保已安装 tkinter 库(通常Python自带)。您将看到一个简单的五子棋游戏窗口,两个玩家可以点击按钮落子,直到一方连成五子为止。游戏结束后会弹出对话框显示获胜玩家,并重置棋盘以便重新开始游戏。

程序有错误,需要修改

代码语言:javascript
代码运行次数:0
运行
复制
return count >= 5   

代码语言:javascript
代码运行次数:0
运行
复制
return count >= 7 

第二次询问

基于上面代码,请完成人与AI互动的代码

第二次回答

你提供的是一个图形化界面的五子棋游戏代码,接下来我将实现一个与AI对战的版本。在这个版本中,玩家将与AI进行轮流下棋。AI将使用简单的随机算法来选择空白的位置进行下棋,当然,实际应用中可以使用更复杂的算法,如Minimax等。

我们将在现有代码的基础上,添加AI逻辑。以下是修改后的代码,包含人与AI下棋的功能:

代码语言:javascript
代码运行次数:0
运行
复制
import tkinter as tk
from tkinter import messagebox
import random
           
class Gomoku:
    def __init__(self, master):
        self.master = master
        self.master.title("五子棋")
        self.size = 15
        self.board = [['' for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'X'  # 玩家为 X,AI 为 O
        self.buttons = [[None for _ in range(self.size)] for _ in range(self.size)]    
        self.create_board()
           
    def create_board(self):
        for row in range(self.size):
            for col in range(self.size):
                button = tk.Button(self.master, text='', width=4, height=2,
                                   command=lambda r=row, c=col: self.make_move(r, c))
                button.grid(row=row, column=col)
                self.buttons[row][col] = button
           
    def make_move(self, row, col):
        if self.board[row][col] == '' and self.current_player == 'X':  # 只有玩家能下棋
            self.board[row][col] = self.current_player
            self.buttons[row][col].config(text=self.current_player)
            if self.check_winner(row, col):
                messagebox.showinfo("游戏结束", f"玩家 {self.current_player} 胜利!")
                self.reset_game()
            else:
                self.current_player = 'O'    
                self.ai_move()  # AI轮到下棋
           
    def ai_move(self):
        row, col = self.random_move()  # AI随机选择一个空位
        self.board[row][col] = self.current_player
        self.buttons[row][col].config(text=self.current_player)
        if self.check_winner(row, col):
            messagebox.showinfo("游戏结束", "AI 胜利!")
            self.reset_game()
        else:
            self.current_player = 'X'  # 玩家轮到下棋
           
    def random_move(self):
        while True:
            row = random.randint(0, self.size - 1)
            col = random.randint(0, self.size - 1)
            if self.board[row][col] == '':
                return row, col
           
    def check_winner(self, row, col):
        # 检查是否有五子连珠
        return (self.check_direction(row, col, 1, 0) or  # 水平    
                self.check_direction(row, col, 0, 1) or  # 垂直
                self.check_direction(row, col, 1, 1) or  # 右下对角线
                self.check_direction(row, col, 1, -1))   # 左下对角线
           
    def check_direction(self, row, col, delta_row, delta_col):
        count = 1
        count += self.count_in_direction(row, col, delta_row, delta_col)
        count += self.count_in_direction(row, col, -delta_row, -delta_col)
        return count >= 5  # 检查是否有五个相同的棋子连成一线
           
    def count_in_direction(self, row, col, delta_row, delta_col):
        count = 0
        while 0 <= row < self.size and 0 <= col < self.size and self.board[row][col] == self.current_player:
            count += 1
            row += delta_row
            col += delta_col
        return count
           
    def reset_game(self):
        self.board = [['' for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'X'    
        for row in range(self.size):
            for col in range(self.size):
                self.buttons[row][col].config(text='')
           
if __name__ == "__main__":
    root = tk.Tk()
    game = Gomoku(root)
root.mainloop()

主要修改内容:

AI的下棋逻辑:在玩家下完棋后,AI会自动选择一个空的位置进行下棋。这里的AI实现很简单,仅采用随机选择空位置的策略,确保每次AI都会在一个空白的位置下棋。

玩家和AI轮流下棋:游戏逻辑变为玩家先行('X'),然后轮到AI('O')。每次玩家下完棋后,AI会自动做出决策。

胜利检查:保持了原有的胜利检查方法,判断是否有五子连珠。

游戏流程:

玩家点击棋盘上的一个空位进行下棋。

玩家下完棋后,AI会自动选择一个空位进行下棋。

每次下棋后,都会检查是否有五子连珠,若有则显示胜利消息并重置游戏。

后续扩展:

可以使用更加复杂的算法(如Minimax或Alpha-Beta剪枝)来提高AI的棋力。

可以加入棋盘的大小调整、难度设置等功能。

这个版本是一个基础的五子棋游戏框架,具有图形化界面和AI对战功能。如果你有任何问题或希望进一步修改,可以随时告诉我!

仍旧修改

代码语言:javascript
代码运行次数:0
运行
复制
return count >= 5 

代码语言:javascript
代码运行次数:0
运行
复制
return count >= 7

使用这个方法,随机性太强,没有互动的感觉。

第三次询问

请用Alpha-Beta剪枝提高AI的棋力

第三次回答

为了提高AI的棋力,我们可以使用Alpha-Beta剪枝算法。Alpha-Beta剪枝是Minimax算法的一种优化,它能有效减少搜索树的大小,提高计算效率。下面的代码实现了基于Alpha-Beta剪枝的五子棋AI。

主要步骤:

1.评估函数:首先,我们需要为每种棋盘状态设计一个评估函数。这个函数将为当前棋盘上的每个位置赋予一个分数,以便AI选择最佳的下一步。

2.Minimax搜索:Minimax算法模拟所有可能的下棋步骤,通过递归计算每一步的最佳价值,AI选择最优解。

3.Alpha-Beta剪枝:通过剪枝的方式,避免无效的分支计算,减少计算量。

修改后的代码:

代码语言:javascript
代码运行次数:0
运行
复制
import tkinter as tk
from tkinter import messagebox
import random    
           
class Gomoku:
    def __init__(self, master):
        self.master = master
        self.master.title("五子棋")
        self.size = 15
        self.board = [['' for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'X'  # 玩家为 X,AI 为 O
        self.buttons = [[None for _ in range(self.size)] for _ in range(self.size)]
        self.create_board()
           
    def create_board(self):
        for row in range(self.size):
            for col in range(self.size):
                button = tk.Button(self.master, text='', width=4, height=2,
                                   command=lambda r=row, c=col: self.make_move(r, c))
                button.grid(row=row, column=col)
                self.buttons[row][col] = button
               
    def make_move(self, row, col):
        if self.board[row][col] == '' and self.current_player == 'X':  # 只有玩家能下棋
            self.board[row][col] = self.current_player
            self.buttons[row][col].config(text=self.current_player)
            if self.check_winner(row, col):
                messagebox.showinfo("游戏结束", f"玩家 {self.current_player} 胜利!")
                self.reset_game()
            else:
                self.current_player = 'O'
                self.ai_move()  # AI轮到下棋
           
    def ai_move(self):
        # AI使用Alpha-Beta剪枝来选择最优棋步
        best_score = float('-inf')
        best_move = None
        for row in range(self.size):
            for col in range(self.size):
                if self.board[row][col] == '':
                    self.board[row][col] = 'O'
                    score = self.alpha_beta(3, float('-inf'), float('inf'), False)  # 深度3    
                    self.board[row][col] = ''
                    if score > best_score:
                        best_score = score
                        best_move = (row, col)
        
        if best_move:
            row, col = best_move
            self.board[row][col] = 'O'
            self.buttons[row][col].config(text='O')
            if self.check_winner(row, col):
                messagebox.showinfo("游戏结束", "AI 胜利!")
                self.reset_game()
            else:
                self.current_player = 'X'  # 玩家轮到下棋
           
    def alpha_beta(self, depth, alpha, beta, is_maximizing):
        if depth == 0 or self.is_game_over():
            return self.evaluate_board()
           
        if is_maximizing:
            max_score = float('-inf')    
            for row in range(self.size):
                for col in range(self.size):
                    if self.board[row][col] == '':
                        self.board[row][col] = 'O'
                        score = self.alpha_beta(depth-1, alpha, beta, False)
                        self.board[row][col] = ''
                        max_score = max(max_score, score)
                        alpha = max(alpha, score)
                        if beta <= alpha:
                            break
            return max_score
        else:
            min_score = float('inf')
            for row in range(self.size):
                for col in range(self.size):
                    if self.board[row][col] == '':
                        self.board[row][col] = 'X'
                        score = self.alpha_beta(depth-1, alpha, beta, True)
                        self.board[row][col] = ''
                        min_score = min(min_score, score)    
                        beta = min(beta, score)
                        if beta <= alpha:
                            break
            return min_score
           
    def evaluate_board(self):
        # 简单的评估函数,评估当前棋盘的状态
        # 返回一个分数,越大代表对AI越有利,越小代表对玩家越有利
        score = 0
        for row in range(self.size):
            for col in range(self.size):
                if self.board[row][col] == 'O':
                    score += self.evaluate_position(row, col)
                elif self.board[row][col] == 'X':
                    score -= self.evaluate_position(row, col)
        return score
           
    def evaluate_position(self, row, col):
        # 评估某一位置的得分,可以基于棋盘的周围状态进行设计
        score = 0
        # 这里是一个简单的评分策略,实际中可以根据连子数等进行改进
        for delta_row, delta_col in [(1, 0), (0, 1), (1, 1), (1, -1)]:    
            count = 1
            for i in range(1, 5):
                new_row, new_col = row + delta_row * i, col + delta_col * i
                if 0 <= new_row < self.size and 0 <= new_col < self.size:
                    if self.board[new_row][new_col] == 'O':
                        count += 1
                    elif self.board[new_row][new_col] == 'X':
                        break
                else:
                    break
            score += count
        return score
           
    def is_game_over(self):
        # 检查游戏是否结束
        for row in range(self.size):
            for col in range(self.size):
                if self.board[row][col] == '' and (self.check_winner(row, col)):
                    return True
        return False
               
    def check_winner(self, row, col):
        # 检查是否有五子连珠
        return (self.check_direction(row, col, 1, 0) or  # 水平
                self.check_direction(row, col, 0, 1) or  # 垂直
                self.check_direction(row, col, 1, 1) or  # 右下对角线
                self.check_direction(row, col, 1, -1))   # 左下对角线
           
    def check_direction(self, row, col, delta_row, delta_col):
        count = 1
        count += self.count_in_direction(row, col, delta_row, delta_col)
        count += self.count_in_direction(row, col, -delta_row, -delta_col)
        return count >= 5  # 检查是否有五个相同的棋子连成一线
           
    def count_in_direction(self, row, col, delta_row, delta_col):
        count = 0
        while 0 <= row < self.size and 0 <= col < self.size and self.board[row][col] == self.current_player:
            count += 1
            row += delta_row
            col += delta_col
        return count
               
    def reset_game(self):
        self.board = [['' for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'X'
        for row in range(self.size):
            for col in range(self.size):
                self.buttons[row][col].config(text='')
           
if __name__ == "__main__":
    root = tk.Tk()
    game = Gomoku(root)
    root.mainloop()

解释:

1.Alpha-Beta剪枝算法: 在alpha_beta函数中,AI通过递归地模拟棋盘上的所有可能走法,并在每个节点(棋盘状态)上评估分数。alpha和beta是用于剪枝的值,alpha表示当前已知的最佳选择(最大值),beta表示当前已知的最差选择(最小值)。如果beta <= alpha,则会剪掉该分支。

2.评估函数: evaluate_board是一个简单的评估函数,它会计算每个位置的得分,并根据棋盘上的棋子数量返回一个分数。你可以根据实际情况改进该评估函数,例如加入连子数、活三、冲四等棋局特征。

3.游戏逻辑

i.玩家('X')下棋后,AI('O')通过Alpha-Beta剪枝算法选择最佳位置并下棋。

ii.游戏结束时,如果有五子连珠则显示胜利消息。

后续扩展:

·评估函数改进:可以根据棋盘的具体情况设计更复杂的评估函数。

·算法优化:可以进一步优化Alpha-Beta剪枝的深度和评估函数。

希望这段代码能帮助你实现更智能的AI。如果有任何问题,随时告诉我!

仍旧修改

代码语言:javascript
代码运行次数:0
运行
复制
return count >= 5 

代码语言:javascript
代码运行次数:0
运行
复制
return count >= 7

速度特别慢

第四次询问

速度可否优化,死机了

第四次回答

Alpha-Beta剪枝时,计算量可能会很大,尤其是在棋盘较大或搜索深度较深的情况下。为了优化速度并避免程序卡死,可以考虑以下几种方法:

1.减少搜索深度:降低搜索深度可以显著减少计算量。虽然这可能会降低AI的棋力,但可以通过改进评估函数来弥补。

2.启发式搜索:在搜索过程中,优先考虑某些更有可能是好棋的走法。例如,优先考虑靠近已有棋子的空位。

3.缓存结果:使用记忆化技术(如Zobrist哈希)来缓存已经计算过的棋盘状态及其评估值,以避免重复计算。

4.多线程或异步计算:如果可能,可以将计算放在后台线程中进行,以避免阻塞主线程。

下面是一个优化后的版本,主要通过减少搜索深度和启发式搜索来提高速度:

代码语言:javascript
代码运行次数:0
运行
复制
import tkinter as tk
from tkinter import messagebox
import random
           
class Gomoku:
    def __init__(self, master):
        self.master = master
        self.master.title("五子棋")
        self.size = 15
        self.board = [['' for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'X'  # 玩家为 X,AI 为 O
        self.buttons = [[None for _ in range(self.size)] for _ in range(self.size)]
        self.create_board()
           
    def create_board(self):
        for row in range(self.size):
            for col in range(self.size):    
                button = tk.Button(self.master, text='', width=4, height=2,
                                   command=lambda r=row, c=col: self.make_move(r, c))
                button.grid(row=row, column=col)
                self.buttons[row][col] = button
           
    def make_move(self, row, col):
        if self.board[row][col] == '' and self.current_player == 'X':  # 只有玩家能下棋
            self.board[row][col] = self.current_player
            self.buttons[row][col].config(text=self.current_player)
            if self.check_winner(row, col):
                messagebox.showinfo("游戏结束", f"玩家 {self.current_player} 胜利!")
                self.reset_game()
            else:
                self.current_player = 'O'
                self.master.after(100, self.ai_move)  # 使用after方法异步调用AI
           
    def ai_move(self):    
        # AI使用Alpha-Beta剪枝来选择最优棋步
        best_score = float('-inf')
        best_move = None
        for row, col in self.get_possible_moves():
            self.board[row][col] = 'O'
            score = self.alpha_beta(2, float('-inf'), float('inf'), False)  # 深度2
            self.board[row][col] = ''
            if score > best_score:
                best_score = score
                best_move = (row, col)
        
        if best_move:
            row, col = best_move
            self.board[row][col] = 'O'
            self.buttons[row][col].config(text='O')
            if self.check_winner(row, col):
                messagebox.showinfo("游戏结束", "AI 胜利!")
                self.reset_game()
            else:
                self.current_player = 'X'  # 玩家轮到下棋
               
    def get_possible_moves(self):
        # 只考虑靠近已有棋子的空位
        possible_moves = []
        for row in range(self.size):
            for col in range(self.size):
                if self.board[row][col] == '':
                    if any(self.board[r][c] != '' for r in range(max(0, row-1), min(self.size, row+2))
                           for c in range(max(0, col-1), min(self.size, col+2))):
                        possible_moves.append((row, col))
        return possible_moves
           
    def alpha_beta(self, depth, alpha, beta, is_maximizing):
        if depth == 0 or self.is_game_over():
            return self.evaluate_board()
           
        if is_maximizing:
            max_score = float('-inf')
            for row, col in self.get_possible_moves():
                self.board[row][col] = 'O'
                score = self.alpha_beta(depth-1, alpha, beta, False)    
                self.board[row][col] = ''
                max_score = max(max_score, score)
                alpha = max(alpha, score)
                if beta <= alpha:
                    break
            return max_score
        else:
            min_score = float('inf')
            for row, col in self.get_possible_moves():
                self.board[row][col] = 'X'
                score = self.alpha_beta(depth-1, alpha, beta, True)
                self.board[row][col] = ''
                min_score = min(min_score, score)
                beta = min(beta, score)
                if beta <= alpha:
                    break
            return min_score
           
    def evaluate_board(self):
        # 简单的评估函数,评估当前棋盘的状态
        score = 0
        for row in range(self.size):    
            for col in range(self.size):
                if self.board[row][col] == 'O':
                    score += self.evaluate_position(row, col)
                elif self.board[row][col] == 'X':
                    score -= self.evaluate_position(row, col)
        return score
           
    def evaluate_position(self, row, col):
        # 评估某一位置的得分,可以基于棋盘的周围状态进行设计
        score = 0
        for delta_row, delta_col in [(1, 0), (0, 1), (1, 1), (1, -1)]:
            count = 1
            for i in range(1, 5):
                new_row, new_col = row + delta_row * i, col + delta_col * i
                if 0 <= new_row < self.size and 0 <= new_col < self.size:
                    if self.board[new_row][new_col] == 'O':
                        count += 1
                    elif self.board[new_row][new_col] == 'X':
                        break
                else:
                    break
            score += count    
        return score
           
    def is_game_over(self):
        # 检查游戏是否结束
        for row in range(self.size):
            for col in range(self.size):
                if self.board[row][col] == '' and (self.check_winner(row, col)):
                    return True
        return False
           
    def check_winner(self, row, col):
        # 检查是否有五子连珠
        return (self.check_direction(row, col, 1, 0) or  # 水平
                self.check_direction(row, col, 0, 1) or  # 垂直
                self.check_direction(row, col, 1, 1) or  # 右下对角线
                self.check_direction(row, col, 1, -1))   # 左下对角线
           
    def check_direction(self, row, col, delta_row, delta_col):
        count = 1
        count += self.count_in_direction(row, col, delta_row, delta_col)
        count += self.count_in_direction(row, col, -delta_row, -delta_col)    
        return count >= 7  # 检查是否有五个相同的棋子连成一线
           
    def count_in_direction(self, row, col, delta_row, delta_col):
        count = 0
        while 0 <= row < self.size and 0 <= col < self.size and self.board[row][col] == self.current_player:
            count += 1
            row += delta_row
            col += delta_col
        return count
           
    def reset_game(self):
        self.board = [['' for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'X'
        for row in range(self.size):
            for col in range(self.size):
                self.buttons[row][col].config(text='')
           
if __name__ == "__main__":
    root = tk.Tk()
    game = Gomoku(root)
    root.mainloop()    

优化说明:

减少搜索深度:将搜索深度减少到2。虽然这会降低AI的棋力,但可以显著提高速度。可以根据需要调整深度。

启发式搜索:get_possible_moves函数只返回靠近已有棋子的空位,减少了需要考虑的可能走法数量。

异步调用AI:使用self.master.after(100, self.ai_move)来异步调用AI的下棋逻辑,避免阻塞主线程。

这些优化可以帮助提高程序的响应速度。如果需要更高的AI棋力,可以逐步增加搜索深度或改进评估函数。希望这些改进能帮助你实现更流畅的游戏体验!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档