战就战——与AI对弈五子棋,真的打不过

棋盘即战场,黑白双色如阴阳激荡!此刻,人类智慧与人工智能的史诗对决轰然展开。指尖悬停的刹那,血脉奔涌如江河咆哮——这是跨越千年的谋略传承与算法洪流的正面对撞!每一步落子皆是灵感的惊雷,每一轮攻防都是思维的核爆。AI的算力如银河倾泻,而人类以直觉为刃,以韧性为盾,在精密代码的围剿中劈开血色黎明。纵使败局已定,那永不屈服的瞳孔仍将点燃文明的火种:机器可计算亿万可能,却算不透人类以凡躯比肩神明的孤勇!此战无关胜负,唯见灵魂在钢铁森林中迸射的光芒,永恒闪耀于星辰之间。

文章目录

一、游戏界面预览

二、游戏制作框架

1. 采用Python语言

2. 游戏功能介绍

3.具体实现步骤

三、AI的策略说明

四、完整代码

五、结论——AI很强大

一、游戏界面预览

二、游戏制作框架

1. 采用Python语言

只引入 tkinter 、messagebox两个库,没有引入pygame,我们自己定义AI的实现方法使他更智能,对弈时更难以取胜。

2. 游戏功能介绍

1. 玩家点击棋盘落黑子
2. AI会自动响应落白子
3. 实时显示当前步数和胜负统计
4. 支持"新游戏"按钮重置对局
5. AI具有基本的攻防判断能力
6. 自动判断五连胜利

运行后会出现一个25x25的五子棋棋盘,玩家可以点击棋盘进行对弈,AI会自动响应。当有一方五连时会出现胜利提示,可以通过"新游戏"按钮随时开始新对局。

3.具体实现步骤

1)创建主窗口和Canvas:设置窗口大小为800x800左右,Canvas用于绘制棋盘和棋子。棋盘线间隔30像素,25条线,总长度24*30=720,所以棋盘区域可能从(40,40)开始,留出边距,或者调整格子大小。或者计算合适的起始位置,使得棋盘居中。

2)棋盘绘制:使用循环绘制横线和竖线,间隔30像素,共25行25列。

3)处理鼠标点击:绑定Canvas的鼠标点击事件。将鼠标的x,y坐标转换为棋盘的行列索引。检查该位置是否为空,如果是,放置黑子,更新数组,绘制黑子。

4)调用AI函数,让AI下白子。AI逻辑:遍历所有空位,计算每个位置的得分。选择得分最高的位置下子。得分计算包括进攻和防守因素。

5)胜负判断:每次落子后,检查该位置是否形成五连。如果有,游戏结束,显示结果。新游戏按钮:创建按钮,点击时重置棋盘数组,清空Canvas上的棋子,重置步数和比分。

6)显示步数和比分:使用Label组件显示当前步数,黑子和白子的胜利次数。

三、AI的策略说明

1. 首先给不同的棋型赋予不同的分数:

连五:100000分(直接胜利)
活四:10000分
冲四:1000分
活三:1000分
眠三:100分
活二:100分
眠二:10分

2. 评估函数evaluate_position 对于AI下白子时,计算该位置的白子连击情况,同时也要计算如果玩家下黑子在该位置的连击情况,防守分是后者的评分。总分为进攻分+防守分*权重

ai_move函数中的评分逻辑:

score_attack = self.evaluate_position(row, col, 2) # AI下白子的得分

score_defend = self.evaluate_position(row, col, 1) # 玩家下黑子的得分,

需要防守 total_score = score_attack + score_defend * 1.2 # 防守权重更高

这样,AI会优先防守玩家的高威胁位置,同时寻找自己的进攻机会。

3. 为了提高AI的智能,选择每一步的下法都有相对应的评分。

在evaluate_position函数中,可以针对给定的颜色,评估在该位置下子后的得分。例如,检查四个方向,计算每个方向的连续棋子数,并根据情况加分。

例如,对于某个方向,如果连续有四个同色棋子,且两端为空,则是活四,得分很高。如果连续四个,但一端被堵,则是冲四,得分次之。

实现逻辑:在评估某个方向时,除了统计连续的同色棋子数,还要检查两端的情况。

例如,在某个方向的正方向和反方向延伸,统计连续的同色棋子数,并检查延伸后的下一个位置是否为空或被对方堵住。

evaluate_position函数:

