贪吃蛇java代码.docx
《贪吃蛇java代码.docx》由会员分享,可在线阅读,更多相关《贪吃蛇java代码.docx(12页珍藏版)》请在冰豆网上搜索。
贪吃蛇java代码
用mvc方式实现的贪吃蛇游戏,共有4个类。
运行greedsnake运行即可。
主要是观察者模式的使用,已经添加了很多注释了。
1、
/*
*程序名称:
贪食蛇
*原作者:
bigf
*修改者:
algo
*说明:
以前也用c写过这个程序,现在看到bigf用java写的这个,发现虽然作者自称是java的初学者,
* 但是明显编写程序的素养不错,程序结构写得很清晰,有些细微得地方也写得很简洁,一时兴起之
* 下,认真解读了这个程序,发现数据和表现分开得很好,而近日正在学习mvc设计模式,
* 因此尝试把程序得结构改了一下,用mvc模式来实现,对源程序得改动不多。
* 同时也为程序增加了一些自己理解得注释,希望对大家阅读有帮助。
*/
packagemvctest;
/**
*@authorwangyu
*@version1.0
*description:
*
*createon:
date:
2005-6-13 time:
15:
57:
16
*lastmodified:
*history:
*/
publicclassgreedsnake{
publicstaticvoidmain(string[]args){
snakemodelmodel=newsnakemodel(20,30);
snakecontrolcontrol=newsnakecontrol(model);
snakeviewview=newsnakeview(model,control);
//添加一个观察者,让view成为model的观察者
model.addobserver(view);
(newthread(model)).start();
}
}
-------------------------------------------------------------
2、
packagemvctest;
//snakecontrol.java
importjava.awt.event.keyevent;
importjava.awt.event.keylistener;
/**
*mvc中的controler,负责接收用户的操作,并把用户操作通知model
*/
publicclasssnakecontrol implementskeylistener{
snakemodelmodel;
publicsnakecontrol(snakemodelmodel){
this.model=model;
}
publicvoidkeypressed(keyevente){
intkeycode=e.getkeycode();
if(model.running){ //运行状态下,处理的按键
switch(keycode){
casekeyevent.vk_up:
model.changedirection(snakemodel.up);
break;
casekeyevent.vk_down:
model.changedirection(snakemodel.down);
break;
casekeyevent.vk_left:
model.changedirection(snakemodel.left);
break;
casekeyevent.vk_right:
model.changedirection(snakemodel.right);
break;
casekeyevent.vk_add:
casekeyevent.vk_page_up:
model.speedup();
break;
casekeyevent.vk_subtract:
casekeyevent.vk_page_down:
model.speeddown();
break;
casekeyevent.vk_space:
casekeyevent.vk_p:
model.changepausestate();
break;
default:
}
}
//任何情况下处理的按键,按键导致重新启动游戏
if(keycode==keyevent.vk_r||
keycode==keyevent.vk_s||
keycode==keyevent.vk_enter){
model.reset();
}
}
publicvoidkeyreleased(keyevente){
}
publicvoidkeytyped(keyevente){
}
}
-------------------------------------------------------------
3、
/*
*
*/
packagemvctest;
/**
*游戏的model类,负责所有游戏相关数据及运行
*@authorwangyu
*@version1.0
*description:
*
*createon:
date:
2005-6-13 time:
15:
58:
33
*lastmodified:
*history:
*/
//snakemodel.java
importjavax.swing.*;
importjava.util.arrays;
importjava.util.linkedlist;
importjava.util.observable;
importjava.util.random;
/**
*游戏的model类,负责所有游戏相关数据及运行
*/
classsnakemodelextendsobservableimplementsrunnable{
boolean[][]matrix; //指示位置上有没蛇体或食物
linkedlistnodearray=newlinkedlist(); //蛇体
nodefood;
intmaxx;
intmaxy;
intdirection=2; //蛇运行的方向
booleanrunning=false; //运行状态
inttimeinterval=200; //时间间隔,毫秒
doublespeedchangerate=0.75; //每次得速度变化率
booleanpaused=false; //暂停标志
intscore=0; //得分
intcountmove=0; //吃到食物前移动的次数
//upanddownshouldbeeven
//rightandleftshouldbeodd
publicstaticfinalintup=2;
publicstaticfinalintdown=4;
publicstaticfinalintleft=1;
publicstaticfinalintright=3;
publicsnakemodel(intmaxx,intmaxy){
this.maxx=maxx;
this.maxy=maxy;
reset();
}
publicvoidreset(){
direction=snakemodel.up; //蛇运行的方向
timeinterval=200; //时间间隔,毫秒
paused=false; //暂停标志
score=0; //得分
countmove=0; //吃到食物前移动的次数
//initialmatirx,全部清0
matrix=newboolean[maxx][];
for(inti=0;i matrix[i]=newboolean[maxy];
arrays.fill(matrix[i],false);
}
//initialthesnake
//初始化蛇体,如果横向位置超过20个,长度为10,否则为横向位置的一半
intinitarraylength=maxx>20?
10:
maxx/2;
nodearray.clear();
for(inti=0;i intx=maxx/2+i;//maxx被初始化为20
inty=maxy/2; //maxy被初始化为30
//nodearray[x,y]:
[10,15]-[11,15]-[12,15]~~[20,15]
//默认的运行方向向上,所以游戏一开始nodearray就变为:
// [10,14]-[10,15]-[11,15]-[12,15]~~[19,15]
nodearray.addlast(newnode(x,y));
matrix[x][y]=true;
}
//创建食物
food=createfood();
matrix[food.x][food.y]=true;
}
publicvoidchangedirection(intnewdirection){
//改变的方向不能与原来方向同向或反向
if(direction%2!
=newdirection%2){
direction=newdirection;
}
}
/**
*运行一次
*@return
*/
publicbooleanmoveon(){
noden=(node)nodearray.getfirst();
intx=n.x;
inty=n.y;
//根据方向增减坐标值
switch(direction){
caseup:
y--;
break;
casedown:
y++;
break;
caseleft:
x--;
break;
caseright:
x++;
break;
}
//如果新坐标落在有效范围内,则进行处理
if((0<=x&&x
if(matrix[x][y]){ //如果新坐标的点上有东西(蛇体或者食物)
if(x==food.x&&y==food.y){ //吃到食物,成功
nodearray.addfirst(food); //从蛇头赠长
//分数规则,与移动改变方向的次数和速度两个元素有关
intscoreget=(10000-200*countmove)/timeinterval;
score+=scoreget>0?
scoreget:
10;
countmove=0;
food=createfood(); //创建新的食物
matrix[food.x][food.y]=true; //设置食物所在位置
returntrue;
}else //吃到蛇体自身,失败
returnfalse;
}else{ //如果新坐标的点上没有东西(蛇体),移动蛇体
nodearray.addfirst(newnode(x,y));
matrix[x][y]=true;
n=(node)nodearray.removelast();
matrix[n.x][n.y]=false;
countmove++;
returntrue;
}
}
returnfalse; //触到边线,失败
}
publicvoidrun(){
running=true;
while(running){
try{
thread.sleep(timeinterval);
}catch(exceptione){
break;
}
if(!
paused){
if(moveon()){
setchanged(); //model通知view数据已经更新
notifyobservers();
}else{
joptionpane.showmessagedialog(null,
"youfailed",
"gameover",
joptionpane.information_message);
break;
}
}
}
running=false;
}
privatenodecreatefood(){
intx=0;
inty=0;
//随机获取一个有效区域内的与蛇体和食物不重叠的位置
do{
randomr=newrandom();
x=r.nextint(maxx);
y=r.nextint(maxy);
}while(matrix[x][y]);
returnnewnode(x,y);
}
publicvoidspeedup(){
timeinterval*=speedchangerate;
}
publicvoidspeeddown(){
timeinterval/=speedchangerate;
}
publicvoidchangepausestate(){
paused=!
paused;
}
publicstringtostring(){
stringresult="";
for(inti=0;i noden=(node)nodearray.get(i);
result+="["+n.x+","+n.y+"]";
}
returnresult;
}
}
classnode{
intx;
inty;
node(intx,inty){
this.x=x;
this.y=y;
}
}
------------------------------------------------------------
4、
packagemvctest;
//snakeview.java
importjavax.swing.*;
importjava.awt.*;
importjava.util.iterator;
importjava.util.linkedlist;
importjava.util.observable;
importjava.util.observer;
/**
*mvc模式中得viewer,只负责对数据的显示,而不用理会游戏的控制逻辑
*/
publicclasssnakeviewimplementsobserver{
snakecontrolcontrol=null;
snakemodelmodel=null;
jframemainframe;
canvaspaintcanvas;
jlabellabelscore;
publicstaticfinalintcanvaswidth=200;
publicstaticfinalintcanvasheight=300;
publicstaticfinalintnodewidth=10;
publicstaticfinalintnodeheight=10;
publicsnakeview(snakemodelmodel,snakecontrolcontrol){
this.model=model;
this.control=control;
mainframe=newjframe("greedsnake");
containercp=mainframe.getcontentpane();
//创建顶部的分数显示
labelscore=newjlabel("score:
");
cp.add(labelscore,borderlayout.north);
//创建中间的游戏显示区域
paintcanvas=newcanvas();
paintcanvas.setsize(canvaswidth+1,canvasheight+1);
pa