java贪吃蛇小游戏代码设计

用Java编写的贪吃蛇代码
下面是我用java编写的一个贪吃蛇游戏源代码.我个人是比较喜欢玩游戏的,所以学习编程二年多了,很想做个游戏程序,由于能力有限,一直没能做好,后来突然看同学在手机上玩“贪吃蛇”,故想做出来,其一是因为此游戏界面容易设计,算法也比较简单,今天我就把我程序的代码和算法介绍一下,顺便把程序界面皮肤设计说一下......
程序中一个关于游戏信息的类如下,由于类的说明在程序中写的很清楚了,就不再多解释了:#include "time.h"
//方向定义
const CPoint UP(CPoint(0,-1));
const CPoint DOWN(CPoint(0,1));
const CPoint LEFT(CPoint(-1,0));
const CPoint RIGHT(CPoint(1,0));
//速度快慢定义
const int HIGH = 75;
const int NORMAL = 180;
const int SLOW = 300;
const int MAX = 80; //表示转向数
const int LENGTH = 10;
class GameMsg
{
public:
GameMsg(void)
: m_icon(0)
{
InitGame();
}
void InitGame(int up = VK_UP, int down = VK_DOWN, int left = VK_LEFT, int right = VK_RIGHT)
{
srand((unsigned)time(NULL));
m_gameSpeed = NORMAL;
m_speedNum = 2;
m_snakeNum = 4;
for(int i=0; i<m_snakeNum; ++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:
int m_gameSpeed;//游戏速度
int m_speedNum;//游戏速度数
CPoint m_foodPoint; //食物定义
bool m_run;//游戏状态,运得态还是暂停(结束)态
CPoint m_snakePoint[MAX]; //蛇身定义
CPoint m_direction;//蛇运动方向
int m_snakeNum; //蛇身结点数
int m_icon;//用来设定食物是那种图标的
int turnUP;//用来表示玩家“上”键设的键int turnDOWN;//用来表示玩家“下”键设的键int turnLEFT;//用来表示玩家“左”键设的键int turnRIGHT;//用来表示玩家“右”键设的键
int m_num;//用来记录所选水果的编号
};
再让读者看一下程序主干类的设计,其中以下只列出由我们自己添加的一些变量的说明,其他的是由程序向导自动生成的,我就不说了:
public:
afx_msg void OnTimer(UINT_PTR nIDEvent);//程序中运行函数,即是一个定时器,时间就是上面类
中的m_gameSpeed来控制的CStatic *m_staticArray;//这是一个蛇定义,是用来显示蛇的,上面只告诉蛇身结点的中心点位置坐标,然后在此中心画一个控件就类似于蛇身了afx_msg void OnClose();//结束,主要是在其中销毁定时器的
void GameOver(void);//游戏结束函数
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);//当
点击鼠标右键出现菜单afx_msg void OnNewGame();//菜单选项,新游戏afx_msg void OnPauseOrStart();//菜单选项,暂停/开始 游戏afx_msg void OnUpdateQuick(CCmdUI *pCmdUI);//这3个函数本来是来标记速度的,和上面类中的m_speedNum对应,但是没有标记成功
afx_msg void OnUpdateNormal(CCmdUI *pCmdUI);
afx_msg void OnUpdateSlow(CCmdUI *pCmdUI);
afx_msg void OnNormal();//菜单选项,设定为普通速度afx_msg void OnSlow();//菜单选项,设定为慢速度afx_msg void OnQuick();//菜单选项,设定为快速度afx_msg void OnIntroduce();//游戏介绍,就是弹出一个对话框而以
afx_msg void OnMoreprogram();//进入我的博客的函数
afx_msg void OnAbout();//关于“贪吃蛇”说明的对话框
afx_msg void OnExit();//退出游戏
CFont m_font;//这就是上图中显示“空心字体”的字体设置void ShowHollowFont(int cx, int cy, CString str);//显示空心字体函数,在(Cx,Cy)处显示字符串str
afx_msg void OnBnClickedExit();//退出游戏
private:
int m_icon1;//表明蛇吃第1种水果的个数
int m_icon2;//表明蛇吃第2种水果的个数
int m_icon3;//表明蛇吃第3种水果的个数
然后给读者写的是我程序运行很重要的一个函数,WM_TIMER显示函数,里面有食物位置随机出现,判断蛇死,蛇移动等:
void CSnakeDlg::OnTimer(UINT_PTR nIDEvent)
{
if(game.m_snakePoint[0].x < 0 || game.m_snakePoint[0].y < LENGTH || game.m_snakePoint[0].x > 700 || game.m_snakePoint[0].y > 500)//当蛇跑出边界,游戏结束
{
高泰克斯GameOver();
}
for(int j=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(int i=0; i<game.m_snakeNum; ++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(int j=1; j<game.m_snakeNum; ++j)//当蛇撞到自己也结束游戏if(game.m_snakePoint[0] == 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_foodPoint.x+20+LENGTH && 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 = CPoin
t(LENGTH*game.RandNum(2,37), LENGTH*game.RandNum(2,27));
CString str;
if(game.m_num == 0)
{
++m_icon1;
str.Format("%d",m_icon1);
GetDlgItem(IDC_EDIT1)->SetWindowTextA(str);
}
else if(game.m_num == 1)
{
++m_icon2;
str.Format("%d",m_icon2);
GetDlgItem(IDC_EDIT2)->SetWindowTextA(str);
}
else
{
++m_icon3;
str.Format("%d",m_icon3);
GetDlgItem(IDC_EDIT3)->SetWindowTextA(str);
}
game.m_num = game.RandNum(0,3);
game.m_icon = IDI_ICON1 + game.m_num;//重新加1个水果game.m_snakeNum++;//蛇的长度加1 str.Format("%d",game.m_snakeNum);
GetDlgItem(IDC_EDIT4)->SetWindowTextA(str);
}
CDialog::OnTimer(nIDEvent);
}
如下再介绍应用在对话框中来响应键盘消息,我写的是一个键盘“钩子”,代码如下:
HHOOK g_hKeyboard = NULL;
HWND g_hWnd = NULL;
LRESULT CALLBACK KeyboardProc(
int code,      // hook code WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if(wParam == game.turnUP)
{
if(game.m_direction.y == 0) game.m_direction = UP;
}
else if(wParam == game.turnDOWN)
{
if(game.m_direction.y == 0) game.m_direction = DOWN;
}
else if(wParam == game.turnLEFT)
{
if(game.m_direction.x == 0) game.m_direction = LEFT;
}
else if(wParam == game.turnRIGHT)
{
if(game.m_direction.x == 0) game.m_direction = RIGHT;
}
else
;
return 1;
}
然后介绍一下,点击鼠标右键出现菜单:void CSnakeDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
华北油田if(game.m_run)
KillTimer(1);
CMenu oMenu;
if (oMenu.LoadMenu(IDR_MENU1))
{
CMenu* pPopup = oMenu.GetSubMenu(0);eph
ASSERT(pPopup != NULL);
CPoint oPoint;
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控件在程序中是不可以输入信息的,所以我选的是下拉列表,代码如下,解释也在程序中相应给出:int keyNum[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};
void CSnakeDlg::OnKeyset()//键盘设置响应消息
函数
{
// TODO:在此添加命令处理程序代码
if(game.m_run)
KillTimer(1);
CKeySetDlg dlg;
if(dlg.DoModal() == 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;
}
game.turnUP = keyNum[GetMarkNum(dlg.m_up)];//重新设置键game.turnDOWN = keyNum[GetMarkNum(dlg.m_down)];
game.turnLEFT = keyNum[GetMarkNum(dlg.m_left)];
game.turnRIGHT = keyNum[GetMarkNum(dlg.m_right)];
}
if(game.m_run) SetTimer(1,game.m_gameSpeed,NULL);
}
int CSnakeDlg::GetMarkNum(CString str)//返回重新设置键对应数组的“索引”
{
int backNum = 0;
if(str == "上")
backNum = 0;
else if(str == "下")
backNum = 1;
else if(str == "左")
backNum = 2;
else if(str == "右")
backNum = 3;
else
{
CString ss;
for(char i='A'; i<='Z'; ++i)
{
ss.Format("%c",i);
if(ss == str.Right(1))
{
backNum = i - 'A' + 4;
return backNum;
}
}
for(int i=0; i<=9; ++i)
{
ss.Format("%d",i);
if(ss == str.Right(1))
{
backNum = i + 30;
淋巴肉瘤return backNum;
}
}
}
return backNum;
}
最后写一下程序更换皮肤的一段代码,本来觉得不算很难的,不过还是介绍一下吧,对了我用的是Skinmagic做的皮肤,不过这个软件你可以通过网上的说明进行注册,也可以自己把它破解,其实很简单,大家可以试试:
void CSnakeDlg::OnChangSkin()
{
// TODO:在此添加命令处理程序代码
if(game.m_run)
iitaKillTimer(1);
CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Skin Files(*.smf)|*.smf||",AfxGetMainWnd());
CString strPath,strText="";
if(dlg.DoModal() == IDOK)
{
strPath = dlg.GetPathName();
VERIFY(1 == LoadSkinFile(strPath));
}
if(game.m_run) SetTimer(1,game.m_gameSpeed,NULL);
}
还有很多小函数,由于都是比较简单的,就不多写了,程序介绍就到这里,呵呵,希望我能够帮你解决你写程序遇到的问题,如果大家想知道如何做程序的皮肤的话,网上有很多这样的博客,我就是在那样的博客里学到的,如果还是想我来介绍的话,那给我留言说下哦,呵呵,谢了,有问题请在下面留言......

本文发布于:2024-09-22 15:39:01,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/244860.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:程序   游戏   设定   代码   设置   菜单   用来   函数
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议