zhangjinxuan 发表于 2023-5-25 18:44:48

用 Python 的 tkinter 做一个简单的五子棋

本帖最后由 zhangjinxuan 于 2023-7-18 23:01 编辑

程序实现

两个人互相下棋子,看谁的棋子先连成5连方,谁就获胜

思路

打算使用 tkinter。

使用二维数组存储棋盘,每一个格子都是一个 button,这个 button 都有对应的指令和 string

并且定义函数 ckeck, draw, back, init , check 位判断是否有玩家获胜,draw 为将本位置改为对应的棋子(直接修改 string),back 为悔棋,init 为初始化。

代码
from tkinter import *
from tkinter.messagebox import *
from threading import Thread as ths
import sys,time

buttons = [ for j in range(18)]
strings = [ for j in range(18)] #对应的字符串
command = [ for j in range(18)]
now_type = 0
last_opts = []
tot = -1
window = Tk()
window.resizable(False, False)
window.geometry("800x600+100+120")
window.title("五子棋——tkinter")
huiqi_state = StringVar(window, "")
white_win = 0
black_win = 0
state = StringVar(window, "")
def clear():
    for i in range(15):
      for j in range(15):
            x = i * 30 + 40
            y = j * 30 + 70
            buttons.destroy()
            buttons = Button(window, bg = "orange", textvariable = strings, state = 'disabled')
            buttons.place(x = x, y = y, width = 30, height = 30)
def check():
    for i in range(15):
      for j in range(15):
            if i + 4 < 15:
                if strings.get() == strings.get() == strings.get() == strings.get() == strings.get():
                  if strings.get() == '':
                        continue
                  clear()
                  if strings.get() == 'X':
                        showinfo("获胜提示", "黑子获胜")
                  else:
                        showinfo("获胜提示", "白子获胜")
                  for k in range(5):
                        x = (i + k) * 30 + 40
                        y = j * 30 + 70
                        buttons.destroy()
                        buttons = Button(window, bg = "red", textvariable = strings, state = 'disabled')
                        buttons.place(x = x, y = y, width = 30, height = 30)
                  state.set("游戏结束")
                  return
            if j + 4 < 15:
                if strings.get() == strings.get() == strings.get() == strings.get() == strings.get():
                  if strings.get() == '':
                        continue
                  clear()
                  if strings.get() == 'X':
                        showinfo("获胜提示", "黑子获胜")
                  else:
                        showinfo("获胜提示", "白子获胜")
                  for k in range(5):
                        x = i * 30 + 40
                        y = (j + k) * 30 + 70
                        buttons.destroy()
                        buttons = Button(window, bg = "red", textvariable = strings, state = 'disabled')
                        buttons.place(x = x, y = y, width = 30, height = 30)
                  state.set("游戏结束")
                  return
            if j + 4 < 15 and i + 4 < 15:
                if strings.get() == strings.get() == strings.get() == strings.get() == strings.get():
                  if strings.get() == '':
                        continue
                  clear()
                  if strings.get() == 'X':
                        showinfo("获胜提示", "黑子获胜")
                  else:
                        showinfo("获胜提示", "白子获胜")
                  for k in range(5):
                        x = (i + k) * 30 + 40
                        y = (j + k) * 30 + 70
                        buttons.destroy()
                        buttons = Button(window, bg = "red", textvariable = strings, state = 'disabled')
                        buttons.place(x = x, y = y, width = 30, height = 30)
                  state.set("游戏结束")
                  return
            if j + 4 < 15 and i - 4 >= 0:
                if strings.get() == strings.get() == strings.get() == strings.get() == strings.get():
                  if strings.get() == '':
                        continue
                  clear()
                  if strings.get() == 'X':
                        showinfo("获胜提示", "黑子获胜")
                  else:
                        showinfo("获胜提示", "白子获胜")
                  for k in range(5):
                        x = (i - k) * 30 + 40
                        y = (j + k) * 30 + 70
                        buttons.destroy()
                        buttons = Button(window, bg = "red", textvariable = strings, state = 'disabled')
                        buttons.place(x = x, y = y, width = 30, height = 30)
                  state.set("游戏结束")
                  return
