存档资料 成绩:
华东交通大学理工学院
课 程 设 计 报 告 书
所属课程名称 Java游戏课程设计
题 目 贪吃蛇游戏Java课程设计
分 院
专业班级
学 号
学生姓名
指导教师
20 年 月 日
华东交通大学理工学院
课 程 设 计( 论 文 )任 务 书
专 业 班 级 姓名
一、课程设计(论文)题目 贪吃蛇游戏Java课程设计
二、课程设计(论文)工作:自 20 年 月 日起至 20 年 月 日止。
三、课程设计(论文)的内容要求:
设计题目: 贪吃蛇Java游戏程序设计
设计目的:
1.巩固和加深课堂所学知识;
2.学习掌握一般的软件的设计方法和查阅、运用资料的能力;
3.掌握JAVA程序设计语言,面向对象的软件设计思想、方法。
设计任务:(在规定的时间内完成下列任务)
1、任务: 设计一个贪吃蛇的游戏
功能要求:
能够显示贪吃蛇的运动,能通过键盘控制贪吃蛇的运行,能够处理
蛇在运中个各种情况,以及其它的辅助功能; 要提供主要的设计思
路、数据结构的设计。
2 、设计任务要完成设计、编码、测试等过程,给出设计思路、设计说明书、主
要的代码的说明、使用说明书。源代码以及可运行的贪吃蛇游戏。
具体要求:设计报告撰写格式要求(按提供的设计报告统一格式撰写)
具体内容如下:
① 设计任务与要求
② 总体方案与说明
③ 面向对象的设计(主要类的设计)
④ 源程序清单与注释
⑤ 软件主要模块流程图
⑥ 问题分析与解决方案(包括调式记录、调式报告,即在调式过程中遇到的主要问
题、解决方法及改进设想);
⑦ 小结与体会
学生签名:
20 年 月 日
课程设计(论文)评阅意见
评阅人 职称
20 年 月 日
目录
课 程 设 计( 论 文 )任 务 书............................................................. 2
1.设计任务与要求..................................................................................................... 6
1.1设计任务...................................................................................................... 6
设计一个贪吃蛇的游戏............................................................................... 6
1.2具体要求:.................................................................................................. 6
2.软件主要模块流程图............................................................................................. 6
3.总体方案与说明..................................................................................................... 8
3.1总体方案...................................................................................................... 8
3.2系统模块...................................................................................................... 8
3.2.1游戏界面设........................................................................................ 8
3.2.2贪吃蛇蛇身及运动设置..................................................................... 11
3.2.3游戏控制设置................................................................................... 17
4.程序设计............................................................................................................. 17
4.1 GreedSnake类............................................................................................ 17
4.2.SnakeModel类............................................................................................ 18
5.分析问题与解决方案............................................................................................ 19
5.1 问题处理................................................................................................... 19
6小结与体会.......................................................................................................... 19
参考文献(资料).................................................................................................. 20
程序代码:............................................................................................................. 21
1.设计任务与要求
1.1设计任务
设计一个贪吃蛇的游戏
功能要求:能够显示贪吃蛇的运动,能通过键盘控制贪吃蛇的运行,能够处理蛇在运
行中个各种情况,以及其它的辅助功能;要提供主要的设计思路、数据结
构的设计。
设计任务要完成设计、编码、测试等过程,给出设计思路、设计说明书、主要代码的 说明、使用说明书。源代码以及可运行的贪吃蛇游戏。
1.2具体要求:
具体内容如下:
① 设计任务与要求
② 总体方案与说明
③ 面向对象的设计(主要类的设计)
④ 源程序清单与注释
⑤ 软件主要模块流程图
⑥ 问题分析与解决方案(包括调式记录、调式报告,即在调式过程中遇到的主要
问题、解决方法及改进设想);
⑦ 小结与体会
2.软件主要模块流程图
软件的主要模块流程如下图5-1所示
3.总体方案与说明
3.1总体方案
我设计的贪吃蛇主要利用键盘控制蛇的前进移动方向,是否吃到食物,是否撞墙以及是否暂停、开始游戏等。当吃到食物的时候,蛇就自动长大一格,在游戏中可进行暂停和开始操作。中途若是撞到墙或是撞到自己,同样也结束。背景和蛇的颜色可随时更换。
3.2系统模块
根据总体方案,我把贪吃蛇游戏分为:游戏界面设置(即绘图)、贪吃蛇蛇身及运动设置和游戏龙之设置三大模块来设计。
3.2.1游戏界面设
游戏界面设置包括:游戏区设置、游戏帮助信息设置、游戏分数查看区。
游戏界面使用简单和直观的布局设计,游戏区放置在界面的主题位置上,在游戏
区上部放置分数,在游戏区下部放置使用说明帮助,具体设计效果如图2-1所示。
图2-1游戏主题界面设计效果
附加代码:
class MyWindow extends Frame implements ActionListener//自定义窗口类
{
MyPanel my;
Button btn;
Panel panel;
MyWindow()
{
super("GreedSnake");
my=new MyPanel();
btn=new Button("begin");
panel=new Panel();
btn.addActionListener(this);
panel.add(new Label("begin后请按Tab键选定蛇"));
panel.add(btn);
panel.add(new Label("按上下左右键控制蛇行动"));
add(panel,BorderLayout.NORTH);
add(my,BorderLayout.CENTER);
setBounds(100,100,610,500);
setVisible(true);
validate();
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
public void actionPerformed(ActionEvent e)//按下begin按钮
{
if(e.getSource()==btn)
{
try
{
my.thread.start(); //开始线程
my.validate();
}
catch(Exception ee){}
}
}
}
3.2.2贪吃蛇蛇身及运动设置
贪吃蛇的蛇身设置是整个游戏设计的关键。它的基本思路是:去掉蛇尾,显示并移动出蛇头外蛇身,根据蛇身的运动方向,决定蛇头的位置,完成蛇头吃食物的处理操作,显示蛇头。具体效果如图2-2所示。
而蛇运动的四个方向,则通过按键来控制。蛇吃到一个食物,就加分。每次食物出现的位置不能在蛇身上,如果蛇在运动的过程中撞到自己或者撞墙,则游戏结束,具体效果如图2-3所示。
图2-2游戏运行中的效果
图2-3就是蛇撞到墙之后,提示游戏结束。
附加代码:class MyPanel extends Panel implements KeyListener,Runnable//自定义面板类,继承了键盘和线程接口
{
Button snake[]; //定义蛇按钮
int shu=0; //蛇的节数
int food[]; //食物数组
boolean result=true; //判定结果是输 还是赢
Thread thread; //定义线程
static int weix,weiy; //食物位置
boolean t=true; //判定游戏是否结束
int fangxiang=0; //蛇移动方向
int x=0,y=0; //蛇头位置
MyPanel()
{
setLayout(null);
snake=new Button[20];
food=new int [20];
thread=new Thread(this);
for(int j=0;j<20;j++)
{
food[j]=(int)(Math.random()*99);//定义20个随机食物
}
weix=(int)(food[0]*0.1)*60; //十位*60为横坐标
weiy=(int)(food[0]%10)*40; //个位*40为纵坐标
for(int i=0;i<20;i++)
{
snake[i]=new Button();
}
add(snake[0]);
snake[0].setBackground(Color.black);
snake[0].addKeyListener(this); //为蛇头添加键盘监视器
snake[0].setBounds(0,0,10,10);
setBackground(Color.cyan);
}
public void run() //接收线程
{
while(t)
{
if(fangxiang==0)//向右
{
try
{
x+=10;
snake[0].setLocation(x, y);//设置蛇头位置
if(x==weix&&y==weiy) //吃到食物
{
shu++;
weix=(int)(food[shu]*0.1)*60;
weiy=(int)(food[shu]%10)*40;
repaint(); //重绘下一个食物
add(snake[shu]); //增加蛇节数和位置
snake[shu].setBounds(snake[shu-1].getBounds());
}
thread.sleep(100); //睡眠100ms
}
catch(Exception e){}
}
else if(fangxiang==1)//向左
{
try
{
x-=10;
snake[0].setLocation(x, y);
if(x==weix&&y==weiy)
{
shu++;
weix=(int)(food[shu]*0.1)*60;
weiy=(int)(food[shu]%10)*40;
repaint();
add(snake[shu]);
snake[shu].setBounds(snake[shu-1].getBounds());
}
thread.sleep(100);
}
catch(Exception e){}
}
else if(fangxiang==2)//向上
{
try
{
y-=10;
snake[0].setLocation(x, y);
if(x==weix&&y==weiy)
{
shu++;
weix=(int)(food[shu]*0.1)*60;
weiy=(int)(food[shu]%10)*40;
repaint();
add(snake[shu]);
snake[shu].setBounds(snake[shu-1].getBounds());
}
thread.sleep(100);
}
catch(Exception e){}
}
else if(fangxiang==3)//向下
{
try
{
y+=10;
snake[0].setLocation(x, y);
if(x==weix&&y==weiy)
{
shu++;
weix=(int)(food[shu]*0.1)*60;
weiy=(int)(food[shu]%10)*40;
repaint();
add(snake[shu]);
snake[shu].setBounds(snake[shu-1].getBounds());
}
thread.sleep(100);
}
catch(Exception e){}
}
int num1=shu;
while(num1>1)//判断是否咬自己的尾巴
{
if(snake[num1].getBounds().x==snake[0].getBounds().x&&snake[num1].getBounds().y==snake[0].getBounds().y)
{
t=false;
result=false;
repaint();
}
num1--;
}
if(x<0||x>=this.getWidth()||y<0||y>=this.getHeight())//判断是否撞墙
{
t=false;
result=false;
repaint();
}
int num=shu;
while(num>0) //设置蛇节位置
{
snake[num].setBounds(snake[num-1].getBounds());
num--;
}
if(shu==15) //如果蛇节数等于15则胜利
{
t=false;
result=true;
repaint();
}
}
}
public void keyPressed(KeyEvent e) //按下键盘方向键
{
if(e.getKeyCode()==KeyEvent.VK_RIGHT)//右键
{
if(fangxiang!=1)//如果先前方向不为左
fangxiang=0;
}
else if(e.getKeyCode()==KeyEvent.VK_LEFT)
{ if(fangxiang!=0)
fangxiang=1;
}
else if(e.getKeyCode()==KeyEvent.VK_UP)
{ if(fangxiang!=3)
fangxiang=2;
}
else if(e.getKeyCode()==KeyEvent.VK_DOWN)
{ if(fangxiang!=2)
fangxiang=3;
}
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
}
public void paint(Graphics g) //在面板上绘图
{
int x1=this.getWidth()-1;
int y1=this.getHeight()-1;
g.setColor(Color.red);
g.fillOval(weix, weiy, 10, 10);//食物
g.drawRect(0, 0, x1, y1); //墙
if(t==false&&result==false)
g.drawString("GAME OVER!", 250, 200);//输出游戏失败
else if(t==false&&result==true)
g.drawString("YOU WIN!", 250, 200);//输出游戏成功
}
}
3.2.3游戏控制设置
游戏控制设置就是控制游戏的暂停与开始。设置PageUp(加速), PageDown(减速)按键来控制速度,设置空格或着p按键来暂停进行中的游戏,设置ENTER或着R或者S按键来开始暂停的游戏。
4.程序设计
贪吃蛇游戏各模块及程序流程有若干类实现,下面阐述各个类的设计与实现。
4.1 GreedSnake类
该类包含六个主要的功能方法,分别是:
(1)构造函数public GreedSnake(),主要用来设置用户控制界面。
(2)public void keyPressed()方法,主要用来对游戏的按键操作进行处理。
(3)void repaint()主要用来绘制游戏界面包括蛇和食物。
(4)private void drawNode()主要用来绘制某一结点。
(5)public void updateScore()方法主要用来改变积分器。
(6)void begin()方法用来控制游戏的开始界面。
4.2.SnakeModel类
该类包含多个功能方法,分别是:
(1) 构造函数public SnakeModel(),该方法主要用来初始化游戏界。其中
matrix[][]用来存储地图上面的信息,如果什么也没有设置为false,如果
有食物或蛇,设置为true;nodeArray,一个LinkedList,用来保存蛇的每
一节;food用来保存食物的位置;而Node类是保存每个位置的信息。
(2) public void changeDirection()方法主要用来改变蛇的运动方向,
changeDirection(int newDirection) ,用来改变蛇前进的方向,而且只是
保存头部的前进方向,因为其他的前进方向已经用位置来指明了。其中
newDirection必须和原来的direction不是相反方向,所以相反方向的值
用了同样的奇偶性。在测试的时候使用了direction%2!=newDirection%2
进行判断。
(3) public boolean moveOn()方法使实现蛇运动的函数,其中moveOn()用来更
新蛇的位置,对于当前方向,把头部位置进行相应改变。如果越界,结束;
否则,检测是否遇到食物(加头部)或身体(结束);如果什么都没有,加
上头部,去掉尾部。由于用了LinkedList数据结构,省去了相当多的麻烦。
(4) public void run()方法主要用来完成游戏主体运行流程控制功能。
(5) private Node createFood()方法用来生成食物及放置地点。
(6) public void speedUp()和()两个方法对蛇运行的速度进行控制。
(7) public void changePauseState() 方法用来改变游戏的状态,是“暂停”还
是“继续”。
5.分析问题与解决方案
通过NetBeans来运行程序。
5.1问题处理
问题一: 游戏在运行过程中不能暂停 解决方法:在游戏中增加暂停控制
panelButtom.add(labelHelp, BorderLayout.CENTER); labelHelp =
new JLabel("按 空格 或 p 暂停 ", JLabel.CENTER);
问题二: 贪吃蛇在吃掉一个食物后,不能实现分数累加 解决方案:定义
updateScore专门统计分数,每吃掉一个食物,累加分数 public void
updateScore()
{String s = "分数: " + snakeModel.score; labelScore.setText(s);
6小结与体会
在为期两周的Java小游戏课程设计中我选择了贪吃蛇这一小游戏,本身玩起来贪吃蛇这游戏比较简单,但程序设计还是有点复杂。通过完成这次课程设计我学会了许多以前不懂得编程方法,可以简单的了解了Java世界的奥妙,我发现Java比以前学的任何一种语言多灵活,我相信Java语言将会越来越好。我认为我在这次课设中学到的东西会让我受益匪浅。
参考文献(资料)
[1] 谢希仁. 计算机网络(第五版)[M]. 北京:电子工业出版社,20##年2月
[2] 胡小强 计算机网络[M] 北京:北京邮电大学出版社20##年1月
[3] 陈轶.姚晓昆编著.Java程序设计实验指导.北京:清华大学出版社,2006
[4] 杨昭编著.二级Java语言程序设计教程.北京:中国水利水电出版社,2006
[5] 赵文靖编著.Java程序设计基础与上机指导.北京:清华大学出版社,2006
[6] 赵毅主编.跨平台程序设计语言——Java.西安:西安电子科技大学出版社,2006
[7] 王路群.Java高级程序设计.北京:中国水利水电出版社,2006
[8] 雍俊海编著.Java程序设计习题集.北京:清华大学出版社,2006
[9] 朱福喜编著.Java语言习题与解析.北京:清华大学出版社,2006
[10] 吴其庆编著.Java程序设计实例教程.北京:冶金产业出版社,2006
[11] 柳西玲.许斌编著.Java语言应用开发基础.北京:清华大学出版社,2006
[12] 施霞萍等编著.Java程序设计教程 第2版.北京:机械产业出版社,2006
[13] [美]Herbert Schidt著.Java参考大全.鄢爱兰.鹿江春译.北京:清华大学出版社,2006
[14] 宛延闿等编著.实用Java程序设计教程.北京:机械产业出版社,2006
[15] 陈国君等编著.Java2程序设计基础.北京:清华大学出版社,2006
[16] 郑莉.王行言.马素霞编著.Java语言程序设计.北京:清华大学出版社,2006
[17] 丁振凡主编.Java语言实用教程.北京:北京邮电大学出版社,2005
[18] 朱喜福等编.Java程序设计.北京:人民邮电出版社,2005
[19] http://java.sun.com/
[20 ] http://www.javaworld.com/
程序代码:
import java.awt.*;
import java.awt.event.*;
public class GreedSnake //主类
{
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new MyWindow();
}
}
class MyPanel extends Panel implements KeyListener,Runnable//自定义面板类,继承了键盘和线程接口
{
Button snake[]; //定义蛇按钮
int shu=0; //蛇的节数
int food[]; //食物数组
boolean result=true; //判定结果是输 还是赢
Thread thread; //定义线程
static int weix,weiy; //食物位置
boolean t=true; //判定游戏是否结束
int fangxiang=0; //蛇移动方向
int x=0,y=0; //蛇头位置
MyPanel()
{
setLayout(null);
snake=new Button[20];
food=new int [20];
thread=new Thread(this);
for(int j=0;j<20;j++)
{
food[j]=(int)(Math.random()*99);//定义20个随机食物
}
weix=(int)(food[0]*0.1)*60; //十位*60为横坐标
weiy=(int)(food[0]%10)*40; //个位*40为纵坐标
for(int i=0;i<20;i++)
{
snake[i]=new Button();
}
add(snake[0]);
snake[0].setBackground(Color.black);
snake[0].addKeyListener(this); //为蛇头添加键盘监视器
snake[0].setBounds(0,0,10,10);
setBackground(Color.cyan);
}
public void run() //接收线程
{
while(t)
{
if(fangxiang==0)//向右
{
try
{
x+=10;
snake[0].setLocation(x, y);//设置蛇头位置
if(x==weix&&y==weiy) //吃到食物
{
shu++;
weix=(int)(food[shu]*0.1)*60;
weiy=(int)(food[shu]%10)*40;
repaint(); //重绘下一个食物
add(snake[shu]); //增加蛇节数和位置
snake[shu].setBounds(snake[shu-1].getBounds());
}
thread.sleep(100); //睡眠100ms
}
catch(Exception e){}
}
else if(fangxiang==1)//向左
{
try
{
x-=10;
snake[0].setLocation(x, y);
if(x==weix&&y==weiy)
{
shu++;
weix=(int)(food[shu]*0.1)*60;
weiy=(int)(food[shu]%10)*40;
repaint();
add(snake[shu]);
snake[shu].setBounds(snake[shu-1].getBounds());
}
thread.sleep(100);
}
catch(Exception e){}
}
else if(fangxiang==2)//向上
{
try
{
y-=10;
snake[0].setLocation(x, y);
if(x==weix&&y==weiy)
{
shu++;
weix=(int)(food[shu]*0.1)*60;
weiy=(int)(food[shu]%10)*40;
repaint();
add(snake[shu]);
snake[shu].setBounds(snake[shu-1].getBounds());
}
thread.sleep(100);
}
catch(Exception e){}
}
else if(fangxiang==3)//向下
{
try
{
y+=10;
snake[0].setLocation(x, y);
if(x==weix&&y==weiy)
{
shu++;
weix=(int)(food[shu]*0.1)*60;
weiy=(int)(food[shu]%10)*40;
repaint();
add(snake[shu]);
snake[shu].setBounds(snake[shu-1].getBounds());
}
thread.sleep(100);
}
catch(Exception e){}
}
int num1=shu;
while(num1>1)//判断是否咬自己的尾巴
{
if(snake[num1].getBounds().x==snake[0].getBounds().x&&snake[num1].getBounds().y==snake[0].getBounds().y)
{
t=false;
result=false;
repaint();
}
num1--;
}
if(x<0||x>=this.getWidth()||y<0||y>=this.getHeight())//判断是否撞墙
{
t=false;
result=false;
repaint();
}
int num=shu;
while(num>0) //设置蛇节位置
{
snake[num].setBounds(snake[num-1].getBounds());
num--;
}
if(shu==15) //如果蛇节数等于15则胜利
{
t=false;
result=true;
repaint();
}
}
}
public void keyPressed(KeyEvent e) //按下键盘方向键
{
if(e.getKeyCode()==KeyEvent.VK_RIGHT)//右键
{
if(fangxiang!=1)//如果先前方向不为左
fangxiang=0;
}
else if(e.getKeyCode()==KeyEvent.VK_LEFT)
{ if(fangxiang!=0)
fangxiang=1;
}
else if(e.getKeyCode()==KeyEvent.VK_UP)
{ if(fangxiang!=3)
fangxiang=2;
}
else if(e.getKeyCode()==KeyEvent.VK_DOWN)
{ if(fangxiang!=2)
fangxiang=3;
}
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
}
public void paint(Graphics g) //在面板上绘图
{
int x1=this.getWidth()-1;
int y1=this.getHeight()-1;
g.setColor(Color.red);
g.fillOval(weix, weiy, 10, 10);//食物
g.drawRect(0, 0, x1, y1); //墙
if(t==false&&result==false)
g.drawString("GAME OVER!", 250, 200);//输出游戏失败
else if(t==false&&result==true)
g.drawString("YOU WIN!", 250, 200);//输出游戏成功
}
}
class MyWindow extends Frame implements ActionListener//自定义窗口类
{
MyPanel my;
Button btn;
Panel panel;
MyWindow()
{
super("GreedSnake");
my=new MyPanel();
btn=new Button("begin");
panel=new Panel();
btn.addActionListener(this);
panel.add(new Label("begin后请按Tab键选定蛇"));
panel.add(btn);
panel.add(new Label("按上下左右键控制蛇行动"));
add(panel,BorderLayout.NORTH);
add(my,BorderLayout.CENTER);
setBounds(100,100,610,500);
setVisible(true);
validate();
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
public void actionPerformed(ActionEvent e)//按下begin按钮
{
if(e.getSource()==btn)
{
try
{
my.thread.start(); //开始线程
my.validate();
}
catch(Exception ee){}
}
}
}