1项目总体框架
![](https://i-blog.csdnimg.cn/blog_migrate/ee0eb92dee6c1dc0c2cb83ba1ef8e319.png)
2系统详细设计
2.1 statics
静态资源
2.2Data.java
数据类,用来存放常量
2.3GamePanel.java
页面初始化
![](https://i-blog.csdnimg.cn/blog_migrate/c58d2482a06963d15f36cdee424316de.png)
2.4Mainwindow.java
游戏主页面最外层面板
2.5Start.java
启动页
2.6Start.java
游戏初始化页面
3关键算法分析
3.1蛇身的数据结构
·具体算法
定义两个一维数组来存贪吃蛇的身体
![](https://i-blog.csdnimg.cn/blog_migrate/3c3922c273bf2c8eb8f9da13ff46cdfd.png)
定义一个定时器来实现动画效果
![](https://i-blog.csdnimg.cn/blog_migrate/4f3b39e00000e465032a5bfc0103396f.png)
为当前类添加键盘监听事件,使用了适配器模式,简化了代码的书写
public GamePanel() {
init();
this.setFocusable(true);//获得焦点事件
this.addKeyListener(new KeyAdapter() {
@Override
publicvoid keyPressed(KeyEvent e) {
int keyCode =e.getKeyCode();//获得键盘的值
if (keyCode==KeyEvent.VK_SPACE) {//按下空格键
if(isFail){//游戏失败,重新开始
isFail = !isFail;
init();//初始化
}else{
isStart = !isStart;//取反操作,再次按下就停止游戏
}
repaint();//重新绘制
}
//小蛇移动方向判断
if (keyCode==KeyEvent.VK_UP&&direction!="D"){
direction="U";
}
if (keyCode==KeyEvent.VK_DOWN&&direction!="U"){
direction="D";
}
if (keyCode==KeyEvent.VK_LEFT&&direction!="R"){
direction="L";
}
if (keyCode==KeyEvent.VK_RIGHT&&direction!="L") {
direction = "R";
}
}
});//获得键盘监听事件
}
重写actionPerformed和paintComponent方法,使用定时器执行重写的actionPerformed方法,在actionPerformed中调用paintComponent
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.darkGray);
//绘制静态面板
Data.header.paintIcon(this,g,0,0);//绘制标题栏
g.setColor(Color.WHITE);
g.fillRect(25,75,850,600);//矩形的游戏框
//画积分
g.setColor(Color.BLACK);
g.setFont(new Font("微软雅黑",Font.BOLD,15));//设置字体样式,Bold指粗体
g.drawString("长度:"+length,750,115);
g.drawString("分数:"+score,750,145);
//把小蛇画上去
if(direction.equals("R")){//判断头的方向
Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);
}else if (direction.equals("L")){
Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);
}else if (direction.equals("U")){
Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);
}else {
Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);
}
for(int i = 1; i <length; i++) {
Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);
}
//食物绘制
Data.food.paintIcon(this,g,foodx,foody);
//游戏状态
if(isStart==false){//开始
g.setColor(Color.WHITE);//画笔颜色
g.setFont(new Font("微软雅黑",Font.BOLD,40));//设置字体样式,Bold指粗体
String s1 = new String("按下空格开始游戏");
g.drawString(s1,300,300);
}
if(isFail){//失败
g.setColor(Color.red);//画笔颜色
g.setFont(new Font("宋体",Font.BOLD,30));//设置字体样式,Bold指粗体
g.drawString("游戏失败!你最好再练习两年半!",300,300);
}
}
public void actionPerformed(ActionEvente) {
if (isStart && isFail== false){//游戏开始时
//吃食物
if (snakeX[0] == foodx && snakeY[0]==foody){
//长度加1
length++;
score +=10;
//再次生成随机数组
foodx= 25+25*random.nextInt(34);
foody = 75+25*random.nextInt(24);
}
//身体移动
for (int i = length-1;i>0;i--){//后一节身体移到前面一节的位置,snakeX[1]=snakeX[0];
snakeX[i]=snakeX[i-1];
snakeY[i]=snakeY[i-1];//Y方向上值都一样,这里没有变化
}
//走向
if(direction.equals("R")){
snakeX[0] +=25;if(snakeX[0]>850){isFail=true;}//边界判断
}else if (direction.equals("L")){
snakeX[0] -=25;if(snakeX[0]<25){isFail=true;}//边界判断
}else if (direction.equals("U")){
snakeY[0] -=25;if(snakeY[0]==75){isFail=true;}
}else if (direction.equals("D")){
snakeY[0] +=25;if(snakeY[0]>650){isFail=true;}
}
//失败判断,撞到自己就算失败
for (int i = 1; i < length; i++) {//遍历每节身体的坐标
if(snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]){
isFail = true;
}
}
repaint();//重画页面
}
}