def draw(x, y):
    global now_type, window, buttons, strings, commands, tot
    if now_type == 0:
      strings.set("X")
      now_type = 1
      state.set("请白手落子")
    else:
      strings.set("O")
      now_type = 0
      state.set("请黑手落子")
    buttons.destroy()
    buttons = Button(window, textvariable = strings, bg = "orange", fg = "white" if now_type == 0 else "black")
    buttons.place(x = x * 30 + 40, y = y * 30 + 70, width = 30, height = 30)
    tot += 1
    last_opts.append((x, y))
    huiqi_state.set(f"")
    check()
def back():
    if state.get() == "游戏结束":
      return
    global now_type, window, buttons, strings, commands, tot, huiqi_state
    if tot == -1:
      huiqi_state.set(f"无效悔棋。")
      return
    x = last_opts
    y = last_opts
    if now_type == 1:
      strings = StringVar(window, "")
      now_type = 0
      state.set("请黑手落子")
    else:
      state.set("请白手落子")
      strings = StringVar(window, "")
      now_type = 1
    buttons.destroy()
    buttons = Button(window, textvariable = strings, command = command, bg = "orange")
    buttons.place(x = x * 30 + 40, y = y * 30 + 70, width = 30, height = 30)
    huiqi_state.set(f"已撤销 {'白子' if now_type == 1 else '黑子'} \n 在 ({x}, {y}) 的操作。")
    tot -= 1
    last_opts.pop()
def init():
    global tot, now_type, last_opts
    tot = -1
    now_type = 0
    state.set("请黑手落子")
    huiqi_state = StringVar(window, "")
    last_opts = []
    for i in range(15):
      for j in range(15):
            strings = StringVar(window, "")
            x = i * 30 + 40
            y = j * 30 + 70
            if buttons != None:
                buttons.destroy()
            buttons = Button(window, bg = "orange", textvariable = strings, command = command)
            buttons.place(x = x, y = y, width = 30, height = 30)
def main():
    global now_type, window, buttons, strings, commands
    Label(window, text = "五子棋", font = ('等线', 20)).place(x = 350, y = 20)
    Label(window, textvariable = huiqi_state, font = ('等线', 13)).place(x = 630, y = 500)
    Button(window, text = "悔棋", command = back).place(x = 550, y = 500, width = 70, height = 40)
    Button(window, text = "重置", command = init).place(x = 550, y = 400, width = 70, height = 40)
    Label(window, textvariable = state, font = ('等线', 14)).place(x = 550, y = 300)
    init()
    Label(window, textvariable = huiqi_state, font = ('等线', 13)).place(x = 630, y = 500)
main()
mainloop()


本程序主要不是求得评分,而是为了狠狠地打 @sfqxx 的脸,整个代码创作的时间小于 3 小时,码量适中,165 行,大部分都是复制粘贴。

sfqxx,不服来战!

@歌者文明清理员 @元豪

sfqxx 发表于 2023-5-25 18:46:46

行,有空我拿你的来对比一下我的

看看谁打谁的脸?

sfqxx 发表于 2023-5-25 18:48:43

啊评错了

zhangjinxuan 发表于 2023-5-25 18:49:33

不是我不想做,而是这个太简单了。

zhangjinxuan 发表于 2023-5-25 18:51:30

sfqxx 发表于 2023-5-25 18:46
行,有空我拿你的来对比一下我的

看看谁打谁的脸?

你要更精美的界面,可以,但我不想做,这样的简易版就能满足很多要求了。

歌者文明清理员 发表于 2023-5-25 18:52:05

zhangjinxuan 发表于 2023-5-25 18:49
不是我不想做,而是这个太简单了。

巧了,我也在做五子棋(pygame)
元豪也在做{:10_277:},而且他也是pygame

zhangjinxuan 发表于 2023-5-25 18:52:32

sfqxx 发表于 2023-5-25 18:48
啊评错了

