井字棋代码
1.1导入需要使用的包
import tkinter as tk
import tkinter.messagebox
1.2使用canvas组件画出九宫格
def draw_grid(canvas, width, height, line_color='black'):
# 计算每个格子的宽度高度
cell_width = width / 3
cell_height = height / 3
# 绘制垂直线
for i in range(3):
x = i * cell_width
canvas.create_line(x, 0, x, height, fill=line_color)
canvas.create_line(x + cell_width, 0, x + cell_width, height, fill=line_color)
# 绘制水平线
for i in range(3):
y = i * cell_height
canvas.create_line(y, 0, y, width, fill=line_color)
canvas.create_line(0, y + cell_height, width, y + cell_height, fill=line_color)
def draw_numbers(canvas, width, height):
# 计算每个格子的宽度高度
cell_width = width / 3
cell_height = height / 3
代码解释:
(1)这段代码定义了两个函数draw_grid和draw_numbers,用于在Python的Tkinter库中绘制一个网格和数字。
(2)draw_grid函数接收四个参数:canvas表示绘制的画布,width和height表示画布的宽度和高度,line_color表示线条的颜色,默认为黑色。
(3)在draw_grid函数中,首先计算每个格子的宽度和高度,然后使用两个嵌套循环绘制垂直和水平的线条。循环变量i从0到2,表示绘制三条线。x和y分别表示线条的起点坐标,cell_width和cell_height表示每个格子的宽度和高度。canvas.create_line()函数用于绘制线条,其中参数分别为线条的起点和终点坐标,以及线条的颜色。
(4)draw_numbers函数接收两个参数:canvas表示绘制的画布,width和height表示画布的宽度和高度。这个函数的作用是在每个格子中绘制数字,但是在这段代码中没有实现数字的绘制部分。
1.3在每个九宫格中心写上数字1-9
这段代码是draw_numbers函数的一部分,用于在之前绘制的3x3网格中绘制数字。它使用了两层嵌套的for循环来遍历网格的每个单元格,并为每个单元格中心位置绘制一个数字。
for i in range(3):
for j in range(3):
x = i * cell_width + cell_width / 2
y = j * cell_height + cell_height / 2
number = i * 3 + j + 1
canvas.create_text(y, x, text=str(number), font=("Helvetica", 20))
代码解释:
(1)for i in range(3): 这行代码开始了一个外部循环,循环变量i从0到2,表示网格的行。
(2)for j in range(3): 这行代码开始了一个内部循环,循环变量j从0到2,表示网格的列。
(3)x = i * cell_width + cell_width / 2 这行代码计算当前单元格中心的x坐标。i * cell_width计算当前行的起始x坐标,再加上cell_width / 2得到单元格中心的x坐标。
(4)y = j * cell_height + cell_height / 2 这行代码计算当前单元格中心的y坐标。j * cell_height计算当前列的起始y坐标,再加上cell_height / 2得到单元格中心的y坐标。
(5)number = i * 3 + j + 1 这行代码计算当前单元格应该绘制的数字。由于数字是从1开始的,所以i * 3计算当前行之前的所有数字,j加上当前列之前的数字,最后加上1得到当前单元格的数字。
(6)canvas.create_text(y, x, text=str(number), font=("Helvetica", 20)) 这行代码在画布上创建文本。y和x参数指定文本的位置,text=str(number)将数字转换为字符串,font=("Helvetica", 20)指定字体和大小。
1.4两个按钮和1输入框
root = tk.Tk()
root.geometry("600x500")
root.title("Welcome")
canvas = tk.Canvas(root, width=300, height=300, bg="white")
canvas.pack()
draw_grid(canvas, 300, 300)
draw_numbers(canvas, 300, 300)
label2 = tk.Label(text="请输入要落下棋子的位置(1-9):", width=30, height=2)
label2.pack()
label2.place(x=190, y=310)
entry2 = tk.Entry(width=20)
entry2.pack()
entry2.place(x=220, y=350)
# 按钮落下棋子
button11 = tk.Button(text="落下棋子", width=10, height=2,command=button1_click)
button11.pack()
button11.place(x=250, y=380)
# 按钮重新开始
button22 = tk.Button(text="重新开始", width=10, height=2,command=button2_click)
button22.pack()
button22.place(x=250, y=430)
root.mainloop()
1.5棋手落下棋子
# 落下棋子按钮的回调函数
def button1_click():
if check_input():
place_piece("X") # 假设玩家1总是落下“X”
代码解释:
定义了一个名为 button1_click 的函数,用于在一个棋盘游戏中落下棋子。在这个函数中,首先调用了 check_input 函数来检查玩家的输入是否有效。如果输入有效(通常这意味着玩家已经选择了要落子的位置,且该位置当前是空的),那么将调用 place_piece 函数,并传入字符串 "X" 作为参数,表示玩家1在棋盘上落下一个“X”标记的棋子
1.6判断落下的位置是否有效
# 检查输入的数字是否有效的函数
def check_input():
try:
position = int(entry2.get())
if 1 <= position <= 9:
return True
else:
tk.messagebox.showerror("错误", "输入的数字必须在1到9之间!")
return False
except ValueError:
tk.messagebox.showerror("错误", "请输入一个有效的数字!")
return False
代码解释:
(1)position = int(entry2.get()) 这行代码尝试将entry2小部件(输入框)中的内容转换为整数。如果输入的内容不能转换为整数,将会引发ValueError异常,并且弹出提醒输入有效数字的提示框。
(2)再判断是否满足条件,满足就返回True,不满足则弹出警告框。
判断胜利
1.创建一个长度为9的列表,用于存储每个格子的状态
game_state = [""] * 9
2.写出胜利和平局的全部可能
def check_win(player):
hs_list = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], # 行
[0, 3, 6], [1, 4, 7], [2, 5, 8], # 列
[0, 4, 8], [2, 4, 6] # 对角线
]
for y in hs_list:
if all(game_state[i] == player for i in y):
return True
return False
# 在place_piece函数中,当“X”落下后,检查是否获胜
def place_piece(piece):
global move_count # 声明全局变量
position = int(entry2.get()) - 1 # 获取玩家输入的位置
if 0 <= position < 9 and game_state[position] == "": # 检查位置是否有效且未被占用
canvas.create_text((position % 3) * 100 + 50, (position // 3) * 100 + 50,
text=piece, font=("Helvetica", 40))
game_state[position] = piece # 更新游戏状态
move_count += 1 # 增加步数计数
if check_win(piece): # 检查是否获胜
tk.messagebox.showinfo("胜利", f"{piece} 获胜!")
root.quit() # 获胜后关闭窗口
elif move_count == 5: # 如果下了五步且没有获胜
tk.messagebox.showinfo("平局", "游戏结束,平局!")
root.quit() # 平局后关闭窗口
else:
tk.messagebox.showerror("错误", "位置已被占用或无效,请重新输入!")
代码解释:
(1) check_win函数接收一个参数player,表示当前玩家的棋子(“X")。函数内部定义了一个列表hs_list,包含了所有可能的获胜组合,即三行、三列和两条对角线。然后,它遍历这个列表,对于每个组合,检查是否所有的位置都被当前玩家的棋子占据。如果是,则返回True表示当前玩家获胜。如果遍历完所有组合都没有获胜,则返回False。
(2)place_piece函数接收一个参数piece,表示当前玩家要放置的棋子。在这个函数中,首先声明了一个全局变量move_count,用于记录已经进行的步数。然后,它获取玩家输入的位置,并检查这个位置是否有效且未被占用。如果是,则在棋盘上相应的位置放置棋子,并更新游戏状态。之后,增加步数计数,并检查当前玩家是否获胜。如果获胜,则弹出消息框显示获胜信息,并关闭窗口。如果下了五步且没有获胜,则弹出消息框显示平局信息,并关闭窗口。如果位置已被占用或无效,则弹出错误消息框,提示玩家重新输入。
全部代码
import tkinter as tk
import tkinter.messagebox
move_count = 0 # 计数器,用于跟踪下了多少步棋
def draw_grid(canvas, width, height, line_color='black'):
# 计算每个格子的宽度高度
cell_width = width / 3
cell_height = height / 3
# 绘制垂直线
for i in range(3):
x = i * cell_width
canvas.create_line(x, 0, x, height, fill=line_color)
canvas.create_line(x + cell_width, 0, x + cell_width, height, fill=line_color)
# 绘制水平线
for i in range(3):
y = i * cell_height
canvas.create_line(y, 0, y, width, fill=line_color)
canvas.create_line(0, y + cell_height, width, y + cell_height, fill=line_color)
def draw_numbers(canvas, width, height):
# 计算每个格子的宽度高度
cell_width = width / 3
cell_height = height / 3
# 在每个格子中心绘制数字
for i in range(3):
for j in range(3):
x = i * cell_width + cell_width / 2
y = j * cell_height + cell_height / 2
number = i * 3 + j + 1
canvas.create_text(y, x, text=str(number), font=("Helvetica", 20))
# 游戏状态变量
game_state = [""] * 9 # 创建一个长度为9的列表,用于存储每个格子的状态
def check_win(player):
hs_list = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], # 行
[0, 3, 6], [1, 4, 7], [2, 5, 8], # 列
[0, 4, 8], [2, 4, 6] # 对角线
]
for y in hs_list:
if all(game_state[i] == player for i in y):
return True
return False
# 在place_piece函数中,当“X”落下后,检查是否获胜
def place_piece(piece):
global move_count # 声明全局变量
position = int(entry2.get()) - 1 # 获取玩家输入的位置
if 0 <= position < 9 and game_state[position] == "": # 检查位置是否有效且未被占用
canvas.create_text((position % 3) * 100 + 50, (position // 3) * 100 + 50,
text=piece, font=("Helvetica", 40))
game_state[position] = piece # 更新游戏状态
move_count += 1 # 增加步数计数
if check_win(piece): # 检查是否获胜
tk.messagebox.showinfo("胜利", f"{piece} 获胜!")
root.quit() # 获胜后关闭窗口
elif move_count == 5: # 如果下了五步且没有获胜
tk.messagebox.showinfo("平局", "游戏结束,平局!")
root.quit() # 平局后关闭窗口
else:
tk.messagebox.showerror("错误", "位置已被占用或无效,请重新输入!")
# 检查输入的数字是否有效的函数
def check_input():
try:
position = int(entry2.get())
if 1 <= position <= 9:
return True
else:
tk.messagebox.showerror("错误", "输入的数字必须在1到9之间!")
return False
except ValueError:
tk.messagebox.showerror("错误", "请输入一个有效的数字!")
return False
# 落下棋子按钮的回调函数
def button1_click():
if check_input():
place_piece("X") # 假设玩家1总是落下“X”
root = tk.Tk()
root.geometry("600x500")
root.title("Welcome")
canvas = tk.Canvas(root, width=300, height=300, bg="white")
canvas.pack()
draw_grid(canvas, 300, 300)
draw_numbers(canvas, 300, 300)
label2 = tk.Label(text="请输入要落下棋子的位置(1-9):", width=30, height=2)
label2.pack()
label2.place(x=190, y=310)
entry2 = tk.Entry(width=20)
entry2.pack()
entry2.place(x=220, y=350)
# 按钮落下棋子
button11 = tk.Button(text="落下棋子", width=10, height=2,command=button1_click)
button11.pack()
button11.place(x=250, y=380)
# 按钮重新开始
button22 = tk.Button(text="重新开始", width=10, height=2)
button22.pack()
button22.place(x=250, y=430)
root.mainloop()