我罗斯方块阶段报告(1)

作业描述 详情
这个作业属于哪个课程 2020面向对象程序设计
这个作业要求在哪里 我罗斯方块汇报1
这个作业的目标 -汇报自己这个阶段的开发进度。(完成了哪几个模块)
-讲述自己遇到的问题和尝试解决的方法和最后的结果(解决与否)
-制作一篇开发日记,例子如此,描述自己开发某一个模块的过程
作业正文 我罗斯方块阶段报告(1)
其他参考文献
小组成员 031903146 罗佳昱
031903144 李雨情
111900811 林杞垒

开发进度

本组设计涉及到四个类:方块类(Mino)、玩家类(Player)、渲染类(Tetris)、游戏类(Game)

方块类(Mino): 目前已经完成方块的显示、擦除、方块的旋转以及随机生成,方块的下落和垃圾行的生成还未完成

玩家类(Player): 两个玩家键盘响应已完成

渲染类(Tetris): 完成首界面、欢迎界面以及游戏界面,光标移动控制,增加了对方块的颜色设置

游戏类(Game): 考虑到双人对战(只要有玩家方块触顶,对方就获胜),打算不设置游戏计分。(如果双方玩家都比较厉害,后期可以考虑阶段下落速度提升)


开发难题

一、线程问题,游戏中若采用单线程,在双方玩家的信息传递,时间控制上容易出现问题。而采用双线程,难点在于两个线程彼此需同步调配。两个玩家均同从键盘按键中获取键值进行相应操作,要避免二者相互冲突,还需引进临界区变量。

二、目前还处于分工阶段,未进行整合,在一些参数设置上可能会有些不同,一些函数调用,友元函数使用也会出现问题。

三、游戏中,基于单人俄罗斯方块,存在游戏区方块位置异常的情况(在几次调试中,偶尔会出现方块左右偏移的情况,出现bug的原因还没找到)


开发日记

罗佳昱

2020.05.08

在小组内进行讨论各个模块的实现方法

2020.05.11

进行了组内分工
我负责的是方块的下落,旋转,随机生成,边界判断,玩家键盘读入

2020.05.12

看起来玩家的键盘读入好像会比较简单的样子呢!那就先完成它吧
w,s,d,a键的读入没啥问题,,,,键才是让我比较懵的,后来查询了资料,知道了,,,有两个键值。
实际上完成起来还算是挺容易的哈哈哈,不过还是需要配合其他模块的很多函数才能实现真正的可行
void Mino1::readKey()

2020.05.14

开始折腾方块类
刚开始动手就遇到了一个头疼的问题,要怎么生成随机方块
查了好一些资料之后总算是发现了srand(), rand(), time()函数,再结合之前已经想好的各种方块的形状记录,开始动工!

参考如下

void Mino1::Random()
{
	srand((int)time(0));

	id1 = rand() % 15;
	next_id1 = rand() % 15;
	Draw(point[0], point[1], id1); 
	Draw(6, 15, next_id1);
}

2020.05.17

完成了随机生成方块部分的代码,开始做方块旋转。
在之前的讨论中分析了旋转部分依然是与各种方块的形状记录有关,给每个形状一个编号,旋转时将编号改变即可切换图形。
所以这一块做的比较快

参考如下

void Mino1::TurnFirst(int num)//旋转函数 
{
	switch(num)
	{
	case a1: id1 = a2; break;					//条形互换
	case a2: id1 = a1; break;

	case b: id1 = b; break;					//方块无法旋转

	case c1: id1 = c2; break;					//各种L形互换
	case c2: id1 = c3; break;
	case c3: id1 = c4; break;
	case c4: id1 = c1; break; 

	case d1: id1 = d2; break;					//各种T形互换
	case d2: id1 = d3; break;
	case d3: id1 = d4; break;
	case d4: id1 = d1; break;

	case e1: id1 = e2; break;					//两种Z形互换
	case e2: id1 = e1; break;	

	case f1: id1 = f2; break;
	case f2: id1 = f1; break;
	}
 } 

2020.05.18

完成了方块旋转部分的代码,开始研究方块下落与边界判断
void Mino1::Down()//下落函数
bool Mino1::JudgeFirst(int x, int y, int num)

2020.05.22

方块下落未完成
已完成边界判断

现在都是分模块做,不敢想到时候整合起来会出什么问题,估计会疯狂报错以及方块乱走吧哈哈哈哈。


李雨情

2020.05.13

我负责方块类的显示擦除,以及消行增行。
基于已经初始化的方块以及基点,方块显示和擦除都较容易

void Tetris::Draw(int x, int y, int num)//方块显示
{
      int nx, ny;

      for (int i = 0; i < 4; i++)
      {
            nx = x + sharp[num][2 * i];
            ny = y + sharp[num][2 * i + 1];
      	    SetPos((ny + 1) * 2, nx + 1);
	    SetColor(i + 1);
	    cout << "■";
      }
}

void Tetris::ReDraw(int x, int y, int num);//方块擦除,实现方法与显示类似

void ClearLine(int x, int y, int num);//消除行
//其中通过一个循环判定某一行是否满, 用flag来标记

对于方块偏移的bug,查看了其它一些代码写法,问题可能是出现在字段宽度上
参考如下:

void Mino::PlaceOn();//此函数用于初始化最开始4*4数组的方块信息

void Mino::Show(bool info = false)  //将方块在屏幕上输出,info表示是否是信息栏
{
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
        {
            MagicShow(Point(p.x + i, p.y + j), state[i][j], info);
        }
}
void MagicShow(const Point& p, bool flag = false, bool info = false)  //因为输出/擦除类似,可以通过同一个函数实现
                                                                      //因为信息栏里也有方块信息,也需要变换
 
template<typename T>
void PrintAt(const Point& p, T data, int wid = 0) //在点p处输出data
{
    SetCursor(p);
    if (wid)
        cout.width(wid);//控制符int width()将用来调整字段的宽度
    cout << data;
}

然后,垃圾行的生成还没完成
需考虑生成行的空格数、空格位置位置以及什么时候显示,实现过程需要借助srand(), rand()函数

后期可以在消行上增加一些flash_times闪烁效果


林杞垒

2020.05.12

在构思界面设计的时候,觉得原有的颜色过于单一,并且在实际打块过程中不容易识别辨认方块,于是设置了5种颜色

void Tetris::SetColor(int color_num)			//设置颜色
{
	int n;
	switch (color_num)
	{
	case 0: n = 0x08; break;
	case 1: n = 0x0C; break;
	case 2: n = 0x0D; break;
	case 3: n = 0x0E; break;
	case 4: n = 0x0A; break;
	}
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), n);
}

接下来是欢迎界面设置

void Tetris::Welocme()			//欢迎界面
{
	SetColor(1);
	char x;
	while (1)
	{
		system("cls");
		cout << "■■■■■■■■■■■■■■■■■■■■■" << endl;
		cout << "           我  罗  斯  方  块		" << endl;
		cout << "■■■■■■■■■■■■■■■■■■■■■" << endl;
		cout << "       疫  情  宅  家  无  事  做		" << endl;
		cout << "       来  玩  我  罗  斯  方  块		" << endl;
		cout << "            双  人  运  动		    " << endl;
		cout << "            激  情  对  战		    " << endl;
		cout << "■■■■■■■■■■■■■■■■■■■■■" << endl;
		cout << "	Press any key to continue " << endl;
		SetPos(20, 10);
	}
}

尽可能的设计的足够土

在设计双人对战框架时,自己曾试过12×20,或者15×25的playfield,但在测试下,既不美观对称,也不够合理。后来去搜索了Tetris OnlineTetris 99等在线对战俄罗斯方块的详细规则,参考了其中对于playfield的搭建,选用了Tetris Online的10×20(宽*高)的规格。


效果图预览

void Tetris::DrawMap()   //画游戏时界面
void Tetris::SetColor(int color_num)			//设置颜色
void Tetris::Welocme()			//欢迎界面
void SetPos(int i, int j)			//控制光标位置, 列, 行

渲染类中的四个函数已完成

GitHub地址:我罗斯方块阶段报告(1)

原文地址:https://www.cnblogs.com/2002ljy/p/12937403.html