项目采用easyX编程操作实现:
学完C语言即可完全实现。
1.欢迎和基本界面
(1)初始界面函数:
//一定要边该边调试 void initGameSence() { char str[16]; cleardevice();//清除屏幕 rectangle(27,27,336,635); //调用两个矩形函数,在左边创建两个方框 rectangle(29,29,334,633); rectangle(370,50,515,195); //右边创建接下来出现的提示方块 setfont(24,0,_T("楷体")); //下一个方块的提示文字 setcolor(LIGHTGRAY); //设置颜色灰色 outtextxy(405,215,_T("下一个")); setcolor(RED); outtextxy(405,280,_T("分数")); //显示分数 sprintf(str,"%d",score); //将整型分数score转化为字符输入到字符串str outtextxy(415,310,str); //该项目属性,字符集Unicode修改为多字符集 //显示游戏等级 outtextxy(405,375,_T("等级")); //显示等级 sprintf(str,"%d",myrank); outtextxy(415,405,str); //等级数,outtextxy显示变量的方法 //操作说明 setcolor(LIGHTBLUE); //设置颜色蓝色 outtextxy(390,475,_T("操作说明")); outtextxy(390,500,"↑:旋转"); //显示箭头提示 outtextxy(390,525,"↓:下降"); //显示箭头提示 outtextxy(390,550,"←:左移"); //显示箭头提示 outtextxy(390,575,"→:右移"); //显示箭头提示 outtextxy(390,600,"空格:暂停"); //显示箭头提示 } //培训编程一定要轻松听着舒服的氛围,且废话不多
void welcome() { //画布、文本 //初始化画布,ctrl+j自动提示(非常方便) initgraph(550,650); //设置窗口标题 HWND window = GetHWnd();//获取当前窗口 SetWindowText(window,_T("荔枝番 俄罗斯方块"));//哪个窗口,设置什么值 //文本1:字体样式、颜色、内容 setfont(40,0,_T("微软雅黑")); //高度,宽度(不指定),样式,_T是转码 setcolor(WHITE); //颜色 outtextxy(205,200,_T("俄罗斯方块")); //输出文本在坐标位置(X,Y)和内容 //文本1:字体样式、颜色、内容 setfont(20,0,_T("楷体")); //高度,宽度(不指定),样式 setcolor(WHITE); //文本颜色 outtextxy(175,300,_T("学习C++编程,开始游戏!")); Sleep(1500);//休息1.5s }
2.游戏控制功能
// 如果在指定位置可以向指定方向移动,就返回1, 否则就返回0 int moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) { // 计算当前方块的左上角在30x15的游戏区中的位置(第多少行,第多少列) int x = (y0 - minY) / UNIT_SIZE; int y = (x0 - minX) / UNIT_SIZE; int id = BlockIndex * 4 + blockDir; int ret = 1; if (moveDir == MOVE_DOWN) { for (int i=0; i<5; i++) { for (int j=0; j<5; j++) { if (block[id][i][j] == 1 && (x + i + 1 >= 30 || visit[x+i+1][y+j] == 1)) { ret = 0; } } } } else if (moveDir == MOVE_LEFT) { for (int i=0; i<5; i++) { for (int j=0; j<5; j++) { if (block[id][i][j] == 1 && (y + j == 0 || visit[x+i][y+j-1]==1)) { ret = 0; } } } } else if (moveDir == MOVE_RIGHT) { for (int i=0; i<5; i++) { for (int j=0; j<5; j++) { if (block[id][i][j] == 1 && (y+j+1>=15 || visit[x+i][y+j+1]==1)) { ret = 0; } } } } return ret; } // 检测游戏是否结束 void failCheck() { if (!moveable(START_X, START_Y, MOVE_DOWN, BLOCK_UP)) { setcolor(WHITE); setfont(45, 0, "隶体"); outtextxy(75, 300, "GAME OVER!"); Sleep(1000); system("pause"); closegraph(); exit(0); } } // 判断当前方块是否可以转向到指定方向 // 注意, 此时还没有转到该方向!!! int rotatable(int x, int y, block_dir_t dir) { int id = BlockIndex * 4 + dir; int xIndex = (y - minY) / 20; int yIndex = (x - minX) / 20; if (!moveable(x, y, MOVE_DOWN, dir)) { return 0; } for (int i=0; i<5; i++) { for (int j=0; j<5; j++) { if (block[id][i][j] == 1 && (yIndex+j<0 || yIndex+j>=15 || visit[xIndex+i][yIndex+j]==1)) { return 0; } } } return 1; } void wait(int interval) { int count = interval / 10; for (int i=0; i<count; i++) { Sleep(10); if (kbhit()) { return; } } } void mark(int x, int y, int blockIndex, block_dir_t dir) { int id = blockIndex * 4 + dir; int x2 = (y - minY) / 20; int y2 = (x - minX) / 20; for (int i=0; i<5; i++) { for (int j=0; j<5; j++) { if (block[id][i][j] == 1) { visit[x2+i][y2+j] = 1; markColor[x2+i][y2+j] = color[blockIndex]; } } } } void move(void){ int x = START_X; int y = START_Y; int k = 0; block_dir_t blockDir = BLOCK_UP; int curSpeed = speed; // 检测游戏是否结束 failCheck(); // 持续向下降落 while (1) { if (kbhit()) { int key = getch(); if (key == KEY_SPACE) { getch(); } } // 清除当前方块 clearBlock(x, k, blockDir); if (kbhit()) { int key = getch(); if(key == KEY_UP) { block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4); if (rotatable(x, y+k, nextDir)) { blockDir = nextDir; } } else if (key == KEY_DOWN) { curSpeed = 50; } else if (key == KEY_LEFT) { if (moveable(x, y+k+20, MOVE_LEFT, blockDir)) { x -= 20; } } else if (key ==KEY_RIGHT) { if (moveable(x, y+k+20, MOVE_RIGHT, blockDir)) { x += 20; //x = x + 20; } } } k += 20; // 绘制当前方块 drawBlock(x, y+k, BlockIndex, blockDir); wait(curSpeed); //k += 20; // 方块的“固化”处理 if (!moveable(x, y+k, MOVE_DOWN, blockDir)) { mark(x, y+k, BlockIndex, blockDir); break; } } } void newblock() { // 确定即将使用的方块的类别 BlockIndex = NextIndex; // 绘制刚从顶部下降的方块 drawBlock(START_X, START_Y); // 让新出现的方块暂停一会,让用户识别到 Sleep(100); //0.1秒 // 在右上角区域,绘制下一个方块 nextblock(); // 方块降落 move(); } //消除第x行,并把上面的行都下移 void down(int x){ for (int i=x; i>0; i--) { // 消除第i行,第j列的方格消除 for (int j=0; j<15; j++) { if (visit[i-1][j]) { visit[i][j] = 1; markColor[i][j] = markColor[i-1][j]; setcolor(markColor[i][j]); outtextxy(20*j + minX, 20*i+minY, "■"); } else { visit[i][j] = 0; setcolor(BLACK); outtextxy(20*j + minX, 20*i+minY, "■"); } } } // 清除最顶上的哪一行(就是行标为0的那一行) setcolor(BLACK); for (int j=0; j<15; j++) { visit[0][j] = 0; outtextxy(20*j + minX, minY, "■"); } } // 更新分数,参数lines表示消除的行数 void addScore(int lines) { char str[32]; setcolor(RED); score += lines * 10; sprintf(str, "%d", score); outtextxy(415, 310, str); } void updateGrade() { // 更新等级的提示 // 假设:50分一级 rank = score / 50; char str[16]; sprintf(str, "%d", rank); outtextxy(425, 405, str); // 更新速度, 等级越高,速度越快,speed越小! // 最慢:500, 最快是100 speed = 500 - rank*100; if (speed <= 100) { speed = 100; } } void check(void) { int i, j; int clearLines = 0; for (i=29; i>=0; i--) { // 检查第i行有没有满 for (j=0; j<15 && visit[i][j]; j++) ; //执行到此处时,有两种情况: // 1. 第i行没有满,即表示有空位 此时 j<15 // 2. 第i行已满了,此时 j>=15 if (j >= 15) { // 此时,第i行已经满了,就需要消除第i行 down(i); //消除第i行,并把上面的行都下移 i++; // 因为最外层的循环中有 i--, 所以我们先i++, 使得下次循环时,再把这一行检查一下 clearLines++; } } // 更新分数 addScore(clearLines); // 更新等级(更新等级提示,更新速度) updateGrade(); } int main(void) { welcome(); initGameScene(); // 产生新方块 nextblock(); Sleep(500); // 初始化访问数组 memset(visit, 0, sizeof(visit)); while (1) { newblock(); // 消除满行,并更新分数和速度 check(); } system("pause"); closegraph(); return 0; }