鱼C论坛

 找回密码
 立即注册
查看: 136|回复: 6

[技术交流] 五子棋人机对战

[复制链接]
发表于 2025-1-18 21:05:32 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
用python cocos2d写的五子棋人机对战。
import cocos
from cocos import draw
from cocos.scene import Scene
from cocos.director import director
from cocos.particle_systems import Fireworks
from pyglet.gl import *
import pyglet

SIZE = 40
WIDTH = SIZE*15
HEIGHT = SIZE*15
N = '0'
W = 'w'
B = 'b'
S = '0'
cdata=[
       [N,N,N,S,B],[B,S,N,N,N],[N,N,N,S,B],[N,B,S,N,N],
       [N,N,S,B,N],[N,N,B,S,N],[N,N,N,S,W],[W,S,N,N,N],
       [N,N,N,S,W],[N,W,S,N,N],[N,N,S,W,N],[N,N,W,S,N],
       [B,B,S,N,N],[N,N,S,B,B],[B,S,B,N,N],[N,N,B,S,B],
       [N,B,S,B,N],[N,B,B,S,N],[N,S,B,B,N],[W,W,S,N,N],
       [N,N,S,W,W],[W,S,W,N,N],[N,N,W,S,W],[N,W,S,W,N],
       [N,W,W,S,N],[N,S,W,W,N],
       [N,S,B,B,B],[B,B,B,S,N],[N,B,B,B,S],[N,B,S,B,B],
       [B,B,S,B,N],[N,S,W,W,W],[W,W,W,S,N],[N,W,W,W,S],
       [N,W,S,W,W],[W,W,S,W,N],
       [S,B,B,B,B],[B,S,B,B,B],[B,B,S,B,B],[B,B,B,S,B],
       [B,B,B,B,S],[S,W,W,W,W],[W,S,W,W,W],[W,W,S,W,W],
       [W,W,W,S,W],[W,W,W,W,S]]
AI_x = -1
AI_y = -1
max_level = -1
board = [['0' for i in range(15)] for j in range(15)]
turn = 'b'
last_turn = 'w'

