⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 贪吃蛇vc++.txt

📁 模仿NOKIA公司经典的贪吃蛇游戏做的VC++的源程序代码
💻 TXT
字号:
应该是C的程序,而且是borland c
这个东西应该不是原创吧?

我发一个win32版,真正原创.注意有三个文件.
SnakeWin32.cpp SnakeWin32.rc resource.h
命令行编译:
-----visual c++-----
rc SnakeWin32.rc
cl /MT /nologo SnakeWin32.cpp SnakeWin32.res gdi32.lib user32.lib 
-----Gcc(Cygwin/Mingw32)-----
windres -i SnakeWin32.rc --input-format=rc -0 coff -o SnakeWin32.res
g++ SnakeWin32.cpp SnakeWin32.res -mwindows -lgdi32 -luser32 -o SnakeWin32 -s
如果不知道如何用命令行,那就留下邮箱,我发vs2003.net的工程给你.

----------SnakeWin32.cpp------
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <iterator>

#include <time.h>

#include <windows.h>
#include <windowsX.h>

#include "resource.h"

class point_t : public POINT
{
public:
point_t()
{
this->x = 0;
this->y = 0;
}
point_t(long x, long y)
{
this->x = x;
this->y = y;
}
};

inline bool operator==(point_t const& a, point_t const& b)
{
return a.x == b.x && a.y == b.y;
}

inline bool operator!=(point_t const& a, point_t const& b)
{
return !(a==b);
}


/*!生成横向连续的点
*/
class SequenceGen
{
point_t priv_;
public:
typedef point_t result_type;

SequenceGen(size_t width, size_t height) 
{
priv_.x = static_cast<long>(width / 2);
priv_.y = static_cast<long>(height / 2);
}
point_t operator()()
{
priv_.x++;
return priv_;
}
};

struct Drawer
{
virtual void DrawBox(size_t w, size_t h) = 0;
virtual void DrawSnakeBody(size_t x, size_t y, size_t block) =0;
virtual void DrawSnakeFood(size_t x, size_t y, size_t block) =0;
};

/*! 贪吃的蛇
*/
template <typename Random>
class Snake //: public std::unary_function<point_t, bool>
{
public:
enum Direction { NO_CHANGE, UP, DOWN, LEFT, RIGHT};
typedef std::list<point_t> PointList;
typedef PointList::iterator PointListIter;
private:
PointList body_;
Direction direction_;
Direction newDirection_;
PointList foods_;

bool directionChanged_; 

long width_;
long height_;
long step_;
public:
static size_t MAX_FOODS;
static size_t INITIAL_SIZE;

Snake(long width, long height, long step = 5)
: direction_(LEFT), newDirection_(NO_CHANGE), width_(width - 1), height_(height - 1), step_(step)
{
CreateFoods();
InitialSnake(); 
}

bool StepLeft()
{
return DirectTo(LEFT, direction_ == RIGHT); 
}
bool StepRight()
{
return DirectTo(RIGHT, direction_ == LEFT); 
}
bool StepUp()
{
return DirectTo(UP, direction_ == DOWN);
}
bool StepDown()
{
return DirectTo(DOWN, direction_ == UP);
}

bool DirectTo(Direction direct, bool go_back)
{
if(!go_back && newDirection_ == NO_CHANGE)
{
newDirection_ = direct; 
return true;
}
return false;
}
point_t GetNextStep()
{
point_t nextStep = body_.front();
Direction direction =
(newDirection_ == NO_CHANGE) ? direction_ : newDirection_;

switch(direction)
{
case UP:
nextStep.x; nextStep.y--;
break;
case DOWN:
nextStep.x; nextStep.y++;
break;
case LEFT:
nextStep.x--; nextStep.y;
break;
case RIGHT:
nextStep.x++; nextStep.y;
break;
default:
//assert(!"Should not go here");
break;
}
direction_ = direction;
newDirection_ = NO_CHANGE;
return nextStep;
}

//heart of snake, call this every times!
bool Engine()
{
point_t thisPoint = GetNextStep(); 

if(IsDead(thisPoint))
{
return false;
}

if(NeedFeed(thisPoint))
{
//NOTE: feed means append one, so I did not call pop_back.

if(foods_.empty())
{
CreateFoods();
}
}
else
{
body_.pop_back();
}

//go ahead
body_.push_front(thisPoint);


return true;
}

void Draw(Drawer* myDrawer)
{
myDrawer->DrawBox(width_, height_);

for(PointListIter i = body_.begin(); i != body_.end(); i++)
{
myDrawer->DrawSnakeBody(i->x, i->y, step_);
}

for(PointListIter i = foods_.begin(); i != foods_.end(); i++)
{
myDrawer->DrawSnakeFood(i->x, i->y, step_);
}
}

int GetScore()
{
return body_.size();
}

protected:
void CreateFoods()
{
foods_.clear();
std::generate_n(std::back_inserter(foods_), MAX_FOODS, Random(width_, height_));
}

void InitialSnake()
{
body_.clear();
std::generate_n(std::back_inserter(body_), INITIAL_SIZE, SequenceGen(width_, height_));
direction_ = LEFT; 
}

bool NeedFeed(point_t& thisPoint)
{
PointListIter p = std::find(foods_.begin(), foods_.end(), thisPoint);
if(p != foods_.end())
{
foods_.erase(p);
return true;
}
return false;
}

bool IsDead(point_t& point)
{
return (IsPointInBox(point) || IsPointOnBody(point));
}

bool IsPointInBox(point_t& point)
{
return point.x < 0 || point.y < 0 || point.x >= width_ || point.y >= height_;
}
bool IsPointOnBody(point_t& point)
{
//skip header
return find(++body_.begin(), body_.end(), point) != body_.end();
}

};