至少我还完成了与 歌者文明清理员 相同的挑战{:10_256:}

zhangjinxuan 发表于 2023-5-25 18:53:05

歌者文明清理员 发表于 2023-5-25 18:52
巧了,我也在做五子棋(pygame)
元豪也在做,而且他也是pygame

pygame 已经被我忘得一干二净{:10_250:}

歌者文明清理员 发表于 2023-5-25 18:53:33

zhangjinxuan 发表于 2023-5-25 18:53
pygame 已经被我忘得一干二净

https://fishc.com.cn/forum.php?mod=forumdisplay&fid=243&filter=typeid&typeid=605

zhangjinxuan 发表于 2023-5-25 18:53:36

歌者文明清理员 发表于 2023-5-25 18:52
巧了,我也在做五子棋(pygame)
元豪也在做,而且他也是pygame

主要是 tkinter 容易实现落子,就是一个按钮

歌者文明清理员 发表于 2023-5-25 18:54:12

zhangjinxuan 发表于 2023-5-25 18:53
主要是 tkinter 容易实现落子,就是一个按钮

pygame的按钮,棋子啥的都要自己做,比较好控制

sfqxx 发表于 2023-5-25 18:55:42

zhangjinxuan 发表于 2023-5-25 18:53
主要是 tkinter 容易实现落子,就是一个按钮

你有背景吗

zhangjinxuan 发表于 2023-5-25 18:57:23

sfqxx 发表于 2023-5-25 18:55
你有背景吗

纯色背景,你的还不是纯色背景

zhangjinxuan 发表于 2023-5-25 18:58:07

歌者文明清理员 发表于 2023-5-25 18:54
pygame的按钮,棋子啥的都要自己做,比较好控制

好主意{:10_256:}

可我只会 tkinter{:10_250:}

sfqxx 发表于 2023-5-25 18:58:25

怎么就不是纯色的呢?

zhangjinxuan 发表于 2023-5-25 18:59:09

歌者文明清理员 发表于 2023-5-25 18:53
https://fishc.com.cn/forum.php?mod=forumdisplay&fid=243&filter=typeid&typeid=605

可以供个参考{:10_275:}

但我搞竞赛,可惜竞赛不考 pygame{:10_266:}

歌者文明清理员 发表于 2023-5-25 19:02:49

zhangjinxuan 发表于 2023-5-25 18:59
可以供个参考

但我搞竞赛,可惜竞赛不考 pygame

没事啦,我也要更pygame教程了https://fishc.com.cn/thread-228565-1-1.html

zhangjinxuan 发表于 2023-5-25 19:04:06

本帖最后由 zhangjinxuan 于 2023-5-25 19:08 编辑

sfqxx 发表于 2023-5-25 18:58
怎么就不是纯色的呢?

都是纯色啊,你是橘色,我是灰色。

我的程序有以下优势:

1. 不受界面限制,scratch 界面受限,tkinter 界面几乎不受限制,这就可以让我的程序空间发挥更大。
2. 界面简洁,有直观的文字提示;
3. 可以直接重置棋盘,对局结束无需重新运行,直接一键重置‘
4. 有"谁获胜“了的提示,并且高亮连成 5 子的棋子。
5. 当场上无子,终止悔棋操作。

sfqxx 发表于 2023-5-25 19:13:21

zhangjinxuan 发表于 2023-5-25 19:04
都是纯色啊,你是橘色,我是灰色。

我的程序有以下优势:


不都一样吗?第3条比较多余

直接点绿旗

zhangjinxuan 发表于 2023-5-25 19:15:14

sfqxx 发表于 2023-5-25 19:13
不都一样吗?第3条比较多余

直接点绿旗

点绿棋还不是相当于重新开始程序?

重新开始的话就无法统计获胜的次数,我这样就可以很好实现,只不过懒{:10_250:}

这样,说程序优势没意义,只能说语言优势。
页: [1] 2
查看完整版本: 用 Python 的 tkinter 做一个简单的五子棋