win32贪吃蛇实现
写程序是一个循序渐进的过程,一开始都是加加减减,修修补补,这和我们做企业做创新的原理都是一样的,没有一蹴而就的成功,最近看了周鸿祎的《我的互联网方法论》蛮有启发,分享给大家几句摘抄:
1.所有的颠覆式创新都不是敲锣打鼓来的,而是隐藏在一片噪声里。
2.颠覆式创新,就像自然界的新陈代谢一样,不断把老的、旧的公司从行业中挤出去。所以,这种颠覆式创新已经成为美国硅谷的一个象征。破坏和颠覆,都是强调打破原有的平衡,建立新秩序。但这两个词在中文里都是贬义词,因为中国文化崇尚平衡、稳定、和谐。一说颠覆式创新,我们的潜意识就会觉得是反动的东西,就不由自主地想到阶级敌人搞破坏。我有些时候受邀给一些单位讲互联网里的颠覆式创新。讲完后,有的领导就过来跟我握手说:小周,讲得挺好的嘛,只不过以后不要讲颠覆、讲破坏,影响社会和谐。
3.我不赞成企业大张旗鼓地搞创新,非要巨额投入资金,非要设立创新研究院,非要做一个整套的创新战略。我觉得休克式疗法的创新很难成功,我主张把创新从神坛上拉下来,从一些细微点上进行持续创新,这样反而更有效。
4.乔布斯有一天给谷歌高管打电话,说苹果iOS有一个谷歌地图图标,放大多少倍之后,第三行一个像素颜色不对,他认为这影响了iOS的美观。这就是对细节的一种坚持。
下面我们来看一个贪吃蛇的实现代码:
主要有两个大的步骤:
1.界面的绘制
2.蛇的绘制
主要代码:
// Snake.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "Snake.h"
#include <vector>
#include<time.h>
#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 1
std::vector<POINT> 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;
}
win32贪吃蛇实现的更多相关文章
- Win32小游戏--贪吃蛇
近日里学习了关于win32编程的相关知识,利用这些知识制作了一款贪吃蛇小游戏,具体细节还是分模块来叙述 前期准备:在网上找到一些贪吃蛇的游戏素材图片,以及具体的逻辑框图 在正式写功能之前,先把一系列环 ...
- C项目实践--贪吃蛇(1)
1.功能需求分析 1.1主要功能 i.游戏欢迎界面 ii.游戏执行功能,包括计算得分 iii.游戏结束界面 1.2游戏基本规则 游戏开始时蛇的长度是4个单位,并且按照当前方向不停地移动.移动范围是CO ...
- Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录
一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...
- 用C++实现的贪吃蛇游戏
我是一个C++初学者,控制台实现了一个贪吃蛇游戏. 代码如下: //"贪吃蛇游戏"V1.0 //李国良于2016年12月29日编写完成 #include <iostream& ...
- [LeetCode] Design Snake Game 设计贪吃蛇游戏
Design a Snake game that is played on a device with screen size = width x height. Play the game onli ...
- JavaScript-简单的贪吃蛇小游戏
实现逻辑: //获取Html中的格子(行,列) //建立数组存储所有格子(x,y) //建立数组用于存储蛇身(x,y) //生成随机坐标(x,y)的函数 //随机创建蛇身并存储到蛇身数组 //创建食物 ...
- juery实现贪吃蛇的游戏
今天用juery做了一个贪吃蛇的游戏,代码比较简陋,不过作为这些天学习juery的成果,非常有成就感.另外关于代码内容如有雷同不胜荣幸. 更改了下 让头和身子的颜色不一样 这样好区分些,虽然还是不怎么 ...
- HTML 5 背离贪吃蛇 写成了类似于屏幕校准
中间写了改 改了写 还是没做出自己满意的效果 ,看来自己的确不是一个走前端的料子.当然h5还是学一点好一点 具体说来 就是 在canvas 的画布中 鼠标点击后画上一个圆形 然后就有随机的在画布上面出 ...
- 控制台游戏引擎CGE——贪吃蛇
今天我也来发一个控制台游戏.先看图: 缘起 LZ是一个有严重拖延症的人,表现的形式就是隔一段时间就要刷一刷博客园. 这不前几天,看到了魏大师<使用Lua脚本语言开发出高扩展性的系统...> ...
随机推荐
- [BZOJ 4919]大根堆
Description 题库链接 给定一棵 \(n\) 个节点的有根树,每个点有一个权值 \(val_i\) .你需要选择尽可能多的节点,使得:对于任意两个点 \(i,j\) ,如果 \(i\) 在树 ...
- [HNOI2004]树的计数
题目描述 输入输出格式 输入格式: 输入文件第一行是一个正整数n,表示树有n个结点.第二行有n个数,第i个数表示di,即树的第i个结点的度数.其中1<=n<=150,输入数据保证满足条件的 ...
- 【BZOJ1835】【ZJOI2010】基站选址
原题传送门 Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距 ...
- poj 2774 最长公共子串 后缀数组
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 25752 Accepted: 10 ...
- TOJ 数据结构实验--静态顺序栈
描述 创建一个顺序栈(静态),栈大小为5.能够完成栈的初始化.入栈.出栈.获取栈顶元素.销毁栈等操作. 顺序栈类型定义如下: typedef struct { int data[Max]; i ...
- 一个小小的抽奖活动测试脚本(python2.7)
# coding=utf-8import requestsimport cx_Oracletns=cx_Oracle.makedsn('172.30.0.155',1521,'szdev')db1=c ...
- Python中的文件路径的分隔符
主要是需要考虑分隔符的问题: 在Windows系统下的分隔符是:\ (反斜杠). 在Linux系统下的分隔符是:/(斜杠). 当在字符中出现\时,大家就要考虑到转义字符了. 转义字符的概念,参考维基百 ...
- jvm(二):内存管理
jvm内存区域总体分为5大块:方法区,java堆,虚拟机栈,本地方法栈,程序计数器,按照线程来分的话又分为线程共享区和线程独占区 程序计数器: a.程序计数器是一块较小的内存空间,可以看做是当前线程所 ...
- android高德地图网络路径实现自定义marker并点击弹出自定义窗口
android中使用地图的地方随处可见,今天记录一下网络路径生成自定义marker,点击标记弹出自定义的窗口(在这里使用的是高德地图) 在这里我们使用Grilde去加载网络图片,因为这个简直太方便了! ...
- 【vuejs深入二】vue源码解析之一,基础源码结构和htmlParse解析器
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. vuejs是一个优秀的前端mvvm框架,它的易用性和渐进式的理念可以使每一个前端开发人员感到舒服,感到easy.它内 ...