template <typename T> size_t Snake<T>::MAX_FOODS = 20;
template <typename T> size_t Snake<T>::INITIAL_SIZE = 13;


#define ID_TIMER 10001
BOOL ResizeClient(HWND hWnd, int nWidth, int nHeight, BOOL bRedraw = TRUE);

/*! 随机生成一个点
*/
class RandomPoint
{
public:
typedef point_t result_type;
private:
size_t width_, height_;
public:
RandomPoint(size_t width, size_t height) : width_(width), height_(height)
{
static bool seed = false;
if(!seed)
{
srand(static_cast<unsigned int>(time(0)));
seed = true;
}
}

point_t operator()()
{
point_t res;

res.x = static_cast<long>(Random() % width_);
res.y = static_cast<long>(Random() % height_);
return res;
}

protected:
int Random()
{
return rand();

}
};

class WindowGame : public Drawer, Snake<RandomPoint>
{
HWND hwnd_;
int iSelection_ ;
int width_, height_;
bool pause_;
HDC hdc_;
HBITMAP oldbmp_, hbmp_;
public:
explicit WindowGame(int w = 300, int h = 300)
: Snake<RandomPoint>(w / 5, h / 5), width_(w), height_(h), iSelection_(1), pause_(false)
{
}
void Create(HINSTANCE hInst)
{
static LPSTR szClass = "SnakeWndClass";

if(!InitialWindowClass(hInst, szClass, WindowGame::WindowProcedure))
{
return;
}

hwnd_ = CreateWindowEx(0, szClass, "Snake", WS_OVERLAPPEDWINDOW, 
CW_USEDEFAULT, CW_USEDEFAULT, width_, height_, 
0, NULL, hInst, NULL );

ResizeClient(hwnd_, width_, height_ + 20, FALSE);

ShowWindow(hwnd_, SW_SHOW);
}

void MessageLoop()
{
MSG messages;
while (GetMessage(&messages, NULL, 0, 0))
{
DispatchMessage(&messages);
}
}

bool InitialWindowClass(HINSTANCE hInst, LPSTR szClassName, WNDPROC proc)
{
WNDCLASSEX wincl;

/* The Window structure */
wincl.hInstance = hInst;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = proc;      /* This function is called by windows */
wincl.style = 0;
wincl.cbSize = sizeof(WNDCLASSEX);

/* Use default icon and mouse-pointer */
wincl.hIcon =   LoadIcon(hInst, (LPCSTR) IDI_ICON1);
wincl.hIconSm = LoadIcon(hInst, (LPCSTR) IDI_ICON1);
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
wincl.lpszMenuName = (LPCSTR) IDR_MENU1;                 /* Have a menu */
wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
wincl.cbWndExtra = 0;                      /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

return RegisterClassEx(&wincl) != 0;
}

static WindowGame* Instance()
{
static WindowGame instance;
return &instance;
}

static LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{ 
Instance()->hwnd_ = hwnd; 
return Instance()->Proc(hwnd, msg, wparam, lparam);
}

virtual void DrawBox(size_t w, size_t h)
{
//background
SelectObject(hdc_, GetStockObject(LTGRAY_BRUSH));
Rectangle(hdc_, 0, 0, w * 5 + 2, h * 5 + 2);
}

virtual void DrawSnakeBody(size_t x, size_t y, size_t block)
{
    //SelectObject(hdc_, GetStockObject(WHITE_BRUSH));

        //Rectangle(hdc_, x * block - 1, y * block - 1, (x + 1) * block + 1, (y + 1) * block + 1);

RECT rc;
rc.left = x * block + 1;
rc.right = rc.left + block;
rc.top = y * block + 1;
rc.bottom = rc.top + block;
FillRect(hdc_, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH));

}
virtual void DrawSnakeFood(size_t x, size_t y, size_t block)
{
        SelectObject(hdc_, GetStockObject(GRAY_BRUSH));
        Rectangle(hdc_, x * block + 1, y * block + 1, (x + 1) * block + 1, (y + 1) * block + 1);
}

