俄罗斯方块code
来源:互联网 发布:劳拉克劳馥 知乎 编辑:程序博客网 时间:2024/05/20 17:26
#include<windows.h>#include<winuser.h>#include<time.h>#include<mmsystem.h>#include"resource.h"#include"rect.h"const int FSIZE = 22 ; //方块大小int m , n;int Rstate[10][23]; //记录方块的位置int Cstate[10][23]; //记录对应的位置的颜色int Sx, Sy;HBRUSH Color[9]; //9种颜色画刷int icolor; int PrevShape, PrevColor; //记录预览窗口的图形的形状和对应的颜色,用于下一次在游戏窗口画出同样的图形int Px, Py; //记录预览框中图形的位置,之所以这样是因为要保持其位置不变,以免刷新时图形移出预览框struct sRect{int x, y, dir, shape;}Pos;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevShapeInstance, PSTR szCmdLine, int iCmdShow){static TCHAR szAppName[] = TEXT("Tetris");HWND hwnd;MSG msg;WNDCLASS winclass;winclass.style = 0;winclass.lpfnWndProc = WinProc;winclass.cbClsExtra = 0;winclass.cbWndExtra = 0;winclass.hInstance = hInstance;winclass.hIcon = LoadIcon(hInstance, (LPCSTR)ID_ICON);winclass.hCursor = LoadCursor(NULL, NULL);winclass.hbrBackground = CreateSolidBrush(RGB(27,65,61));winclass.lpszClassName = szAppName;winclass.lpszMenuName = (LPCSTR)ID_MENU;if(!RegisterClass(&winclass)){MessageBox(NULL,TEXT("创建窗口失败!"),TEXT("错误"),MB_OK);return 0;}hwnd = CreateWindow(szAppName, TEXT("~俄罗斯方块~"), WS_SYSMENU|WS_CAPTION, 500, 200, 400, 590, NULL, NULL, hInstance, NULL); ShowWindow(hwnd,iCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) {TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){HWND hwndBtnPause, hwndBtnQuit, hwndBtnNew, hwndBtnMusic;HWND hwndEdit, hwndEditscore, hwndEditLine; HDC hdc;PAINTSTRUCT ps;static int speed = 600; //在计时器中用于控制速度static int num = 0; static int puase = 1, misa = 1; static int TotalLines = 0; //统计消去的行数static int TotalScore = 0; //统计总得分int line = 0; //用来记录每次消去的行数TCHAR szStr[256], szLines[256] = TEXT("行数: ");TCHAR szStb[256], szScore[256] = TEXT("分数: ");switch(message){case WM_CREATE: //创建一些子窗口{ hwndBtnPause = CreateWindow(TEXT("button"), TEXT("暂停"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 280, 320, 80, 30, hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)-> hInstance, NULL);hwndBtnQuit = CreateWindow(TEXT("button"), TEXT("离开"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 280, 355, 80, 30, hwnd, (HMENU)2, ((LPCREATESTRUCT)lParam)-> hInstance, NULL);hwndBtnNew = CreateWindow(TEXT("button"), TEXT("新游戏"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 280, 390, 80, 30, hwnd, (HMENU)3, ((LPCREATESTRUCT)lParam)-> hInstance, NULL);hwndBtnMusic = CreateWindow(TEXT("button"), TEXT("音乐开"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 280, 425, 80, 30, hwnd, (HMENU)7, ((LPCREATESTRUCT)lParam)-> hInstance, NULL);hwndEdit = CreateWindow(TEXT("edit"), TEXT("第 1 关"), WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER |WS_DISABLED, 280, 220, 80, 20, hwnd, (HMENU)4, ((LPCREATESTRUCT)lParam)-> hInstance, NULL);hwndEditscore = CreateWindow(TEXT("edit"), TEXT("分数: 0"), WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER | WS_DISABLED, 280, 250, 80, 20, hwnd, (HMENU)5, ((LPCREATESTRUCT)lParam)-> hInstance, NULL);hwndEditLine = CreateWindow(TEXT("edit"), TEXT("行数: 0"), WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER | WS_DISABLED, 280, 280, 80, 20, hwnd, (HMENU)6, ((LPCREATESTRUCT)lParam)-> hInstance, NULL);//创建9中颜色画刷 Color[0] = CreateSolidBrush(RGB(0, 0, 0)); //黑色背景画刷Color[1] = CreateSolidBrush(RGB(0, 255, 255));Color[2] = CreateSolidBrush(RGB(73, 213, 73)); Color[3] = CreateSolidBrush(RGB(221, 37, 13));Color[4] = CreateSolidBrush(RGB(216, 232, 0));Color[5] = CreateSolidBrush(RGB(229, 106, 50));Color[6] = CreateSolidBrush(RGB(64, 0, 207));Color[7] = CreateSolidBrush(RGB(166, 0, 218));Color[8] = CreateSolidBrush(RGB(255, 255, 255));srand((unsigned)time(0)); //创建时取随机种子SetTimer(hwnd, 1, speed, NULL);}break;case WM_PAINT:{hdc = BeginPaint(hwnd, &ps); DrawWindow(hdc); //画边框LoadRectangle(hdc); //加载方块if(0 == num) //第一次响应WM_PAINT消息时num为0{Init(); //第一次初始化在WM_PAINT中,以后就不能在WM_PAINT中了Px = Pos.x; //记录此时位置信息,这样就避免了因拖动窗口等刷新客户区时 预览框图形随着Pos.X或Pos.y的自增而移位Py = Pos.y;DrawP(hdc, Pos.dir, Pos.shape, icolor, Px +9, Py +5); //在预览框中画图形PrevShape = rand()%7; PrevColor = PrevShape +1;DrawP(hdc, Pos.dir, PrevShape, PrevColor, Pos.x, Pos.y);num = 1;}else{DrawP(hdc, Pos.dir, Pos.shape, icolor, Px +9, Py +5); //在预览框中画图形DrawP(hdc, Pos.dir, PrevShape, PrevColor, Pos.x, Pos.y); //在游戏窗口区画上次预览窗口中的图形}EndPaint(hwnd, &ps);}break; case WM_TIMER:{hdc=GetDC(hwnd);if(Check(Pos.dir, PrevShape, Pos.x, Pos.y +1)){DrawP(hdc, Pos.dir, PrevShape, 0, Pos.x, Pos.y++);DrawP(hdc, Pos.dir, PrevShape, PrevColor, Pos.x, Pos.y);}else{ line = SaveRectangle(hdc, hwnd, Pos.dir, PrevShape, Pos.x, Pos.y);TotalLines += line; itoa(TotalLines, szStr, 10);lstrcat(szLines, szStr);SetWindowText(GetDlgItem(hwnd,6), szLines); //编辑框中填入行数if(1 == line) //判断加多少分{TotalScore += 10;}else if(2 == line){TotalScore += 30;}else if(3 == line){TotalScore += 60;}else if(4 == line){TotalScore += 100;}itoa(TotalScore, szStb, 10);lstrcat(szScore, szStb);SetWindowText(GetDlgItem(hwnd,5), szScore); //编辑框中填入得分if(TotalScore<200)//判断到达第几关,并调速度{SetWindowText(GetDlgItem(hwnd,4), TEXT("第 1 关"));}else if(TotalScore<600){speed = 500;SetTimer(hwnd, 1, speed, NULL);SetWindowText(GetDlgItem(hwnd,4), TEXT("第 2 关")); }else if(TotalScore<1000){ speed = 450; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 3 关")); }else if(TotalScore<1800){ speed = 400;SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 4 关"));}else if(TotalScore<2800){ speed = 350; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 5 关"));} else if(TotalScore<5000){ speed = 300; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 6 关"));}else if(TotalScore<7500){ speed = 250; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 7 关"));} else if(TotalScore<10000){ speed = 200; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 8 关"));}else { speed = 100; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 9 关"));}if(!GameOver()) //判断游戏是否结束,为TRUE时结束{ PrevShape = Pos.shape %7; //保存预览框中图形信息,用于游戏区画下一个图形 PrevColor = PrevShape +1; Init(); Px = Pos.x; //记录此时位置信息,这样就避免了因拖动窗口等刷新客户区时 预览框图形随着Pos.X或Pos.y的自增而移位 Py = Pos.y; InvalidateRect(hwnd, NULL, FALSE);}else{KillTimer(hwnd, 1);MessageBox(NULL,TEXT("游戏结束!"), "", MB_OK);}} ReleaseDC(hwnd, hdc);}break;case WM_KEYDOWN:{hdc = GetDC(hwnd);switch(wParam){ case 87: //'W' case VK_UP: { if(Check((Pos.dir+1)%4, PrevShape, Pos.x, Pos.y)) { DrawP(hdc, Pos.dir, PrevShape, 0, Pos.x, Pos.y); Pos.dir = (Pos.dir+1) % 4; DrawP(hdc, Pos.dir, PrevShape, PrevColor, Pos.x, Pos.y); PlaySound(TEXT("wave1"),(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), SND_RESOURCE|SND_ASYNC|SND_NOSTOP); } } break; case 68: //'D' case VK_RIGHT: { if(Check(Pos.dir, PrevShape, Pos.x+1, Pos.y)) { DrawP(hdc, Pos.dir, PrevShape, 0, Pos.x++, Pos.y); DrawP(hdc, Pos.dir, PrevShape, PrevColor, Pos.x, Pos.y); } } break; case 65: //'A' case VK_LEFT: { if(Check(Pos.dir, PrevShape, Pos.x-1,Pos.y)) { DrawP(hdc, Pos.dir, PrevShape, 0, Pos.x--, Pos.y); DrawP(hdc, Pos.dir, PrevShape, PrevColor, Pos.x, Pos.y); } } break; case 83: //'S' case VK_DOWN: { if(Check(Pos.dir, PrevShape, Pos.x, Pos.y+1)) { DrawP(hdc, Pos.dir, PrevShape, 0, Pos.x, Pos.y++); DrawP(hdc, Pos.dir, PrevShape, PrevColor, Pos.x, Pos.y); } else { line = SaveRectangle(hdc, hwnd, Pos.dir, PrevShape, Pos.x, Pos.y); TotalLines += line; itoa(TotalLines, szStr, 10); lstrcat(szLines, szStr); SetWindowText(GetDlgItem(hwnd,6), szLines); if(1 == line) { TotalScore += 10; } else if(2 == line) { TotalScore += 30; } else if(3 == line) { TotalScore += 60; } else if(4 == line) { TotalScore += 100; } itoa(TotalScore, szStb, 10); lstrcat(szScore, szStb); SetWindowText(GetDlgItem(hwnd,5), szScore); if(TotalScore<200)//判断到达第几关,并调速度 { SetWindowText(GetDlgItem(hwnd,4), TEXT("第 1 关")); } else if(TotalScore<600) { speed = 500; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 2 关")); } else if(TotalScore<1000) { speed = 450; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 3 关")); } else if(TotalScore<1800) { speed = 400; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 4 关")); } else if(TotalScore<2800) { speed = 350; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 5 关")); } else if(TotalScore<5000) { speed = 300; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 6 关")); } else if(TotalScore<7500) { speed = 250; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 7 关")); } else if(TotalScore<10000) { speed = 200; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 8 关")); } else { speed = 100; SetTimer(hwnd, 1, speed, NULL); SetWindowText(GetDlgItem(hwnd,4), TEXT("第 9 关")); } if(!GameOver()) //判断游戏是否结束,为TRUE时结束 { PrevShape = Pos.shape %7; //保存预览框中图形信息,用于游戏区画下一个图形 PrevColor = PrevShape +1; Init(); Px = Pos.x; Py = Pos.y; InvalidateRect(hwnd, NULL, FALSE); } else { KillTimer(hwnd, 1); MessageBox(NULL,TEXT("游戏结束!"), "", MB_OK); } } } break;}ReleaseDC(hwnd, hdc);}break;case WM_COMMAND:{switch(wParam){case 1: //暂停或继续{if(!GameOver()) //判断游戏是否结束,为FALSE时没有结束{if(1 == puase){puase = 0;KillTimer(hwnd, 1);SetWindowText(GetDlgItem(hwnd,1), "继续");}else{puase = 1;SetTimer(hwnd, 1, speed, NULL);SetWindowText(GetDlgItem(hwnd,1), "暂停"); SetFocus(hwnd); //把输入焦点换回到主窗口}}}break;case 2: //是否离开{KillTimer(hwnd, 1);if(IDYES == MessageBox(NULL, TEXT("确定退出游戏?"), "", MB_YESNO)){PostQuitMessage(0);}else{if(!GameOver()) //判断游戏是否结束,为TRUE时结束{SetTimer(hwnd, 1, speed, NULL); SetFocus(hwnd);}}}break;case 3: //是否开始新游戏{KillTimer(hwnd, 1);if(IDYES == MessageBox(NULL, TEXT("开始新游戏?"), "", MB_YESNO)){ZeroMemory(Rstate, sizeof(Rstate)); //清空数组,重置一些内容ZeroMemory(Cstate, sizeof(Cstate));TotalLines = 0; TotalScore = 0;SetWindowText(GetDlgItem(hwnd,5), TEXT("分数: 0"));SetWindowText(GetDlgItem(hwnd,6), TEXT("行数: 0"));Init();InvalidateRect(hwnd, NULL, TRUE);SetTimer(hwnd, 1, speed, NULL);SetFocus(hwnd);}else{if(!GameOver()) //判断游戏是否结束,为TRUE时结束{SetTimer(hwnd, 1, speed, NULL); SetFocus(hwnd);}}}break;case 7: //音乐关闭{if(1 == misa){misa = 0;PlaySound(TEXT("wave3"), (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), SND_RESOURCE|SND_ASYNC|SND_LOOP|SND_NOSTOP);SetWindowText(GetDlgItem(hwnd,7), "音乐关");}else{misa = 1;PlaySound(TEXT("wave1"), (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), SND_RESOURCE|SND_ASYNC);SetWindowText(GetDlgItem(hwnd,7), "音乐开");}SetFocus(hwnd); //把输入焦点换回到主窗口}break;case IDM_AUTHOR: //作者{DialogBox((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), MAKEINTRESOURCE(IDD_DIALOG1), NULL, AboutDlgProc);}break;case IDM_DS:{MessageBox(NULL, TEXT("==================\n" "W或 ↑: 改变形状\n" "A 或 ←: 向左移动\n" "D 或 →: 向右移动\n" "S 或 ↓: 向下加速\n" "==================\n" "行数多不一定得分多~~\n" "拼命一次消3、4行吧~~"), TEXT("游戏说明"), MB_OK);}break;default:break;}}break;case WM_DESTROY:{KillTimer(hwnd, 1);PostQuitMessage(0);}break;default:break;}return DefWindowProc(hwnd, message, wParam, lParam);}//初始化void Init(void){ Pos.dir = 0;Pos.shape = rand()%7; icolor = Pos.shape + 1;Pos.x = 2;Pos.y = 0;}//画方块void Draw(HDC hdc, int x, int y, int sele){ int screenx = 13 + x *FSIZE; //方块左上角的坐标是x乘方块大小再加上起始位置 int screeny = 16 + y *FSIZE; RECT rt; rt.left = screenx + 1; rt.top = screeny + 1; rt.right = screenx + FSIZE; rt.bottom = screeny + FSIZE; FillRect(hdc, &rt, Color[sele]); //填充}//画图形void DrawP(HDC hdc, int dir, int shape, int color, int x, int y){int i;for(i=0; i<4; i++){Sx = Rect[shape][dir][i].x + x;Sy = Rect[shape][dir][i].y + y;Draw(hdc, Sx, Sy, color);}}//画边框void DrawWindow(HDC hdc){HBRUSH hBrush; hBrush = CreateSolidBrush(RGB(0,0,0)); //创黑色色画刷SelectObject(hdc, CreatePen(PS_DOT, 0, RGB(255, 0, 255))); //创建红色画笔,描外边框SelectObject(hdc, hBrush); Rectangle(hdc, 10, 14, 237, 527); SelectObject(hdc, CreatePen(PS_SOLID, 0, RGB(0, 255, 0))); //创建绿色画笔,描内边框SelectObject(hdc, hBrush); //将黑色画刷选进设备描述表,用黑色填充图形内部 Rectangle(hdc, 12, 16, 235, 525);SelectObject(hdc, CreatePen(PS_SOLID, 0, RGB(255, 255, 0))); //创建画笔,描预览框SelectObject(hdc, hBrush); Rectangle(hdc, 260, 110, 380, 185); }BOOL Check(int dir, int shape, int Px, int Py)//检查是否越界,越界返回FALSE, { int i, x, y;for(i=0; i<4; i++){x = Rect[shape][dir][i].x + Px;y = Rect[shape][dir][i].y + Py;if(x<0||x>=10 || y>=23 || Rstate[x][y]!=0){return FALSE;}}return TRUE;}//存储落下的方块int SaveRectangle(HDC hdc, HWND hwnd, int dir, int shape, int x, int y){int i, j, line = 0, temp = 0; bool State;for(i=0; i<4; i++){Sx = Rect[shape][dir][i].x + x;Sy = Rect[shape][dir][i].y + y; Rstate[Sx][Sy] = 1; //存储落下的方块,记录位置Cstate[Sx][Sy] = PrevColor; //记录对应的颜色}for(j=0; j<23; j++) //判断是否有满行,有则用该行的上一行填充该行,以达到消去的目的{for(i=0; i<10; i++){if(Rstate[i][j] !=1 ) //有一个没被占就说明此行未满,跳出内循环,对下一行进行判断{State = false;break;}}if(10 == i && 1 == Rstate[9][j]) //此条件为真时说明该行以满{State = true; line++; //统计行数if(1 == line) //判断第一个满行时,记录行数{temp = j;}if(line > 1) //当满行数超过1时{for(i=0; i<10; i++) //重绘第一个判断满行的那一行{Draw(hdc, i, temp, 8);}for(i=0; i<10; i++) //重绘剩下的满行的那些行{Draw(hdc, i, j, 8);} Sleep(200); //PS: 之所以这样我也很郁闷,代码都写成这样了不知道过几个月还能看懂不了。。。}}if(State) //满行时,用该行的上一行填充该行,以达到消去的目的{for(m=j; m>1; m--){for(int n=0; n<10; n++){Rstate[n][m] = Rstate[n][m-1];Cstate[n][m] = Cstate[n][m-1];}}} }//在循环外面if(1 == line) //当仅有一行满行时,就重绘那一行,并播放声音,这样才能看见重绘的效果,没有声音,就看不见重绘的效果,这是为什么?{for(i=0; i<10; i++){Draw(hdc, i, temp, 8);}PlaySound(TEXT("wave2"), (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), SND_RESOURCE|SND_ASYNC|SND_NOSTOP);Sleep(200);}else if(line > 1) //满行数超过1时就播放声音,最好在循环外,保证其只播放一次{PlaySound(TEXT("wave2"), (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), SND_RESOURCE|SND_ASYNC|SND_NOSTOP);}//PS:很乱,为什么重绘和声音播放还是有关系呢。。当开了背景音乐时,仅有一行满行并重绘时,仍然无法看到效果,应该是此时声音无效的原因return line;}//屏幕刷新时加载已经存在的方块void LoadRectangle(HDC hdc) {int i, j;for(i=0; i<10; i++){for(j=0; j<23; j++){if(1 == Rstate[i][j]){ Draw(hdc, i, j, Cstate[i][j]); }}}}//判断游戏是否结束BOOL GameOver(void){int i, j;BOOL over = FALSE;for(j=0, i=0; i<10; i++){if(1 == Rstate[i][j]) //最上面一行有一个格子被占就返回TRUE,游戏结束{ over = TRUE;break;}}return over;}BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){switch(message){case WM_INITDIALOG:return TRUE;case WM_COMMAND:switch(LOWORD(wParam)){case IDOK:EndDialog(hDlg,0);break;}break;}return FALSE;}
0 0
- 俄罗斯方块code
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块!
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- 俄罗斯方块
- [5]ARM-Linux S5PV210 UART驱动----串口的open操作(tty_open、uart_open)
- (30 hackdays day 21) Wakatime - 现在几点了,你在做什么呢
- UVa 1586 字符串处理
- SCP命令详解-转
- (30 hackdays day 22) Import.io - 最简单好用的网页爬虫服务
- 俄罗斯方块code
- 2014年总结——技术篇
- Android 将程序崩溃信息保存到本地
- GC的三种方式,读RUBY之父写的《编程语言的过去、现在和未来》笔记
- 回溯法解决素数环问题
- (30 hackdays day 24) Atatus - what happened before crash
- NSDate 最大最小时间配置
- linux第一个用户进程init--systemd
- (30 hackdays day 25) Tuling123 - 光棍节找个机器人聊天吧