废话不多说咯,直接上代码,求上墙:
格子类
package engorgesnake; import java.awt.p_w_picpath.BufferedImage; /** * 这是一个小方格类,它可以组成贪吃蛇,也可以是食物 它有row col Image三个属性 * 还重写了toString方法 * * @author yufeng * */ public class Cell { private int row; private int col; private BufferedImage Image; public Cell(){} public Cell(int row, int col, BufferedImage p_w_picpath) { super(); this.row = row; this.col = col; this.Image = p_w_picpath; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + col; result = prime * result + row; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Cell other = (Cell) obj; if (col != other.col) return false; if (row != other.row) return false; return true; } public int getRow() { return row; } public void setRow(int row) { this.row = row; } public int getCol() { return col; } public void setCol(int col) { this.col = col; } public BufferedImage getImage() { return Image; } public void setImage(BufferedImage p_w_picpath) { this.Image = p_w_picpath; } public String toString() { return "(" + row + "," + col /*+","+Image*/+")"; } }
蛇类和食物类:
package engorgesnake; import java.awt.p_w_picpath.BufferedImage; import java.util.LinkedList; import java.util.List; import java.util.Random; /** * 这时一个描述蛇的类 * @author yufeng * */ public class Snake extends LinkedList<Cell>{ private static final long serialVersionUID = 1L; private List<Cell> snake=new LinkedList<Cell>(); public Snake(List<Cell> snake) { this.snake = snake; } public List<Cell> getSnake() { return snake; } public void setSnake(List<Cell> snake) { this.snake = snake; } /** * 可以通过类名调用该方法生成蛇 * @return 一条长度为3的蛇 */ public static Snake start1(){ Snake snake=new Snake(new LinkedList<Cell>()); snake.add(new Cell(20,2,Game.snakeHead)); snake.add(new Cell(20,1,Game.snakeImage)); snake.add(new Cell(20,0,Game.snakeTail)); return snake; } public static Snake start2(){ Snake snake=new Snake(new LinkedList<Cell>()); snake.add(new Cell(20,57,Game.snakeHead)); snake.add(new Cell(20,58,Game.snakeImage)); snake.add(new Cell(20,59,Game.snakeTail)); return snake; } /** * 去掉蛇的尾部元素,并且把蛇集合小标为1的元素图片设置为蛇身图片 * @param snake */ public void move(Snake snake){ snake.remove(snake.size()-1); snake.get(1).setImage(Game.snakeImage); snake.get(snake.size()-1).setImage(Game.snakeTail); } /** * 蛇左移 * @param snake */ public void moveLeft(Snake snake){ snake.add(0,new Cell(snake.get(0).getRow(),snake.get(0).getCol()-1,Game.snakeHead)); snake.move(snake); } /** * 蛇右移 * @param snake */ public void moveRight(Snake snake){ snake.add(0,new Cell(snake.get(0).getRow(),snake.get(0).getCol()+1,Game.snakeHead)); snake.move(snake); } /** * 蛇上移 * @param snake */ public void moveUp(Snake snake){ snake.add(0,new Cell(snake.get(0).getRow()-1,snake.get(0).getCol(),Game.snakeHead)); snake.move(snake); } /** * 蛇下移 * @param snake */ public void moveDown(Snake snake){ snake.add(0,new Cell(snake.get(0).getRow()+1,snake.get(0).getCol(),Game.snakeHead)); snake.move(snake); } /** * 吃食物的方法 * @param snake * @param str */ public void eatFood(Snake snake,String str){ if("up".equals(str)){ snake.add(0,new Cell(snake.get(0).getRow()-1,snake.get(0).getCol(),Game.snakeHead)); snake.get(1).setImage(Game.snakeImage); }else if("down".equals(str)){ snake.add(0,new Cell(snake.get(0).getRow()+1,snake.get(0).getCol(),Game.snakeHead)); snake.get(1).setImage(Game.snakeImage); }else if("left".equals(str)){ snake.add(0,new Cell(snake.get(0).getRow(),snake.get(0).getCol()-1,Game.snakeHead)); snake.get(1).setImage(Game.snakeImage); }else if("right".equals(str)){ snake.add(0,new Cell(snake.get(0).getRow(),snake.get(0).getCol()+1,Game.snakeHead)); snake.get(1).setImage(Game.snakeImage); } } } /** * 这是一个描述食物的类 * @author yufeng * */ class Food extends Cell{ private int row; private int col; private BufferedImage Image; public int getRow() { return row; } public void setRow(int row) { this.row = row; } public int getCol() { return col; } public void setCol(int col) { this.col = col; } public BufferedImage getImage() { return Image; } public void setImage(BufferedImage p_w_picpath) { Image = p_w_picpath; } public Food(int row, int col, BufferedImage p_w_picpath) { super(); this.row = row; this.col = col; Image = p_w_picpath; } public String toString() { return "(" + row + "," + col + ")"; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + col; result = prime * result + row; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; Food other = (Food) obj; if (col != other.col) return false; if (row != other.row) return false; return true; } public Food(){} /** * 这个是食物随机生成的方法 * @return */ public static Food getFood(){ Food food=new Food(); Random random=new Random(); int x=random.nextInt(Game.ROWS); int y=random.nextInt(Game.COLS); food.setRow(x); food.setCol(y); return food; } }
游戏类:
package engorgesnake; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.p_w_picpath.BufferedImage; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.Timer; import java.util.TimerTask; import javax.p_w_picpathio.ImageIO; import javax.management.RuntimeErrorException; import javax.swing.JFrame; import javax.swing.JPanel; /** * 游戏类扩展了系统的现实面板 * @author yufeng * */ public class Game extends JPanel{ public static final int ROWS = 40; public static final int COLS = 60; public static final int CELL_SIZE = 10; private Cell[][] wall = new Cell[ROWS][COLS]; private Snake snake1; private Snake snake2; private Food food1; private Food food2; private int SCORE; private String str; private int level=50; private int index=0; private boolean gameover=false; private boolean pause=false; private Timer timer = new Timer(); public static BufferedImage background; public static BufferedImage snakeHead; public static BufferedImage snakeImage; public static BufferedImage snakeTail; public static BufferedImage gameOver; /* * 获取图片资源 */ static{ try { background=ImageIO.read(Game.class.getResource("background.jpg")); snakeHead=ImageIO.read(Game.class.getResource("SnakeHead.jpg")); snakeImage=ImageIO.read(Game.class.getResource("SnakeImage.jpg")); snakeTail=ImageIO.read(Game.class.getResource("SnakeTail.jpg")); gameOver=ImageIO.read(Game.class.getResource("gameover.png")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void paint(Graphics g){ /* * 绘制背景贴图 */ g.drawImage(background, 0, 0, null); g.translate(11, 11); /* * 绘制墙 */ paintWall(g); /* * 绘制蛇 */ paintSnake(g); /* * 绘制食物 */ paintFood(g); /* * 绘制分数 */ paintScore(g); } /** * 绘制分数的方法 * @param g */ private void paintScore(Graphics g) { Font font = new Font(getFont().getName(), Font.BOLD, 36); g.setColor(Color.gray); g.setFont(font); String str = "" + this.SCORE; g.drawString(str, 650, 370); g.setColor(Color.gray); g.setFont(font); str=""+this.str; g.drawString(str, 670, 115); if(!pause&&!gameover){ g.setColor(Color.gray); g.setFont(font); str="[P]暂停"; g.drawString(str, 635, 242); } if(pause&&!gameover){ g.setColor(Color.gray); g.setFont(font); str="[C]继续"; g.drawString(str, 635, 242); } if(gameover){ g.drawImage(gameOver, 0, 0, null); font = new Font(getFont().getName(), Font.BOLD, 26); g.setColor(Color.gray); g.setFont(font); str="[R]重新游戏"; g.drawString(str, 625, 242); } } /** * 绘制食物的方法 * @param g */ private void paintFood(Graphics g) { // TODO Auto-generated method stub if(food1==null||food2==null){ return; } int row1=food1.getRow(); int col1=food1.getCol(); int row2=food2.getRow(); int col2=food2.getCol(); int x1=col1*CELL_SIZE; int y1=row1*CELL_SIZE; int x2=col2*CELL_SIZE; int y2=row2*CELL_SIZE; g.drawImage(snakeImage,x1,y1,null); g.drawImage(snakeImage,x2,y2,null); } /** * 绘制蛇的方法 * @param g */ private void paintSnake(Graphics g) { // TODO Auto-generated method stub if(snake1==null&&snake2==null){ return; } for(int i=snake1.size()-1;i>=0;i--){ Cell cells=snake1.get(i); int row=cells.getRow(); int col=cells.getCol(); int x=col*CELL_SIZE; int y=row*CELL_SIZE; g.drawImage(cells.getImage(), x, y, null); } for(int i=snake2.size()-1;i>=0;i--){ Cell cells=snake2.get(i); int row=cells.getRow(); int col=cells.getCol(); int x=col*CELL_SIZE; int y=row*CELL_SIZE; g.drawImage(cells.getImage(), x, y, null); } } /** * 绘制墙,背景图片 * @param g */ private void paintWall(Graphics g) { // TODO Auto-generated method stub for (int row = 0; row < wall.length; row++) { Cell[] line = wall[row]; for (int col = 0; col < line.length; col++) { Cell cell = line[col]; int x = CELL_SIZE * col; int y = CELL_SIZE * row; /*g.drawRect(x, y, CELL_SIZE, CELL_SIZE);*/ if (cell != null) { // 如果有砖块 把砖块的图片贴在x,y的位置上 g.drawImage(cell.getImage(), x, y, null); } } } } /** * 这个是本游戏的流程控制(包括各种功能)的代码 */ private void action(){ // TODO Auto-generated method stub startGameAction(); KeyAdapter l = new KeyAdapter() { public void keyPressed(KeyEvent e) { final int key = e.getKeyCode(); if (key == KeyEvent.VK_Q) { System.exit(0); } if(gameover){ if(key==KeyEvent.VK_R){ clearAll(); } return; } if(pause){ if(key==KeyEvent.VK_C){ pause=false; } return; } switch (key) { case KeyEvent.VK_DOWN: snake_MoveDown(snake2, snake1, food1, food2); break; case KeyEvent.VK_RIGHT: snake_MoveRight(snake2, snake1, food1, food2); break; case KeyEvent.VK_LEFT: snake_MoveLeft(snake2, snake1, food1, food2); break; case KeyEvent.VK_UP: snake_MoveUp(snake2, snake1, food1, food2); break; case KeyEvent.VK_S: snake_MoveDown(snake1, snake2, food1, food2); break; case KeyEvent.VK_D: snake_MoveRight(snake1, snake2, food1, food2); break; case KeyEvent.VK_A: snake_MoveLeft(snake1, snake2, food1, food2); break; case KeyEvent.VK_W: snake_MoveUp(snake1, snake2, food1, food2); break; case KeyEvent.VK_P: pause=true; break; default: break; } repaint(); } }; this.addKeyListener(l); this.requestFocus(); /** * 启动主刷新 */ timer.schedule(new TimerTask() { public void run() { if(!pause&&!gameover){ index++; if (index % level == 0) { move(snake1, snake2, food1, food2); move(snake2, snake1, food1, food2); } if(SCORE<200){ str="初级"; level=50; }else if(SCORE<400){ str="中级"; level=30; }else if(SCORE<600){ str="高级"; level=15; }else{ str="终极"; level=5; } } repaint(); } }, 0, 10); } /** * 重新游戏,需要把游戏结束的画面全部清空,再重新开始游戏 */ protected void clearAll() { for(Cell[] cells:wall){ Arrays.fill(cells, null); } startGameAction(); pause=false; gameover=false; } /** * 蛇移动的方法,这里主要是对参数snake1移动 * @param snake1 * @param snake2 * @param food1 * @param food2 */ protected void move(Snake snake1,Snake snake2,Food food1,Food food2){ if(canDown(snake1)){ snake_MoveDown(snake1, snake2,food1,food2); }else if(canUp(snake1)){ snake_MoveUp(snake1,snake2,food1,food2);/*}*/ }else if(canLeft(snake1)){ snake_MoveLeft(snake1,snake2,food1,food2);/*}*/ }else if(canRight(snake1) ){ snake_MoveRight(snake1,snake2,food1,food2);/*}*/ }else{ if(gameover){ gameOverAction(); } } } /** * 这个是游戏结束的方法,停止计时 */ private void gameOverAction() { // TODO Auto-generated method stub timer.cancel(); } /** * 判断参数snake是否能够向右移动 * @param snake * @return 能向右移动 返回true * 不能则返回false */ private boolean canRight(Snake snake) { if(snake.get(0).getRow()==snake.get(1).getRow()&&snake.get(0).getCol()>snake.get(1).getCol()){ return true; } return false; } /** * 判断参数snake能否向左移动 * @param snake * @return */ private boolean canLeft(Snake snake) { if(snake.get(0).getRow()==snake.get(1).getRow()&&snake.get(0).getCol()<snake.get(1).getCol()){ return true; } return false; } private boolean canUp(Snake snake) { if(snake.get(0).getCol()==snake.get(1).getCol()&&snake.get(0).getRow()<snake.get(1).getRow()){ return true; } return false; } private boolean canDown(Snake snake) { if(snake==null){ return false; } if(snake.get(0).getCol()==snake.get(1).getCol()&&snake.get(0).getRow()>snake.get(1).getRow()){ return true; } return false; } /** * 参数snakeA上移的方法 * @param snakeA * @param snakeB * @param foodA * @param foodB */ protected void snake_MoveUp(Snake snakeA,Snake snakeB,Food foodA,Food foodB) { if((snakeA.get(0).getCol()==foodA.getCol()&&(snakeA.get(0).getRow()-1==foodA.getRow())) ||(snakeA.get(0).getCol()==foodB.getCol()&&(snakeA.get(0).getRow()-1==foodB.getRow()))){ snakeA.eatFood(snakeA, "up"); updateFood(foodA,foodB,snakeA,snakeB,"up"); repaint(); SCORE+=10; }else if (canMove(snakeA,snakeB)&& (snakeA.get(0).getRow() < snakeA.get(1).getRow() ||snakeA.get(0).getRow()==snakeA.get(1).getRow()) ){ snakeA.moveUp(snakeA); } if(!canMove(snakeA,snakeB)){ snakeA.remove(0); snakeB.remove(0); gameOver(); } } /** * 参数snakeA左移的方法 * @param snakeA * @param snakeB * @param foodA * @param foodB */ protected void snake_MoveLeft(Snake snakeA,Snake snakeB,Food foodA,Food foodB) { if((snakeA.get(0).getCol()-1==foodA.getCol()&&(snakeA.get(0).getRow()==foodA.getRow())) ||(snakeA.get(0).getCol()-1==foodB.getCol()&&(snakeA.get(0).getRow()==foodB.getRow()))){ snakeA.eatFood(snakeA, "left"); updateFood(foodA,foodB,snakeA,snakeB,"left"); repaint(); SCORE+=10; } else if(canMove(snakeA,snakeB)&& (snakeA.get(0).getCol() < snakeA.get(1).getCol() ||snakeA.get(0).getCol()==snakeA.get(1).getCol())) { snakeA.moveLeft(snakeA); } if(!canMove(snakeA,snakeB)){ snakeA.remove(0); snakeB.remove(0); gameOver(); } } /** * 当食物被吃了,更新食物的方法 * @param foodA * @param foodB * @param snakeA * @param snakeB * @param str */ private void updateFood(Food foodA,Food foodB,Snake snakeA,Snake snakeB,String str) { /** * 假如2个食物都被吃了,则生成2个食物 */ if((foodA.getRow()==snakeA.get(0).getRow()&&foodA.getCol()==snakeA.get(0).getCol()) &&foodB.getRow()==snakeB.get(0).getRow()&&foodB.getCol()==snakeB.get(0).getCol()){ Food food1=getFoods(snakeA, snakeB); Food food2=getFoods(snakeA, snakeB, food1); foodA.setRow(food1.getRow()); foodA.setCol(food1.getCol()); foodB.setRow(food2.getRow()); foodB.setCol(food2.getCol()); } if((foodA.getRow()==snakeB.get(0).getRow()&&foodA.getCol()==snakeB.get(0).getCol()) &&foodB.getRow()==snakeA.get(0).getRow()&&foodB.getCol()==snakeA.get(0).getCol()){ Food food1=getFoods(snakeA, snakeB); Food food2=getFoods(snakeA, snakeB, food1); foodA.setRow(food1.getRow()); foodA.setCol(food1.getCol()); foodB.setRow(food2.getRow()); foodB.setCol(food2.getCol()); } /** * 假如被吃了一个 */ if(foodA.getRow()==snakeA.get(0).getRow()&&foodA.getCol()==snakeA.get(0).getCol()){ Food food=getFoods(snakeA,snakeB,foodB); foodA.setRow(food.getRow()); foodA.setCol(food.getCol()); } if(foodB.getRow()==snakeA.get(0).getRow()&&foodB.getCol()==snakeA.get(0).getCol()){ Food food=getFoods(snakeA,snakeB,foodA); foodB.setRow(food.getRow()); foodB.setCol(food.getCol()); } } /** * 参数snakeA右移的方法 * @param snakeA * @param snakeB * @param foodA * @param foodB */ protected void snake_MoveRight(Snake snakeA,Snake snakeB,Food foodA,Food foodB) { if((snakeA.get(0).getCol()+1==foodA.getCol()&&(snakeA.get(0).getRow()==foodA.getRow())) ||(snakeA.get(0).getCol()+1==foodB.getCol()&&(snakeA.get(0).getRow()==foodB.getRow()))){ snakeA.eatFood(snakeA, "right"); updateFood(foodA,foodB,snakeA,snakeB,"right"); repaint(); SCORE+=10; }else if(canMove(snakeA,snakeB)&& (snakeA.get(0).getCol() > snakeA.get(1).getCol() ||snakeA.get(0).getCol()==snakeA.get(1).getCol())) { snakeA.moveRight(snakeA); } if(!canMove(snakeA,snakeB)){ snakeA.remove(0); snakeB.remove(0); gameOver(); } } /** * 参数snakeA下移的方法 * @param snakeA * @param snakeB * @param foodA * @param foodB */ protected void snake_MoveDown(Snake snakeA,Snake snakeB,Food foodA,Food foodB) { if((snakeA.get(0).getCol()==foodA.getCol()&&(snakeA.get(0).getRow()+1==foodA.getRow())) ||(snakeA.get(0).getCol()==foodB.getCol()&&(snakeA.get(0).getRow()+1==foodB.getRow()))){ snakeA.eatFood(snakeA, "down"); updateFood(foodA,foodB,snakeA,snakeB,"down"); repaint(); SCORE+=10; } else if(canMove(snakeA,snakeB)&& (snakeA.get(0).getRow() > snakeA.get(1).getRow() ||snakeA.get(0).getRow()==snakeA.get(1).getRow()) ){ snakeA.moveDown(snakeA); } if(!canMove(snakeA,snakeB)){ snakeA.remove(0); snakeB.remove(0); gameOver(); } } /** * 游戏结束,gameover重新赋值true */ private void gameOver() { gameover=true; } private boolean canMove(Snake snakeA,Snake snakeB){ if(outOfBounds(snakeB)||outOfBounds(snakeA)||coincide(snakeA,snakeB)){ return false; } return true; } private boolean outOfBounds(Snake snake22){ if(snake22.get(0).getCol()>=COLS||snake22.get(0).getCol()<0 ||snake22.get(0).getRow()>=ROWS||snake22.get(0).getRow()<0){ return true; } return false; } private boolean coincide(Snake snakeA,Snake snakeB){ for(int i=snakeA.size()-1;i>2;i--){ if(snakeA.get(0).equals(snakeA.get(i))){ /* * 重合 */ return true; } } for(int i=snakeB.size()-1;i>=0;i--){ if(snakeA.get(0).equals(snakeB.get(i))){ /* * 重合 */ return true; } } return false; } /** * 这个是游戏开始的方法 */ private void startGameAction() { snake1=Snake.start1(); /*snake1.add(0,new Cell(20,3,Game.snakeHead));*/ snake2=Snake.start2(); food1=getFoods(snake1,snake2); /* System.out.println(food1);*/ food2=getFoods(snake1,snake2,food1); SCORE=0; str="初级"; } /** * 这个是生成food2的方法 * @param snake1 * @param snake2 * @param food1 * @return */ private Food getFoods(Snake snake1, Snake snake2, Food food1) { Food food=null; boolean used=true; do{ food=Food.getFood(); if(food.getRow()!=food1.getRow()||food.getCol()!=food1.getCol()){ used=false; }else{ continue; } for(Cell cells:snake1){ if(food.getRow()!=cells.getRow()||food.getCol()!=cells.getCol()){ used=false; }else{ used=true; } } if(used){ continue; } for(Cell cells:snake2){ if(food.getRow()!=cells.getRow()||food.getCol()!=cells.getCol()){ used=false; }else{ used=true; } } }while(used); return food; } /** * 这个是生成food1的方法 * @param snake1 * @param snake2 * @return */ private Food getFoods(Snake snake1,Snake snake2) { Food food=null; boolean used=true; do{ food=Food.getFood(); for(int i=snake1.size()-1;i>=0;i--){ if(food.getRow()!=snake1.get(i).getRow()||food.getCol()!=snake1.get(i).getCol()){ used=false; break; } } if(used){ continue; } for(int i=snake2.size()-1;i>=0;i--){ if(food.getRow()!=snake1.get(i).getRow()||food.getCol()!=snake1.get(i).getCol()){ used=false; break; }else{ used=true; } } }while(used); return food; } /** * 主方法,画出面板,让后把墙放在面板上,调用流程控制方法action * @param args */ public static void main(String[] args){ JFrame jframe=new JFrame(); Game game=new Game(); jframe.setSize(815,625); jframe.setTitle("双龙戏珠"); jframe.add(game); jframe.setLocationRelativeTo(null); jframe.setVisible(true); jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); game.action(); } }