小游戏---贪吃蛇
来源:互联网 发布:c语言 stdio.h 编辑:程序博客网 时间:2024/06/16 19:00
这几天一直在写贪吃蛇小游戏,ACM都没时间去做,但是收获还是很大的。程序中包函了线程、监听、界面的应用,最大的困难的如何实现动画,经过反复修改,感觉采用线程的方法是最好控制的。动画是通过JPanel.updateUI()函数来重画,每各一定时间重画一下,就形成了动画效果。很假O(∩_∩)O哈哈~….
//package 课后练习.d1104;import java.awt.Color;import java.awt.Container;import java.awt.FlowLayout;import java.awt.Graphics;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.util.Iterator;import java.util.LinkedList;import java.util.Random;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;import javax.swing.JPanel;public class Snake extends JFrame implements KeyListener{ private final int JPS_WIDTH = 400;//蛇活动范围的宽度 private final int JPS_HEIGHT = 400;//蛇活动范围的高度 private JLabel lbScore;//显示得分的标签 private SnakeJPanel snakePanel;//蛇活动的面板 private SnakeList S_List;//实现Runnable接口成动画的关键 //存放蛇身体每个节点的链表 private LinkedList<Point> snakeList = new LinkedList<Point>(); Point food;//食物 public Snake() { setTitle("贪吃蛇"); setBounds(450, 150, 410, 485);//窗口大小需要自己调... setDefaultCloseOperation(EXIT_ON_CLOSE); setResizable(false);//设置不可改变大小 addKeyListener(this);//添加键盘监听 Container contentPane = getContentPane();//获取内容窗格 contentPane.setLayout(null);//设置空布局 //从新开始 JMenuBar bar = new JMenuBar();//创建菜单栏 setJMenuBar(bar);//给框架添加菜单栏 bar.setLayout(new FlowLayout(FlowLayout.LEFT)); JMenuItem afresh = new JMenuItem("从新开始");//创建菜单项 afresh.addActionListener(new ActionListener() {//添加监听 @Override public void actionPerformed(ActionEvent e) { S_List.running=false; snakeList = new LinkedList<Point>(); begin(); } }); bar.add(afresh);//菜单栏添加菜单项 //帮助 JMenuItem help = new JMenuItem("帮助");//创建菜单项 help.addActionListener(new ActionListener() {//添加监听 @Override public void actionPerformed(ActionEvent e) { S_List.changeCondition(); JOptionPane.showMessageDialog(Snake.this, "向上按 ↑ 键\n向下按 ↓ 键\n" + "向左按 ← 键\n向右按 → 键\n按空格键暂停"); S_List.changeCondition(); } }); bar.add(help);//菜单栏添加菜单项 JPanel scorePanel = new JPanel();//创建存放得分标签的面板 scorePanel.setSize(JPS_WIDTH, 30);//设置位置和大小 lbScore = new JLabel("得分:0");//创建得分标签 scorePanel.add(lbScore);//添加得分标签到面板上 contentPane.add(scorePanel);//得分面板添加到内容窗格 snakePanel = new SnakeJPanel();//创建蛇活动面板 snakePanel.setBounds(0, 30 , JPS_WIDTH, JPS_HEIGHT);//设置位置和大小 contentPane.add(snakePanel);//蛇活动面板添加到内容窗格 setVisible(true); begin();//实现动画的关键 } public JLabel getLbScore() { return lbScore; } public SnakeJPanel getSnakePanel() { return snakePanel; } public LinkedList<Point> getSnakeList() { return snakeList; } public int getJPS_WIDTH() { return JPS_WIDTH; } public int getJPS_HEIGHT() { return JPS_HEIGHT; } //实现动画:采用线程,让线程sleep一定的时间,然后更新面板从而实现动画 private void begin() { if (S_List==null||S_List.running==false) { S_List = new SnakeList(this); new Thread(S_List).start(); } } //画每一瞬间的蛇与食物 class SnakeJPanel extends JPanel { @Override public void paint(Graphics g) { g.setColor(Color.WHITE);//设置画笔颜色 g.fillRect(0, 0, JPS_WIDTH, JPS_HEIGHT);//设置背景颜色 g.setColor(Color.GREEN);//设置画笔颜色 if (snakeList == null) {//卫条件 return; } Iterator<Point> it = snakeList.iterator();//通过迭代器获取链表中的每个节点 while (it.hasNext()) { Point p = it.next(); g.fillRect(p.x*10, p.y*10, 9, 9); } if (food == null) {//卫条件 return; } g.setColor(Color.black); g.fillRect(food.x*10, food.y*10, 9, 9); } } @Override public void keyTyped(KeyEvent e) { } //实现键盘监听 @Override public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); switch (keyCode) { case KeyEvent.VK_UP: S_List.changDirection(SnakeList.UP); break; case KeyEvent.VK_DOWN: S_List.changDirection(SnakeList.DOWN); break; case KeyEvent.VK_LEFT: S_List.changDirection(SnakeList.LEFT); break; case KeyEvent.VK_RIGHT: S_List.changDirection(SnakeList.RIGHT); break; case KeyEvent.VK_SPACE: S_List.changeCondition(); break; default: break; } } @Override public void keyReleased(KeyEvent e) { } //主函数 public static void main(String[] args) { Snake snake = new Snake(); }}//实现Runnable接口,动态改变蛇的位置和食物的位置,以便实现动画class SnakeList implements Runnable { private int w;// 活动区间的宽度 private int h;// 活动区间的高度 private boolean[][] matrix;// 活动区间 matrix[i][j]为真说明该点有东西(食物/蛇身节点) private Snake snake;// 框架 private LinkedList<Point> list;// 蛇身 private int direction;// 方向 // UP和DOWN是偶数,RIGHT和LEFT是奇数,避免冲突,例如向上跑时按向上或者向下是无法改变蛇的跑动方向 public static final int UP = 2; public static final int DOWN = 4; public static final int LEFT = 1; public static final int RIGHT = 3; boolean running;//判断游戏是否结束 boolean isPause = true;//判断游戏是否暂停 private long time = 200;//sleep时间(单位是毫米) private int score;//得分 public SnakeList(Snake snake) { //构造传参 this.snake = snake; list = snake.getSnakeList(); w = snake.getJPS_WIDTH(); h = snake.getJPS_HEIGHT(); matrix = new boolean[w / 10][h / 10]; direction = 1;// 初始方向向左 running = true; isPause = false; initlist();//初始化蛇 } //初始化蛇的函数 public void initlist() { int x = h / 20; int y = w / 20; for (int i = 0; i < 10; i++) { Point point = new Point((x + i) , y ); matrix[x + i][y] = true; list.add(point); } createFood(); } //创建食物:通过调用Random是食物随机出现 public void createFood() { int x = 0; int y = 0; do { Random random = new Random(); x = random.nextInt(w / 10);//随机数的范围0 ~ w/10 y = random.nextInt(h / 10); } while (matrix[x][y]);// 如果matrix[x][y]为真说明这是蛇身不能从新创建食物 snake.food = new Point(x, y); matrix[x][y] = true; } //关键函数,控制蛇位置函数 public boolean move() { Point first = list.getFirst();//通过头节点来控制蛇运动方向 int x = first.x; int y = first.y; switch (direction) { case LEFT: x--; break; case RIGHT: x++; break; case UP: y--; break; case DOWN: y++; } if (0 <= x && x < w / 10 && 0 <= y && y < h / 10) {//如果在活动区间说明蛇不是撞墙死的 if(matrix[x][y]){//matrix[x][y]为真说明这个位置要么是食物,要么是自己身体的某个节点 if(x==snake.food.x&&y==snake.food.y){//能进来说明是食物 score += (int)1000/time+list.size();//结算得分 list.addFirst(snake.food); createFood();//创建新的食物 return true;//蛇没死 }else{ //System.out.println("撞自己"); return false; } } //能到这里说明matrix[x][y]值为假,此时该点应该是蛇头到达的点 Point point = new Point(x, y); matrix[x][y] = true; list.addFirst(point); point=list.removeLast();//同时蛇尾应该变成它的上一个节点 matrix[point.x][point.y] = false; return true;//蛇没死 } //System.out.println("撞墙"); return false; } //不能180度转弯 public void changDirection(int dcn){ if(dcn%2!=direction%2){ direction = dcn; } }// public void up(){// direction = UP;// }// public void down(){// direction = DOWN;// }// public void left(){// direction = LEFT;// }// public void right(){// direction = RIGHT;// } //改变蛇状态函数 public void changeCondition(){ isPause = !isPause; } //重写run方法 @Override public void run() { while(running){ try {//这里只是控制蛇的移动速度,当分数达到一定值时,蛇移速变快 if (score>222) { Thread.sleep(time/2); }else if(score>666){ Thread.sleep(time/3); }else{ Thread.sleep(time); } } catch (InterruptedException e) { e.printStackTrace(); } if(!isPause){ if (move()) { snake.getSnakePanel().updateUI(); snake.getLbScore().setText("得分:"+score); continue; } JOptionPane.showMessageDialog(null, "游戏结束!"); running = false; } } }}class Point { int x; int y; public Point(int x, int y) { this.x = x; this.y = y; }}
阅读全文
0 0
- 小游戏 贪吃蛇
- 贪吃蛇小游戏
- 贪吃蛇小游戏
- 贪吃蛇小游戏
- Applet贪吃蛇小游戏
- 贪吃蛇小游戏记录:
- 贪吃蛇小游戏笔记
- [小游戏]贪吃蛇
- 经典贪吃蛇小游戏
- 贪吃蛇小游戏~
- 【java】贪吃蛇小游戏
- 【java】贪吃蛇小游戏
- javascript贪吃蛇小游戏
- 贪吃蛇简单小游戏
- java贪吃蛇小游戏
- javascript贪吃蛇小游戏
- JS-贪吃蛇小游戏
- js贪吃蛇小游戏
- 编写过滤器,完成对bmp图片的信息隐写操作和读取
- matplotlib函数库使用contour绘制等高线图形
- 防止tableview下移
- 伤害网站seo的javascript技术
- libsvm库简介及使用
- 小游戏---贪吃蛇
- HTML百度首页
- ios-ARC和MRC混编问题
- Android ViewPager轮播
- 洛谷P2331 [SCOI2005]最大子矩阵(BZOJ1084)
- 2017ICPC青岛区域赛-后感
- Android逆向之某游单机SDK破解
- 数据结构与算法分析(Java语言描述)(9)—— (双轴)快速排序
- main函数的参数解析