class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
        super().__init__(245, 214, 122, 255)
        cocos.layer.Layer.is_event_handler = True
        self.label1 = cocos.text.Label('你赢了!', font_name='kaiti', font_size=100, color=(255, 0, 0, 255),
                                      anchor_x="center", anchor_y="center")
        self.label1.position = (300, 300)

        self.label2 = cocos.text.Label('电脑赢了!', font_name='kaiti', font_size=95, color=(255, 0, 0, 255),
                                       anchor_x="center", anchor_y="center")
        self.label2.position = (300, 300)

        for i in range(0, 15):
            line1 = draw.Line((20, SIZE*i+20), (580, SIZE*i+20), (0, 0, 0, 255), 1)
            self.add(line1)
            line2 = draw.Line((SIZE*i+20, 20), (SIZE*i+20, 580), (0, 0, 0, 255), 1)
            self.add(line2)

    def change_side(self):
        global turn
        if turn == 'b':
            turn = 'w'
        else:
            turn = 'b'

    def check_win(self):
        a = turn
        for i in range(11):
            for j in range(11):
                if board[i][j] == a and board[i + 1][j + 1] == a and board[i + 2][j + 2] == a \
                        and board[i + 3][j + 3] == a and board[i + 4][j + 4] == a:
                    return True
        for i in range(11):
            for j in range(4, 15):
                if board[i][j] == a and board[i + 1][j - 1] == a and board[i + 2][j - 2] == a \
                        and board[i + 3][j - 3] == a and board[i + 4][j - 4] == a:
                    return True
        for i in range(15):
            for j in range(11):
                if board[i][j] == a and board[i][j + 1] == a and board[i][j + 2] == a \
                        and board[i][j + 3] == a and board[i][j + 4] == a:
                    return True
        for i in range(11):
            for j in range(15):
                if board[i][j] == a and board[i + 1][j] == a and board[i + 2][j] == a \
                        and board[i + 3][j] == a and board[i + 4][j] == a:
                    return True
        return False

    def on_mouse_press(self, x, y, button, _):
        global turn, AI_x, AI_y
        if button == pyglet.window.mouse.LEFT:
            x = round((x - 20) / SIZE)
            y = round((y - 20) / SIZE)
            if turn == 'b':
                if board[y][x] != '0':
                    return None
                elif x < 0 or y < 0 or x > 14 or y > 14:
                    return None
                blk0 = cocos.sprite.Sprite('black.png')
                blk0.position = (SIZE * x + 20, SIZE * y + 20)
                self.add(blk0)
                board[y][x] = 'b'
                if self.check_win():
                    self.add(self.label1)
                    width, height = director.get_window_size()
                    pe = Fireworks()
                    pe.position = (width // 2, 80)
                    pe.duration = 6
                    pe.speed = 260
                    pe.size = 10.0
                    pe.auto_remove_on_finish = True
                    self.add(pe)
                    director.window.remove_handlers(self)
                self.change_side()

                self.AI_play()
                wht0 = cocos.sprite.Sprite('white.png')
                wht0.position = (SIZE * AI_x + 20, SIZE * AI_y + 20)
                self.add(wht0)
                wht0.do(cocos.actions.Blink(2, 0.5))
                if self.check_win():
                    self.add(self.label2)
                    director.window.remove_handlers(self)
                self.change_side()

    def AI_play(self):
        global AI_x, AI_y, max_level
        AI_x = -1
        AI_y = -1
        max_level = -1

        for y in range(15):
            for x in range(15):
                for level in range(len(cdata) - 1, -1, -1):
                    if level <= max_level:
                        break
                    if x + 4 < 15:
                        if self.auto_match(x, y, level, 1, 0):
                            break
                    if y + 4 < 15:
                        if self.auto_match(x, y,  level, 0, 1):
                            break
                    if x - 4 >= 0 and y + 4 < 15:
                        if self.auto_match(x, y,  level, -1, 1):
                            break
                    if x + 4 < 15 and y + 4 < 15:
                        if self.auto_match(x, y,  level, 1, 1):
                            break
        if AI_x != -1 and AI_y != -1:
            if board[AI_y][AI_x] != '0':
                return None
            else:
                board[AI_y][AI_x] = 'w'
                return True

    def auto_match(self, x, y, level, dx, dy):
        global AI_x, AI_y, max_level
        x_sel = -1
        y_sel = -1
        isfind = True
        for j in range(5):
            cs = board[y + j * dy][x + j * dx]
            if cs == '0':
                if cdata[level][j] == S:
                    x_sel = x + j * dx
                    y_sel = y + j * dy
                elif cdata[level][j] != '0':
                    isfind = False
                    break

            elif cs == 'b' and cdata[level][j] != 'b':
                isfind = False
                break
            elif cs == 'w' and cdata[level][j] != 'w':
                isfind = False
                break

        if isfind:
            max_level = level
            AI_x = x_sel
            AI_y = y_sel
            return True
        return False

director.init(WIDTH, HEIGHT, caption="五子棋")
display = director.window.display
screen_width, screen_height = display.get_default_screen().width, display.get_default_screen().height
window_x = (screen_width - WIDTH) // 2
window_y = (screen_height - HEIGHT) // 2
director.window.set_location(window_x, window_y)
mainscene = Scene()
mainscene.add(GameLayer(), z=1)
director.run(mainscene)
black.png
white.png

点评

我很赞同!: 5.0
我很赞同!: 5
太好了!  发表于 2025-1-19 10:02

评分

参与人数 4荣誉 +18 鱼币 +11 贡献 +12 收起 理由
liuhongrun2022 + 5 + 3
foxiangzun + 5 + 5 + 3
zhangjinxuan + 6 + 3 + 3 鱼C有你更精彩^_^
不二如是 + 2 + 3 + 3 鱼C有你更精彩^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-1-18 21:09:27 | 显示全部楼层
加油
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-1-18 21:11:52 | 显示全部楼层
支持
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-1-18 23:12:54 | 显示全部楼层
厉害了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-1-19 10:00:48 | 显示全部楼层
厉害!

点评

发表于 2025-1-19 10:01
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-2-24 02:02

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表