项目一
package Test; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Arrays; import java.util.Objects; import java.util.Stack; import javax.swing.*; //Calculator类,继承JFrame框架,实现事件监听器接口 class Calculator extends JFrame implements ActionListener { private final String[] KEYS = {"7", "8", "9", "AC", "4", "5", "6", "-", "1", "2", "3", "+", "0", "/", "^2", "*", "(", ")", ".", "="}; private JButton keys[] = new JButton[KEYS.length]; private JTextArea resultText = new JTextArea(); // 文本域组件TextArea可容纳多行文本;文本框内容初始值设为0 private JTextArea HistoryText = new JTextArea(); // 历史记录文本框初始值设为空 private JPanel jp2 = new JPanel(); private JScrollPane gdt1 = new JScrollPane(resultText); private JScrollPane gdt2 = new JScrollPane(HistoryText); private JLabel label = new JLabel("历史记录"); private String input = ""; //计算文本框输入的中缀表达式 // 构造方法 public Calculator() { resultText.setBounds(20, 18, 255, 120); // 设置文本框大小 resultText.setAlignmentX(LEFT_ALIGNMENT); // 文本框内容左对齐 resultText.setEditable(false); // 文本框不允许修改结果 resultText.setFont(new Font("font", Font.PLAIN, 18)); //设置结果文本框输入文字的字体、类型、大小 HistoryText.setFont(new Font("font", Font.PLAIN, 18)); //设置历史记录文本框输入文字的字体、类型、大小 HistoryText.setBounds(290, 40, 250, 330); // 设置文本框大小 HistoryText.setAlignmentX(LEFT_ALIGNMENT); // 文本框内容左对齐 HistoryText.setEditable(false); // 文本框不允许修改结果 label.setBounds(300, 15, 100, 20); //设置标签位置及大小 jp2.setBounds(290, 40, 250, 330); //设置面板窗口位置及大小 jp2.setLayout(new GridLayout()); JPanel jp1 = new JPanel(); jp1.setBounds(20, 18, 255, 120); //设置面板窗口位置及大小 jp1.setLayout(new GridLayout()); resultText.setLineWrap(true); // 激活自动换行功能 resultText.setWrapStyleWord(true); // 激活断行不断字功能 HistoryText.setLineWrap(true); //自动换行 HistoryText.setWrapStyleWord(true); jp1.add(gdt1); //将滚动条添加入面板窗口中 jp2.add(gdt2); this.add(jp1); //将面板添加到总窗体中 this.add(jp2); //将面板添加到总窗体中 this.setLayout(null); this.add(label); // 新建“历史记录”标签 // 放置按钮 x,y为按钮的横纵坐标 int x = 20, y = 200; for (int i = 0; i < KEYS.length; i++) { keys[i] = new JButton(); keys[i].setText(KEYS[i]); keys[i].setBounds(x, y, 50, 40); if (x < 215) { x += 65; } else { x = 20; y += 45; } this.add(keys[i]); } for (int i = 0; i < KEYS.length; i++) // 每个按钮都注册事件监听器 { keys[i].addActionListener(this); } this.setResizable(false);//不允许调整计算器界面大小 this.setBounds(700, 300, 560, 450);//计算器界面位置和大小 this.setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭计算器程序终止 this.setVisible(true); } // 事件处理 public void actionPerformed(ActionEvent e) { String label = e.getActionCommand(); //获得事件源的标签 if (Objects.equals(label, "AC")) //清空按钮,消除显示屏文本框前面所有的输入和结果 { input = ""; resultText.setText(""); //更新文本域的显示 } else if (Objects.equals(label, "^2")) { String m; if(input.isEmpty()) m="error!"; else m = String.valueOf(pfys(input)); resultText.setText(input + "^2" + "=" + m); HistoryText.setText(HistoryText.getText() + resultText.getText() + "\n"); input = m; } else if (Objects.equals(label, "=")) { if (input.isEmpty()) return; String[] s = houzhui(input); //将中缀表达式转换为后缀表达式 double result = Result(s); //计算后缀表达式得出最终算式结果 resultText.setText(input + "=" + result); HistoryText.setText(HistoryText.getText() + resultText.getText() + "\n"); } else { input = input + label; resultText.setText(input); } } //将中缀表达式转换为后缀表达式 private String[] houzhui(String infix) { //infix 中缀 String s = "";// 用于承接多位数的字符串 Stack<String> opStack = new Stack<String>(); Stack<String> postQueue = new Stack<String>(); // 后缀表达式,为了将多位数存储为独立的字符串 System.out.println("中缀:" + infix); for (int i = 0; i < infix.length(); i++) // 遍历中缀表达式 // indexof函数,返回字串首次出现的位置;charAt函数返回index位置处的字符; { if ("1234567890.".indexOf(infix.charAt(i)) >= 0) { // 遇到数字字符直接入队 s = "";// 作为承接字符,每次开始时都要清空 for (; i < infix.length() && "0123456789.".indexOf(infix.charAt(i)) >= 0; i++) { s = s + infix.charAt(i); } i--; //避免跳过对非数字字符的处理 postQueue.push(s); // 数字字符直接加入后缀表达式 } else if ("(".indexOf(infix.charAt(i)) >= 0) { // 遇到左括号 opStack.push(String.valueOf(infix.charAt(i))); // 左括号入栈 } else if (")".indexOf(infix.charAt(i)) >= 0) { // 遇到右括号 while (!opStack.peek().equals("(")) { // 栈顶元素循环出栈,直到遇到左括号为止 postQueue.push(opStack.pop()); } opStack.pop(); //删除左括号 } else if ("*%/+-".indexOf(infix.charAt(i)) >= 0) // 遇到运算符 { if (opStack.empty() || "(".contains(opStack.peek())) {// 若栈为空或栈顶元素为左括号则直接入栈 opStack.push(String.valueOf(infix.charAt(i))); } else { // 当栈顶元素为高优先级或同级运算符时,让栈顶元素出栈进入后缀表达式后,直到符合规则后,当前运算符再入栈 boolean rule = ("*%/+-".contains(opStack.peek()) && "+-".indexOf(infix.charAt(i)) >= 0) || ("*%/".contains(opStack.peek()) && "*%/".indexOf(infix.charAt(i)) >= 0); while (!opStack.empty() && rule) { postQueue.push(opStack.peek()); //peek()方法:返回栈顶的元素但不移除它 opStack.pop(); } opStack.push(String.valueOf(infix.charAt(i))); // 当前元素入栈 } } } while (!opStack.empty()) {// 遍历结束后将栈中剩余元素依次出栈进入后缀表达式 postQueue.push(opStack.pop()); } //将后缀表达式栈转换为字符串数组格式 String[] suffix = new String[postQueue.size()]; for (int i = postQueue.size() - 1; i >= 0; i--) { suffix[i] = postQueue.pop(); } System.out.println("后缀:" + Arrays.toString(suffix.clone())); return suffix; } //平方运算方法 public double pfys(String str) { double a = Double.parseDouble(str); return Math.pow(a, 2); } // 计算后缀表达式,并返回最终结果 public double Result(String[] suffix) { //suffix 后缀 Stack<String> Result = new Stack<>();// 顺序存储的栈,数据类型为字符串 int i; for (i = 0; i < suffix.length; i++) { if ("1234567890.".indexOf(suffix[i].charAt(0)) >= 0) { //遇到数字,直接入栈 Result.push(suffix[i]); } else { // 遇到运算符字符,将栈顶两个元素出栈计算并将结果返回栈顶 double x, y, n = 0; x = Double.parseDouble(Result.pop()); // 顺序出栈两个数字字符串,并转换为double类型 y = Double.parseDouble(Result.pop()); switch (suffix[i]) { case "*": n = y * x; break; case "/": if (x == 0) return 0; else n = y / x; break; case "-": n = y - x; break; case "+": n = y + x; break; } Result.push(String.valueOf(n)); // 将运算结果重新入栈 } } System.out.println("return:" + Result.peek()); return Double.parseDouble(Result.peek()); // 返回最终结果 } // 主函数 public static void main(String[] args) { Calculator a = new Calculator(); } }
项目二
package com.itheima; import javax.swing.*; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; public class MainFrame extends JFrame { private Snake snake; //蛇 private JPanel jPanel; //游戏棋盘 private Timer timer; //定时器,在规定的时间内调用蛇移动的方法 private Node food; //食物 public MainFrame() throws HeadlessException { //初始化窗体参数 initFrame(); //初始化游戏棋盘 initGamePanel(); //初始化蛇 initSnake(); //初始化食物 initFood(); //初始化定时器 initTimer(); //设置键盘监听,让蛇随着上下左右方向移动 setKeyListener(); } //初始化食物 private void initFood() { food=new Node(); food.random(); } //设置键盘监听 private void setKeyListener() { addKeyListener(new KeyAdapter() { //当键盘按下时,会自动掉此方法 public void keyPressed(KeyEvent e) { //键盘中的一个键都有一个编号 switch (e.getKeyCode()){ case KeyEvent.VK_W: //上键 if(snake.getDirection()!=Direction.DOWN){ snake.setDirection(Direction.UP); } break; case KeyEvent.VK_S: //下键 if(snake.getDirection()!=Direction.UP){ snake.setDirection(Direction.DOWN); } break; case KeyEvent.VK_A: //左键 if(snake.getDirection()!=Direction.RIGHT){ snake.setDirection(Direction.LEFT); } break; case KeyEvent.VK_D: //右键 if(snake.getDirection()!=Direction.LEFT){ snake.setDirection(Direction.RIGHT); } break; } } }); } //初始化定时器 private void initTimer() { //创建定时器对象 timer=new Timer(); //初始化定时任务 TimerTask timerTask=new TimerTask() { @Override public void run() { snake.move(); //判断蛇头是否和食物重合 Node head = snake.getBody().getFirst(); if(head.getX()==food.getX()&&head.getY()==food.getY()){ snake.eat(food); food.random(); } //重绘游戏棋盘 jPanel.repaint(); } }; //每100毫秒,执行一次定时任务 timer.scheduleAtFixedRate(timerTask,0,100); } private void initSnake() { snake=new Snake(); } //初始化游戏棋盘 private void initGamePanel() { jPanel=new JPanel(){ //绘制游戏棋盘中的内容 @Override public void paint(Graphics g) { //清空棋盘 g.clearRect(0,0,600,600); //Graphics g 可以看做是一个画笔,它提供了很多方法可以来绘制一些基本的图形(直线、矩形) //绘制40条横线 for (int i = 0; i <=40; i++) { g.drawLine(0,i*15,600,i*15); } //绘制40条竖线 第n条: (n*15,0) (n*15,600) for (int i = 0; i <=40; i++) { g.drawLine(i*15,0,i*15,600); } //绘制蛇 LinkedList<Node> body = snake.getBody(); for (Node node : body) { g.fillRect(node.getX()*15,node.getY()*15,15,15); } //绘制食物 g.fillRect(food.getX()*15,food.getY()*15,15,15); } }; //把棋盘添加到窗体中 add(jPanel); } //初始化窗体参数 private void initFrame() { //窗体宽高 setSize(610,640); //窗体的位置 setLocation(400,400); //关闭按钮 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //窗体大小不可变 setResizable(false); } public static void main(String[] args) { //创建窗体对象,并显示 new MainFrame().setVisible(true); } }
项目三
import tkinter as tk from mazegenerator import mazeutils import numpy as np import math import threading import time import random import copy class UnionSet(object): """ 并查集实现,构造函数中的matrix是一个numpy类型 """ def __init__(self, arr): self.parent = {pos: pos for pos in arr} self.count = len(arr) def find(self, root): if root == self.parent[root]: return root return self.find(self.parent[root]) def union(self, root1, root2): self.parent[self.find(root1)] = self.find(root2) class Maze(object): """ 迷宫生成类 """ def __init__(self, width=11, height=11): assert width >= 5 and height >= 5, "Length of width or height must be larger than 5." self.width = (width // 2) * 2 + 1 self.height = (height // 2) * 2 + 1 self.start = [1, 0] self.destination = [self.height - 2, self.width - 1] self.matrix = None self.path = [] def generate_matrix_dfs(self): # 地图初始化,并将出口和入口处的值设置为0 self.matrix = -np.ones((self.height, self.width)) self.matrix[self.start[0], self.start[1]] = 0 self.matrix[self.destination[0], self.destination[1]] = 0 visit_flag = [[0 for i in range(self.width)] for j in range(self.height)] def check(row, col, row_, col_): temp_sum = 0 for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]: temp_sum += self.matrix[row_ + d[0]][col_ + d[1]] return temp_sum <= -3 def dfs(row, col): visit_flag[row][col] = 1 self.matrix[row][col] = 0 if row == self.start[0] and col == self.start[1] + 1: return directions = [[0, 2], [0, -2], [2, 0], [-2, 0]] random.shuffle(directions) for d in directions: row_, col_ = row + d[0], col + d[1] if row_ > 0 and row_ < self.height - 1 and col_ > 0 and col_ < self.width - 1 and visit_flag[row_][ col_] == 0 and check(row, col, row_, col_): if row == row_: visit_flag[row][min(col, col_) + 1] = 1 self.matrix[row][min(col, col_) + 1] = 0 else: visit_flag[min(row, row_) + 1][col] = 1 self.matrix[min(row, row_) + 1][col] = 0 dfs(row_, col_) dfs(self.destination[0], self.destination[1] - 1) self.matrix[self.start[0], self.start[1] + 1] = 0 # prim算法 def generate_matrix_prim(self): # 地图初始化,并将出口和入口处的值设置为0 self.matrix = -np.ones((self.height, self.width)) def check(row, col): temp_sum = 0 for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]: temp_sum += self.matrix[row + d[0]][col + d[1]] return temp_sum < -3 queue = [] row, col = (np.random.randint(1, self.height - 1) // 2) * 2 + 1, ( np.random.randint(1, self.width - 1) // 2) * 2 + 1 queue.append((row, col, -1, -1)) while len(queue) != 0: row, col, r_, c_ = queue.pop(np.random.randint(0, len(queue))) if check(row, col): self.matrix[row, col] = 0 if r_ != -1 and row == r_: self.matrix[row][min(col, c_) + 1] = 0 elif r_ != -1 and col == c_: self.matrix[min(row, r_) + 1][col] = 0 for d in [[0, 2], [0, -2], [2, 0], [-2, 0]]: row_, col_ = row + d[0], col + d[1] if row_ > 0 and row_ < self.height - 1 and col_ > 0 and col_ < self.width - 1 and self.matrix[row_][ col_] == -1: queue.append((row_, col_, row, col)) self.matrix[self.start[0], self.start[1]] = 0 self.matrix[self.destination[0], self.destination[1]] = 0 # 递归切分算法,还有问题,现在不可用 def generate_matrix_split(self): # 地图初始化,并将出口和入口处的值设置为0 self.matrix = -np.zeros((self.height, self.width)) self.matrix[0, :] = -1 self.matrix[self.height - 1, :] = -1 self.matrix[:, 0] = -1 self.matrix[:, self.width - 1] = -1 # 随机生成位于(start, end)之间的偶数 def get_random(start, end): rand = np.random.randint(start, end) if rand & 0x1 == 0: return rand return get_random(start, end) # split函数的四个参数分别是左上角的行数、列数,右下角的行数、列数,墙壁只能在偶数行,偶数列 def split(lr, lc, rr, rc): if rr - lr < 2 or rc - lc < 2: return # 生成墙壁,墙壁只能是偶数点 cur_row, cur_col = get_random(lr, rr), get_random(lc, rc) for i in range(lc, rc + 1): self.matrix[cur_row][i] = -1 for i in range(lr, rr + 1): self.matrix[i][cur_col] = -1 # 挖穿三面墙得到连通图,挖孔的点只能是偶数点 wall_list = [ ("left", cur_row, [lc + 1, cur_col - 1]), ("right", cur_row, [cur_col + 1, rc - 1]), ("top", cur_col, [lr + 1, cur_row - 1]), ("down", cur_col, [cur_row + 1, rr - 1]) ] random.shuffle(wall_list) for wall in wall_list[:-1]: if wall[2][1] - wall[2][0] < 1: continue if wall[0] in ["left", "right"]: self.matrix[wall[1], get_random(wall[2][0], wall[2][1] + 1) + 1] = 0 else: self.matrix[get_random(wall[2][0], wall[2][1] + 1), wall[1] + 1] = 0 # self.print_matrix() # time.sleep(1) # 递归 split(lr + 2, lc + 2, cur_row - 2, cur_col - 2) split(lr + 2, cur_col + 2, cur_row - 2, rc - 2) split(cur_row + 2, lc + 2, rr - 2, cur_col - 2) split(cur_row + 2, cur_col + 2, rr - 2, rc - 2) self.matrix[self.start[0], self.start[1]] = 0 self.matrix[self.destination[0], self.destination[1]] = 0 split(0, 0, self.height - 1, self.width - 1) # 最小生成树算法-kruskal(选边法)思想生成迷宫地图,这种实现方法最复杂。 def generate_matrix_kruskal(self): # 地图初始化,并将出口和入口处的值设置为0 self.matrix = -np.ones((self.height, self.width)) def check(row, col): ans, counter = [], 0 for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]: row_, col_ = row + d[0], col + d[1] if row_ > 0 and row_ < self.height - 1 and col_ > 0 and col_ < self.width - 1 and self.matrix[ row_, col_] == -1: ans.append([d[0] * 2, d[1] * 2]) counter += 1 if counter <= 1: return [] return ans nodes = set() row = 1 while row < self.height: col = 1 while col < self.width: self.matrix[row, col] = 0 nodes.add((row, col)) col += 2 row += 2 unionset = UnionSet(nodes) while unionset.count > 1: row, col = nodes.pop() directions = check(row, col) if len(directions): random.shuffle(directions) for d in directions: row_, col_ = row + d[0], col + d[1] if unionset.find((row, col)) == unionset.find((row_, col_)): continue nodes.add((row, col)) unionset.count -= 1 unionset.union((row, col), (row_, col_)) if row == row_: self.matrix[row][min(col, col_) + 1] = 0 else: self.matrix[min(row, row_) + 1][col] = 0 break self.matrix[self.start[0], self.start[1]] = 0 self.matrix[self.destination[0], self.destination[1]] = 0 # 迷宫寻路算法DFS def find_path_dfs(self, destination): visited = [[0 for i in range(self.width)] for j in range(self.height)] def dfs(path): visited[path[-1][0]][path[-1][1]] = 1 if path[-1][0] == destination[0] and path[-1][1] == destination[1]: self.path = path[:] return for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]: row_, col_ = path[-1][0] + d[0], path[-1][1] + d[1] if row_ > 0 and row_ < self.height - 1 and col_ > 0 and col_ < self.width and visited[row_][ col_] == 0 and self.matrix[row_][col_] == 0: dfs(path + [[row_, col_]]) dfs([[self.start[0], self.start[1]]]) if __name__ == '__main__': maze = Maze(51, 51) maze.generate_matrix_kruskal() maze.find_path_dfs(maze.destination) def draw_cell(canvas, row, col, color="#FFFFFF"): x0, y0 = col * cell_width, row * cell_width x1, y1 = x0 + cell_width, y0 + cell_width canvas.create_rectangle(x0, y0, x1, y1, fill=color, outline=color, width=0) def draw_path(canvas, matrix, row, col, color, line_color): # 列 if row + 1 < rows and matrix[row - 1][col] >= 1 and matrix[row + 1][col] >= 1: x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width x1, y1 = x0 + cell_width / 5, y0 + cell_width # 行 elif col + 1 < cols and matrix[row][col - 1] >= 1 and matrix[row][col + 1] >= 1: x0, y0 = col * cell_width, row * cell_width + 2 * cell_width / 5 x1, y1 = x0 + cell_width, y0 + cell_width / 5 # 左上角 elif col + 1 < cols and row + 1 < rows and matrix[row][col + 1] >= 1 and matrix[row + 1][col] >= 1: x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5 x1, y1 = x0 + 3 * cell_width / 5, y0 + cell_width / 5 canvas.create_rectangle(x0, y0, x1, y1, fill=color, outline=line_color, width=0) x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5 x1, y1 = x0 + cell_width / 5, y0 + 3 * cell_width / 5 # 右上角 elif row + 1 < rows and matrix[row][col - 1] >= 1 and matrix[row + 1][col] >= 1: x0, y0 = col * cell_width, row * cell_width + 2 * cell_width / 5 x1, y1 = x0 + 3 * cell_width / 5, y0 + cell_width / 5 canvas.create_rectangle(x0, y0, x1, y1, fill=color, outline=line_color, width=0) x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5 x1, y1 = x0 + cell_width / 5, y0 + 3 * cell_width / 5 # 左下角 elif col + 1 < cols and matrix[row - 1][col] >= 1 and matrix[row][col + 1] >= 1: x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width x1, y1 = x0 + cell_width / 5, y0 + 3 * cell_width / 5 canvas.create_rectangle(x0, y0, x1, y1, fill=color, outline=line_color, width=0) x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5 x1, y1 = x0 + 3 * cell_width / 5, y0 + cell_width / 5 # 右下角 elif matrix[row - 1][col] >= 1 and matrix[row][col - 1] >= 1: x0, y0 = col * cell_width, row * cell_width + 2 * cell_width / 5 x1, y1 = x0 + 3 * cell_width / 5, y0 + cell_width / 5 canvas.create_rectangle(x0, y0, x1, y1, fill=color, outline=line_color, width=0) x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width x1, y1 = x0 + cell_width / 5, y0 + 3 * cell_width / 5 else: x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5 x1, y1 = x0 + cell_width / 5, y0 + cell_width / 5 canvas.create_rectangle(x0, y0, x1, y1, fill=color, outline=line_color, width=0) def draw_maze(canvas, matrix, path, moves): """ 根据matrix中每个位置的值绘图: -1: 墙壁 0: 空白 1: 参考路径 2: 移动过的位置 """ for r in range(rows): for c in range(cols): if matrix[r][c] == 0: draw_cell(canvas, r, c) elif matrix[r][c] == -1: draw_cell(canvas, r, c, '#330000') elif matrix[r][c] == 1: draw_cell(canvas, r, c) draw_path(canvas, matrix, r, c, '#E5FFCC', '#E5FFCC') elif matrix[r][c] == 2: draw_cell(canvas, r, c) draw_path(canvas, matrix, r, c, '#CCCCFF', '#CCCCFF') for p in path: matrix[p[0]][p[1]] = 1 for move in moves: matrix[move[0]][move[1]] = 2 def update_maze(canvas, matrix, path, moves): canvas.delete("all") matrix = copy.copy(matrix) for p in path: matrix[p[0]][p[1]] = 1 for move in moves: matrix[move[0]][move[1]] = 2 row, col = movement_list[-1] colors = ['#330000', '#F2F2F2', '#330000', '#F2F2F2', '#330000', '#F2F2F2', '#330000', '#F2F2F2'] if level > 2: colors = ['#232323', '#252525', '#2a2a32', '#424242', '#434368', '#b4b4b4', '#525288', '#F2F2F2'] for r in range(rows): for c in range(cols): distance = (row - r) * (row - r) + (col - c) * (col - c) if distance >= 100: color = colors[0:2] elif distance >= 60: color = colors[2:4] elif distance >= 30: color = colors[4:6] else: color = colors[6:8] if matrix[r][c] == 0: draw_cell(canvas, r, c, color[1]) elif matrix[r][c] == -1: draw_cell(canvas, r, c, color[0]) elif matrix[r][c] == 1: draw_cell(canvas, r, c, color[1]) draw_path(canvas, matrix, r, c, '#00FF22', '#00FF22') elif matrix[r][c] == 2: draw_cell(canvas, r, c, color[1]) draw_path(canvas, matrix, r, c, '#ee3f4d', '#ee3f4d') def _eventHandler(event): global movement_list global click_counter global next_maze_flag global level if not next_maze_flag and event.keysym in ['A', 'D', 'W', 'S']: click_counter += 1 windows.title("Maze Level-{} Steps-{}".format(level, click_counter)) cur_pos = movement_list[-1] ops = {'A': [0, -1], 'D': [0, 1], 'W': [-1, 0], 'S': [1, 0]} r_, c_ = cur_pos[0] + ops[event.keysym][0], cur_pos[1] + ops[event.keysym][1] if len(movement_list) > 1 and [r_, c_] == movement_list[-2]: movement_list.pop() while True: cur_pos = movement_list[-1] counter = 0 for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]: r_, c_ = cur_pos[0] + d[0], cur_pos[1] + d[1] if c_ >= 0 and maze.matrix[r_][c_] == 0: counter += 1 if counter != 2: break movement_list.pop() elif r_ < maze.height and c_ < maze.width and maze.matrix[r_][c_] == 0: while True: movement_list.append([r_, c_]) temp_list = [] for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]: r__, c__ = r_ + d[0], c_ + d[1] if c__ < maze.width and maze.matrix[r__][c__] == 0 and [r__, c__] != cur_pos: temp_list.append([r__, c__]) if len(temp_list) != 1: break cur_pos = [r_, c_] r_, c_ = temp_list[0] update_maze(canvas, maze.matrix, maze.path, movement_list) elif next_maze_flag: next_maze_flag = False movement_list = [maze.start] click_counter = 0 maze.generate_matrix_kruskal() maze.path = [] draw_maze(canvas, maze.matrix, maze.path, movement_list) level += 1 def _paint(event): x, y = math.floor((event.y - 1) / cell_width), math.floor((event.x - 1) / cell_width) if maze.matrix[x][y] == 0: maze.find_path_dfs([x, y]) update_maze(canvas, maze.matrix, maze.path, movement_list) def _reset(event): maze.path = [] update_maze(canvas, maze.matrix, maze.path, movement_list) if __name__ == '__main__': # 基础参数 cell_width = 10 rows = 30 cols = 40 height = cell_width * rows width = cell_width * cols level = 1 click_counter = 0 next_maze_flag = False windows = tk.Tk() windows.title("迷宫") canvas = tk.Canvas(windows, background="#F2F2F2", width=width, height=height) canvas.pack() maze = Maze(cols, rows) movement_list = [maze.start] maze.generate_matrix_kruskal() draw_maze(canvas, maze.matrix, maze.path, movement_list) canvas.bind("<Button-1>", _paint) canvas.bind("<Button-3>", _reset) canvas.bind_all("<KeyPress>", _eventHandler) windows.mainloop()