def evaluate_position(self, row, col, color): score = 0 directions = [(0,1), (1,0), (1,1), (1,-1)] for dx, dy in directions:

# 检查正方向 consecutive = 1 block = 0 x, y = row + dx, col + dy while 0 <= x < self.board_size and 0 <= y < self.board_size: if self.chess_board[x][y] == color: consecutive +=1 else: if self.chess_board[x][y] != 0: block +=1 break x += dx y += dy

# 检查反方向 x, y = row - dx, col - dy while 0 <= x < self.board_size and 0 <= y < self.board_size: if self.chess_board[x][y] == color: consecutive +=1 else: if self.chess_board[x][y] !=0: block +=1 break x -= dx y -= dy

# 根据连续数和block数来评分 if consecutive >=5: score += 100000 else: if consecutive ==4: if block ==0: score += 10000 # 活四 elif block ==1: score += 1000 # 冲四 elif consecutive ==3: if block ==0: score += 1000 # 活三 elif block ==1: score += 200 # 眠三 elif consecutive ==2: if block ==0: score += 100 # 活二 elif block ==1: score += 50 # 眠二 elif consecutive ==1: score +=10 return score

这样,当连续的同色棋子数为4,且没有被堵住(block=0),则视为活四,得分高。如果被堵住一端(block=1),则是冲四,得分次之。

同样,对于其他数量的连续棋子,根据block的情况赋予不同的分数。

这样,AI在评估时会优先形成活四、冲四等高威胁棋型,同时防守对方的类似棋型。

最后需AI会确保不会下在已经有棋子的位置,并且优先选择得分高的位置。

四、完整代码

import tkinter as tk
from tkinter import messagebox


