多语言展示
当前在线:1392今日阅读:113今日分享:31

C++实现贪吃蛇

这里打算使用较为简单的方法写一个十分简单的游戏——贪吃蛇,这里尽量使用较为直白的叙述,让大家能短时间内写出一个贪吃蛇,下面就是贪吃蛇的截图。
工具/原料

VC++6.0

方法/步骤
1

新建工程,这里新建的是单文档程序,然后一步步按照图示来,就能把工程建好了。这里注意的是一定要建立的是 单文档程序

2

新建 贪吃蛇类 ,CSnakeGame,这个类实现贪吃蛇的大部分功能,包含,初始化贪吃蛇,生成食物的位置,eat一个实物,向上下左右四个方向,next是下一步。代码如下// SnakeGame.h: interface for the CSnakeGame class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_SNAKEGAME_H__074FBCE0_CE02_48E4_978F_AF89899F85A5__INCLUDED_)#define AFX_SNAKEGAME_H__074FBCE0_CE02_48E4_978F_AF89899F85A5__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include struct Point{    int x;    int y;    Point():x(0),y(0){}    Point(int _x,int _y):x(_x),y(_y){}};class CSnakeGame  {public:    Point head;    Point food;    int direct; // 0 down 1 up 2 left 3 right    CArray arr ;    CSnakeGame();    virtual ~CSnakeGame();    void InitGame(){        head.x = 4 ;        head.y = 4 ;        arr.RemoveAll() ;        AddHead() ;        GenerateFood() ;    }    void AddHead(){arr.Add(head);}    void Left(){if(direct!=3)direct = 2 ;}    void Right(){if(direct!=2)direct = 3 ;}    void Up(){if(direct!=0)direct = 1 ;}    void Down(){if(direct!=1)direct = 0 ;}    bool Next(){        head = arr.ElementAt(0) ;        switch(direct){            case 0:                head.x+=1;                break;            case 1:                head.x-=1;                break;            case 2:                head.y-=1;                break;            case 3:                head.y+=1;                break;        }        if(IsOver(head))return false ;        if(head.x == food.x && head.y == food.y) {            eat();            GenerateFood() ;        }else{            arr.InsertAt(0,head) ;            arr.RemoveAt(arr.GetSize()-1) ;        }        return true ;    }    bool IsOver(Point head){        if(head.x<0||head.x>=10||head.y<0||head.y>=10)return true ;        return false ;    }    void eat(){        arr.InsertAt(0,food) ;    }    void GenerateFood(){        food.x = rand() % 10  ;        food.y = rand() % 10  ;     }    };#endif // !defined(AFX_SNAKEGAME_H__074FBCE0_CE02_48E4_978F_AF89899F85A5__INCLUDED_)

3

然后就是编写界面和实现响应函数了,界面部分就是注意添加一个菜单,按照图中的说明,添加好菜单项的属性ID等信息。在通过类向导添加每个菜单项的响应函数。如图所示。添加定时器相应函数,添加KeyUp和keydown响应函数

4

