借用了俄罗斯方块中的界面类,写的很快
5个文件,共能基本实现,有一些功能懒得写了
用到了数据结构_双向链表
1 //2016/10/5 2 //c++和windows 简单api函数 贪吃蛇 3 //一言难尽 4 //下次设个随机数生成器,在界面设置食物就好了 5 //再写个eatfood函数,先移动重,然后在里面在链表尾部添加一个节点,再重绘就结束了 6 //哎,有空把食物颜色设置一下好了 7 #include"Interface.h" 8 #include"snake.h" 9 #include <windows.h> 10 #include<random> 11 #include<iostream> 12 13 #define TIMER_SEC 1 14 #define TIMER_UPDATE 2 15 16 17 18 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 19 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 20 PSTR szCmdLine, int iCmdShow) 21 { 22 23 24 static TCHAR szAppName[] = TEXT("俄罗斯方块"); 25 HWND hwnd; 26 MSG msg; 27 WNDCLASS wndclass; 28 wndclass.style = CS_HREDRAW | CS_VREDRAW; 29 wndclass.lpfnWndProc = WndProc; 30 wndclass.cbClsExtra = 0; 31 wndclass.cbWndExtra = 0; 32 wndclass.hInstance = hInstance; 33 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 34 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 35 wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH); 36 wndclass.lpszMenuName = NULL; 37 wndclass.lpszClassName = szAppName; 38 if (!RegisterClass(&wndclass)) 39 { 40 MessageBox(NULL, TEXT("This program requires Windows NT!"), 41 szAppName, MB_ICONERROR); 42 return 0; 43 } 44 hwnd = CreateWindow(szAppName, // window class name 45 TEXT("俄罗斯方块"), // window caption 46 WS_OVERLAPPEDWINDOW, // window style 47 50, // initial x position 48 10, // initial y position 49 700, // initial x size 50 700, // initial y size 51 NULL, // parent window handle 52 NULL, // window menu handle 53 hInstance, // program instance handle 54 NULL); // creation parameters 55 ShowWindow(hwnd, iCmdShow); 56 UpdateWindow(hwnd); 57 while (GetMessage(&msg, NULL, 0, 0)) 58 { 59 TranslateMessage(&msg); 60 DispatchMessage(&msg); 61 } 62 return msg.wParam; 63 } 64 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 65 { 66 static int cxClient, cyClient; 67 static Interface face(hwnd, BLOCK_NON_EXISTENT); 68 static snake snk(15,15); 69 static int guide = 3; 70 static std::default_random_engine e_x; 71 static std::default_random_engine e_y; 72 static std::uniform_int_distribution<unsigned> u(0, 21); 73 static std::uniform_int_distribution<unsigned> u_2(0, 21); 74 75 PAINTSTRUCT ps; 76 //HDC hdc; 77 //RECT rect; 78 switch (message) 79 { 80 case WM_CREATE: 81 SetTimer(hwnd, TIMER_SEC, 500, NULL); 82 SetTimer(hwnd, TIMER_UPDATE, 2000, NULL); 83 return 0; 84 case WM_SIZE: 85 cxClient = LOWORD(lParam); 86 cyClient = HIWORD(lParam); 87 face.changeSize(cxClient, cyClient); 88 return 0; 89 case WM_TIMER: 90 switch (wParam) 91 { 92 case TIMER_SEC: 93 if (!snk.move(guide, face)) 94 { 95 KillTimer(hwnd, TIMER_SEC); 96 } 97 InvalidateRect(hwnd, NULL, true); 98 break; 99 case TIMER_UPDATE: 100 face.set_food(u(e_x), u(e_x)); 101 InvalidateRect(hwnd, NULL, true); 102 break; 103 } 104 return 0; 105 case WM_KEYDOWN: 106 switch (wParam) 107 { 108 case VK_RIGHT: 109 //ter.Right_Movement(face); 110 if (guide == 4) 111 break; 112 guide = 2; 113 if (!snk.move(guide, face)) 114 { 115 KillTimer(hwnd, TIMER_SEC); 116 } 117 InvalidateRect(hwnd, NULL, true); 118 break; 119 case VK_LEFT: 120 if (guide == 2) 121 break; 122 guide = 4; 123 if (!snk.move(guide, face)) 124 { 125 KillTimer(hwnd, TIMER_SEC); 126 } 127 InvalidateRect(hwnd, NULL, true); 128 break; 129 case VK_UP: 130 if (guide == 3) 131 break; 132 guide = 1; 133 if (!snk.move(guide, face)) 134 { 135 KillTimer(hwnd, TIMER_SEC); 136 } 137 InvalidateRect(hwnd, NULL, true); 138 break; 139 case VK_DOWN: 140 if (guide == 1) 141 break; 142 guide = 3; 143 if (!snk.move(guide, face)) 144 { 145 KillTimer(hwnd, TIMER_SEC); 146 } 147 InvalidateRect(hwnd, NULL, true); 148 break; 149 } 150 case WM_PAINT: 151 snk.draw(face); 152 face.drawBlock(ps, BLACK_BRUSH, GRAY_BRUSH); 153 return 0; 154 case WM_DESTROY: 155 KillTimer(hwnd, TIMER_SEC); 156 /* KillTimer(hwnd, TIMER_UPDATE);*/ 157 PostQuitMessage(0); 158 return 0; 159 } 160 return DefWindowProc(hwnd, message, wParam, lParam); 161 }
1 class snake 2 { 3 public: 4 snake(int _x, int _y, int len = 6); 5 bool move(int guide,const Interface &face); 6 void insert(int _x, int _y); 7 void inital(int _x = 5, int _y = 5); 8 void draw(Interface &face); 9 private: 10 bool inspect(int _x,int _y,const Interface &face); //检查有无出界或者碰撞 11 int length = 0; 12 Node *head = nullptr; 13 Node *rear = nullptr; 14 };
1 #include"snake.h" 2 snake::snake(int _x, int _y, int len) 3 { 4 rear = head = new Node; 5 inital(_x, _y); 6 int i; 7 for (i = 0; i < len - 1; i++) 8 { 9 insert(++_x, _y); 10 } 11 } 12 void snake::insert(int _x, int _y) 13 { 14 Node *p = new Node; 15 p->x = _x; 16 p->y = _y; 17 rear->next = p; 18 p->before = rear; 19 rear = p; 20 length++; 21 } 22 23 void snake::inital(int _x, int _y) 24 { 25 Node *p = new Node; 26 p->x = _x; 27 p->y = _y; 28 rear->next = p; 29 p->before = rear; 30 rear = p; 31 length++; 32 } 33 34 bool snake::move(int guide,const Interface &face) 35 { 36 Node *q = rear; 37 Node *p = q->before; 38 if (q == nullptr) 39 return false; 40 //开始检查 41 int inspect_x = head->next->x; 42 int inspect_y = head->next->y; 43 switch (guide) 44 { 45 case 1: inspect_x++; break; 46 case 2: inspect_y++; break; 47 case 3: inspect_x--; break; 48 case 4: inspect_y--; break; 49 default: 50 break; 51 } 52 if (inspect(inspect_x, inspect_y, face) == false) 53 { 54 return false; 55 } 56 if (face.isBlock[inspect_x][inspect_y] == BLOCK_FOOD) 57 { 58 Node *n = new Node; 59 rear->next = n; 60 n->before = rear; 61 rear = n; 62 q = rear; 63 p = rear->before; 64 } 65 //结束检查 66 int _x = head->next->x; 67 int _y = head->next->y; 68 while (p != head) 69 { 70 q->x = p->x; 71 q->y = p->y; 72 p = p->before; 73 q = p->next; 74 } 75 p = p->next; 76 switch (guide) 77 { 78 case 1: p->x = _x + 1; p->y = _y; break; 79 case 2: p->x = _x; p->y = _y + 1; break; 80 case 3: p->x = _x - 1; p->y = _y; break; 81 case 4: p->x = _x; p->y = _y - 1; break; 82 default: 83 break; 84 } 85 86 return true; 87 } 88 89 void snake::draw(Interface &face) //写入但不显示,显示让interface去完成 90 { 91 face.clear(); 92 Node *p = head->next; 93 while (p != nullptr) 94 { 95 face.isBlock[p->x][p->y] = BLOCK_FASTENED; 96 p = p->next; 97 } 98 } 99 100 101 bool snake::inspect(int _x, int _y,const Interface &face) 102 { 103 if (_x >= face.cx || _x < 0 || _y >= face.cy || _y < 0) 104 { 105 return false; 106 } 107 Node *p = head->next; 108 while (p != nullptr) 109 { 110 if (_x == p->x && _y == p->y) 111 { 112 return false; 113 } 114 p = p->next; 115 } 116 return true; 117 }
1 #ifndef TETERFACE 2 #define TETERFACE 3 4 constexpr int BLOCK_FASTENED = 1; //方块状态存在固定 5 constexpr int BLOCK_FALL = 2; //下降 6 constexpr int BLOCK_FOOD = 3; //食物 7 constexpr int BLOCK_NON_EXISTENT = 0; //空 8 9 #include<Windows.h> 10 #include<random> 11 class Interface 12 { 13 //friend class Tetris; 14 friend class snake; 15 public: 16 Interface(HWND, int b_ = true); 17 void drawBlock(PAINTSTRUCT&, int fnObject_1 = BLACK_BRUSH, int fnObject_2 = GRAY_BRUSH, int fnObject_3 = BLACK_BRUSH); 18 void changeSize(unsigned, unsigned); 19 bool checkState(); 20 void set_food(int _x, int _y); 21 void clear(); //特殊化为不清楚食物 22 private: 23 static const size_t cx = 22, cy = 22, c = 0; //12 + 4行8列 24 void Sink(unsigned); 25 int isBlock[cy + c][cx] = {}; 26 HWND hwnd; //界面内容代号 27 unsigned int width = 0, height = 0; //设置界面的高度和宽度 28 }; 29 #endif
1 #include"interface.h" 2 3 static const size_t cx, cy; 4 5 Interface::Interface(HWND hd, int b_ /*= BLOCK_FASTENED*/) :hwnd(hd) 6 { 7 for (auto &row : isBlock) 8 { 9 for (auto &col : row) 10 { 11 col = b_; 12 } 13 } 14 } 15 16 void Interface::drawBlock(PAINTSTRUCT &ps, int fnObject_1, int fnObject_2, int fnObject_3) 17 { 18 //HDC hdc = GetDC(hwnd); //用了这个占用cpu大 19 HDC hdc = BeginPaint(hwnd, &ps); 20 HBRUSH hBrush_1 = (HBRUSH)::GetStockObject(fnObject_1); //方块画刷 21 HBRUSH hBrush_2 = (HBRUSH)::GetStockObject(fnObject_2); //方块画刷 22 HBRUSH hBrush_3 = (HBRUSH)::GetStockObject(fnObject_3); //食物画刷 23 RECT rect; 24 unsigned Block_h = height / cy; 25 unsigned Block_w = width / cx; 26 for (size_t i = 0; i < cy; ++i) 27 for (size_t j = 0; j < cx; ++j) 28 { 29 if (isBlock[i][j] == BLOCK_FASTENED || 30 isBlock[i][j] == BLOCK_FALL || 31 isBlock[i][j] == BLOCK_FOOD) 32 { 33 //以后可以在这里定义内嵌厚度 34 rect.left = j * Block_w + 2; 35 rect.top = (cy - i - 1) * Block_h + 2; 36 rect.right = (j + 1) * Block_w - 2; 37 rect.bottom = (cy - i) * Block_h - 2; 38 FrameRect(hdc, &rect, hBrush_1); 39 if (isBlock[i][j] == BLOCK_FOOD) 40 { 41 FillRect(hdc, &rect, hBrush_3); 42 } 43 else 44 { 45 FillRect(hdc, &rect, hBrush_2); 46 } 47 } 48 } 49 EndPaint(hwnd, &ps); 50 } 51 52 53 void Interface::changeSize(unsigned wh, unsigned ht) 54 { 55 width = wh; 56 height = ht; 57 } 58 59 60 bool Interface::checkState() 61 { 62 for (size_t i = 0; i < cx; i++) 63 { 64 if (isBlock[cy][i] != BLOCK_NON_EXISTENT) 65 return false; 66 } 67 bool isFull; 68 for (size_t i = 0; i < cy; i++) 69 { 70 isFull = true; 71 for (size_t j = 0; j < cx; j++) 72 { 73 if (isBlock[i][j] != BLOCK_FASTENED) 74 { 75 isFull = false; 76 break; 77 } 78 } 79 if (isFull && i != cy - 1) 80 { 81 Sink(i); 82 i--; //i不可少 83 } 84 else if (isFull && i == cy - 1) 85 { 86 for (size_t i = 0; i < cx; i++) 87 { 88 isBlock[cy - 1][i] = BLOCK_NON_EXISTENT; 89 } 90 } 91 } 92 return true; 93 } 94 95 96 void Interface::Sink(unsigned line) 97 { 98 for (size_t i = line + 1; i < cy; ++i) 99 { 100 for (size_t j = 0; j < cx; j++) 101 { 102 isBlock[i - 1][j] = isBlock[i][j]; 103 } 104 } 105 } 106 107 void Interface::clear() 108 { 109 for (size_t i = 0; i < cy + c; i++) 110 { 111 for (size_t j = 0; j < cx; j++) 112 { 113 if(isBlock[i][j] != BLOCK_FOOD) 114 isBlock[i][j] = BLOCK_NON_EXISTENT; 115 } 116 } 117 } 118 119 void Interface::set_food(int x, int y) 120 { 121 if (isBlock[x][y] != BLOCK_FASTENED) 122 { 123 isBlock[x][y] = BLOCK_FOOD; 124 } 125 }
时间: 2024-10-13 00:46:19