用java写一个俄罗斯方块游戏,只要代码,快点写。

时间: 2023-05-30 15:04:50 浏览: 41
这是一个简单的俄罗斯方块游戏的 Java 代码示例,它使用了 Swing 库来创建图形用户界面: ```java import java.awt.*; import java.util.Random; import javax.swing.*; public class TetrisGame extends JFrame { // 定义游戏界面的大小 private static final int WIDTH = 300; private static final int HEIGHT = 400; // 定义俄罗斯方块的大小和颜色 private static final int BLOCK_SIZE = 20; private static final Color[] COLORS = { Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE, Color.YELLOW }; // 定义游戏区域的宽度和高度(单位:个方块) private static final int PLAY_WIDTH = 10; private static final int PLAY_HEIGHT = 20; // 定义一个二维数组来表示游戏区域 private int[][] playArea; // 当前正在下落的俄罗斯方块 private Tetromino currentTetromino; // 下一个要下落的俄罗斯方块 private Tetromino nextTetromino; // 随机数生成器,用于随机生成俄罗斯方块 private Random random; public TetrisGame() { // 初始化游戏界面 setSize(WIDTH, HEIGHT); setTitle("俄罗斯方块"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 初始化游戏区域 playArea = new int[PLAY_WIDTH][PLAY_HEIGHT]; // 初始化随机数生成器 random = new Random(); // 生成第一个俄罗斯方块和下一个俄罗斯方块 currentTetromino = new Tetromino(random.nextInt(COLORS.length));

相关推荐

好的,以下是一个简单的俄罗斯方块游戏程序的JAVA代码: java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.Random; public class Tetris extends JFrame implements ActionListener { private final int BOARD_WIDTH = 10; private final int BOARD_HEIGHT = 22; private Timer timer; private boolean isFallingFinished = false; private boolean isStarted = false; private boolean isPaused = false; private int numLinesRemoved = 0; private int curX = 0; private int curY = 0; private JLabel statusbar; private Shape curPiece; private Shape.Tetrominoes[] board; public Tetris() { initUI(); } private void initUI() { Board board = new Board(this); add(board); statusbar = new JLabel(" 0"); add(statusbar, BorderLayout.SOUTH); setSize(200, 400); setTitle("Tetris"); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocationRelativeTo(null); } public JLabel getStatusBar() { return statusbar; } public boolean isStarted() { return isStarted; } public boolean isPaused() { return isPaused; } public Shape.Tetrominoes[] getBoard() { return board; } public void start() { if (isPaused) return; isStarted = true; isFallingFinished = false; numLinesRemoved = 0; clearBoard(); newPiece(); timer.start(); } public void pause() { if (!isStarted) return; isPaused = !isPaused; if (isPaused) { timer.stop(); statusbar.setText("paused"); } else { timer.start(); statusbar.setText(String.valueOf(numLinesRemoved)); } repaint(); } private void clearBoard() { for (int i = 0; i < BOARD_HEIGHT * BOARD_WIDTH; i++) { board[i] = Shape.Tetrominoes.NoShape; } } private void newPiece() { curPiece = new Shape(); curX = BOARD_WIDTH / 2 + 1; curY = BOARD_HEIGHT - 1 + curPiece.minY(); if (!tryMove(curPiece, curX, curY)) { curPiece.setShape(Shape.Tetrominoes.NoShape); timer.stop(); isStarted = false; statusbar.setText("game over"); } } private boolean tryMove(Shape newPiece, int newX, int newY) { for (int i = 0; i < 4; i++) { int x = newX + newPiece.x(i); int y = newY - newPiece.y(i); if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) return false; if (shapeAt(x, y) != Shape.Tetrominoes.NoShape) return false; } curPiece = newPiece; curX = newX; curY = newY; repaint(); return true; } private void oneLineDown() { if (!tryMove(curPiece, curX, curY - 1)) pieceDropped(); } private void pieceDropped() { for (int i = 0; i < 4; i++) { int x = curX + curPiece.x(i); int y = curY - curPiece.y(i); board[(y * BOARD_WIDTH) + x] = curPiece.getShape(); } removeFullLines(); if (!isFallingFinished) newPiece(); } private void removeFullLines() { int numFullLines = 0; for (int i = BOARD_HEIGHT - 1; i >= 0; i--) { boolean lineIsFull = true; for (int j = 0; j < BOARD_WIDTH; j++) { if (shapeAt(j, i) == Shape.Tetrominoes.NoShape) { lineIsFull = false; break; } } if (lineIsFull) { numFullLines++; for (int k = i; k < BOARD_HEIGHT - 1; k++) { for (int j = 0; j < BOARD_WIDTH; j++) board[(k * BOARD_WIDTH) + j] = shapeAt(j, k + 1); } } } if (numFullLines > 0) { numLinesRemoved += numFullLines; statusbar.setText(String.valueOf(numLinesRemoved)); isFallingFinished = true; curPiece.setShape(Shape.Tetrominoes.NoShape); } } private Shape.Tetrominoes shapeAt(int x, int y) { return board[(y * BOARD_WIDTH) + x]; } @Override public void actionPerformed(ActionEvent e) { if (isFallingFinished) { isFallingFinished = false; newPiece(); } else { oneLineDown(); } } private void startGame() { isPaused = false; isStarted = true; isFallingFinished = false; numLinesRemoved = 0; clearBoard(); newPiece(); timer.start(); } public static void main(String[] args) { Tetris game = new Tetris(); game.setVisible(true); game.startGame(); } private class Board extends JPanel { private final int SQUARE_SIZE = 20; public Board(ActionListener listener) { setPreferredSize(new Dimension(BOARD_WIDTH * SQUARE_SIZE, BOARD_HEIGHT * SQUARE_SIZE)); setBackground(Color.BLACK); setFocusable(true); addKeyListener(new TAdapter()); timer = new Timer(400, listener); board = new Shape.Tetrominoes[BOARD_WIDTH * BOARD_HEIGHT]; clearBoard(); } private void drawSquare(Graphics g, int x, int y, Shape.Tetrominoes shape) { Color colors[] = {new Color(0, 0, 0), new Color(204, 102, 102), new Color(102, 204, 102), new Color(102, 102, 204), new Color(204, 204, 102), new Color(204, 102, 204), new Color(102, 204, 204), new Color(218, 170, 0) }; Color color = colors[shape.ordinal()]; g.setColor(color); g.fillRect(x + 1, y + 1, SQUARE_SIZE - 2, SQUARE_SIZE - 2); g.setColor(color.brighter()); g.drawLine(x, y + SQUARE_SIZE - 1, x, y); g.drawLine(x, y, x + SQUARE_SIZE - 1, y); g.setColor(color.darker()); g.drawLine(x + 1, y + SQUARE_SIZE - 1, x + SQUARE_SIZE - 1, y + SQUARE_SIZE - 1); g.drawLine(x + SQUARE_SIZE - 1, y + SQUARE_SIZE - 1, x + SQUARE_SIZE - 1, y + 1); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Dimension size = getSize(); int boardTop = (int) size.getHeight() - BOARD_HEIGHT * SQUARE_SIZE; for (int i = 0; i < BOARD_HEIGHT; i++) { for (int j = 0; j < BOARD_WIDTH; j++) { Shape.Tetrominoes shape = shapeAt(j, BOARD_HEIGHT - i - 1); if (shape != Shape.Tetrominoes.NoShape) drawSquare(g, j * SQUARE_SIZE, boardTop + i * SQUARE_SIZE, shape); } } if (curPiece.getShape() != Shape.Tetrominoes.NoShape) { for (int i = 0; i < 4; i++) { int x = curX + curPiece.x(i); int y = curY - curPiece.y(i); drawSquare(g, x * SQUARE_SIZE, boardTop + (BOARD_HEIGHT - y - 1) * SQUARE_SIZE, curPiece.getShape()); } } } } private class TAdapter extends KeyAdapter { @Override public void keyPressed(KeyEvent e) { if (!isStarted || curPiece.getShape() == Shape.Tetrominoes.NoShape) { return; } int keycode = e.getKeyCode(); if (keycode == 'p' || keycode == 'P') { pause(); return; } if (isPaused) return; switch (keycode) { case KeyEvent.VK_LEFT: tryMove(curPiece, curX - 1, curY); break; case KeyEvent.VK_RIGHT: tryMove(curPiece, curX + 1, curY); break; case KeyEvent.VK_DOWN: tryMove(curPiece.rotateRight(), curX, curY); break; case KeyEvent.VK_UP: tryMove(curPiece.rotateLeft(), curX, curY); break; case KeyEvent.VK_SPACE: dropDown(); break; case 'd': oneLineDown(); break; case 'D': oneLineDown(); break; } } } private void dropDown() { int newY = curY; while (newY > 0) { if (!tryMove(curPiece, curX, newY - 1)) break; newY--; } pieceDropped(); } } class Shape { public enum Tetrominoes {NoShape, ZShape, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape} private Tetrominoes pieceShape; private int coords[][]; private int[][][] coordsTable; public Shape() { coords = new int[4][2]; setShape(Tetrominoes.NoShape); } public void setShape(Tetrominoes shape) { coordsTable = new int[][][]{ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, {{0, -1}, {0, 0}, {-1, 0}, {-1, 1}}, {{0, -1}, {0, 0}, {1, 0}, {1, 1}}, {{0, -1}, {0, 0}, {0, 1}, {0, 2}}, {{-1, 0}, {0, 0}, {1, 0}, {0, 1}}, {{0, 0}, {1, 0}, {0, 1}, {1, 1}}, {{-1, -1}, {0, -1}, {0, 0}, {0, 1}}, {{1, -1}, {0, -1}, {0, 0}, {0, 1}} }; for (int i = 0; i < 4; i++) { for (int j = 0; j < 2; ++j) { coords[i][j] = coordsTable[shape.ordinal()][i][j]; } } pieceShape = shape; } private void setX(int index, int x) { coords[index][0] = x; } private void setY(int index, int y) { coords[index][1] = y; } public int x(int index) { return coords[index][0]; } public int y(int index) { return coords[index][1]; } public Tetrominoes getShape() { return pieceShape; } public void setRandomShape() { Random r = new Random(); int x = Math.abs(r.nextInt()) % 7 + 1; Tetrominoes[] values = Tetrominoes.values(); setShape(values[x]); } public int minX() { int m = coords[0][0]; for (int i = 0; i < 4; i++) { m = Math.min(m, coords[i][0]); } return m; } public int minY() { int m = coords[0][1]; for (int i = 0; i < 4; i++) { m = Math.min(m, coords[i][1]); } return m; } public Shape rotateLeft() { if (pieceShape == Tetrominoes.SquareShape) return this; Shape result = new Shape(); result.pieceShape = pieceShape; for (int i = 0; i < 4; ++i) { result.setX(i, y(i)); result.setY(i, -x(i)); } return result; } public Shape rotateRight() { if (pieceShape == Tetrominoes.SquareShape) return this; Shape result = new Shape(); result.pieceShape = pieceShape; for (int i = 0; i < 4; ++i) { result.setX(i, -y(i)); result.setY(i, x(i)); } return result; } } 这个程序使用了 Java Swing 框架来创建游戏界面和用户交互,实现了俄罗斯方块的基本功能。
### 回答1: 代码示例: # 引入必要的模块 import pygame import random # 定义常量 BLOCKSIZE = 20 BOARDWIDTH = 10 BOARDHEIGHT = 20 FPS = 10 # 定义颜色 BLACK = (0, 0, 0) WHITE = (255, 255, 255) # 初始化pygame pygame.init() # 设置游戏窗口 windowSurface = pygame.display.set_mode((BOARDWIDTH * BLOCKSIZE, BOARDHEIGHT * BLOCKSIZE)) pygame.display.set_caption('俄罗斯方块') # 加载游戏图片 blockImg = pygame.image.load('block.png') # 定义游戏变量 blockX = BOARDWIDTH // 2 blockY = 0 blockDir = 0 # 定义游戏主循环 while True: # 检查游戏事件 for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: # 控制方块的移动 if event.key == K_LEFT and blockX > 0: blockX -= 1 elif event.key == K_RIGHT and blockX < BOARDWIDTH - 1: blockX += 1 elif event.key == K_UP and blockY > 0: blockY -= 1 elif event.key == K_DOWN and blockY < BOARDHEIGHT - 1: blockY += 1 elif event.key == K_SPACE: # 旋转方块 blockDir = (blockDir + 1) % 4 # 绘制游戏背景 windowSurface.fill(BLACK) # 绘制方块 drawBlock(blockX, blockY, blockDir) # 刷新游戏窗口 pygame.display.update() # 设置帧率 fpsClock.tick(FPS) ### 回答2: 俄罗斯方块是一款经典的益智游戏,玩家需要操控不同形状的方块,使其在屏幕上形成完整的一行或多行,以获得分数。以下是一个简单的俄罗斯方块游戏的代码示例: # 导入必要的模块 import pygame import random # 初始化游戏 pygame.init() WIDTH, HEIGHT = 800, 600 win = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("俄罗斯方块") # 定义方块和游戏区域的尺寸 block_size = 30 play_width, play_height = 10 * block_size, 20 * block_size play_x, play_y = (WIDTH - play_width) // 2, (HEIGHT - play_height) play_surface = pygame.Surface((play_width, play_height)) # 定义方块的形状 shapes = [ [[1, 1, 1, 1]], # I形状 [[1, 1], [1, 1]], # O形状 [[1, 0, 0], [1, 1, 1]], # L形状 [[0, 0, 1], [1, 1, 1]], # J形状 [[1, 1, 0], [0, 1, 1]], # S形状 [[0, 1, 1], [1, 1, 0]], # Z形状 [[1, 1, 1], [0, 1, 0]], # T形状 ] # 定义方块类 class Block: def __init__(self, x, y, shape): self.x = x self.y = y self.shape = shape self.color = (random.randint(50, 255), random.randint(50, 255), random.randint(50, 255)) def draw(self): for i in range(len(self.shape)): for j in range(len(self.shape[0])): if self.shape[i][j]: pygame.draw.rect(play_surface, self.color, (self.x + j * block_size, self.y + i * block_size, block_size, block_size)) # 游戏主循环 run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False play_surface.fill((0, 0, 0)) # 绘制方块及游戏区域 block = Block(0, 0, random.choice(shapes)) block.draw() play_surface.blit(block, (0, 0)) win.blit(play_surface, (play_x, play_y)) pygame.display.update() pygame.quit() 注意,这只是一个迷你版的俄罗斯方块游戏代码示例,其中只包括了方块的绘制和游戏区域的更新,还没有包括方块的移动、消除行等功能。如果你想要完整的俄罗斯方块游戏,还需要添加更多的逻辑和功能实现。 ### 回答3: 在这里提供一个简单的俄罗斯方块游戏代码: python import pygame import random # 初始化pygame pygame.init() # 窗口大小 window_width = 800 window_height = 600 # 定义方块大小 block_size = 30 # 定义颜色 black = (0, 0, 0) white = (255, 255, 255) blue = (0, 0, 255) red = (255, 0, 0) green = (0, 255, 0) # 创建游戏窗口 window = pygame.display.set_mode((window_width, window_height)) pygame.display.set_caption("俄罗斯方块") # 定义方块类 class Block: def __init__(self, x, y): self.x = x self.y = y def draw(self): pygame.draw.rect(window, blue, (self.x, self.y, block_size, block_size)) def move_down(self): self.y += block_size def move_left(self): self.x -= block_size def move_right(self): self.x += block_size # 创建一个方块 block = Block(window_width // 2, 0) # 游戏循环 running = True while running: # 设置窗口背景颜色 window.fill(white) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: block.move_left() elif event.key == pygame.K_RIGHT: block.move_right() elif event.key == pygame.K_DOWN: block.move_down() # 绘制方块 block.draw() # 更新窗口 pygame.display.update() # 退出游戏 pygame.quit() 这是一个基本的俄罗斯方块游戏代码,游戏窗口大小为800x600像素。在游戏循环中,根据事件监听键盘的左右和下方向键,移动方块的位置,并通过调用方块的绘制方法将方块绘制在窗口上。 请注意,这只是一个基本的示例代码,不包括游戏的其他功能,如方块的旋转、消行、计分等,实际的游戏开发中可能需要更多的代码和功能实现。
### 回答1: 好的,我可以帮你解决这个问题。以下是Java实现经典游戏“俄罗斯方块”的简单步骤: 1.创建一个游戏窗口。 2.创建方块的形状和位置,包括旋转和下落。 3.监听按键事件,让方块移动和旋转。 4.控制方块下落的速度。 5.检测方块与其他方块的碰撞,实现方块的合并。 6.实现游戏结束的判断。 7.计分和级别的设定。 通过以上步骤,就可以完成一个简单的俄罗斯方块游戏的编写。希望对你有帮助。 ### 回答2: 俄罗斯方块是一款经典的游戏,可以用Java编程语言来实现。 首先,我们需要创建一个游戏窗口,可以使用Java窗体组件来实现,例如JFrame。游戏窗口的大小可以根据需要设置,以适应游戏界面。 接下来,我们需要定义方块的形状,可以使用二维数组来表示。每个方块可以由几个小方块组成,我们可以用数字0或1来表示方块是否存在。 然后,我们需要实现方块的移动和旋转功能。可以通过监听键盘事件来实现方向键的控制,按下左右方向键可以使方块水平移动,按下下方向键可以使方块垂直下落,按下上方向键可以使方块进行旋转。在每次移动或旋转后,我们需要更新方块的位置和形状。 同时,我们需要检测方块是否与其他方块碰撞,从而决定是否可以继续移动或旋转。可以通过判断方块的位置和周围方块的状态来实现。当方块无法继续下落或移动时,我们需要将方块固定在游戏界面中,并生成新的方块。 游戏中还可以加入计分系统,记录玩家的得分和等级。当方块被固定时,可以根据固定的方块数量和消除的行数来计算玩家的得分,并根据得分来提升玩家的等级。 最后,我们可以加入音效和游戏结束的判断。当固定的方块超出游戏界面时,游戏结束,并弹出游戏结束的提示框。 通过以上步骤,我们可以使用Java编程语言来实现一个简单的俄罗斯方块游戏。当然,还可以根据需要进行功能扩展,增加游戏的可玩性和乐趣。 ### 回答3: 用Java写一个俄罗斯方块游戏是一个很有趣的编程挑战。首先,需要创建一个图形用户界面(GUI),使玩家能够与游戏进行交互。可以使用Java的Swing库来实现GUI组件的绘制和事件处理。 在游戏开始时,需要创建一个空白的游戏区域,通常是一个矩形网格。可以使用一个二维数组来表示游戏区域的状态,每个方块的位置有一个对应的数组元素。初始时所有数组元素都为空。 接下来,需要定义不同形状的俄罗斯方块及其旋转状态。可以使用枚举类型或类来表示每个方块的形状和旋转状态。根据方块的形状和位置,可以更新游戏区域的状态数组。 游戏中需要实现方块的移动、旋转和下落功能。可以使用定时器来定期触发方块的下落操作,或者通过键盘事件监听来实现玩家控制方块的移动和旋转。 当一个方块无法再下落时,需要判断是否有满行的方块。如果有满行的方块,需要将该行删除,上面的方块下移,并更新游戏得分。此外,还要判断游戏是否结束,即当有方块堆满整个游戏区域时游戏结束。 最后,可以在游戏界面显示当前得分、下一个方块的形状等信息,以增强游戏体验。同时,还可以添加音效和动画效果,使游戏更加生动有趣。 总的来说,用Java写一个俄罗斯方块需要理解游戏规则和机制,设计合适的数据结构和算法,以及熟悉JAVA GUI开发和事件处理。通过不断的练习和改进,可以编写出一个功能完善的俄罗斯方块游戏。

最新推荐

Python小游戏之300行代码实现俄罗斯方块

主要给大家介绍了关于Python小游戏之300行代码实现俄罗斯方块的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧

JSP+sql实验教学管理系统(系统+论文+开题报告+封面+中期检查表+英文文献).zip

JSP+sql实验教学管理系统(系统+论文+开题报告+封面+中期检查表+英文文献)

ChatGPT技术在人工智能教育中的应用展望.docx

ChatGPT技术在人工智能教育中的应用展望

直播弹幕互动游戏,可二次开发,有源码,可任意修改和换皮.rar

直播弹幕互动游戏,可二次开发,有源码,可任意修改和换皮

Java 开发中型购物系统 +数据库.rar

Java 开发中型购物系统 +数据库

基于at89c51单片机的-智能开关设计毕业论文设计.doc

基于at89c51单片机的-智能开关设计毕业论文设计.doc

"蒙彼利埃大学与CNRS联合开发细胞内穿透载体用于靶向catphepsin D抑制剂"

由蒙彼利埃大学提供用于靶向catphepsin D抑制剂的细胞内穿透载体的开发在和CNRS研究单位- UMR 5247(马克斯·穆塞隆生物分子研究专长:分子工程由Clément Sanchez提供于2016年5月26日在评审团面前进行了辩护让·吉隆波尔多大学ARNA实验室CNRS- INSERM教授报告员塞巴斯蒂安·帕波特教授,CNRS-普瓦捷大学普瓦捷介质和材料化学研究所报告员帕斯卡尔·拉斯特洛教授,CNRS-审查员让·马丁内斯蒙彼利埃大学Max Mousseron生物分子研究所CNRS教授审查员文森特·利索夫斯基蒙彼利埃大学Max Mousseron生物分子研究所CNRS教授论文主任让-弗朗索瓦·赫尔南德斯CNRS研究总监-蒙彼利埃大学Max Mousseron生物分子研究论文共同主任由蒙彼利埃大学提供用于靶向catphepsin D抑制剂的细胞内穿透载体的开发在和CNRS研究单位- UMR 5247(马克斯·穆塞隆生物分子研究专长:分子工程由Clément Sanchez提供�

设计一个程序有一个字符串包含n个字符 写一个函数 将此字符串中从第m个字符开始的全部字符复制成为另一个字符串 用指针c语言

以下是用指针实现将字符串中从第m个字符开始的全部字符复制成为另一个字符串的C语言程序: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> void copyString(char *a, char *b, int n, int m); int main() { int n, m; char *a, *b; printf("请输入字符串长度n:"); scanf("%d", &n); a = (char*)malloc(n * sizeof(char)); b =

基于C#多机联合绘图软件的实现-毕业设计论文.doc

基于C#多机联合绘图软件的实现-毕业设计论文.doc

4G车载网络中无线电资源的智能管理

4G车载网络中无线电资源的智能管理汽车网络从4G到5G的5G智能无线电资源管理巴黎萨克雷大学博士论文第580号博士学院博士专业:网络、信息与通信研究单位:巴黎萨克雷大学,UVSQ,LI PARAD,78180,法国伊夫林省圣昆廷参考:凡尔赛大学-伊夫林省圣昆廷论文于11月30日在巴黎萨克雷发表并答辩2021年,由玛丽亚姆·阿卢奇·马迪陪审团组成Pascal Lorenz总裁上阿尔萨斯大学大学教授Mohamed Yacine Ghamri-Doudane拉罗谢尔大学报告员和审查员教授Rami Langar报告员和审查员马恩河谷大学Oyunchimeg SHAGDARVEDECOM研发(HDR)团队负责人审查员论文方向Samir TOHME博士生导师巴黎萨克雷大学名誉教授UVSQ/LI- PARADKALLEL KHEMIRI共同监督巴黎萨克雷UVSQ/大卫Guy Pujolle受邀索邦大学Tara Yahiya邀请巴黎萨克雷大学/LISN高级讲师(HDR)博士论文NNT:2021UPASG061谢谢你首先,我要感谢我的论文导师M.萨米