python tkinter实现一个五子棋棋盘

实现一个无限大小的五子棋棋盘

主要思想:创建GlobalGame类,完成大部分操作。使用tkinter进行灵活的布局

完整代码:

import tkinter


class GlobalGame:

    def __init__(self, in_canvas: tkinter.Canvas, call_back, update_back):
        self._in_canvas = in_canvas
        self._call_back = call_back
        self._update_back = update_back
        self._width = 17
        self._elements = []
        self._now_player = -1  # -1为黑,1为白
        self._datas: dict = {(0, 0): None}
        self._step_datas: list = []
        self._coord = [0, 0]
        self._update()

        # init drawing
        for i in range(1, self._width + 1):
            self._in_canvas.create_line(i * 30, 30, i * 30, 510, width=3, fill='#66593E')
            self._in_canvas.create_line(30, i * 30, 510, i * 30, width=3, fill='#66593E')

        # init event binding
        self._in_canvas.bind('<ButtonRelease-1>', self._cin)

    @property
    def now_player(self):
        return self._now_player

    def _cin(self, event):
        coord = self._real_to(event.x, event.y)
        # print(self.real_to(event.x, event.y))
        if self._datas.get(coord) is None:
            self._datas[coord] = self._now_player
            self._step_datas.append(coord)
            # print(coord)

            # 获胜判定
            last_times = 0
            for v, p in [(i, (coord[0] - i[0] * 4, coord[1] - i[1] * 4)) for i in ((1, 0), (1, 1), (0, 1), (-1, 1))]:
                last_times_t = 0
                for i in range(9):
                    # print(self._datas.get((p[0] + v[0] * i, p[1] + v[1] * i)))
                    if self._datas.get((p[0] + v[0] * i, p[1] + v[1] * i)) == self._now_player:
                        last_times_t += 1
                        last_times = max(last_times_t, last_times)
                    else:
                        last_times_t = 0
            # print(last_times)

            if last_times >= 5:
                self._call_back('{}棋获胜!!!\n'.format({-1: '黑', 1: '白'}[self._now_player]))
                self.clear()

            self._now_player *= -1
        else:
            self._call_back('此处有棋!\n')
        self._update()
        # print(self.datas)

    def get_output(self):
        pass

    def change_mod(self):
        pass

    def _to_real(self, ix, iy) -> tuple:
        if isinstance(ix, tuple):
            return (ix[0] - self._coord[0] + 9) * 30, (-ix[1] + self._coord[1] + 9) * 30
        else:
            return (ix - self._coord[0] + 9) * 30, (-iy + self._coord[1] + 9) * 30

    def _real_to(self, rx, ry) -> tuple:
        if isinstance(rx, tuple):
            return (round(rx[0] / 30) - 9 + self._coord[0]), -(round(rx[1] / 30) - 9 - self._coord[1])
        else:
            return (round(rx / 30) - 9 + self._coord[0]), -(round(ry / 30) - 9 - self._coord[1])

    def set_coord(self, x, y):
        if isinstance(x, (tuple, list)):
            self._coord[0] = x[0]
            self._coord[1] = x[1]
        else:
            self._coord[0] = x
            self._coord[1] = y
        self._update()

    def add_v_coord(self, dx, dy):
        if isinstance(dx, (tuple, list)):
            self._coord[0] += dx[0]
            self._coord[1] += dx[1]
        else:
            self._coord[0] += dx
            self._coord[1] += dy
        self._update()

    def undo(self):
        try:
            del self._datas[self._step_datas[-1]], self._step_datas[-1]
            self._now_player *= -1
            self._update()
        except IndexError:
            self._call_back('无棋子可撤销\n')

    def clear(self):
        self._datas = {(0, 0): None}
        self._step_datas = []
        self._update()
        self._call_back('已清空\n')
        self._now_player = -1

    def _update(self):
        self._update_back(self)
        for i in self._elements:
            cav.delete(i)
        w = self._width
        for ix, iy in tuple((i % w - 8 + self._coord[0], i // w - 8 + self._coord[1]) for i in range(w ** 2)):
            rc = self._to_real(ix, iy)
            if ix % 6 == 0 and iy % 6 == 0:
                # print(ix, iy)
                self._elements.append(self._in_canvas.create_oval(rc[0] - 5, rc[1] - 5, rc[0] + 5, rc[1] + 5,
                                                                  outline='#66593E', fill='#66593E'))
            if self._datas.get((ix, iy)):
                self._elements.append(self._in_canvas.create_oval(rc[0] - 9, rc[1] - 9, rc[0] + 9, rc[1] + 9,
                                                                  outline='#000000' if self._datas.get((ix, iy)) == -1 else '#FFFFFF',
                                                                  fill='#000000' if self._datas.get((ix, iy)) == -1 else '#FFFFFF'))
        ft = ('微软雅黑', 11)
        self._elements.append(self._in_canvas.create_text(30, 30, text='({}, {})'.format(self._coord[0] - 8, self._coord[1] + 8), font=ft, anchor='s'))
        self._elements.append(self._in_canvas.create_text(510, 30, text='({}, {})'.format(self._coord[0] + 8, self._coord[1] + 8), font=ft, anchor='s'))
        self._elements.append(self._in_canvas.create_text(30, 510, text='({}, {})'.format(self._coord[0] - 8, self._coord[1] - 8), font=ft, anchor='n'))
        self._elements.append(self._in_canvas.create_text(510, 510, text='({}, {})'.format(self._coord[0] + 8, self._coord[1] - 8), font=ft, anchor='n'))


def player_update(in_game: GlobalGame, in_lb: tkinter.Label):
    if in_game.now_player == -1:
        in_lb.config(foreground='#000000')
    else:
        in_lb.config(foreground='#FFFFFF')


if __name__ == '__main__':
    root = tkinter.Tk()
    root.title('五子棋棋盘')
    root.geometry('960x540')
    root.minsize(960, 540)  # 设置窗口最小值

    fr1 = tkinter.Frame(root, background='black', width=540)
    fr1.place(relx=0.0, rely=0.0, relwidth=0.5625, relheight=1.0)
    fr2 = tkinter.Frame(root, background='#A8975E')
    fr2.place(relx=0.5625, rely=0.0, relwidth=0.4375, relheight=1.0)

    cav = tkinter.Canvas(fr1, bg='#D6CD91', width=540, height=540)
    cav.pack(side=tkinter.TOP)

    fr21 = tkinter.Frame(fr2, background='#A8975E')
    fr21.pack(side=tkinter.BOTTOM, fill=tkinter.X)
    fr211 = tkinter.Frame(fr21, background='#A8975E', width=180, height=180)
    fr212 = tkinter.Frame(fr21, background='#A8975E', width=180, height=180)
    fr211.pack(side=tkinter.LEFT)
    fr212.pack(side=tkinter.RIGHT)
    lb = tkinter.Label(fr21, text='●', foreground='#000000', font=('微软雅黑', 60), background='#A8975E')
    lb.pack(expand=True)

    bt_n = tkinter.Button(fr211, text='↑', command=lambda: game.add_v_coord(0, 1))
    bt_ne = tkinter.Button(fr211, text='↗', command=lambda: game.add_v_coord(1, 1))
    bt_e = tkinter.Button(fr211, text='→', command=lambda: game.add_v_coord(1, 0))
    bt_se = tkinter.Button(fr211, text='↘', command=lambda: game.add_v_coord(1, -1))

    bt_s = tkinter.Button(fr211, text='↓', command=lambda: game.add_v_coord(0, -1))
    bt_sw = tkinter.Button(fr211, text='↙', command=lambda: game.add_v_coord(-1, -1))
    bt_w = tkinter.Button(fr211, text='←', command=lambda: game.add_v_coord(-1, 0))
    bt_nw = tkinter.Button(fr211, text='↖', command=lambda: game.add_v_coord(-1, 1))

    bt_n16 = tkinter.Button(fr211, text='↑x16', command=lambda: game.add_v_coord(0, 16))
    bt_ne16 = tkinter.Button(fr211, text='↗x16', command=lambda: game.add_v_coord(16, 16))
    bt_e16 = tkinter.Button(fr211, text='→x16', command=lambda: game.add_v_coord(16, 0))
    bt_se16 = tkinter.Button(fr211, text='↘x16', command=lambda: game.add_v_coord(16, -16))

    bt_s16 = tkinter.Button(fr211, text='↓x16', command=lambda: game.add_v_coord(0, -16))
    bt_sw16 = tkinter.Button(fr211, text='↙x16', command=lambda: game.add_v_coord(-16, -16))
    bt_w16 = tkinter.Button(fr211, text='←x16', command=lambda: game.add_v_coord(-16, 0))
    bt_nw16 = tkinter.Button(fr211, text='↖x16', command=lambda: game.add_v_coord(-16, 16))

    bt_n.place(relx=0.4, rely=0.2, relwidth=0.2, relheight=0.2)
    bt_ne.place(relx=0.6, rely=0.2, relwidth=0.2, relheight=0.2)
    bt_e.place(relx=0.6, rely=0.4, relwidth=0.2, relheight=0.2)
    bt_se.place(relx=0.6, rely=0.6, relwidth=0.2, relheight=0.2)

    bt_s.place(relx=0.4, rely=0.6, relwidth=0.2, relheight=0.2)
    bt_sw.place(relx=0.2, rely=0.6, relwidth=0.2, relheight=0.2)
    bt_w.place(relx=0.2, rely=0.4, relwidth=0.2, relheight=0.2)
    bt_nw.place(relx=0.2, rely=0.2, relwidth=0.2, relheight=0.2)

    bt_n16.place(relx=0.4, rely=0.0, relwidth=0.2, relheight=0.2)
    bt_ne16.place(relx=0.8, rely=0.0, relwidth=0.2, relheight=0.2)
    bt_e16.place(relx=0.8, rely=0.4, relwidth=0.2, relheight=0.2)
    bt_se16.place(relx=0.8, rely=0.8, relwidth=0.2, relheight=0.2)

    bt_s16.place(relx=0.4, rely=0.8, relwidth=0.2, relheight=0.2)
    bt_sw16.place(relx=0.0, rely=0.8, relwidth=0.2, relheight=0.2)
    bt_w16.place(relx=0.0, rely=0.4, relwidth=0.2, relheight=0.2)
    bt_nw16.place(relx=0.0, rely=0.0, relwidth=0.2, relheight=0.2)

    bt_mid = tkinter.Button(fr211, text='⊚', command=lambda: game.set_coord(0, 0))
    bt_mid.place(relx=0.4, rely=0.4, relwidth=0.2, relheight=0.2)

    bt_undo = tkinter.Button(fr212, text='撤销')
    bt_undo.place(relx=0.0, rely=0.0, relwidth=0.5, relheight=0.5)
    bt_clear = tkinter.Button(fr212, text='清空')
    bt_clear.place(relx=0.5, rely=0.0, relwidth=0.5, relheight=0.5)

    txt = tkinter.Text(fr2, font=('微软雅黑', 9))
    txt.pack(padx=30, pady=30)

    game = GlobalGame(cav, lambda x: txt.insert(0.0, x), lambda x: player_update(x, lb))

    bt_undo.config(command=game.undo)
    bt_clear.config(command=game.clear)

    root.mainloop()

奇怪的东西: 马云在不经意间这样说过,最大的挑战和突破在于用人,而用人最大的突破在于信任人。这启发了我, 我们一般认为,抓住了问题的关键,其他一切则会迎刃而解。 五子棋棋盘因何而发生?我们不得不面对一个非常尴尬的事实,那就是, 王阳明在不经意间这样说过,故立志者,为学之心也;为学者,立志之事也。这启发了我, 现在,解决五子棋棋盘的问题,是非常非常重要的。 所以, 经过上述讨论五子棋棋盘的发生,到底需要如何做到,不五子棋棋盘的发生,又会如何产生。 所谓五子棋棋盘,关键是五子棋棋盘需要如何写。 带着这些问题,我们来审视一下五子棋棋盘。 要想清楚,五子棋棋盘,到底是一种怎么样的存在。 既然如此, 五子棋棋盘因何而发生?现在,解决五子棋棋盘的问题,是非常非常重要的。 所以, 既然如何, 我们都知道,只要有意义,那么就必须慎重考虑。 五子棋棋盘,到底应该如何实现。 西班牙曾经说过,自知之明是最难得的知识。我希望诸位也能好好地体会这句话。
佛又曰:楞数输啰婆苏烁苏哆呼俱埵谨罚钵遮罚墀羯度醯穆楞迦唵南摩钵帝参沙悉舍埵楞伊度曳参输摩帝迦娑迦唎摩迦豆羯婆咩啰舍

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
tkinter 实现五子棋UI界面 import tkinter as tk from tkinter import messagebox from chessboard import ChessBoard ChessBoard = ChessBoard() class GUI(object): def __init__(self): self.counter = 0 self.winner = 0 self.is_start = False self.is_surrender = False self.window = tk.Tk() # 窗口对象(首字母大写) self.window.title('Gobang') self.window.geometry('800x540') self.window.resizable(width = False, height = False) # 画布对象 棋盘 self.canvas = tk.Canvas(self.window, height = 540, width = 540) self.chessboard = tk.PhotoImage(file = 'Gobang_chessboard/chessboard.gif') self.blackpoint = tk.PhotoImage(file = 'Gobang_chessboard/blackpoint.gif') self.whitepoint = tk.PhotoImage(file = 'Gobang_chessboard/whitepoint.gif') self.canvas.create_image(0, 0, anchor = 'nw', image = self.chessboard) self.canvas.bind("", self.get_point) self.start_point = 10 # 起始点位置 self.step = 35 # 每个格子的跨度 self.canvas.place(x = 0, y = 0) # 标签对象 self.l_info = tk.Label(self.window, text = 'Not started', font=('Arial', 12), width = 25, height = 2) self.l_info.place(x = 545, y = 0) # 文本框对象 self.t = tk.Text(self.window, height = 15) self.t.place(x = 540, y = 40) # 按钮对象 self.f_header = tk.Frame(self.window, highlightthickness=0) self.b_start = tk.Button(self.f_header, text = 'start', command = self.start) self.b_restart = tk.Button(self.f_header, text = 'restart', command = self.restart) self.b_regret = tk.Button(self.f_header, text = 'regret', command = self.regret) self.b_surrender = tk.Button(self.f_header, text = 'surrender', command = self.surrender) self.f_header.place(x = 545, y = 250) self.b_start.pack(side='left', padx=10) self.b_restart.pack(side = 'left') self.b_surrender.pack(side = 'right') self.b_regret.pac
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值