贪吃蛇Java课程设计.docx
《贪吃蛇Java课程设计.docx》由会员分享,可在线阅读,更多相关《贪吃蛇Java课程设计.docx(24页珍藏版)》请在冰豆网上搜索。
贪吃蛇Java课程设计
基于Java的游戏“贪吃蛇”的设计和实现
内容提要:
“贪吃蛇”游戏是一个经典的游戏,它因操作简单、娱乐性强而广受欢迎。
本文基于Java技术开发环境,开发了一个操作简单、界面美观、功能较齐全的“贪吃蛇”游戏。
整个游戏程序分六个类模块,实现了游戏的开始、暂停、结束。
通过本游戏的开发,达到学习Java技术和熟悉软件开发流程的目的。
1.设计任务与要求
1.1设计任务
设计一个贪吃蛇的游戏
功能要求:
能够显示贪吃蛇的运动,能通过键盘控制贪吃蛇的运行,能够处理蛇在运行中各种情况,以及其它的辅助功能。
设计任务要完成设计、编码、测试等过程,给出设计思路、主要代码。
源代码以及可运行的贪吃蛇游戏。
1.2具体要求
具体内容如下:
1)设计任务与要求
2)总体方案与说明
3)面向对象的设计(主要类的设计)
4)源程序清单与注释
5)软件主要模块流程图
6)问题分析与解决方案(包括调式记录、调式报告,即在调式过程中遇到的主要问题、解决方法及改进设想);
7)小结与体会
2.软件主要模块流程图
软件的主要模块流程如下图5-1所示
3.总体方案与说明
3.1总体方案
我们设计的贪吃蛇主要利用键盘控制蛇的前进移动方向,是否吃到食物,是否撞墙以及是否暂停、开始游戏等。
当吃到食物的时候,蛇就自动长大一格,在游戏中可进行暂停和开始操作。
中途若是撞到墙或是撞到自己,同样也结束。
3.2系统模块
根据总体方案,我把贪吃蛇游戏分为:
游戏界面设置(即绘图)、贪吃蛇蛇身及运动与碰撞问题(食物、蛇身、石头)设置三大模块来设计。
3.2.1游戏界面设计
游戏界面设置包括:
游戏区,蛇的长度信息,获得分数的信息以及历史最高分的信息。
游戏界面使用简单和直观的布局设计,游戏区放置在界面的主题位置上,在游戏区右上方放置蛇的长度数据及获得的分数数据,具体设计效果如图2-1所示。
图2-1游戏界面
附加代码:
importjava.awt.*;
importjava.io.*;
importjava.util.*;
importjavax.swing.JFrame;
publicclassGameFrameextendsJFrame{
publicGamePanelpanel=newGamePanel(this);
publicSnakexiaoqing=newSnake(this);
publicControlct=newControl(this);
publicFoodfood=newFood(this);
publicLinkedListrocks=newLinkedList();
publicGameFrame(){
}
publicvoidintiRocks(){
}
publicvoidinti(){
}
privateSnakesnake;
Propertiesdbconfig=newProperties();
staticFileInputStreamfile;
publicStringmsg()throwsIOException{
}
privateclassSnakeDriverimplementsRunnable{
@Override
publicvoidrun(){
}
publicstaticvoidmain(String[]args){
GameFramegf=newGameFrame();
}
}
3.2.2贪吃蛇蛇身及运动设置
贪吃蛇的蛇身设置是整个游戏设计的关键。
它的基本思路是:
移动的时候去掉蛇尾,将其添加在蛇头(去尾加头),吃到食物时将之前去掉的尾部在重新加上,完成蛇头吃食物的处理操作,显示蛇头。
具体效果如图2-2所示。
而蛇运动的四个方向,则通过按键来控制。
蛇吃到一个食物,就加分。
每次食物出现的位置不能在蛇身上也不能在屏幕外面,如果蛇在运动的过程中撞到自己或者撞墙,则游戏结束,具体效果如图2-3所示。
图2-2游戏运行中的效果
图2-3就是蛇撞到墙之后,提示游戏结束。
附加代码:
蛇的移动
publicvoidmove(){//蛇的移动方法
if(gf.panel.isPause())return;//判断游戏是否暂停
if(!
life)return;//判断游戏是否GAMEOVER
tail=bady.getLast();//记录下它尾节点
bady.removeLast();//删除它的尾节点
intx=bady.getFirst().x;//获取它头结点的X
inty=bady.getFirst().y;//获取它头节点的Y
if(key+KeyBuffer!
=0){
}
switch(key){//就算其头结点坐标
}
//防止蛇跑出屏幕
if(x<0){
x=Constant.COMPANY_WIDTH-1;
}
if(x>Constant.COMPANY_WIDTH-1){
x=0;
}
if(y<0){
y=Constant.COMPANY_HEIGHT-1;
}
if(y>Constant.COMPANY_HEIGHT-1){
y=0;
}
bady.addFirst(newPoint(x,y));//在其头部加上新的X,Y坐标
}
蛇吃食物,撞墙,撞身体
publicbooleaneatFood(Foodfood){
}
publicbooleaneatRock(Rocksrock){
}
publicbooleaneatBody(){
}
3.2.3游戏控制设置
游戏控制设置就是控制游戏的暂停与开始及重新游戏。
W、S、A、D或上、下、左、右键控制蛇的上、下、左、右移动,设置enter按键来暂停或开始进行中的游戏,设置F1来重新开始游戏。
4.程序设计
贪吃蛇游戏各模块及程序流程有若干类实现,下面阐述各个类的设计与实现。
4.1GamePanel类
该类包含六个主要的功能方法,分别是:
(1)构造函数publicpaintComponrnt(),主要用来设置用户控制面。
(2)publicvoidkeyPressed()方法,主要用来对游戏的按键操作进行处理。
(3)voiddrawFood()drawRocks()主要用来绘制游戏界面食物和石头。
(4)publicvoiddrawfenshu()方法主要用来改变积分器。
(5)publicvoiddrawPause()方法用来实现暂停
(6)voiddrawGameOver()方法用来控制游戏的开始界面。
类
该类包含多个功能方法,分别是:
(1)构造函数publicSnake(),该方法主要用来初始化游戏界蛇的位置及大小且给其一个初始方向。
用一个LinkedList,用来保存蛇的每一节;在利用drawMe()方法遍历LinkedList中保存的节点来画出游戏界面中的蛇。
(2)publicvoidmove()方法主要用来改变蛇的运动方向,
首先判断游戏是否暂停,还有是否GameOver跳出该方法,蛇不能移动否则先保存它的尾节点,在将其尾节点删除,获取其头节点的XY坐标,如果你同时按下2个按键其和为0则按原始方向移动,在获取到移动后XY坐标,将其加在蛇的头部
(3)publicbooleaneatRocks()方法使实现蛇吃石头的函数,首先判断蛇身体的头节点是否和石头重合如果重合,去除蛇身体的头节点,在再其尾节点出加一节身体,并设置Life为false。
(4)publicbooleaneatBody()方法实现蛇吃到自己的身体。
(5)publicBooleaneatFood()方法实现蛇吃到食物
5.分析问题与解决方案
5.1问题处理
问题一:
不能实现游戏中最高分数的存储与读取
使用.properties来存储其最高分数
在用msg()方法来实现其对应数据的读取与存储
问题二:
蛇在吃掉食物时,画出其身体的方法
将先前去除的尾节点在重新加在其尾部
问题三:
图形界面的覆盖
使用双缓冲技术:
双缓冲技术在很多动画中被采用。
主要原理是创建一幅图像,将每一帧画入图像,然后将整个图像一次画到屏幕上去,将其原来的东西覆盖掉。
问题四:
线程的使用
如何将其节点无限重画,及睡眠时间
使用死循环
问题五:
实现键盘操控游戏
使用键盘监听器
6小结与体会
回顾这个设计过程,我学到了许多书本上没有学到的知识。
通过这次自己制作的软件,丰富了自己的实践技能,扩展了本专业的知识面,使我受益非浅,同时也体验到了搞软件开发的困难度。
在这次设计的同时,我又从中学到了许多东西。
但由于我对这样的软件开发还只是一个开始,了解的不多,这其中或许还有很多的不足,有些模块做得不是很好,界面的设计及整体的布局还比较简单,没有突出特色出来,这也可能是我这个系统的不足之处,在这里也恳请各位老师能够对我的作品指明不足并加以改正。
总之,在这一次的课程设计过程中,我查阅了大量的资料,对Java有了一点初步的认识,对于软件工程这些辅助性的教材也巩固了不少,为我这次的课设提供了很大的帮助,锻炼了我的能力让我掌握了一门新的程序设计语言:
java语言,系统地学习了数据库方面的知识,并更进一步提高了我在程序设计、调试方面的技巧。
更重要的是,它还让我认识到了自己的不足,在编程方面,我仅仅是刚刚入门而已,以后的道路任重道远,需要我不断的丰富自己、充实自己,这样才能在程序设计方面有所收获。
参考文献(资料)
[1]谢希仁.计算机网络(第五版).北京:
电子工业出版社,2008
[2]胡小强计算机网络.北京:
北京邮电大学出版社2005
[3]陈轶.姚晓昆编著.Java程序设计实验指导.北京:
清华大学出版社,2006
[4]杨昭编著.二级Java语言程序设计教程.北京:
中国水利水电出版社,2006
[5]赵文靖编著.Java程序设计基础与上机指导.北京:
清华大学出版社,2006
[6]赵毅主编.跨平台程序设计语言——Java.西安:
西安电子科技大学出版社,2006
[7]王路群.Java高级程序设计.北京:
中国水利水电出版社,2006
[8]雍俊海编著.Java程序设计习题集.北京:
清华大学出版社,2006
[9]朱福喜编著.Java语言习题与解析.北京:
清华大学出版社,2006
[10]吴其庆编著.Java程序设计实例教程.北京:
冶金产业出版社,2006
程序代码:
packagecn;
importjava.awt.*;
importjava.io.*;
importjava.util.LinkedList;
importjava.util.Properties;
importjavax.swing.JFrame;
//游戏界面的主要类
publicclassGameFrameextendsJFrame{
publicGamePanelpanel=newGamePanel(this);
publicSnakexiaoqing=newSnake(this);
publicControlct=newControl(this);
publicFoodfood=newFood(this);
publicLinkedListrocks=newLinkedList();
publicGameFrame(){
intwidth=Constant.COMPANY*Constant.COMPANY_WIDTH;
intheight=Constant.COMPANY*Constant.COMPANY_HEIGHT;
panel.setSize(width,height);
panel.setLayout(newBorderLayout());
panel.addKeyListener(ct);
this.add(panel,BorderLayout.CENTER);
this.setSize(width+5,height+28);
this.setLocation((1366-width)/2,(768-height)/2);
this.setVisible(true);
this.setTitle("̰贪吃蛇");
this.setResizable(false);
this.intiRocks();
this.inti();
this.addKeyListener(ct);
this.setDefaultCloseOperation(GameFrame.EXIT_ON_CLOSE);
newThread(newSnakeDriver()).start();
}
publicvoidintiRocks(){
for(inti=0;ifor(intj=0;j//if(0==i||19==i)rocks.add(newRocks(i,j,this));
if((0==j||19==j)&&(0!
=i||19!
=i))
rocks.add(newRocks(i,j,this));
}
}
}
publicvoidinti(){
xiaoqing=newSnake(this);
food=newFood(this);
panel.setPause(true);
panel.setScore(0);
}
privateSnakesnake;
Propertiesdbconfig=newProperties();
staticFileInputStreamfile;
publicStringmsg()throwsIOException{
file=newFileInputStream("src/num.properties");
dbconfig.load(file);
Stringurl1=dbconfig.getProperty("high");
if(!
xiaoqing.isLife()){
intx=panel.getScore();
if(x>Integer.parseInt(url1)){
dbconfig.setProperty("high",panel.getScore()+"");
panel.setHigh(panel.getScore());
OutputStreamout=newFileOutputStream("src/num.properties");
dbconfig.store(out,null);
}
}
returnurl1;
}
privateclassSnakeDriverimplementsRunnable{
@Override
publicvoidrun(){
while(true){
GameFrame.this.panel.repaint();
try{
Thread.sleep(xiaoqing.getSpeed());
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
publicstaticvoidmain(String[]args){
GameFramegf=newGameFrame();
}
}
//在游戏界面中画出事物的主要类
importjava.awt.*;
importjava.io.*;
importjava.util.Properties;
importjavax.swing.JPanel;
publicclassGamePanelextendsJPanel{
privateGameFramegf;
privateSnakes;
privateintscore;
privateinthigh;
privatebooleanpause;
publicGamePanel(GameFramegf){
pause=true;
score=0;
this.gf=gf;
}
@Override
protectedvoidpaintComponent(Graphicsg){
g.setColor(Color.WHITE);
g.fillRect(0,0,Constant.COMPANY*Constant.COMPANY_WIDTH+20,
Constant.COMPANY*Constant.COMPANY_HEIGHT+40);
drawBackGround(g);
gf.xiaoqing.move();
if(gf.xiaoqing.isLife()){
gf.xiaoqing.eatFood(gf.food);
for(Rocksrock:
gf.rocks){
if(gf.xiaoqing.eatRock(rock)){
break;
}
gf.xiaoqing.eatBody();
}
gf.xiaoqing.drawMe(g);
gf.food.drawMe(g);
if(gf.panel.isPause())
drawPause(g);
}
for(Rocksy:
gf.rocks){
y.drawMe(g);
}
if(!
gf.xiaoqing.isLife()){
gf.xiaoqing.drawMe(g);
gf.food.drawMe(g);
drawGameOver(g);
}
drawlenth(g);
drawfenshu(g);
highnum(g);
}
publicvoiddrawGameOver(Graphicsg){
g.setColor(Color.BLUE);
g.drawString("Game_Over按f1重新开始ʼ",Constant.COMPANY*Constant.COMPANY_WIDTH/2-70,
Constant.COMPANY*Constant.COMPANY_HEIGHT/2);
}
publicvoiddrawlenth(Graphicsg){
g.setColor(Color.BLUE);
g.drawString("length:
"+gf.xiaoqing.getBobay().size(),
10,Constant.COMPANY+20);
}
publicvoiddrawfenshu(Graphicsg){
g.setColor(Color.BLUE);
g.drawString("num:
"+gf.panel.getScore(),
10,Constant.COMPANY+40);
}
publicvoidhighnum(Graphicsg){
g.setColor(Color.BLUE);
try{
g.drawString("highnum:
"+gf.msg(),
10,Constant.COMPANY+60);
}catch(IOExceptione){
e.printStackTrace();
}
}
publicvoiddrawPause(Graphicsg){
g.setColor(Color.BLACK);
g.drawString("按Enter暂停或开始",Constant.COMPANY*Constant.COMPANY_WIDTH/2-50,
Constant.COMPANY*Constant.COMPANY_HEIGHT/2);
}
publicvoiddrawBackGround(Graphicsg){
g.setColor(Color.LIGHT_GRAY);
for(intx=0;xg.drawLine(0,x,Constant.COMPANY*Constant.COMPANY_WIDTH,x);
}
for(inty=0;yg.drawLine(y,0,y,Constant.COMPANY*Constant.COMPANY_HEIGHT);
}
}
publicintgetScore(){
returnscore;
}
publicvoidsetScore(intscore){
this.score=score;
}
publicbooleanisPause(){
returnpause;
}
publicvoidsetPause(booleanpause){
this.pause=pause;
}
publicintgetHigh(){
returnhigh;
}
publicvoidsetHigh(inthigh){
this.high=high;
}
}