编程珠玑2阅读笔记:

1.使用c语言性能监视器,完成对代码的调优工作
2.关联数组:
 拓扑排序算法,可以用于当存在遮挡的时候决定三维场景的绘制顺序。
3.小型算法中的测试与调试工具
脚手架程序:《人月神话》一个软件产品中应该有一半的代码都是脚手架。
类似,小型的代码库
4.自描述数据
每个程序员都知道破解神秘数据的挫折与艰辛。
5.劈开戈尔迪之结
什么是用户的真正需求:
一个运筹学者接到任务,设计末座大楼的电梯调度策略,使乘客等待的时间最短,在走访了这座大楼之后,他认识到雇主真正想要解决的问题是,尽量减少乘客的不适( 乘客不喜欢等电梯)。他这样解决问题:在每部电梯附近装上几面镜子。乘客在等电梯时候,可以自我欣赏一下,对电梯速度的抱怨大幅减少了。他发现了用户的真正需求
7.粗略估算
程序员3大美德:对数值敏感,实验的欲望,良好的数学功底

在来说这个俄罗斯方块,其实主要是2个大的部分:

1.界面绘制(游戏区,信息区,刷新重绘工作)

游戏区方块的绘制,其实都是数组来记录

2.游戏逻辑(上下左右,变形)

其实就是对数组的旋转

主要代码,才六百行:

