java贪吃蛇实验报告(实验二 贪吃蛇java实现)
今天给各位分享java贪吃蛇实验报告的知识,其中也会对实验二 贪吃蛇java实现进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
Java 编写贪吃蛇游戏的大体思路是什么
楼主没有看到蛇移动的本质,蛇虽然是分成很多块,但他们还是一个整体,每一块的移动都和上一块有关,所以不需要对每一块都进行判断。\x0d\x0a原理:\x0d\x0a把蛇身体的每一块看成一个对象(对象存储该块的坐标和相关信息),作为节点存储在线性链表中,再设置一个变量标志蛇的方向(通过按键可以改变)。一般人都是让每一个节点等于他指向的下一个节点,并让头节点改变位置来实现转弯和移动,这个算法复杂度太高(O(n)),实际上只要做两步操作,插入一个头节点,删除一个尾节点就可以了,新插入的头节点位置根据蛇当前的方向决定用一个数组将蛇头的行径记录下来,然后第二段的下一个方格设置为蛇头走过的方格,这样子蛇走过的路径都是前一段走过的,最后将跟着蛇头走了,比如\x0d\x0a蛇身的路径\x0d\x0a for(int i=snakeLength-1;i>0;i--){\x0d\x0arows[i]=rows[i-1];//依次将蛇前面一段走过行的路段赋值给蛇的下一段\x0d\x0acols[i]=cols[i-1];//依次将蛇前面一段走过列的路段赋值给蛇的下一段\x0d\x0a}\x0d\x0afor(int i=1;i 设计游戏,首先就要设计界面。首先看一下我设计的一个界面。界面分为左边的游戏区与右边的控制区。游戏区包含“得分信息”和贪吃蛇的游戏区,右边控制区有“开始”“暂停”“停止”按钮,等级选择单选框以及游戏排行榜。 所以我们需要定义swing组件,并在类初始化时初始化这些组件,添加组件。因为后面设计游戏的时候,我们要确切知道游戏区的大小,所以这里设置游戏区固定大小值。本来想用布局来更好的管理,但作者对布局也掌握不够,所以就先设置固定大小吧。 定义我们的游戏。贪吃蛇游戏其实就是包含很多细小网格,然后蛇在网格中移动。蛇由一连串的网格组成,为了视觉效果,蛇身用蓝色标记,食物用红色标记,背景白色。如第一张图片所示。所以,我们需要定义二维数组,保存网格信息,保存蛇身和食物的位置信息等。初始化时,还需要添加键盘事件控制上下左右移动。 食物的位置信息是二维的,所以我简单定义了一个类用来保存二维信息。 接着就是实现游戏的功能了。开始,暂停,停止按钮添加事件控制游戏开始。等级按钮定义游戏难度等。 开始游戏后,我们定义一个定时器。蛇身按照指定的方向移动,方向是通过初始化时添加的键盘事件,键盘的上下左右按钮来控制。蛇身是连续的位置信息,保存到队列中,所以蛇身的移动就是队首增加一个位置,队尾减少位置,然后重新绘画游戏区就可以了。 在蛇身移动时进一步做吃掉食物、撞墙、撞到自己的处理。这是游戏的主要逻辑。 最后,游戏结束我们弹出一个对话框提示是否保存游戏得分。我们制作了排行榜信息,只保留前10名的游戏得分。首先定义了一个实现Comparable接口的游戏得分类,按得分高,时间最早来排序。 游戏结束时保存得分信息,看是否进入到排行榜中。而之前在初始化排行榜组件时就会加载游戏排行榜信息。 通过保存和读取排行榜信息,我们也熟悉一下文件读取操作,还有集合、排序算法的功能。 用MVC方式实现的贪吃蛇游戏,共有4个类。运行GreedSnake运行即可。主要是观察者模式的使用,我已经添加了很多注释了。 1、 /* *程序名称:贪食蛇 *原作者:BigF *修改者:algo *说明:我以前也用C写过这个程序,现在看到BigF用Java写的这个,发现虽然作者自称是Java的初学者, *但是明显编写程序的素养不错,程序结构写得很清晰,有些细微得地方也写得很简洁,一时兴起之 *下,我认真解读了这个程序,发现数据和表现分开得很好,而我近日正在学习MVC设计模式, *因此尝试把程序得结构改了一下,用MVC模式来实现,对源程序得改动不多。 *我同时也为程序增加了一些自己理解得注释,希望对大家阅读有帮助。 */ package mvcTest; /** *@author WangYu *@version 1.0 * Description: *</pre> * Create on:Date:2005-6-13 Time:15:57:16 * LastModified: * History: */ public class GreedSnake{ public static void main(String[] args){ SnakeModel model= new SnakeModel(20,30); SnakeControl control= new SnakeControl(model); SnakeView view= new SnakeView(model,control); //添加一个观察者,让view成为model的观察者 model.addObserver(view); (new Thread(model)).start(); } } ------------------------------------------------------------- 2、 package mvcTest; //SnakeControl.java import java.awt.event.KeyEvent; import java.awt.event.KeyListener; /** * MVC中的Controler,负责接收用户的操作,并把用户操作通知Model */ public class SnakeControl implements KeyListener{ SnakeModel model; public SnakeControl(SnakeModel model){ this.model= model; } public void keyPressed(KeyEvent e){ int keyCode= e.getKeyCode(); if(model.running){//运行状态下,处理的按键 switch(keyCode){ case KeyEvent.VK_UP: model.changeDirection(SnakeModel.UP); break; case KeyEvent.VK_DOWN: model.changeDirection(SnakeModel.DOWN); break; case KeyEvent.VK_LEFT: model.changeDirection(SnakeModel.LEFT); break; case KeyEvent.VK_RIGHT: model.changeDirection(SnakeModel.RIGHT); break; case KeyEvent.VK_ADD: case KeyEvent.VK_PAGE_UP: model.speedUp(); break; case KeyEvent.VK_SUBTRACT: case KeyEvent.VK_PAGE_DOWN: model.speedDown(); break; case KeyEvent.VK_SPACE: case KeyEvent.VK_P: model.changePauseState(); break; default: } } //任何情况下处理的按键,按键导致重新启动游戏 if(keyCode== KeyEvent.VK_R|| keyCode== KeyEvent.VK_S|| keyCode== KeyEvent.VK_ENTER){ model.reset(); } } public void keyReleased(KeyEvent e){ } public void keyTyped(KeyEvent e){ } } ------------------------------------------------------------- 3、 /* * */ package mvcTest; /** *游戏的Model类,负责所有游戏相关数据及运行 *@author WangYu *@version 1.0 * Description: *</pre> * Create on:Date:2005-6-13 Time:15:58:33 * LastModified: * History: */ //SnakeModel.java import javax.swing.*; import java.util.Arrays; import java.util.LinkedList; import java.util.Observable; import java.util.Random; /** *游戏的Model类,负责所有游戏相关数据及运行 */ class SnakeModel extends Observable implements Runnable{ boolean[][] matrix;//指示位置上有没蛇体或食物 LinkedList nodeArray= new LinkedList();//蛇体 Node food; int maxX; int maxY; int direction= 2;//蛇运行的方向 boolean running= false;//运行状态 int timeInterval= 200;//时间间隔,毫秒 double speedChangeRate= 0.75;//每次得速度变化率 boolean paused= false;//暂停标志 int score= 0;//得分 int countMove= 0;//吃到食物前移动的次数 // UP and DOWN should be even // RIGHT and LEFT should be odd public static final int UP= 2; public static final int DOWN= 4; public static final int LEFT= 1; public static final int RIGHT= 3; public SnakeModel( int maxX, int maxY){ this.maxX= maxX; this.maxY= maxY; reset(); } public void reset(){ direction= SnakeModel.UP;//蛇运行的方向 timeInterval= 200;//时间间隔,毫秒 paused= false;//暂停标志 score= 0;//得分 countMove= 0;//吃到食物前移动的次数 // initial matirx,全部清0 matrix= new boolean[maxX][]; for(int i= 0; i< maxX;++i){ matrix[i]= new boolean[maxY]; Arrays.fill(matrix[i], false); } // initial the snake //初始化蛇体,如果横向位置超过20个,长度为10,否则为横向位置的一半 int initArrayLength= maxX> 20? 10: maxX/ 2; nodeArray.clear(); for(int i= 0; i< initArrayLength;++i){ int x= maxX/ 2+ i;//maxX被初始化为20 int y= maxY/ 2;//maxY被初始化为30 //nodeArray[x,y]: [10,15]-[11,15]-[12,15]~~[20,15] //默认的运行方向向上,所以游戏一开始nodeArray就变为: // [10,14]-[10,15]-[11,15]-[12,15]~~[19,15] nodeArray.addLast(new Node(x, y)); matrix[x][y]= true; } //创建食物 food= createFood(); matrix[food.x][food.y]= true; } public void changeDirection(int newDirection){ //改变的方向不能与原来方向同向或反向 if(direction% 2!= newDirection% 2){ direction= newDirection; } } /** *运行一次 *@return */ public boolean moveOn(){ Node n=(Node) nodeArray.getFirst(); int x= n.x; int y= n.y; //根据方向增减坐标值 switch(direction){ case UP: y--; break; case DOWN: y++; break; case LEFT: x--; break; case RIGHT: x++; break; } //如果新坐标落在有效范围内,则进行处理 if((0<= x&& x< maxX)&&(0<= y&& y< maxY)){ if(matrix[x][y]){//如果新坐标的点上有东西(蛇体或者食物) if(x== food.x&& y== food.y){//吃到食物,成功 nodeArray.addFirst(food);//从蛇头赠长 //分数规则,与移动改变方向的次数和速度两个元素有关 int scoreGet=(10000- 200* countMove)/ timeInterval; score+= scoreGet> 0? scoreGet: 10; countMove= 0; food= createFood();//创建新的食物 matrix[food.x][food.y]= true;//设置食物所在位置 return true; } else//吃到蛇体自身,失败 return false; } else{//如果新坐标的点上没有东西(蛇体),移动蛇体 nodeArray.addFirst(new Node(x, y)); matrix[x][y]= true; n=(Node) nodeArray.removeLast(); matrix[n.x][n.y]= false; countMove++; return true; } } return false;//触到边线,失败 } public void run(){ running= true; while(running){ try{ Thread.sleep(timeInterval); } catch(Exception e){ break; } if(!paused){ if(moveOn()){ setChanged();// Model通知View数据已经更新 notifyObservers(); } else{ JOptionPane.showMessageDialog(null, "you failed", "Game Over", JOptionPane.INFORMATION_MESSAGE); break; } } } running= false; } private Node createFood(){ int x= 0; int y= 0; //随机获取一个有效区域内的与蛇体和食物不重叠的位置 do{ Random r= new Random(); x= r.nextInt(maxX); y= r.nextInt(maxY); } while(matrix[x][y]); return new Node(x, y); } public void speedUp(){ timeInterval*= speedChangeRate; } public void speedDown(){ timeInterval/= speedChangeRate; } public void changePauseState(){ paused=!paused; } public String toString(){ String result=""; for(int i= 0; i< nodeArray.size();++i){ Node n=(Node) nodeArray.get(i); result+="["+ n.x+","+ n.y+"]"; } return result; } } class Node{ int x; int y; Node(int x, int y){ this.x= x; this.y= y; } } ------------------------------------------------------------ 4、 package mvcTest; //SnakeView.java import javax.swing.*; import java.awt.*; import java.util.Iterator; import java.util.LinkedList; import java.util.Observable; import java.util.Observer; /** * MVC模式中得Viewer,只负责对数据的显示,而不用理会游戏的控制逻辑 */ public class SnakeView implements Observer{ SnakeControl control= null; SnakeModel model= null; JFrame mainFrame; Canvas paintCanvas; JLabel labelScore; public static final int canvasWidth= 200; public static final int canvasHeight= 300; public static final int nodeWidth= 10; public static final int nodeHeight= 10; public SnakeView(SnakeModel model, SnakeControl control){ this.model= model; this.control= control; mainFrame= new JFrame("GreedSnake"); Container cp= mainFrame.getContentPane(); //创建顶部的分数显示 labelScore= new JLabel("Score:"); cp.add(labelScore, BorderLayout.NORTH); //创建中间的游戏显示区域 paintCanvas= new Canvas(); paintCanvas.setSize(canvasWidth+ 1, canvasHeight+ 1); paintCanvas.addKeyListener(control); cp.add(paintCanvas, BorderLayout.CENTER); //创建底下的帮助栏 JPanel panelButtom= new JPanel(); panelButtom.setLayout(new BorderLayout()); JLabel labelHelp; labelHelp= new JLabel("PageUp, PageDown for speed;", JLabel.CENTER); panelButtom.add(labelHelp, BorderLayout.NORTH); labelHelp= new JLabel("ENTER or R or S for start;", JLabel.CENTER); panelButtom.add(labelHelp, BorderLayout.CENTER); labelHelp= new JLabel("SPACE or P for pause", JLabel.CENTER); panelButtom.add(labelHelp, BorderLayout.SOUTH); cp.add(panelButtom, BorderLayout.SOUTH); mainFrame.addKeyListener(control); mainFrame.pack(); mainFrame.setResizable(false); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainFrame.setVisible(true); } void repaint(){ Graphics g= paintCanvas.getGraphics(); //draw background g.setColor(Color.WHITE); g.fillRect(0, 0, canvasWidth, canvasHeight); // draw the snake g.setColor(Color.BLACK); LinkedList na= model.nodeArray; Iterator it= na.iterator(); while(it.hasNext()){ Node n=(Node) it.next(); drawNode(g, n); } // draw the food g.setColor(Color.RED); Node n= model.food; drawNode(g, n); updateScore(); } private void drawNode(Graphics g, Node n){ g.fillRect(n.x* nodeWidth, n.y* nodeHeight, nodeWidth- 1, nodeHeight- 1); } public void updateScore(){ String s="Score:"+ model.score; labelScore.setText(s); } public void update(Observable o, Object arg){ repaint(); } } ------------------------------------------------------------- 关于java贪吃蛇实验报告和实验二 贪吃蛇java实现的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。如何用Java语言写一个贪吃蛇游戏
用JAVA设计游戏:贪吃蛇游戏