LRESULT Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)                  /* handle the messages */
{
HANDLE_MSG (hwnd_, WM_COMMAND, Game_OnCommand);
HANDLE_MSG (hwnd_, WM_KEYDOWN, Game_OnKeyDown);
HANDLE_MSG (hwnd_, WM_PAINT, Game_OnPaint);
HANDLE_MSG (hwnd_, WM_TIMER, Game_OnTimer);
HANDLE_MSG (hwnd_, WM_CREATE, Game_OnCreate);
HANDLE_MSG (hwnd_, WM_CLOSE, Game_OnClose);
case WM_SIZE:
width_ = LOWORD(lParam);
height_ = HIWORD(lParam); 
break;   
case WM_DESTROY:
KillTimer(hwnd_, ID_TIMER);  //To kill the Timer let the window not accept timer any more.
PostQuitMessage(0);       /* send a WM_QUIT to the message queue */

break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return TRUE;
}

BOOL Game_OnCreate(HWND hwnd_, LPCREATESTRUCT)
{
InitialSnake();
SetSpeed(iSelection_);

HDC wndDC = ::GetWindowDC(hwnd_);
hdc_ = ::CreateCompatibleDC(wndDC);
hbmp_ = ::CreateCompatibleBitmap(wndDC, width_ - 3, height_- 3);

oldbmp_ = SelectBitmap(hdc_, hbmp_);
::ReleaseDC(hwnd_, wndDC);

return TRUE;
}

VOID Game_OnClose(HWND hwnd_)
{
DeleteBitmap(SelectBitmap(hdc_, oldbmp_));
DeleteDC(hdc_);
DestroyWindow(hwnd_);
}


void Game_OnCommand(HWND hwnd_, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case ID_Start:
InitialSnake();
SetSpeed(iSelection_);
break;
case ID_EXIT:
SendMessage(hwnd_, WM_DESTROY, 0, 0);
break;
case ID_SLOW:
SetSpeed(0);
break;
case ID_NORMAL:
SetSpeed(1);
break;
case ID_FAST:
SetSpeed(2);
break;
case ID_HOWTOPLAY:
MessageBox(hwnd_,
TEXT("Use UP, DOWN, LEFT, KEY to control the snake and tryn")
TEXT("to eat the small gray spot so the snake can grows.  nn")
TEXT("Press SPACE key to pause or  n")
TEXT("restart the game.  "), "HELP", MB_ICONINFORMATION);
break;
case ID_ABOUT:
MessageBox(hwnd_, TEXT("Snake 1.0 test version!nn By: nyra@sohu.com(2005.4.15)"), "ABOUT", MB_ICONINFORMATION);
break;
case ID_PAUSE:
Pause();
break; 
}
}

void Game_OnKeyDown(HWND hwnd_, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
switch (vk)
{
case VK_LEFT:
this->StepLeft();
break;
case VK_RIGHT:
this->StepRight();
break;
case VK_UP:
this->StepUp();
break;
case VK_DOWN:
this->StepDown();
break;
case VK_SPACE:
this->Pause();
break;
}
InvalidateRect(hwnd_, 0, false);
}