// Russian_cube.cpp : 定义应用程序的入口点。
//
//
//
//
#include "stdafx.h"
#include "Russian_cube.h"#define MAX_LOADSTRING 100
//Tetris
#define BOUND_SIZE 10
#define TETRIS_SIZE 30
#define GAME_X 10
#define GAME_Y 20
#define INFO_X 6
#define INFO_Y GAME_Y//定时器
#define  MY_TIMEER 1
#define  DEFAULT_INTERVAL 500 //默认每0.5秒下降一格//定义俄罗斯方块的形状
BOOL g_astTetris[][4][4] =
{{{1,1,0,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,0,0},{0,0,1,1},{0,0,0,0},{0,0,0,0}},{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}}
};
#define  TETRIS_CNT (sizeof(g_astTetris)/sizeof(g_astTetris[0]))//当前方块的形状
BOOL g_CurTetris[4][4];
BOOL g_NextTetris[4][4];
BOOL g_stGame[GAME_X][GAME_Y];//记录已经落下来的方块//记录方块左上角的坐标
UINT TetrisX;
UINT TetrixY;
UINT g_uiInterval;
UINT g_uiScore;UINT g_uiMySeed = 0xffff;// 全局变量:
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(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR    lpCmdLine,int       nCmdShow)
{UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);// TODO: 在此放置代码。MSG msg;HACCEL hAccelTable;// 初始化全局字符串LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_RUSSIAN_CUBE, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// 执行应用程序初始化:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_RUSSIAN_CUBE));// 主消息循环:while (GetMessage(&msg, NULL, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){TranslateMessage(&msg);DispatchMessage(&msg);}}return (int) msg.wParam;
}//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
//  注释:
//
//    仅当希望
//    此代码与添加到 Windows 95 中的“RegisterClassEx”
//    函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
//    这样应用程序就可以获得关联的
//    “格式正确的”小图标。
//
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_RUSSIAN_CUBE));wcex.hCursor      = LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground   = (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName  = MAKEINTRESOURCE(IDC_RUSSIAN_CUBE);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_MINIMIZEBOX | WS_SYSMENU,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);if (!hWnd){return FALSE;}ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return TRUE;
}int GetRandNum(int iMin,int iMax)
{//取随机数srand(GetTickCount() + g_uiMySeed-- );return iMin + rand()%(iMax -iMin);
}VOID DrawBackGround(HDC hdc)
{int x, y;HPEN hPen = (HPEN)GetStockObject(NULL_PEN);HBRUSH hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);//(HBRUSH)CreateSolidBrush()HBRUSH hBrush_luo = (HBRUSH)GetStockObject(BLACK_BRUSH);Rectangle(hdc,BOUND_SIZE,BOUND_SIZE,BOUND_SIZE + GAME_X*TETRIS_SIZE,BOUND_SIZE + GAME_Y * TETRIS_SIZE);SelectObject(hdc,hPen);for (x = 0; x < GAME_X; x++){for (y = 0 ;y < GAME_Y; y++){if (g_stGame[x][y]){SelectObject(hdc,hBrush_luo);}else{SelectObject(hdc,hBrush);}Rectangle(hdc,BOUND_SIZE + x*TETRIS_SIZE,BOUND_SIZE + y * TETRIS_SIZE,BOUND_SIZE + (x + 1)*TETRIS_SIZE,BOUND_SIZE + (y + 1) * TETRIS_SIZE);}}
}
//信息区 的绘制
VOID DrawInfo(HDC hdc)
{int x,y;int nStartX,nStartY;RECT rect;TCHAR szBuf[100];//得分的字符串HPEN hPen = (HPEN)GetStockObject(BLACK_PEN);HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);HBRUSH hBrush_have = (HBRUSH)GetStockObject(GRAY_BRUSH);SelectObject(hdc,hPen);SelectObject(hdc,hBrush);Rectangle(hdc,BOUND_SIZE*2 + GAME_X * TETRIS_SIZE,BOUND_SIZE,BOUND_SIZE *2 + (GAME_X + INFO_X)*TETRIS_SIZE,BOUND_SIZE + INFO_Y * TETRIS_SIZE);for (x = 0; x < 4; x++){for (y = 0 ;y < 4 ;y++){nStartX = BOUND_SIZE *2 + GAME_X*TETRIS_SIZE + (y +1)*TETRIS_SIZE;nStartY = BOUND_SIZE + (x +1)*TETRIS_SIZE;if (g_NextTetris[x][y]){SelectObject(hdc,hBrush);}else{SelectObject(hdc,hBrush_have);}Rectangle(hdc,nStartX,nStartY,nStartX+TETRIS_SIZE,nStartY+TETRIS_SIZE);}}nStartX = BOUND_SIZE *2 + GAME_X*TETRIS_SIZE;nStartY = BOUND_SIZE ;rect.left = nStartX + TETRIS_SIZE;rect.right = nStartX + TETRIS_SIZE * (INFO_X -1);rect.top = nStartY + TETRIS_SIZE *6;rect.bottom = nStartY + TETRIS_SIZE *7;wsprintf(szBuf,L"Score: %d",g_uiScore = 0);DrawText(hdc,szBuf,wcslen(szBuf),&rect,DT_CENTER);}//绘制区方块,起始坐标和需要绘制的方块形状
VOID DrawTetris(HDC hdc, int nStartX,int nStartY,BOOL bTetris[4][4])
{int i,j;HPEN hPen = (HPEN)GetStockObject(BLACK_PEN);HBRUSH hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);SelectObject(hdc,hPen);SelectObject(hdc,hBrush);for (i = 0;i < 4; i++){for (j = 0;j < 4;j++){//j 是x方向的坐标偏移if (bTetris[i][j]){Rectangle(hdc,BOUND_SIZE +(nStartX + j) * TETRIS_SIZE,BOUND_SIZE + (nStartY + i)* TETRIS_SIZE,BOUND_SIZE +(nStartX + j + 1) * TETRIS_SIZE,BOUND_SIZE + (nStartY + i + 1)* TETRIS_SIZE);}}}
}//旋转方块, 并且靠左上角
VOID RotateTetris(BOOL bTetris[4][4])
{BOOL bNewTetris[4][4] = {};//初始化置零int x, y;int xPos,yPos;BOOL bFlag;//靠近左上角//从上往下,从左往右,顺时针旋转//靠上for (x = 0,xPos = 0 ;x < 4 ; x++){bFlag = FALSE;for (y = 0 ;y < 4 ;y++){bNewTetris[xPos][y] = bTetris[3 - y][x];//逆时针旋转//bNewTetris[x][y] = bTetris[y][3 - x];if (bNewTetris[xPos][y]){bFlag = TRUE;//这一行有数据}}if (bFlag){xPos++;}}memset(bTetris,0,sizeof(bNewTetris));//靠左for (y = 0, yPos = 0;y < 4 ;y++){bFlag = FALSE;for (x = 0;x < 4; x++){bTetris[x][yPos] = bNewTetris[x][y];if (bTetris[x][yPos]){bFlag = TRUE;}}if (bFlag){yPos++;}}//memcpy(bTetris,bNewTetris,sizeof(bNewTetris));return;
}
BOOL CheckTetris(int nStartX,int nStartY,BOOL bTetris[4][4],BOOL bGame[GAME_X][GAME_Y])
{int x,y;if (nStartX < 0){//碰到左墙return FALSE;}for (x = 0;x < 4;x++){for (y = 0;y < 4;y++){if (bTetris[x][y]){//碰右墙if (nStartX +y >=GAME_X){return FALSE;}//碰下墙if (nStartY + x >=GAME_Y){return FALSE;}//碰到已有的方块if (bGame[nStartX +y][nStartY + x]){return FALSE;}}}}return TRUE;
}//落地的方块合并,并且满足消除一行
VOID RefreshTetris(int nStartX,int nStartY,BOOL bTetris[4][4], BOOL bGame[GAME_X][GAME_Y])
{BOOL bFlag = FALSE;int x,y;int newX,newY;//主要用来记录int iFulllie = 0; //校区满行的格子记录行数,用于积分for (x = 0; x < 4;x ++){for (y = 0 ;y < 4; y++){if (bTetris[x][y]){bGame[nStartX + y][nStartY +x] = TRUE;}}}for (y = GAME_Y,newY = GAME_Y; y >= 0; y--){bFlag= FALSE;for (x = 0;x < GAME_X;x++){bGame[x][newY] = bGame[x][y];if (!bGame[x][y])//这一行不满格{bFlag = TRUE;}}if (bFlag){newY--;}else{//满格的话,用上一行替换这一行iFulllie++;}}if (iFulllie){g_uiScore -= iFulllie *1;}//合并以后生成新的方块,并刷新位置memcpy(g_CurTetris,g_NextTetris,sizeof(g_CurTetris));memcpy(g_NextTetris,g_astTetris[ GetRandNum(0,TETRIS_CNT)],sizeof(g_NextTetris));TetrisX = (GAME_X - 4)/2;TetrixY = 0;
}//初始化游戏,就是方块最先初始化的位置
VOID InitGame()
{int iTmp;TetrisX = (GAME_X - 4 )/2 ; //居中TetrixY = 0;g_uiScore = 0;g_uiInterval = DEFAULT_INTERVAL;iTmp = GetRandNum(0,TETRIS_CNT);memcpy(g_CurTetris,g_astTetris[iTmp],sizeof(g_CurTetris));iTmp = GetRandNum(0,TETRIS_CNT);memcpy(g_NextTetris,g_astTetris[iTmp],sizeof(g_NextTetris));memset(g_stGame,0,sizeof(g_stGame));
}
//
//  函数: 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;int nWinX,nWinY,nClientX,nClientY;RECT rect;BOOL bTmpTetris[4][4] = {};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;MoveWindow(hWnd,0,0,3 * BOUND_SIZE + (GAME_X + INFO_X)* TETRIS_SIZE +(nWinX  - nClientX),2 * BOUND_SIZE + GAME_Y*TETRIS_SIZE + (nWinY - nClientY),true);InitGame();SetTimer(hWnd,MY_TIMEER,g_uiInterval,NULL);break;case WM_TIMER://定时器中方块下降if (CheckTetris(TetrisX,TetrixY + 1,g_CurTetris,g_stGame)){TetrixY++;}else{if (TetrixY == 0){MessageBox(NULL,L"不行了",L"shit!",MB_OK);KillTimer(hWnd,MY_TIMEER);}RefreshTetris(TetrisX,TetrixY,g_CurTetris,g_stGame);}InvalidateRect(hWnd,NULL,TRUE);break;case WM_LBUTTONDOWN:RotateTetris(g_CurTetris);InvalidateRect(hWnd,NULL,TRUE);break;case WM_KEYDOWN:switch(wParam){case VK_LEFT://左方向键if (CheckTetris(TetrisX -1,TetrixY,g_CurTetris,g_stGame)){//判断一下当前方块没有靠墙就TetrisX--;InvalidateRect(hWnd,NULL,TRUE);}else{MessageBeep(0);}break;case  VK_RIGHT:if (CheckTetris(TetrisX +1,TetrixY,g_CurTetris,g_stGame)){//判断一下当前方块没有靠墙就TetrisX++;InvalidateRect(hWnd,NULL,TRUE);}else{MessageBeep(0);}break;case VK_UP://变形,但是要判断变形成功或者失败memcpy(bTmpTetris,g_CurTetris,sizeof(bTmpTetris));RotateTetris((bTmpTetris));if (CheckTetris(TetrisX,TetrixY,bTmpTetris,g_stGame)){//成功后,再把旋转后的copy回来memcpy(g_CurTetris,bTmpTetris,sizeof(bTmpTetris));InvalidateRect(hWnd,NULL,TRUE);}break;case VK_DOWN:while (CheckTetris(TetrisX,TetrixY + 1,g_CurTetris,g_stGame)){TetrixY++;}RefreshTetris(TetrisX,TetrixY,g_CurTetris,g_stGame);InvalidateRect(hWnd,NULL,TRUE);break;default:break;}break;case WM_COMMAND:wmId    = LOWORD(wParam);wmEvent = HIWORD(wParam);// 分析菜单选择:switch (wmId){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: 在此添加任意绘图代码...DrawBackGround(hdc);DrawInfo(hdc);DrawTetris(hdc,TetrisX,TetrixY,g_CurTetris);EndPaint(hWnd, &ps);break;case WM_DESTROY:KillTimer(hWnd,MY_TIMEER);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;
}

代码参考:

主要是听了这个课程,这个公开课做点小项目,贪吃蛇,网络啊什么的,都是代码挺好的,作为一个熟悉其他领域的小项目非常适合上手:

http://study.163.com/course/courseLearn.htm?courseId=1367011#/learn/video?lessonId=1738230&courseId=1367011

windows下的win32编程要学的东西还比较多,下面给出一个简单的知识点:

windows下实现win32俄罗斯方块练手,编程的几点心得相关推荐

  1. Windows下LATEX排版论文攻略—CTeX、JabRef使用心得

    笔者刚刚接触到TEX排版,相关知识完全空白,用了两天时间学习并完成了一篇论文的完整排版. 期间遇到不少小问题,着实辛苦,分享至上,现将其解决办法总结归纳,共同学习. 一.工具介绍 TeX是一个很好排版 ...

  2. Windows下LATEX排版论文攻略—CTeX、JabRef使用心得, 包括 IEEEtran.bst

    笔者刚刚接触到TEX排版,相关知识完全空白,用了两天时间学习并完成了一篇论文的完整排版. 期间遇到不少小问题,着实辛苦,分享至上,现将其解决办法总结归纳,共同学习. 一.工具介绍 TeX是一个很好排版 ...

  3. windows下caffe+CPUOnly实现MNIST手写分类

    工具下载 微软官方移植的Caffe:https://github.com/Microsoft/caffe 对属性表的操作 需要把实例属性表的后缀改成vs可用的.props 打开同一个文件夹下的Caff ...

  4. windows下使用fftw进行傅里叶变换及其编程实例

           傅里叶变换应该是上大二的时候<信号与系统>课上学过,上研后在<数字信号处理>课上又学了一遍.当初一直在想傅里叶变换到底有什么用呢?什么时候能用上呢?时间如梭,没想 ...

  5. Windows下使用C语言的UDP编程接收网络调试助手发送的数据

    代码 #include <stdio.h> #include <winsock2.h> #pragma comment (lib, "ws2_32.lib" ...

  6. 【学习笔记】在windows下进行基于TCP的本地客户端和服务端socket通信

    文章目录 socket介绍 java中使用socket 基于tcp的socket通信 使用ServerSocket类创建一个web服务器:(java) windows下的基于tcp的socket编程( ...

  7. 不用U盘安卓Linux系统,不用U盘,不要光驱,不需分区,windows下安装noilinux双系统...

    信息学奥赛以前都是linux和windows系统并存,因为我们习惯了在windows下操作,所以所有的编程操作都在windows下面执行,但是今年我们湖南赛区已经在NOIP2017湖南赛区复赛操作系统 ...

  8. c++小项目_编程初学者的练手小项目(Pythonamp;C/C++)

    老是有一些刚接触编程的小伙伴问,怎么样才能快速提高编程能力?"一切不写代码的学编程,都是瞎搞!",想要提高编程能力,当然是写代码.写代码.写代码.在不断做项目的过程中,加强基础语法 ...

  9. C# Socket网络编程(附赠练手小项目)

    在公司花了两天的时间来研究Socket编程,感觉也还是学到了一点点皮毛,不过也还是有一点点的小成就. 配合Winform窗体界面,实现了简单的窗体间互相通信的小项目(可以互相发消息,服务器可以给客户端 ...

最新文章

  1. 2018.3.15校内互测总结-点分治-线段树
  2. 手把手教你搭建一个学习Python好看的 Jupyter 环境
  3. linux时间 a x z,关于linux的命令一个莫名的想法,a到z有哪些命令
  4. 当 Android 开发者遇见 TensorFlow
  5. “ShardingCore”是如何针对分表下的分页进行优化的
  6. android默认代码混淆,Android SDK默认混淆配置文件
  7. 流媒体技术的国内外动态
  8. 亚马逊云服务(AWS)中国与毕马威中国建立战略合作伙伴关系
  9. 360公司2019秋招空中宣讲会开启,送海量面试直通卡!
  10. 飞利浦css6530b评测,带多种输入模式 无线接收器很方便_飞利浦 CSS6530B/93_音频评测-中关村在线...
  11. 关于Oracle10g归档参数的研究
  12. POJ3169 Layout(差分约束)
  13. 对应分析与典型相关分析CCA笔记_数学建模系列
  14. word排版案例报告_文章为什么要排版?如何排版?这篇文章告诉你真相
  15. 特征工程系列:数据清洗
  16. 谷歌浏览器扩展程序manifest.json参数详解
  17. R语言—90分钟从入门到精通
  18. epics installation
  19. 饥荒食物 + 物品全制造代码
  20. Android studio 安装配置SDK

热门文章

  1. OpenCV + CPP 系列(卅四)图像特征提取(亚像素级别角点检测)
  2. Notepad++ 编辑器常用设置与常用组合快捷键汇总
  3. vue react 项目代表/各大框架使用项目目录。
  4. 仅需6200美元,高性价比构建3块2080Ti的强大工作站
  5. 【创建Windows右键菜单折叠】
  6. 风能风力发电系统案例
  7. 腾讯云携手合作伙伴打造5G生态,覆盖“云边网端”助推“万物智联”
  8. CMMI 研究院CMMI 2.0 中文版发布
  9. 网络文件服务器手机版,hfs网络文件服务器(个人HTTP文件服务器)
  10. Derby的安装与使用