教程没有结束的判定,可以自己添加一个。
有个bug就是第一行和第一列不显示。
找不到idea项目目录位置的话,可以用File文件get一下绝对路径,输出到控制台就看到了。引入图片需要用。
public class MySnake {
public static void main(String[] args) {
//创建一个窗口
JFrame frame=new JFrame();
//指定窗口x和y的位置以及窗口的宽度和高度值
frame.setBounds(600,100,700,900);
//不允许拖拽改变大小
frame.setResizable(false);
//当点击窗口关闭按钮执行退出操作
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//显示之前添加画布
frame.add(new MyPanel());
//窗口要显示出来
frame.setVisible(true);
}
}
public class MyPanel extends JPanel implements KeyListener, ActionListener {
//声明右侧蛇头和身体图片
ImageIcon right=new ImageIcon("..\\Game\\images\\right.jpg");
ImageIcon body=new ImageIcon("..\\Game\\images\\body.png");
//声明蛇头的上下左图片
ImageIcon top=new ImageIcon("..\\Game\\images\\top.jpg");
ImageIcon bottom=new ImageIcon("..\\Game\\images\\bottom.jpg");
ImageIcon left=new ImageIcon("..\\Game\\images\\left.jpg");
//声明一个初始值表示蛇的长度
int len =3;
//声明两个数组。分别存放x,y的坐标位置
int [] snakeX= new int[1008]; //最大值 等于 宽度格子*高度格子
int [] snakeY= new int[1008]; //最大值 等于 宽度格子*高度格子
//声明一个枚举类型变量,标识蛇头方向
Direction direction=Direction.right;
//声明一个变量表示游戏是否开始,true为开始否则没有开始
boolean isStart=false;
//声明一个计时器Timer对象
Timer timer=new Timer(100,this);
//声明两个变量表示食物的X,Y坐标
int foodX;
int foodY;
//声明一个随机变量
Random random=new Random();
//声明食物图片
ImageIcon food = new ImageIcon("..\\Game\\images\\body.png");
public MyPanel() {
//设定蛇的头部和身体的初始位置
snakeX[0]=100;
snakeY[0]=100;
snakeX[1]=75;
snakeY[1]=100;
snakeX[2]=50;
snakeY[2]=100;
//获取键盘事件
this.setFocusable(true);
//添加监听
this.addKeyListener(this);
//启动定时器
timer.start();
//生成食物的坐标
foodX = 25 + 25* random.nextInt(20);
foodY = 25 + 25* random.nextInt(20);
}
//重写画组件的方法
@Override
protected void paintComponent(Graphics g) {
//调用父类方法做一些基本工作
super.paintComponent(g);
//设置背景颜色
this.setBackground(Color.BLUE);
g.fillRect(0,0,700,900);
//添加右侧蛇头
// right.paintIcon(this,g,snakeX[0],snakeY[0]);
//根据枚举变量的方向值,进行判断显示哪个方向的蛇头
switch (direction){
case top:
top.paintIcon(this,g,snakeX[0],snakeY[0]);
break;
case bottom:
bottom.paintIcon(this,g,snakeX[0],snakeY[0]);
break;
case left:
left.paintIcon(this,g,snakeX[0],snakeY[0]);
break;
case right:
right.paintIcon(this,g,snakeX[0],snakeY[0]);
break;
}
//添加两个身体
// body.paintIcon(this,g,snakeX[1],snakeY[1]);
// body.paintIcon(this,g,snakeX[2],snakeY[2]);
for(int i=1;i<len;i++){
body.paintIcon(this,g,snakeX[i],snakeY[i]);
}
//判断当前游戏是否开始的值isStart,如果为false则显示提示信息
if(!isStart){
//放上开始提示信息,并设置字体的颜色和字体
g.setColor(Color.white);
g.setFont(new Font("宋体",Font.BOLD,50));
g.drawString("请按下空格表示游戏开始",50,500);
}
//添加食物
food.paintIcon(this,g,foodX,foodY);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
//当按空格键时,数值应该为32做一个判断
if(keyCode==32){
//标记游戏开始的值取反
isStart= !isStart;
//重新画组件
repaint();
}else if(keyCode== KeyEvent.VK_UP){
direction = Direction.top;
}else if(keyCode== KeyEvent.VK_DOWN){
direction = Direction.bottom;
}else if(keyCode== KeyEvent.VK_LEFT){
direction = Direction.left;
}else if(keyCode== KeyEvent.VK_RIGHT){
direction = Direction.right;
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
//当isStart值为true则表示游戏开始,因此移动蛇
if(isStart){
//移动身体
for (int i = len-1; i > 0 ; i--) {
snakeX[i]=snakeX[i-1];
snakeY[i]=snakeY[i-1];
}
//通过方向值direction判断向哪里移动
switch (direction){
case top:
//假如垂直向上移动,则蛇头的值应该Y值 -25
snakeY[0] -=25;
//判断如果蛇头的像素位置小于0 从900再开始
if(snakeY[0] <= 0 ){
snakeY[0]=900;
}
break;
case bottom:
//假如垂直向下移动,则蛇头的值应该Y值 +25
snakeY[0] +=25;
//判断如果蛇头的像素位置超过900则从0再开始
if(snakeY[0] >= 900 ){
snakeY[0]=0;
}
break;
case left:
//假如水平向左移动,则蛇头的值应该-25
snakeX[0] -=25;
//判断如果蛇头的像素位置小于0 从700再开始
if(snakeX[0] <= 0 ){
snakeX[0]=700;
}
break;
case right:
//假如水平向右移动,则蛇头的值应该+25
snakeX[0] +=25;
//判断如果蛇头的像素位置超过700则x再从0开始
if(snakeX[0] >= 700){
snakeX[0]=0;
}
break;
}
//判断当蛇头的食物的坐标一致时,则表示吃到食物
if(snakeX[0]==foodX &&snakeY[0]==foodY){
//蛇的长度+1
len+=1;
//重新生成食物的坐标位置
foodX =25 + 25*random.nextInt(20);
foodY =25 + 25*random.nextInt(20);
}
//重新画组件方法
repaint();
//重新启动定时器
timer.start();
}
}
}
/**
* 蛇头 枚举方向
* 四个取值,上下左右
*/
public enum Direction {
top,bottom,left,right;
}
推荐阅读: