我罗斯方块汇报(1)
这个作业属于哪个课程 | 2020面向对象程序设计张栋班 |
---|---|
这个作业要求在哪里 | 我罗斯方块汇报(1) |
这个作业的目标 | 汇报自己这个阶段的开发进度 讲述自己遇到的问题和尝试解决的方法和最后的结果 制作一篇开发日记 |
作业正文 | https://www.cnblogs.com/Misanthropel/p/12822414.html |
小组成员 | 031902619吴俊玮 031902626许叶源 |
参考资料 | https://blog.csdn.net/liluo_2951121599/article/details/66474233 |
git地址 | https://github.com/xyyuan1/Tetris |
开发进度
目前在四个类中:方块,玩家,游戏,渲染
方块:生成方块,打印方块,清除方块基本完成,还有待测试
渲染:目前选择用控制台渲染,已经初步完成控制台界面的绘制
玩家和游戏类由于比较复杂目前还未进行
开发难题
双人模式开发中,目前对于双人玩家各自的操作需要写各写一个函数来处理,无法做到统一,比如两个玩家的地图map1和map2的操作,极其复杂,一旦放在一个函数中,在光标位置生成方块就会受到影响。
方块的坐标x,y与控制台光标位置相反,在函数中计算光标位置比较难处理,对后续函数影响较大
函数太多又相互关联,放在不同类中的调用难实现,不是很会写
开发日记
在设计我罗斯方块中,首相想到的是对于创造相关的双人界面,在网络上查找相关的图形编程对相关光标函数以及颜色函数进行学习,还有结合相关句柄知识完成了第一个大体框架的构成。
void background_draw(HANDLE hOut) //绘制背景 双人对战
{
SetConsoleTitle("俄罗斯方块双人对战版");//控制台名称
COORD size = { 100, 25 };//控制台屏幕缓冲区大小
SetConsoleScreenBufferSize(hOut, size);
SMALL_RECT rc = { 0, 0, 99, 24 };//矩形左上角,右下角坐标
SetConsoleWindowInfo(hOut, true, &rc);
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };//对光标的隐藏
SetConsoleCursorInfo(hOut, &cursor_info);
}
随后就是对于双人地图界面的制作。俄罗斯方块标准是20×10的界面,制作相关界面即可,不过需要相应计算光标的位置,在相应位置输出。
下面是移动光标的位置的函数,在图形编程中有
void gotoXY(HANDLE hOut, int x, int y)//移动光标到相应位置
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOut, pos);
}
最后是完成渲染类的界面,得分,操作介绍等。
void foreground_draw(HANDLE hOut)
{
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
for (int i = 0; i < 20; ++i)
{
cout << "■ ■○ ○■ ■" << endl;
}
gotoXY(hOut, 26, 0);
cout << "○○○○○○○○○○○";
gotoXY(hOut, 0, 20);
cout << "■■■■■■■■■■■■○○○○○○○○○○○○○■■■■■■■■■■■■";
gotoXY(hOut, 26, 2);
cout << "P1:";
gotoXY(hOut, 36, 2);
cout << "P2:";
gotoXY(hOut, 26, 4);
cout << "下一方块:";
gotoXY(hOut, 26, 10);
cout << "操作方法:";
gotoXY(hOut, 29, 11);
cout << "W :旋转 ↑:旋转";
gotoXY(hOut, 29, 12);
cout << "D :右移 →:右移";
gotoXY(hOut, 29, 13);
cout << "A :左移 ←:左移";
gotoXY(hOut, 29, 14);
cout << "S :速降 ↓:速降";
gotoXY(hOut, 29, 15);
cout << "空格键:开始/暂停";
gotoXY(hOut, 29, 16);
cout << "Esc 键:退出";
gotoXY(hOut, 26, 18);
cout << "作者:wjw & xyy";
}
然后从基本的方块类入手:
方块共有7种,分别以S、Z、L、J、I、O、T这7个字母的形状来命名。
在c++编程中,我们想采用二维数组的方式进行呈现:
7种方块进行上下左右的翻转,扣除重复的情况,可以用19种不同的数组来表示。
在每个二维数组的 [0][0] 位置用不同的数字作为区分颜色的标记。
int block0[4][4] = { { 10,0,0,0 },{ 1,1,1,1 },{ 0,0,0,0 },{ 0,0,0,0 } };
int block1[4][4] = { { 11,0,1,0 },{ 0,0,1,0 },{ 0,0,1,0 },{ 0,0,1,0 } };
int block2[4][4] = { { 12,0,0,0 },{ 0,0,0,0 },{ 1,1,1,0 },{ 0,1,0,0 } };
int block3[4][4] = { { 13,0,0,0 },{ 0,1,0,0 },{ 1,1,0,0 },{ 0,1,0,0 } };
int block4[4][4] = { { 24,0,0,0 },{ 0,0,0,0 },{ 0,1,0,0 },{ 1,1,1,0 } };
int block5[4][4] = { { 25,0,0,0 },{ 0,1,0,0 },{ 0,1,1,0 },{ 0,1,0,0 } };
int block6[4][4] = { { 26,0,0,0 },{ 0,0,0,0 },{ 1,1,1,0 },{ 1,0,0,0 } };
int block7[4][4] = { { 27,0,0,0 },{ 1,1,0,0 },{ 0,1,0,0 },{ 0,1,0,0 } };
int block8[4][4] = { { 30,0,0,0 },{ 0,0,0,0 },{ 0,0,1,0 },{ 1,1,1,0 } };
int block9[4][4] = { { 31,0,0,0 },{ 0,1,0,0 },{ 0,1,0,0 },{ 0,1,1,0 } };
int block10[4][4] = { { 32,0,0,0 },{ 0,0,0,0 },{ 1,1,1,0 },{ 0,0,1,0 } };
int block11[4][4] = { { 33,0,0,0 },{ 0,1,0,0 },{ 0,1,0,0 },{ 1,1,0,0 } };
int block12[4][4] = { { 44,0,0,0 },{ 0,0,0,0 },{ 1,0,0,0 },{ 1,1,1,0 } };
int block13[4][4] = { { 45,0,0,0 },{ 0,1,1,0 },{ 0,1,0,0 },{ 0,1,0,0 } };
int block14[4][4] = { { 46,0,0,0 },{ 0,0,0,0 },{ 0,1,1,0 },{ 1,1,0,0 } };
int block15[4][4] = { { 47,0,0,0 },{ 1,0,0,0 },{ 1,1,0,0 },{ 0,1,0,0 } };
int block16[4][4] = { { 50,0,0,0 },{ 0,0,0,0 },{ 1,1,0,0 },{ 0,1,1,0 } };
int block17[4][4] = { { 51,0,0,0 },{ 0,0,1,0 },{ 0,1,1,0 },{ 0,1,0,0 } };
int block18[4][4] = { { 52,0,0,0 },{ 0,0,0,0 },{ 1,1,0,0 },{ 1,1,0,0 } };
我们将它们加入了方块类中。
接着就是对与方块的操作,我们先从几个简单的入手:
随机生成方块 void block_create();
用生成随机数的方法来决定生成方块的种类,并将 “下一个方块”的图形进行更新替换。
void block_create(HANDLE hOut, int block[4][4]) //随机生成方块
{
clearBlock(hOut, block, 5, 15);
switch (rand() % 19)
{
case 0:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block0[i][j];
}
}
break;
case 1:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block1[i][j];
}
}
break;
case 2:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block2[i][j];
}
}
break;
case 3:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block3[i][j];
}
}
break;
case 4:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block4[i][j];
}
}
break;
case 5:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block5[i][j];
}
}
break;
case 6:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block6[i][j];
}
}
break;
case 7:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block7[i][j];
}
}
break;
case 8:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block8[i][j];
}
}
break;
case 9:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block9[i][j];
}
}
break;
case 10:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block10[i][j];
}
}
break;
case 11:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block11[i][j];
}
}
break;
case 12:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block12[i][j];
}
}
break;
case 13:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block13[i][j];
}
}
break;
case 14:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block14[i][j];
}
}
break;
case 15:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block15[i][j];
}
}
break;
case 16:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block16[i][j];
}
}
break;
case 17:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block17[i][j];
}
}
break;
case 18:
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
block[i][j] = block18[i][j];
}
}
break;
default:
break;
}
printBlock(hOut, block, 5, 15);
}
消除方块 :
在这里我们考虑到 p1、p2玩家在两个map进行操作
所以对方块的清除要分成两个函数
void block_print1(HANDLE hOut, int block[4][4], int x, int y)//打印p1玩家方块
{
switch (block[0][0]%10)
{
case 0:
SetConsoleTextAttribute(hOut, FOREGROUND_GREEN);
break;
case 1:
SetConsoleTextAttribute(hOut, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
break;
case 2:
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
break;
case 3:
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
break;
case 4:
case 7:
SetConsoleTextAttribute(hOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
break;
case 5:
SetConsoleTextAttribute(hOut, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
break;
case 6:
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
break;
default:
break;
}
for (int i = 0; i < 4; ++i)
{
if (i + x >= 0)
{
for (int j = 0; j < 4; ++j)
{
if (block[i][j] == 1)
{
gotoXY(hOut, 2 * (y + j), x + i);
cout << "■";
}
}
}
}
}
void block_print2();
玩家2方块的打印同理 只需要改变玩家1打印位置的横坐标即可。
清除方块
在打印方块的位置对方块进行覆盖,就达到了清除方块的目的。
void block_delete(HANDLE hOut, int block[4][4], int x, int y)
{
for (int i = 0; i < 4; ++i)
{
if (i + x >= 0)
{
for (int j = 0; j < 4; ++j)
{
if (block[i][j] == 1)
{
gotoXY(hOut, 2 * (y + j), x + i);
cout << " ";
}
}
}
}
}
来源:oschina
链接:https://my.oschina.net/u/4352597/blog/4287966