//tool.h #pragma once #include<windows.h> const int ROWS = 30; const int COLS = 30; const int BLOCK_SIZE = 500 / ROWS; void FillRect(HDC hDC,HBRUSH hbr,int x,int y, int width, int height) { RECT r; r.left = x; r.right= x + width; r.top = y; r.bottom = y+height; FillRect(hDC,&r,hbr); } //frame.h #pragma once #include <windows.h> #include "tool.h" extern LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); class Frame { public: bool CreateFrame(); virtual void Draw(HDC hdc){} virtual void KeyDown(WPARAM wParam){} virtual void KeyUp(){} LRESULT EventHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); Frame(){} Frame(int w, int h, HINSTANCE hInst) { width = w; height = h; hInstance = hInst; } int Run() { MSG msg; PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); while (msg.message != WM_QUIT) { DWORD tNow = GetTickCount(); if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else if(tNow - tPre >= 118) { InvalidateRect (hWnd, NULL, FALSE); KeyDown(m_wParam); } } return (int) msg.wParam; } DWORD tPre; WPARAM m_wParam; HWND hWnd; protected: int width; int height; HINSTANCE hInstance; //双缓冲 HDC memDC; HBITMAP hBmp; }; bool Frame::CreateFrame() { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = "GREEDY SNAKE"; wcex.lpszClassName = "GREEDY SNAKE"; wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wcex); hWnd = CreateWindow("GREEDY SNAKE", "GREEDY SNAKE", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, 100, 100, width, height, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); //创建双缓冲dc和位图 memDC = CreateCompatibleDC(GetDC(hWnd)); hBmp = CreateCompatibleBitmap(memDC, width, height); SelectObject(memDC, hBmp); return TRUE; } LRESULT Frame::EventHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: //SetTimer (hWnd, 1, 150, NULL) ; break; case WM_TIMER : // MessageBeep (-1) ; //InvalidateRect (hWnd, NULL, FALSE); break; case WM_KEYDOWN: //KeyDown(wParam); m_wParam = wParam; break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码...; FillRect(memDC,(HBRUSH)GetStockObject(WHITE_BRUSH), 0, 0, width, height); //画到memDC中 Draw(memDC); BitBlt(hdc, 0, 0, width, height, memDC, 0, 0, SRCCOPY);//内存的memDC->hdc EndPaint(hWnd, &ps); tPre = GetTickCount(); break; case WM_DESTROY: //KillTimer (hWnd, 1) ; PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } //yard.h #pragma once #include"Frame.h" #include"Egg.h" #include"Snake.h" #include"tool.h" class Yard : public Frame { public: Egg *e1,*e2,*e3,*e4,*e5,*e6,*e7; Snake *s; HBRUSH hBrush ; Yard(int w, int h, HINSTANCE hInst) { width = w; height = h; hInstance = hInst; e1= new Egg(rand()%(ROWS-4)+1,rand()%(COLS-4)+1); e2= new Egg(rand()%(ROWS-4)+1,rand()%(COLS-4)+1); e3= new Egg(rand()%(ROWS-4)+1,rand()%(COLS-4)+1); e4= new Egg(rand()%(ROWS-4)+1,rand()%(COLS-4)+1); e5= new Egg(rand()%(ROWS-4)+1,rand()%(COLS-4)+1); e6= new Egg(rand()%(ROWS-4)+1,rand()%(COLS-4)+1); e7= new Egg(rand()%(ROWS-4)+1,rand()%(COLS-4)+1); s = new Snake(20,20); } void Draw(HDC hdc); void KeyDown(WPARAM wParam); void KeyUp(); }; void Yard::Draw(HDC hdc) { hBrush = (HBRUSH)GetStockObject (WHITE_PEN) ; SelectObject (hdc, hBrush) ; //画出横线 for(int i=1; i<ROWS; i++) { MoveToEx(hdc, 0, BLOCK_SIZE * i, NULL); LineTo(hdc, COLS * BLOCK_SIZE, BLOCK_SIZE * i); } for(int i=1; i<COLS; i++) { MoveToEx(hdc, BLOCK_SIZE * i, 0, NULL); LineTo(hdc, BLOCK_SIZE * i, BLOCK_SIZE * ROWS); } e1->Draw(hdc); e2->Draw(hdc); e3->Draw(hdc); e4->Draw(hdc); e5->Draw(hdc); e6->Draw(hdc); e7->Draw(hdc); s->Draw(hdc); //if(s->eat(e)) //{ // //e->reAppear(); //} s->eat(e1); s->eat(e2); s->eat(e3); s->eat(e4); s->eat(e5); s->eat(e6); s->eat(e7); } void Yard::KeyDown(WPARAM wParam) { s->KeyDown(wParam); } void Yard::KeyUp() { } //snake.h #pragma once #include<windows.h> //#include"Frame.h" #include"tool.h" #include"Egg.h" enum Dir {L, U, R, D}; class Snake { public: Snake(int r, int c) { n=new Node(r, c,L); n->next = NULL; n->prev = NULL; head = n; tail = n; bPlay=true; } void addToTail(); void addToHead(); void move(); void checkDead(); void deleteFromTail(); void KeyDown(WPARAM wParam); bool eat(Egg *e); //Vector<int> getRect(); int getCol()const; int getRow()const; void Draw(HDC hDC) { if(bPlay) { move(); } for(Node *n = head; n != NULL; n = n->next) n->Draw(hDC); } class Node { public: Node(){} Node(int row,int col,Dir dir) { this->col=col; this->row=row; w=BLOCK_SIZE; h=BLOCK_SIZE; this->dir=dir; } void Draw(HDC hDC) { FillRect(hDC,(HBRUSH)GetStockObject(BLACK_BRUSH), w*col,h*row,w,h); } //private: Node *next; Node *prev; int col,row; int w,h; Dir dir; }; private: bool bPlay; Node* head; Node* tail ; Node* n ; }; void Snake::addToTail() { Node *node ; switch(tail->dir) { case L : node = new Node(tail->row, tail->col + 1, tail->dir); break; case U : node = new Node(tail->row + 1, tail->col, tail->dir); break; case R : node = new Node(tail->row, tail->col - 1, tail->dir); break; case D : node = new Node(tail->row - 1, tail->col, tail->dir); break; } tail->next = node; node->prev = tail; tail = node; } void Snake::addToHead() { Node *node; switch(head->dir) { case L : node = new Node(head->row, head->col- 1, head->dir); break; case U : node = new Node(head->row - 1, head->col, head->dir); break; case R : node = new Node(head->row, head->col+ 1, head->dir); break; case D : node = new Node(head->row + 1, head->col, head->dir); break; } node->next = head; head->prev = node; head = node; } void Snake::move() { addToHead(); deleteFromTail(); checkDead(); } void Snake::checkDead() { if(head->row < 1 || head->col < 1 || head->row > ROWS-3 || head->col > COLS-2) { bPlay=false; } for(Node *n = head->next; n != NULL; n = n->next) { if(head->row == n->row && head->col == n->col) { bPlay=false; } } } void Snake::deleteFromTail() { //if(size == 0) return; tail = tail->prev; delete tail->next; tail->next = NULL; } bool Snake::eat(Egg *e) { if(this->getRow()==(e->getRow())&&this->getCol()==e->getCol()) { e->reAppear(); this->addToTail(); //y.setScore(y.getScore() + 5); return true; } return false; } int Snake::getCol()const { return this->head->col; } int Snake::getRow()const { return this->head->row; } void Snake::KeyDown(WPARAM wParam) { switch (wParam) { case VK_LEFT: if(head->dir!=R) head->dir=L; break; case VK_UP: if(head->dir!=D) head->dir=U; break; case VK_RIGHT: if(head->dir!=L) head->dir=R; break; case VK_DOWN: if(head->dir!=U) head->dir=D; break; //case VK_RETURN: // if(bPlay == true) // bPlay=false; // else // bPlay=true; // break; //SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0) ; } } //egg.h #pragma once #include<windows.h> #include"tool.h" class Egg { private: int col,row; int w,h; bool flag; public: Egg(){} Egg(int col,int row) { this->col=col; this->row=row; w=BLOCK_SIZE; h=BLOCK_SIZE; flag = true; } void Draw(HDC hDC) { flag = !flag; if(flag) { FillRect(hDC,(HBRUSH)GetStockObject(BLACK_BRUSH), w*col,h*row,w,h); } else { FillRect(hDC,(HBRUSH)GetStockObject(LTGRAY_BRUSH), w*col,h*row,w,h); } } void reAppear() { row=rand()%(ROWS-4)+1; col=rand()%(COLS-4)+1; } int getCol()const { return this->col; } int getRow()const { return this->row; } }; //main.cpp #include "Yard.h" Frame *yard = new Yard(500,500, GetModuleHandle(NULL)); LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return yard->EventHandler(hWnd, message, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { yard->CreateFrame(); return yard->Run(); }