实现相应的响应函数代码,整个程序就基本完成了。下面是全部的实现代码SnakeView.cpp// SnakeView.cpp : implementation of the CSnakeView class//#include 'stdafx.h'#include 'Snake.h'#include 'SnakeDoc.h'#include 'SnakeView.h'#include 'SnakeGame.h'#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCSnakeGame snakeGame ;/////////////////////////////////////////////////////////////////////////////// CSnakeViewIMPLEMENT_DYNCREATE(CSnakeView, CView)BEGIN_MESSAGE_MAP(CSnakeView, CView)    //{{AFX_MSG_MAP(CSnakeView)    ON_COMMAND(ID_MENUITEM_START, OnMenuitemStart)    ON_WM_TIMER()    ON_WM_KEYUP()    ON_WM_KEYDOWN()    ON_COMMAND(ID_MENUITEM_STOP, OnMenuitemStop)    ON_COMMAND(ID_MENUITEM_GOON, OnMenuitemGoon)    //}}AFX_MSG_MAP    // Standard printing commands    ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)    ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)    ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CSnakeView construction/destructionCSnakeView::CSnakeView(){    // TODO: add construction code here    my_start = false ;    my_gameOver = false ;    my_stop = false ;    WhiteBrush.CreateSolidBrush(RGB(255,255,255));    BlackBrush.CreateSolidBrush(RGB(0,0,0));    GreenBrush.CreateSolidBrush(RGB(0,255,0));    RedBrush.CreateSolidBrush(RGB(255,0,0));    YellowBrush.CreateSolidBrush(RGB(255,255,0));        datas = new int[10][10] ;}CSnakeView::~CSnakeView(){}BOOL CSnakeView::PreCreateWindow(CREATESTRUCT& cs){    // TODO: Modify the Window class or styles here by modifying    //  the CREATESTRUCT cs    return CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CSnakeView drawingvoid CSnakeView::OnDraw(CDC* pDC){    CSnakeDoc* pDoc = GetDocument();    ASSERT_VALID(pDoc);    // TODO: add draw code for native data here    if(my_start){        RECT rect ;        GetClientRect(&rect) ;        //pDC->FillRect(&rect,&GreenBrush) ;        InitFace(pDC);    }    }/////////////////////////////////////////////////////////////////////////////// CSnakeView printingBOOL CSnakeView::OnPreparePrinting(CPrintInfo* pInfo){    // default preparation    return DoPreparePrinting(pInfo);}void CSnakeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){    // TODO: add extra initialization before printing}void CSnakeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){    // TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CSnakeView diagnostics#ifdef _DEBUGvoid CSnakeView::AssertValid() const{    CView::AssertValid();}void CSnakeView::Dump(CDumpContext& dc) const{    CView::Dump(dc);}CSnakeDoc* CSnakeView::GetDocument() // non-debug version is inline{    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSnakeDoc)));    return (CSnakeDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CSnakeView message handlersvoid CSnakeView::OnMenuitemStart() {    // TODO: Add your command handler code here    my_start = true ;    my_gameOver = false ;    snakeGame.InitGame() ;    Invalidate(TRUE) ;}void CSnakeView::InitFace(CDC* pDC){    CDC *cdc = this->GetDC();        CDC MemDC; //首先定义一个显示设备对象    CBitmap MemBitmap;//定义一个位图对象        CRect crect;    this->GetClientRect(crect);        MemDC.CreateCompatibleDC(NULL);//随后建立与屏幕显示兼容的内存显示设备    //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小    MemBitmap.CreateCompatibleBitmap(cdc, main_rect.right-main_rect.left, main_rect.bottom-main_rect.top);    //将位图选入到内存显示设备中    //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上    CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);    //先用背景色将位图清除干净,颜色自选     MemDC.FillSolidRect(0,0, main_rect.right-main_rect.left, main_rect.bottom-main_rect.top,RGB(255,255,255));    //这里加入自己的画图代码,此时画图都是在内存中完成,操作对象是MemDC    //然后将内存中的图拷贝到屏幕上进行显示    RECT rect ;    CBrush* brush ;    for(int i = 0 ; i < 10 ;i ++)    {        for(int j = 0 ; j < 10 ;j++){            rect.left = uWidth * j - 1;            rect.top =  uHeight * i - 1;            rect.right = rect.left + uWidth -1 ;            rect.bottom = rect.top + uHeight -1 ;            if(datas[i][j] == 0 )brush = &BlackBrush ;            else if(datas[i][j] == 1)brush = &GreenBrush ;            else if(datas[i][j] == 2)brush = &RedBrush ;            else if(datas[i][j] == 3)brush = &YellowBrush ;            MemDC.FillRect(&rect,brush) ;        }    }    cdc->BitBlt(0,0, crect.Width(), crect.Height(),&MemDC,0, 0,SRCCOPY);    //绘图完成后清理临时对象    MemBitmap.DeleteObject();    MemDC.DeleteDC();}void CSnakeView::OnInitialUpdate() {    CView::OnInitialUpdate();    GetClientRect(&main_rect) ;    uWidth = (main_rect.right - main_rect.left) / 10;    uHeight = (main_rect.bottom - main_rect.top) / 10;    InitArr(datas,10,10) ;    SetTimer(1,1000,NULL) ;}void CSnakeView::InitArr(int (*datas) [10],int x,int y){    for(int i = 0 ; i < x ; i++)    {        for(int j = 0 ; j < y ; j++){            datas[i][j] = 0 ;        }    }}void CSnakeView::GetPicMap(){    InitArr(datas,10,10) ;    int len = snakeGame.arr.GetSize() ;    for(int i = 0 ; i < len ; i++ ){        Point p = snakeGame.arr.GetAt(i) ;        datas[p.x][p.y] = 1 ;    }    datas[snakeGame.head.x][snakeGame.head.y] = 2 ;    datas[snakeGame.food.x][snakeGame.food.y] = 3 ;}void CSnakeView::drawOver(){    CDC* pcd =  this->GetDC();    CString str = 'GAME OVER' ;    CRect rect ;    rect.left = main_rect.Width() / 2 - 100;    rect.top = main_rect.Height() / 2 - 100;    rect.right = main_rect.Width() / 2;    rect.bottom = main_rect.Height() / 2;    pcd->DrawText(str,rect, 0) ;}void CSnakeView::OnTimer(UINT nIDEvent) {    // TODO: Add your message handler code here and/or call default    if(nIDEvent == 1){        if(my_start && !my_gameOver && !my_stop){            my_gameOver =            !snakeGame.Next() ;            if(my_gameOver){                drawOver();            return ;}            GetPicMap() ;            Invalidate() ;        }    }    CView::OnTimer(nIDEvent);}void CSnakeView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {    // TODO: Add your message handler code here and/or call default    switch(nChar){        case VK_UP:            snakeGame.Up() ;            break;        case VK_LEFT:            snakeGame.Left() ;            break;        case VK_RIGHT:            snakeGame.Right() ;            break;        case VK_DOWN:            snakeGame.Down() ;            break;    }    CView::OnKeyUp(nChar, nRepCnt, nFlags);}void CSnakeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {    if(my_gameOver){        drawOver();            return ;}    // TODO: Add your message handler code here and/or call default    if(my_gameOver){        drawOver();            return ;}    switch(nChar){    case VK_UP:        snakeGame.Up() ;        break;    case VK_LEFT:        snakeGame.Left() ;        break;    case VK_RIGHT:        snakeGame.Right() ;        break;    case VK_DOWN:        snakeGame.Down() ;        break;    }    my_gameOver =            !snakeGame.Next() ;    GetPicMap();    Invalidate() ;    if(my_gameOver){        drawOver();            return ;}    CView::OnKeyDown(nChar, nRepCnt, nFlags);}void CSnakeView::OnMenuitemStop() {    // TODO: Add your command handler code here        my_stop = true ;}void CSnakeView::OnMenuitemGoon() {    // TODO: Add your command handler code here    my_stop = false ;}

5

最后就是调试运行了,结果图如下

注意事项
1

先调试后运行

2

VC6.0容易崩溃,崩溃了使用任务管理器,重启就好了

推荐信息