博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
win32贪吃蛇实现
阅读量:6368 次
发布时间:2019-06-23

本文共 11811 字,大约阅读时间需要 39 分钟。

写程序是一个循序渐进的过程,一开始都是加加减减,修修补补,这和我们做企业做创新的原理都是一样的,没有一蹴而就的成功,最近看了周鸿祎的《我的互联网方法论》蛮有启发,分享给大家几句摘抄:

1.所有的颠覆式创新都不是敲锣打鼓来的,而是隐藏在一片噪声里。

2.颠覆式创新,就像自然界的新陈代谢一样,不断把老的、旧的公司从行业中挤出去。所以,这种颠覆式创新已经成为美国硅谷的一个象征。破坏和颠覆,都是强调打破原有的平衡,建立新秩序。但这两个词在中文里都是贬义词,因为中国文化崇尚平衡、稳定、和谐。一说颠覆式创新,我们的潜意识就会觉得是反动的东西,就不由自主地想到阶级敌人搞破坏。我有些时候受邀给一些单位讲互联网里的颠覆式创新。讲完后,有的领导就过来跟我握手说:小周,讲得挺好的嘛,只不过以后不要讲颠覆、讲破坏,影响社会和谐。

3.我不赞成企业大张旗鼓地搞创新,非要巨额投入资金,非要设立创新研究院,非要做一个整套的创新战略。我觉得休克式疗法的创新很难成功,我主张把创新从神坛上拉下来,从一些细微点上进行持续创新,这样反而更有效。

4.乔布斯有一天给谷歌高管打电话,说苹果iOS有一个谷歌地图图标,放大多少倍之后,第三行一个像素颜色不对,他认为这影响了iOS的美观。这就是对细节的一种坚持。

下面我们来看一个贪吃蛇的实现代码:

主要有两个大的步骤:
1.界面的绘制
这里写图片描述
2.蛇的绘制
这里写图片描述

主要代码:

// Snake.cpp : 定义应用程序的入口点。//#include "stdafx.h"#include "Snake.h"#include 
#include
#define MAX_LOADSTRING 100//定义游戏区 和 控制区大小#define BOUND_SIZE 10#define SNACK_SIZE 10#define GAME_WIDTH 80#define GAME_HEIGHT 60#define INFO_WIDTH 30#define INFO_HEIGHT GAME_HEIGHT#define MAX_NODE 80 //蛇的最大长度 80 节#define MY_TIMER 1 //定时器ID#define DEFAULT_INTERVAL 200 //定义贪食蛇的默认移动速度 500毫秒移动一节#define PAUSE_ID 1std::vector
vSnake;UCHAR g_ucSnakeLen = 4;UCHAR g_ucSnakeHead = 4; //vSnack[g_ucSnakeHead-1] 表示蛇头的坐标UCHAR g_ucSnakeTail = 0; //vSnack[g_ucSnakeTail] 表示蛇尾的坐标UINT32 g_uiInterval = DEFAULT_INTERVAL; //移动速度POINT g_ptDirect = {
1, 0}; //移动方向,每次x+1, y不变POINT g_ptFoodPos;BOOL g_bState = TRUE; //游戏是否结束BOOL g_bNeedFood = TRUE; //是否要投放食物BOOL g_bPause = FALSE; //暂停// 全局变量: HINSTANCE hInst; // 当前实例TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名// 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance);BOOL InitInstance(HINSTANCE, int);LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow){ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 MSG msg; HACCEL hAccelTable; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_SNAKE, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SNAKE)); // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam;}//// 函数: MyRegisterClass()//// 目的: 注册窗口类。//ATOM MyRegisterClass(HINSTANCE hInstance){ 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(hInstance, MAKEINTRESOURCE(IDI_SNAKE)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_SNAKE); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex);}//// 函数: InitInstance(HINSTANCE, int)//// 目的: 保存实例句柄并创建主窗口//// 注释: //// 在此函数中,我们在全局变量中保存实例句柄并// 创建和显示主程序窗口。//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){ HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE;}VOID InitSnack() //初始化蛇,设定蛇的起始位置{ int i; vSnake.clear(); vSnake.resize(MAX_NODE); g_ucSnakeTail = 0; g_ucSnakeHead = 4; g_ucSnakeLen = 4; g_uiInterval = DEFAULT_INTERVAL; for (i = 0; i < g_ucSnakeLen; i++) { //初始化蛇的各个节点 vSnake[i].x = i; vSnake[i].y = 1; }}POINT &GetSnakeNode(int index) //获取蛇节点位置:倒数第几个节点{ int i = g_ucSnakeTail + index; if (i >= MAX_NODE) { i -= MAX_NODE; } return vSnake[i];}VOID DrawSnake(HDC hdc){ int i; POINT ptNode; HBRUSH hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); SelectObject(hdc, hBrush); for (i = 0; i < g_ucSnakeLen; i++) { //从蛇尾开始画 ptNode = GetSnakeNode(i); Rectangle(hdc, ptNode.x * SNACK_SIZE + BOUND_SIZE, ptNode.y * SNACK_SIZE + BOUND_SIZE, (ptNode.x + 1) * SNACK_SIZE + BOUND_SIZE, (ptNode.y + 1) * SNACK_SIZE + BOUND_SIZE); }}//移动蛇坐标VOID RefreshSnake(){ //采用翻滚的形式 比如,vSnake[0], vSnake[1],vSnake[2] vSnake[3] 表示蛇的话 //移动一节后,vSnake[1],vSnake[2] vSnake[3] vSnake[4] 表示蛇 //vSnake[MAX_NODE -1 ] 后,蛇头存入 vSnake[0] POINT ptNewHead; //新的蛇头位置 POINT ptNode; int i; ptNewHead.x = GetSnakeNode(g_ucSnakeLen - 1).x + g_ptDirect.x; ptNewHead.y = GetSnakeNode(g_ucSnakeLen - 1).y + g_ptDirect.y; if (!g_bNeedFood && ptNewHead.x == g_ptFoodPos.x && ptNewHead.y == g_ptFoodPos.y) { //吃到食物了 vSnake[g_ucSnakeHead] = ptNewHead; g_ucSnakeHead++; if (g_ucSnakeHead == MAX_NODE) g_ucSnakeHead = 0; g_ucSnakeLen++; if (g_ucSnakeLen == MAX_NODE) { //赢了,事实上,我们不应该等到这个时候才判断赢了 g_bState = FALSE; return; } g_bNeedFood = TRUE; return; } if (ptNewHead.x < 0 || ptNewHead.x >= GAME_WIDTH || ptNewHead.y < 0 || ptNewHead.y >= GAME_HEIGHT) { //蛇撞墙了 g_bState = FALSE; return; } for (i = 1; i < g_ucSnakeLen; i++) { ptNode = GetSnakeNode(i); if (ptNode.x == ptNewHead.x && ptNode.y == ptNewHead.y) { //蛇撞到自己了 g_bState = FALSE; return; } } vSnake[g_ucSnakeHead].x = ptNewHead.x; vSnake[g_ucSnakeHead].y = ptNewHead.y;//新的蛇头 g_ucSnakeHead++; if (g_ucSnakeHead == MAX_NODE) g_ucSnakeHead = 0; g_ucSnakeTail++; if (g_ucSnakeTail == MAX_NODE) g_ucSnakeTail = 0; return;}VOID DrawFood(HDC hdc){ int x, y; POINT ptNode; int i; HBRUSH hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH); if (!g_bNeedFood) { SelectObject(hdc, hBrush); Ellipse(hdc, BOUND_SIZE + g_ptFoodPos.x * SNACK_SIZE, BOUND_SIZE + g_ptFoodPos.y * SNACK_SIZE, BOUND_SIZE + (g_ptFoodPos.x + 1) * SNACK_SIZE, BOUND_SIZE + (g_ptFoodPos.y + 1) * SNACK_SIZE); return; } srand(time(0)); //随机数种子 //获取随机坐标,不能是蛇的位置 while (1) { x = rand() % GAME_WIDTH; y = rand() % GAME_HEIGHT; for (i = 0; i < g_ucSnakeLen; i++) { ptNode = GetSnakeNode(i); if (ptNode.x == x && ptNode.y == y) { break; } } if (i == g_ucSnakeLen) //一直没有break,表示不重复 { break; } } g_bNeedFood = FALSE; g_ptFoodPos.x = x; g_ptFoodPos.y = y; SelectObject(hdc, hBrush); Ellipse(hdc, BOUND_SIZE + x * SNACK_SIZE, BOUND_SIZE + y * SNACK_SIZE, BOUND_SIZE + (x + 1) * SNACK_SIZE, BOUND_SIZE + (y + 1) * SNACK_SIZE); return;}//// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)//// 目的: 处理主窗口的消息。//// WM_COMMAND - 处理应用程序菜单// WM_PAINT - 绘制主窗口// WM_DESTROY - 发送退出消息并返回////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; RECT rect; int i; int nWinX, nWinY, nClientX, nClientY; HBRUSH hBrush; static HWND hPause; switch (message) { case WM_CREATE: //创建窗口时候执行的代码 GetWindowRect(hWnd, &rect); //获取窗口大小 nWinX = rect.right - rect.left; nWinY = rect.bottom - rect.top; GetClientRect(hWnd, &rect); //客户区大小 nClientX = rect.right - rect.left; nClientY = rect.bottom - rect.top; //修改窗口大小 客户区大小 + 边框大小 (nWinX-nClientX) MoveWindow(hWnd, 0, 0, (GAME_WIDTH + INFO_WIDTH)*SNACK_SIZE + BOUND_SIZE * 3 + (nWinX - nClientX), GAME_HEIGHT*SNACK_SIZE + BOUND_SIZE * 2 + (nWinY - nClientY), TRUE); hPause = CreateWindow(TEXT("Button"), TEXT("暂停"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 3 * BOUND_SIZE + GAME_WIDTH * SNACK_SIZE, 200, 200, 100, hWnd, (HMENU)PAUSE_ID, hInst, NULL ); InitSnack(); SetTimer(hWnd, MY_TIMER, g_uiInterval,NULL); //起一个定时器 break; case WM_TIMER: //定时器到点 //移动蛇 RefreshSnake(); if (!g_bState) { KillTimer(hWnd, MY_TIMER); //停止计时器 MessageBox(NULL, TEXT("你输了"), TEXT("FAIL"), MB_OK); //InitSnack(); return 0; } InvalidateRect(hWnd, NULL, TRUE); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case PAUSE_ID: if (g_bPause) { g_bPause = FALSE; SetWindowText(hPause, TEXT("暂停")); SetTimer(hWnd, MY_TIMER, g_uiInterval, NULL); } else { g_bPause = TRUE; SetWindowText(hPause, TEXT("继续")); KillTimer(hWnd, MY_TIMER); } break; case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH); SelectObject(hdc, hBrush); Rectangle(hdc, BOUND_SIZE, BOUND_SIZE, BOUND_SIZE + GAME_WIDTH*SNACK_SIZE, BOUND_SIZE + GAME_HEIGHT*SNACK_SIZE); Rectangle(hdc, BOUND_SIZE * 2 + GAME_WIDTH*SNACK_SIZE , BOUND_SIZE, BOUND_SIZE*2 + (GAME_WIDTH + INFO_WIDTH)*SNACK_SIZE, BOUND_SIZE + INFO_HEIGHT*SNACK_SIZE); DrawSnake(hdc); DrawFood(hdc); EndPaint(hWnd, &ps); break; case WM_KEYDOWN: if (!g_bState || g_bPause) { break; } switch (wParam) { case VK_UP: //调节方向:注意点,原来是往上或者往下的话,不做操作 if (g_ptDirect.x != 0) { g_ptDirect.x = 0; g_ptDirect.y = -1; } break; case VK_DOWN: if (g_ptDirect.x != 0) { g_ptDirect.x = 0; g_ptDirect.y = 1; } break; case VK_LEFT: if (g_ptDirect.y != 0) { g_ptDirect.x = -1; g_ptDirect.y = 0; } break; case VK_RIGHT: if (g_ptDirect.y != 0) { g_ptDirect.x = 1; g_ptDirect.y = 0; } break; } break; case WM_DESTROY: KillTimer(hWnd, MY_TIMER); PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}// “关于”框的消息处理程序。INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){ UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE;}
你可能感兴趣的文章
本地串口TCP/IP 映射到远端串口
查看>>
锁机制探究
查看>>
硬盘直接引导启动Manjaro Linux iso
查看>>
CodeSmith代码生成工具介绍
查看>>
几个常用且免费的接口
查看>>
jQuery文件上传插件 Uploadify更改错误提示的弹出框
查看>>
RHEL6下Apache与Tomcat整合
查看>>
Heartbeat+DRBD+MFS高可用
查看>>
要感谢那些曾经慢待你的人
查看>>
常见的global cache等待事件
查看>>
第 7 章 多主机管理 - 047 - 管理 Machine
查看>>
CentOS5和6的系统启动流程
查看>>
怎么看域客户端是否继承了组策略
查看>>
linux防止DDoS***
查看>>
6.4 Linked List 重做
查看>>
小米路由
查看>>
QT 学习 之 窗口拖拽 实现
查看>>
PHP的ftp文件,多文件上传操作类
查看>>
js中清空数组的方法
查看>>
python def说明
查看>>