
贪吃蛇代码
-
2023年3月3日发(作者:零点调查公司)包罗万象网—
用Java编写的贪吃蛇代码
下面是我用java编写的一个贪吃蛇游戏源代码.我个人是比较喜欢玩游戏的,所以学习编程
二年多了,很想做个游戏程序,由于能力有限,一直没能做好,后来突然看同学在手机上玩
“贪吃蛇”,故想做出来,其一是因为此游戏界面容易设计,算法也比较简单,今天我就把
我程序的代码和算法介绍一下,顺便把程序界面皮肤设计说一下......
程序中一个关于游戏信息的类如下,由于类的说明在程序中写的很清楚了,就不再多解
释了:#include"time.h"
//方向定义
constCPointUP(CPoint(0,-1));
constCPointDOWN(CPoint(0,1));
constCPointLEFT(CPoint(-1,0));
constCPointRIGHT(CPoint(1,0));
//速度快慢定义
constintHIGH=75;
constintNORMAL=180;
constintSLOW=300;
constintMAX=80;//表示转向数
constintLENGTH=10;
classGameMsg
{
public:
GameMsg(void)
:m_icon(0)
包罗万象网—
{
InitGame();
}
voidInitGame(intup=VK_UP,intdown=VK_DOWN,intleft=VK_LEFT,intright=
VK_RIGHT)
{
srand((unsigned)time(NULL));
m_gameSpeed=NORMAL;
m_speedNum=2;
m_snakeNum=4;
for(inti=0;i m_snakePoint[i]=CPoint(5+LENGTH*2*5+LENGTH,LENGTH*2*(i+5)); m_run=true; m_direction=RIGHT; turnUP=up; turnDOWN=down; turnLEFT=left; turnRIGHT=right; } public: intm_gameSpeed;//游戏速度 intm_speedNum;//游戏速度数 CPointm_foodPoint;//食物定义 包罗万象网— boolm_run;//游戏状态,运得态还是暂停(结束)态 CPointm_snakePoint[MAX];//蛇身定义 CPointm_direction;//蛇运动方向 intm_snakeNum;//蛇身结点数 intm_icon;//用来设定食物是那种图标的 intturnUP;//用来表示玩家“上”键设的键intturnDOWN;//用来表示玩家“下”键设的 键intturnLEFT;//用来表示玩家“左”键设的键intturnRIGHT;//用来表示玩家“右”键设的键 intm_num;//用来记录所选水果的编号 }; 再让读者看一下程序主干类的设计,其中以下只列出由我们自己添加的一些变量的说 明,其他的是由程序向导自动生成的,我就不说了: public: afx_msgvoidOnTimer(UINT_PTRnIDEvent);//程序中运行函数,即是一个定时器,时间就 是上面类中的m_gameSpeed来控制的CStatic*m_staticArray;//这是一个蛇定义,是用来显示 蛇的,上面只告诉蛇身结点的中心点位置坐标,然后在此中心画一个控件就类似于蛇身了 afx_msgvoidOnClose();//结束,主要是在其中销毁定时器的 voidGameOver(void);//游戏结束函数 afx_msgvoidOnRButtonDown(UINTnFlags,CPointpoint);//当点击鼠标右键出现菜单 afx_msgvoidOnNewGame();//菜单选项,新游戏afx_msgvoidOnPauseOrStart();//菜单选项, 暂停/开始游戏afx_msgvoidOnUpdateQuick(CCmdUI*pCmdUI);//这3个函数本来是来标记 速度的,和上面类中的m_speedNum对应,但是没有标记成功 afx_msgvoidOnUpdateNormal(CCmdUI*pCmdUI); afx_msgvoidOnUpdateSlow(CCmdUI*pCmdUI); afx_msgvoidOnNormal();//菜单选项,设定为普通速度afx_msgvoidOnSlow();//菜单选 项,设定为慢速度afx_msgvoidOnQuick();//菜单选项,设定为快速度afx_msgvoid OnIntroduce();//游戏介绍,就是弹出一个对话框而以 afx_msgvoidOnMoreprogram();//进入我的博客的函数 包罗万象网— afx_msgvoidOnAbout();//关于“贪吃蛇”说明的对话框 afx_msgvoidOnExit();//退出游戏 CFontm_font;//这就是上图中显示“空心字体”的字体设置voidShowHollowFont(intcx, intcy,CStringstr);//显示空心字体函数,在(Cx,Cy)处显示字符串str afx_msgvoidOnBnClickedExit();//退出游戏 private: intm_icon1;//表明蛇吃第1种水果的个数 intm_icon2;//表明蛇吃第2种水果的个数 intm_icon3;//表明蛇吃第3种水果的个数 然后给读者写的是我程序运行很重要的一个函数,WM_TIMER显示函数,里面有食物位置 随机出现,判断蛇死,蛇移动等: voidCSnakeDlg::OnTimer(UINT_PTRnIDEvent) { if(game.m_snakePoint[0].x<0||game.m_snakePoint[0].y game.m_snakePoint[0].x>700||game.m_snakePoint[0].y>500)//当蛇跑出边界,游戏结束 { GameOver(); } for(intj=game.m_snakeNum-1;j>0;--j)//蛇移动的量的变化,当重新设定这些控件的位置 时也就是让蛇移动起来game.m_snakePoint[j]=game.m_snakePoint[j-1]; game.m_snakePoint[0].x+=game.m_direction.x*LENGTH*2;//蛇头移动 game.m_snakePoint[0].y+=game.m_direction.y*LENGTH*2; for(inti=0;i { 包罗万象网— m_staticArray[i].SetWindowPos(NULL,game.m_snakePoint[i].x-LENGTH, game.m_snakePoint[i].y-LENGTH,game.m_snakePoint[i].x+LENGTH,game.m_snakePoint[i].y+ LENGTH, SW_SHOW); } for(intj=1;j ==game.m_snakePoint[j]) { GameOver(); } m_staticArray[MAX].ModifyStyle(0xF,SS_ICON|SS_CENTERIMAGE);//显示水果 m_staticArray[MAX].SetIcon(AfxGetApp()->LoadIcon(game.m_icon)); m_staticArray[MAX].SetWindowPos(NULL,game.m_foodPoint.x,game.m_foodPoint.y,32, 32, SW_SHOW); //当蛇吃到水果 if(game.m_snakePoint[0].x game.m_snakePoint[0].x>game.m_foodPoint.x-LENGTH&&game.m_snakePoint[0].y< game.m_foodPoint.y+20+LENGTH&&game.m_snakePoint[0].y>game.m_foodPoint.y-LENGTH) { game.m_foodPoint=CPoint(LENGTH*m(2,37), LENGTH*m(2,27)); CStringstr; if(game.m_num==0) { ++m_icon1; 包罗万象网— ("%d",m_icon1); GetDlgItem(IDC_EDIT1)->SetWindowTextA(str); } elseif(game.m_num==1) { ++m_icon2; ("%d",m_icon2); GetDlgItem(IDC_EDIT2)->SetWindowTextA(str); } else { ++m_icon3; ("%d",m_icon3); GetDlgItem(IDC_EDIT3)->SetWindowTextA(str); } game.m_num=m(0,3); game.m_icon=IDI_ICON1+game.m_num;//重新加1个水果game.m_snakeNum++;//蛇的 长度加("%d",game.m_snakeNum); GetDlgItem(IDC_EDIT4)->SetWindowTextA(str); } CDialog::OnTimer(nIDEvent); } 如下再介绍应用在对话框中来响应键盘消息,我写的是一个键盘“钩子”,代码如下: 包罗万象网— HHOOKg_hKeyboard=NULL; HWNDg_hWnd=NULL; LRESULTCALLBACKKeyboardProc( intcode,//hookcodeWPARAMwParam,//virtual-keycode LPARAMlParam//keystroke-messageinformation ) { if(wParam==) { if(game.m_direction.y==0)game.m_direction=UP; } elseif(wParam==WN) { if(game.m_direction.y==0)game.m_direction=DOWN; } elseif(wParam==FT) { if(game.m_direction.x==0)game.m_direction=LEFT; } elseif(wParam==GHT) { if(game.m_direction.x==0)game.m_direction=RIGHT; 包罗万象网— } else ; return1; } 然后介绍一下,点击鼠标右键出现菜单:voidCSnakeDlg::OnRButtonDown(UINTnFlags, CPointpoint) { if(game.m_run) KillTimer(1); CMenuoMenu; if(nu(IDR_MENU1)) { CMenu*pPopup=Menu(0); ASSERT(pPopup!=NULL); CPointoPoint; GetCursorPos(&oPoint); SetForegroundWindow(); pPopup->TrackPopupMenu(TPM_LEFTALIGN,oPoint.x,oPoint.y,this); } if(game.m_run)SetTimer(1,game.m_gameSpeed,NULL); CDialog::OnRButtonDown(nFlags,point); 包罗万象网— } 然后来介绍一下程序中是怎样来改变按键的,首先说一下,我开始用EDIT控件来让用户输 入,但是程序中我用的是键盘“钩子”来处理消息的,所以EDIT控件在程序中是不可以输 入信息的,所以我选的是下拉列表,代码如下,解释也在程序中相应给出:intkeyNum[40]= {//定义玩家可以设的键,把所有的键信息存在这个数组中 VK_UP,VK_DOWN,VK_LEFT,VK_RIGHT,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z',VK_NUMPAD0,VK_NUMPAD1,VK_NUMPAD2, VK_NUMPAD3,VK_NUMPAD4,VK_NUMPAD5,VK_NUMPAD6,VK_NUMPAD7,VK_NUMPAD8, VK_NUMPAD9}; voidCSnakeDlg::OnKeyset()//键盘设置响应消息函数 { //TODO:在此添加命令处理程序代码 if(game.m_run) KillTimer(1); CKeySetDlgdlg; if(l()==IDOK) { if(dlg.m_up==dlg.m_down||dlg.m_up==dlg.m_left||dlg.m_up==dlg.m_right|| dlg.m_down==dlg.m_left||dlg.m_down==dlg.m_right||dlg.m_left==dlg.m_right) { MessageBox("键位不能设置为重复的,设置失败!"); if(game.m_run)SetTimer(1,game.m_gameSpeed,NULL); return; } 包罗万象网— =keyNum[GetMarkNum(dlg.m_up)];//重新设置键WN= keyNum[GetMarkNum(dlg.m_down)]; FT=keyNum[GetMarkNum(dlg.m_left)]; GHT=keyNum[GetMarkNum(dlg.m_right)]; } if(game.m_run)SetTimer(1,game.m_gameSpeed,NULL); } intCSnakeDlg::GetMarkNum(CStringstr)//返回重新设置键对应数组的“索引” { intbackNum=0; if(str=="上") backNum=0; elseif(str=="下") backNum=1; elseif(str=="左") backNum=2; elseif(str=="右") backNum=3; else { CStringss; for(chari='A';i<='Z';++i) 包罗万象网— { ("%c",i); if(ss==(1)) { backNum=i-'A'+4; returnbackNum; } } for(inti=0;i<=9;++i) { ("%d",i); if(ss==(1)) { backNum=i+30; returnbackNum; } } } returnbackNum; } 最后写一下程序更换皮肤的一段代码,本来觉得不算很难的,不过还是介绍一下吧,对 了我用的是Skinmagic做的皮肤,不过这个软件你可以通过网上的说明进行注册,也可以自 己把它破解,其实很简单,大家可以试试: 包罗万象网— voidCSnakeDlg::OnChangSkin() { //TODO:在此添加命令处理程序代码 if(game.m_run) KillTimer(1); CFileDialogdlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"Skin Files(*.smf)|*.smf||",AfxGetMainWnd()); CStringstrPath,strText=""; if(l()==IDOK) { strPath=hName(); VERIFY(1==LoadSkinFile(strPath)); } if(game.m_run)SetTimer(1,game.m_gameSpeed,NULL); } 还有很多小函数,由于都是比较简单的,就不多写了,程序介绍就到这里,呵呵,希望 我能够帮你解决你写程序遇到的问题,如果大家想知道如何做程序的皮肤的话,网上有很多 这样的博客,我就是在那样的博客里学到的,如果还是想我来介绍的话,那给我留言说下哦, 呵呵,谢了,有问题请在下面留言......