class Gobang:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("五子棋人机对战")
        self.board_size = 25
        self.cell_size = 28
        self.offset = 30
        self.win_size = self.offset * 2 + (self.board_size - 1) * self.cell_size

        # 初始化游戏数据
        self.chess_board = [[0] * self.board_size for _ in range(self.board_size)]
        self.current_player = 1  # 1: 玩家(黑棋), 2: AI(白棋)
        self.game_over = False
        self.steps = 0
        self.black_wins = 0
        self.white_wins = 0

        # 创建界面
        self.create_widgets()
        self.draw_board()
        self.root.mainloop()

    def create_widgets(self):
        # 创建画布
        self.canvas = tk.Canvas(self.root, width=self.win_size, height=self.win_size, bg="#CDBA96")
        self.canvas.pack(padx=10, pady=10)

        # 信息面板
        info_frame = tk.Frame(self.root)
        info_frame.pack(fill=tk.X, padx=10, pady=5)

        self.step_label = tk.Label(info_frame, text=f"步数: {self.steps}")
        self.step_label.pack(side=tk.LEFT)

        self.score_label = tk.Label(info_frame,
                                    text=f"黑方胜: {self.black_wins}  白方胜: {self.white_wins}")
        self.score_label.pack(side=tk.RIGHT)

        # 控制按钮
        ctrl_frame = tk.Frame(self.root)
        ctrl_frame.pack(padx=10, pady=5)
        tk.Button(ctrl_frame, text="新游戏", command=self.new_game).pack()

        # 绑定事件
        self.canvas.bind("<Button-1>", self.human_play)

    def draw_board(self):
        """绘制棋盘"""
        for i in range(self.board_size):
            x = self.offset + i * self.cell_size
            self.canvas.create_line(x, self.offset,
                                    x, self.win_size - self.offset)
            self.canvas.create_line(self.offset, x,
                                    self.win_size - self.offset, x)

    def human_play(self, event):
        """玩家下棋"""
        if self.game_over or self.current_player != 1:
            return

        # 计算落子位置(修正坐标计算)
        x = (event.x - self.offset + self.cell_size // 2) // self.cell_size
        y = (event.y - self.offset + self.cell_size // 2) // self.cell_size

        if 0 <= x < self.board_size and 0 <= y < self.board_size:
            if self.chess_board[y][x] == 0:
                self.place_chess(y, x, 1)
                if self.check_win(y, x, 1):
                    self.game_over = True
                    self.black_wins += 1
                    messagebox.showinfo("游戏结束", "黑方获胜!")
                else:
                    self.current_player = 2
                    self.steps += 1
                    self.update_info()
                    self.root.after(200, self.ai_play)

    def ai_play(self):
        """AI下棋"""
        if self.game_over:
            return

        # 寻找最佳位置
        best_score = -1
        best_pos = None

        for y in range(self.board_size):
            for x in range(self.board_size):
                if self.chess_board[y][x] == 0:
                    attack_score = self.evaluate_position(y, x, 2)
                    defend_score = self.evaluate_position(y, x, 1)
                    total_score = attack_score + defend_score * 1.2

                    if total_score > best_score or (total_score == best_score and best_pos is None):
                        best_score = total_score
                        best_pos = (y, x)

        if best_pos:
            y, x = best_pos
            self.place_chess(y, x, 2)
            if self.check_win(y, x, 2):
                self.game_over = True
                self.white_wins += 1
                messagebox.showinfo("游戏结束", "白方获胜!")
            else:
                self.current_player = 1
                self.steps += 1
                self.update_info()

    def evaluate_position(self, y, x, color):
        """评估位置得分"""
        directions = [(0, 1), (1, 0), (1, 1), (1, -1)]
        total_score = 0

        for dy, dx in directions:
            score = 0
            consecutive = 1
            blocks = 0
            open_ends = 0

            # 正方向检查
            ny, nx = y + dy, x + dx
            while 0 <= ny < self.board_size and 0 <= nx < self.board_size:
                if self.chess_board[ny][nx] == color:
                    consecutive += 1
                else:
                    if self.chess_board[ny][nx] == 0:
                        open_ends += 1
                    else:
                        blocks += 1
                    break
                ny += dy
                nx += dx

            # 反方向检查
            ny, nx = y - dy, x - dx
            while 0 <= ny < self.board_size and 0 <= nx < self.board_size:
                if self.chess_board[ny][nx] == color:
                    consecutive += 1
                else:
                    if self.chess_board[ny][nx] == 0:
                        open_ends += 1
                    else:
                        blocks += 1
                    break
                ny -= dy
                nx -= dx

            # 评分逻辑
            if consecutive >= 5:
                score += 100000
            else:
                if consecutive == 4:
                    if open_ends > 0:
                        score += 10000 if blocks == 0 else 1000
                elif consecutive == 3:
                    if open_ends > 0:
                        score += 1000 if blocks == 0 else 200
                elif consecutive == 2:
                    if open_ends > 0:
                        score += 200 if blocks == 0 else 50
                elif consecutive == 1:
                    score += 10

                if open_ends == 2 and consecutive >= 3:
                    score *= 2

            total_score += score

        return total_score

    def place_chess(self, y, x, color):
        """在棋盘上放置棋子"""
        self.chess_board[y][x] = color
        cx = self.offset + x * self.cell_size
        cy = self.offset + y * self.cell_size
        self.canvas.create_oval(cx - 12, cy - 12, cx + 12, cy + 12,
                                fill="black" if color == 1 else "white",
                                outline="black")

    def check_win(self, y, x, color):
        """检查是否获胜(完整实现)"""
        directions = [(0, 1), (1, 0), (1, 1), (1, -1)]
        for dy, dx in directions:
            count = 1
            # 向正方向检查
            ny, nx = y + dy, x + dx
            while 0 <= ny < self.board_size and 0 <= nx < self.board_size:
                if self.chess_board[ny][nx] == color:
                    count += 1
                    ny += dy
                    nx += dx
                else:
                    break
            # 向反方向检查
            ny, nx = y - dy, x - dx
            while 0 <= ny < self.board_size and 0 <= nx < self.board_size:
                if self.chess_board[ny][nx] == color:
                    count += 1
                    ny -= dy
                    nx -= dx
                else:
                    break
            if count >= 5:
                return True
        return False

    def update_info(self):
        """更新信息显示"""
        self.step_label.config(text=f"步数: {self.steps}")
        self.score_label.config(text=f"黑方胜: {self.black_wins}  白方胜: {self.white_wins}")

    def new_game(self):
        """开始新游戏"""
        self.canvas.delete("all")
        self.chess_board = [[0] * self.board_size for _ in range(self.board_size)]
        self.current_player = 1
        self.game_over = False
        self.steps = 0
        self.draw_board()
        self.update_info()


if __name__ == "__main__":
    Gobang()

五、结论——AI很强大

和AI打了几把,发现很难取胜,一不留神就输给他了,不信的话大家可以自己尝试挑战下!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穿梭的编织者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值