feat(第7讲 字母卡牌): 实现记忆游戏并添加开始界面
- 新增 jiyi.py 文件,实现字母翻牌记忆游戏功能 - 添加 youxijiemian.py 文件,创建游戏开始界面 - 使用 turtle 和 tkinter 模块分别实现游戏和界面 - 支持选择不同难度的游戏模式
This commit is contained in:
parent
378bd4beec
commit
fa4660abed
136
第23讲扫雷/课堂成果/扫雷.py
Normal file
136
第23讲扫雷/课堂成果/扫雷.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
import random
|
||||||
|
|
||||||
|
class MineSweeper:
|
||||||
|
def __init__(self, master, rows, cols, mines):
|
||||||
|
self.master = master
|
||||||
|
self.rows = rows
|
||||||
|
self.cols = cols
|
||||||
|
self.mines = mines
|
||||||
|
self.buttons = {}
|
||||||
|
self.board = [[0 for _ in range(cols)] for _ in range(rows)]
|
||||||
|
self.revealed = [[False for _ in range(cols)] for _ in range(rows)]
|
||||||
|
self.flags = [[False for _ in range(cols)] for _ in range(rows)]
|
||||||
|
self.game_over = False
|
||||||
|
|
||||||
|
self.generate_mines()
|
||||||
|
self.create_widgets()
|
||||||
|
|
||||||
|
def generate_mines(self):
|
||||||
|
count = 0
|
||||||
|
while count < self.mines:
|
||||||
|
r = random.randint(0, self.rows - 1)
|
||||||
|
c = random.randint(0, self.cols - 1)
|
||||||
|
if self.board[r][c] == -1:
|
||||||
|
continue
|
||||||
|
self.board[r][c] = -1
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
# 更新周围数字
|
||||||
|
for i in range(r - 1, r + 2):
|
||||||
|
for j in range(c - 1, c + 2):
|
||||||
|
if 0 <= i < self.rows and 0 <= j < self.cols and self.board[i][j] != -1:
|
||||||
|
self.board[i][j] += 1
|
||||||
|
|
||||||
|
def create_widgets(self):
|
||||||
|
for r in range(self.rows):
|
||||||
|
for c in range(self.cols):
|
||||||
|
b = tk.Button(self.master, width=2, height=1, font=('Arial', 14),
|
||||||
|
command=lambda r=r, c=c: self.reveal_cell(r, c))
|
||||||
|
b.bind("<Button-3>", lambda e, r=r, c=c: self.toggle_flag(r, c))
|
||||||
|
b.grid(row=r, column=c)
|
||||||
|
self.buttons[(r, c)] = b
|
||||||
|
|
||||||
|
def reveal_cell(self, r, c):
|
||||||
|
if self.game_over or self.revealed[r][c] or self.flags[r][c]:
|
||||||
|
return
|
||||||
|
if self.board[r][c] == -1:
|
||||||
|
self.buttons[(r, c)].config(text="💣", bg="red")
|
||||||
|
self.game_over = True
|
||||||
|
self.show_all_mines()
|
||||||
|
messagebox.showerror("游戏结束", "你踩到雷啦!")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.flood_fill(r, c)
|
||||||
|
self.check_win()
|
||||||
|
|
||||||
|
def flood_fill(self, r, c):
|
||||||
|
if not (0 <= r < self.rows and 0 <= c < self.cols):
|
||||||
|
return
|
||||||
|
if self.revealed[r][c] or self.flags[r][c]:
|
||||||
|
return
|
||||||
|
self.revealed[r][c] = True
|
||||||
|
val = self.board[r][c]
|
||||||
|
btn = self.buttons[(r, c)]
|
||||||
|
btn.config(relief=tk.SUNKEN, text=str(val) if val > 0 else "", state=tk.DISABLED, bg="lightgray")
|
||||||
|
if val == 0:
|
||||||
|
for dr in (-1, 0, 1):
|
||||||
|
for dc in (-1, 0, 1):
|
||||||
|
if dr != 0 or dc != 0:
|
||||||
|
self.flood_fill(r + dr, c + dc)
|
||||||
|
|
||||||
|
def toggle_flag(self, r, c):
|
||||||
|
if self.revealed[r][c] or self.game_over:
|
||||||
|
return
|
||||||
|
if self.flags[r][c]:
|
||||||
|
self.flags[r][c] = False
|
||||||
|
self.buttons[(r, c)].config(text="")
|
||||||
|
else:
|
||||||
|
self.flags[r][c] = True
|
||||||
|
self.buttons[(r, c)].config(text="🚩")
|
||||||
|
|
||||||
|
def show_all_mines(self):
|
||||||
|
for r in range(self.rows):
|
||||||
|
for c in range(self.cols):
|
||||||
|
if self.board[r][c] == -1:
|
||||||
|
self.buttons[(r, c)].config(text="💣")
|
||||||
|
|
||||||
|
def check_win(self):
|
||||||
|
for r in range(self.rows):
|
||||||
|
for c in range(self.cols):
|
||||||
|
if self.board[r][c] != -1 and not self.revealed[r][c]:
|
||||||
|
return
|
||||||
|
self.game_over = True
|
||||||
|
messagebox.showinfo("胜利!", "恭喜你,排雷成功!")
|
||||||
|
|
||||||
|
# 自定义参数
|
||||||
|
def start_game():
|
||||||
|
try:
|
||||||
|
rows = int(entry_rows.get())
|
||||||
|
cols = int(entry_cols.get())
|
||||||
|
mines = int(entry_mines.get())
|
||||||
|
if rows <= 0 or cols <= 0 or mines <= 0 or mines >= rows * cols:
|
||||||
|
raise ValueError
|
||||||
|
except:
|
||||||
|
messagebox.showerror("输入错误", "请输入合理的行列和雷数")
|
||||||
|
return
|
||||||
|
|
||||||
|
settings_window.destroy()
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("扫雷")
|
||||||
|
MineSweeper(root, rows, cols, mines)
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
# 设置窗口
|
||||||
|
settings_window = tk.Tk()
|
||||||
|
settings_window.title("扫雷设置")
|
||||||
|
|
||||||
|
tk.Label(settings_window, text="行数:").grid(row=0, column=0)
|
||||||
|
entry_rows = tk.Entry(settings_window)
|
||||||
|
entry_rows.insert(0, "10")
|
||||||
|
entry_rows.grid(row=0, column=1)
|
||||||
|
|
||||||
|
tk.Label(settings_window, text="列数:").grid(row=1, column=0)
|
||||||
|
entry_cols = tk.Entry(settings_window)
|
||||||
|
entry_cols.insert(0, "10")
|
||||||
|
entry_cols.grid(row=1, column=1)
|
||||||
|
|
||||||
|
tk.Label(settings_window, text="雷数:").grid(row=2, column=0)
|
||||||
|
entry_mines = tk.Entry(settings_window)
|
||||||
|
entry_mines.insert(0, "10")
|
||||||
|
entry_mines.grid(row=2, column=1)
|
||||||
|
|
||||||
|
tk.Button(settings_window, text="开始游戏", command=start_game).grid(row=3, column=0, columnspan=2)
|
||||||
|
|
||||||
|
settings_window.mainloop()
|
||||||
71
第24讲贪吃蛇/课堂成果/贪吃蛇.py
Normal file
71
第24讲贪吃蛇/课堂成果/贪吃蛇.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
"""Snake,经典街机游戏。
|
||||||
|
|
||||||
|
练习:
|
||||||
|
1. 如何让蛇变快或变慢?
|
||||||
|
2. 如何让蛇可以从一边穿越到另一边?
|
||||||
|
3. 如何让食物移动?
|
||||||
|
4. 修改为点击鼠标控制蛇移动。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from random import randrange
|
||||||
|
from turtle import *
|
||||||
|
from freegames import square, vector
|
||||||
|
#pip install freegames -i https://pypi.douban.com/simple/
|
||||||
|
# 食物位置
|
||||||
|
food = vector(0, 0)
|
||||||
|
# 蛇的身体坐标列表(初始只有一个身体段)
|
||||||
|
snake = [vector(10, 0)]
|
||||||
|
# 移动方向
|
||||||
|
aim = vector(10, 0)
|
||||||
|
def change(x, y):
|
||||||
|
"""改变蛇的移动方向。"""
|
||||||
|
aim.x = x
|
||||||
|
aim.y = y
|
||||||
|
def inside(head):
|
||||||
|
"""判断蛇头是否在边界内。"""
|
||||||
|
return -200 < head.x < 190 and -200 < head.y < 190
|
||||||
|
def move():
|
||||||
|
"""让蛇向前移动一个单位。"""
|
||||||
|
head = snake[-1].copy()
|
||||||
|
head.move(aim)
|
||||||
|
# 如果撞墙或撞到自己,则游戏结束
|
||||||
|
if not inside(head) or head in snake:
|
||||||
|
square(head.x, head.y, 9, 'red') # 撞到后显示红色方块
|
||||||
|
update()
|
||||||
|
return
|
||||||
|
snake.append(head) # 增加新的蛇头
|
||||||
|
if head == food:
|
||||||
|
print('蛇长:', len(snake))
|
||||||
|
# 随机生成新的食物位置(在格子上)
|
||||||
|
food.x = randrange(-15, 15) * 10
|
||||||
|
food.y = randrange(-15, 15) * 10
|
||||||
|
else:
|
||||||
|
snake.pop(0) # 移除蛇尾
|
||||||
|
|
||||||
|
clear()
|
||||||
|
|
||||||
|
# 画出蛇的每一节身体
|
||||||
|
for body in snake:
|
||||||
|
square(body.x, body.y, 9, 'black')
|
||||||
|
|
||||||
|
# 画出食物
|
||||||
|
square(food.x, food.y, 9, 'green')
|
||||||
|
update()
|
||||||
|
ontimer(move, 100) # 每100毫秒调用一次 move,实现动画
|
||||||
|
|
||||||
|
|
||||||
|
# 初始化窗口
|
||||||
|
setup(420, 420, 370, 0)
|
||||||
|
hideturtle() # 隐藏箭头图标
|
||||||
|
tracer(False) # 关闭自动刷新
|
||||||
|
listen() # 开启键盘监听
|
||||||
|
|
||||||
|
# 绑定按键改变方向
|
||||||
|
onkey(lambda: change(10, 0), 'Right')
|
||||||
|
onkey(lambda: change(-10, 0), 'Left')
|
||||||
|
onkey(lambda: change(0, 10), 'Up')
|
||||||
|
onkey(lambda: change(0, -10), 'Down')
|
||||||
|
|
||||||
|
# 开始游戏
|
||||||
|
move()
|
||||||
|
done()
|
||||||
Loading…
x
Reference in New Issue
Block a user