void Game_OnPaint(HWND hwnd_)
{
Draw(this);
char buf[] = "Score: xxxxx";
sprintf(buf, "Score: %5d"  , this->GetScore());                                    



PAINTSTRUCT ps;
HDC dc = BeginPaint(hwnd_, &ps);  

LPRECT lprc = &ps.rcPaint;
::BitBlt(dc, lprc->left, lprc->top,
lprc->right - lprc->left, lprc->bottom - lprc->top,
hdc_, lprc->left, lprc->top, SRCCOPY);

SetBkColor(dc, GetSysColor(COLOR_BTNFACE));
TextOut(dc, 0, width_, buf, sizeof(buf) - 1);
EndPaint(hwnd_, &ps);
}

void Game_OnTimer(HWND hwnd_, UINT id)
{
if(!Engine())
{
Pause();
MessageBox(hwnd_, "You lose", "Game", MB_OK);
InitialSnake();
Pause();

}
InvalidateRect(hwnd_, 0, false);
}

void SetSpeed(int idx)
{
HMENU hMenu = GetMenu(hwnd_);
const int speedmap[3] = { 250, 150, 70};

CheckMenuItem(hMenu, ID_SLOW + iSelection_, MF_UNCHECKED);
iSelection_ = idx;
CheckMenuItem(hMenu, ID_SLOW + iSelection_, MF_CHECKED);

KillTimer(hwnd_, ID_TIMER);
SetTimer(hwnd_, ID_TIMER, speedmap[idx], NULL);
}

void Pause()
{
if (pause_)
{
pause_ = false;
SetSpeed(iSelection_);
}
else
{
pause_ = true;
KillTimer(hwnd_, ID_TIMER);
}
}
};

BOOL ResizeClient(HWND hWnd, int nWidth, int nHeight, BOOL bRedraw /*=TRUE*/)
{
RECT rcWnd;
if(!GetClientRect(hWnd, &rcWnd))
{
return FALSE;
}

if(nWidth != -1)
{
rcWnd.right = nWidth;
}

if(nHeight != -1)
{
rcWnd.bottom = nHeight;
}

LONG style = ::GetWindowLong(hWnd, GWL_STYLE);
LONG exStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);

BOOL hasMenu = !(style & WS_CHILD) && (::GetMenu(hWnd) != NULL);

if(!::AdjustWindowRectEx(&rcWnd, style, hasMenu, exStyle))
return FALSE;

UINT uFlags = SWP_NOZORDER | SWP_NOMOVE;
if(!bRedraw)
{
uFlags |= SWP_NOREDRAW;
}

return SetWindowPos(hWnd, NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags);
}

//int _tmain(int argc, _TCHAR* argv[])
INT WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd)
{
WindowGame* game = WindowGame::Instance();

game->Create(hInstance);
game->MessageLoop();

return 0;
}

---------SnakeWin32.rc-----------
#include "resource.h"


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_MENU1 MENU 
BEGIN
    POPUP "&Game"
    BEGIN
        MENUITEM "&Resart",                     ID_Start
        MENUITEM "&Pause",                      40019
        MENUITEM SEPARATOR
        MENUITEM "&Exit",                       ID_EXIT
    END
    POPUP "&Record", GRAYED
    BEGIN
        MENUITEM "&Show...",                    ID_SHOW
        MENUITEM "&Clear",                      ID_CLEAR
    END
    POPUP "&Speed"
    BEGIN
        MENUITEM "S&low",                       ID_SLOW
        MENUITEM "&Normal",                     ID_NORMAL, CHECKED
        MENUITEM "&Fast",                       ID_FAST
    END
    POPUP "&Help"
    BEGIN
        MENUITEM "How to play...",              ID_HOWTOPLAY
        MENUITEM SEPARATOR
        MENUITEM "About Snake...",              ID_ABOUT
    END
END

-----------resource.h--------------
#define IDR_MENU1                       101
#define IDI_ICON1                       102
#define ID_Start                        40001
#define ID_EXIT                         40002
#define ID_SLOW                         40004
#define ID_NORMAL                       40005
#define ID_FAST                         40006
#define ID_SHOW                         40007
#define ID_CLEAR                        40008
#define ID_TIPS                         40009
#define ID_ABOUT                        40010
#define ID_NONE                         40012
#define ID_FEW                          40013
#define ID_MEDIUM                       40014
#define ID_LOT                          40015
#define ID_MAPLOAD                      40017
#define ID_HOWTOPLAY                    40018
#define ID_PAUSE                        40019

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -