我罗斯方块汇报(1)

作业描述 详情
这个作业属于哪个课程 班级链接
这个作业要求在哪里 作业要求
这个作业的目标 讲述你的设计,你选用的渲染方法,你收集到的资料,和你的游戏界面示意图,和。注意:请详细写出你需要的类,和类的成员函数与成员变量。
作业正文 我罗斯方块汇报(1)
其他参考文献
项目地址 项目GitHub地址
小组成员 031902517-田剑心
031902637-廖晓玲
061900414-廖智炫

设计方案



开发进度

对于本组框架中的涉及到的四个类:方块类(Brick)、玩家类(Player)、渲染类(Render)、游戏类(Game)

目前,的开发进度中:
方块类(Brick)已经完成并通过了一定数量的测试;
玩家类(Player)已经完成,但尚未测试;
渲染类(Render)由于涉及到较多的内容,尚在学习中,还未开始;
游戏类(Game)由于设计的过程较多,暂定于方块类、玩家类均通过初步测试后再进行编写



开发难题

对于目前本组开发中遇到的难题列举如下:

一、对于设计方案中太过概括的描述,不利于实现(已解决)

因此本组在 2020.5.17 开会,详细商讨了部分类的具体属性与方法:

由于在设计方案中,游戏中的地图储存在玩家类中,因此,方块类不适合用于判定是否判定边界

为此,细化方块类的职责———只负责移动与变化

而对于是否会碰撞,是否触碰到底边导致加入地图,是否触碰到天花板导致游戏结束,是否加入地图后需要删除一行

以上此类的所有操作,交由玩家类实现

二、如何实现游戏类的调度问题(未解决)

由于比赛涉及到双人对战环节,且俄罗斯方块有每隔一段时间会下落一格的特性

因此,如何在实现双人对战的消息转递的同时,还要同时考虑时间的处理

目前,本组可能会考虑使用双线程来处理,即一个线程进行对战过程中的消息传递,另一个线程进行时间的记录。当运行时间达到方块下落的单位时间时,将消息传递到对战

但考虑到双线程这一块目前知识点为 0 ,如果在后续设计过程中有想到其他处理方法可能会取消该想法

三、友元函数在不同文件下的写法(尚未解决)

根据上课所学,如果类 A 中的一个成员函数作为类 B 的友元函数,必须先定义类 A

本游戏实现游戏类时,很可能需要其中渲染的函数需要作为玩家类的友元函数

但游戏类的申明和定义分别在 Game.hGame.cpp 中,玩家类在 Player.hPlayer.cpp

而按照所学,需要先定义游戏类,才能定义玩家类中的友元函数;但游戏类中又存在对玩家类方法的调用

且两个类的申明、定义分别放在不同的文件内,贸然在前面加上申明可能会产生不知名的错误

这一块的代码具体怎么写,还需要写游戏类的时候进行研究



开发日记

田剑心

2020.5.18

实现了上、下、左、右移动的方法。。。

void brickSet(int x, int y);

实现了brickSet()方法,通过中心块(x,y)来推导其他三块的坐标。。

直接暴力枚举,也就13种方块(其实有19种,太懒了就摸了

2020.5.19

实现了方块类的旋转方法roteBrick(),

一开始感觉挺复杂,后面突然意识到旋转其实等价于变换形状

所以在中心块确认的条件下,可以直接通过改变参数BrickType,然后调用brickSet()方法重新对其他坐标进行推导,代码就简化成了13个选择语句。。

后续和同学讨论下指令的类型及参数的涵义把identifyOrder()方法解决,Brick类就基本实现了。。。。

2020.5.20

实现了最后的一个方法指令分发,同时优化了Brick的架构,进一步提高了封装性

class Brick {
private:
	int BrickColor;//方块颜色
	int BrickType;//方块类型
	int BrickPos[9];//坐标集合
	int CenterX, CenterY;//中心点坐标
	void shiftLeft(int pace = 1);//左移
	void shiftRight(int pace = 1);//右移
	void shiftDown(int pace = 1);//下移
	void shiftUp(int pace = 1);//上移
	void brickUpdate();//更新颜色和类型
	void rotateBrick();//顺时针旋转
	static const int TotalBrickType = 17, TotalColorType = 4;
public:
	static const int Up = 1, Down = 2,Left = 3, Right = 4, Rotate = 5, Update = 6;
	Brick();//初始化类型和颜色
	void brickSet(int x, int y);//通过x,y初始化坐标
	void Operation(int _Order);//识别指令
	int* getInformation();//返回信息
};



廖晓玲

2020.5.18

我先设计了一个首界面。

void Tetris::Welocme()	//游戏刚进去的界面	
{
	SetColor(3);//设置颜色 (这是后面加进去的)
	char x;
	while(1)
	{
		system("cls");
		cout <<"		俄罗斯方块		" << endl;
		cout << "操作方式:" << endl;
		cout <<"单人				双人"<<endl; 
		cout << "↑ - 旋转			w - 旋转" << endl;
		cout << "↓ - 加速下移			s - 加速下移"  << endl;
		cout << "← - 左移			a - 左移" << endl;
		cout << "→ - 右移			d - 右移" << endl;
		cout <<"按1选择单人模式-按2选择双人模式" << endl;
		SetPos(20, 10);//控制光标位置, 列, 行
		x = getchar();
		if(x <= '9' && x >= '0')
		{
			type = x - '0';//模式 
			break;
		}
	}
}

2020.5.19

我上百度搜索了渲染(包括字体颜色的改变)
渲染也包括界面的设计。
然后我设置了9种的颜色改字体的颜色。,主要是用上system("")来实现颜色的改变。

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;
		case 5: n = 0x0F; break;
		case 6: n = 0x09; break;
		case 7: n = 0x0B; break;
		case 8: n = 0x05; break;
		case 9: n = 0x03; break;
	}
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), n);
}

2020.5.20

我设计了两个游戏界面,且用了两个函数,绘画出一个是单人模式一个是双人模式

这是单人模式

void Tetris::DrawMap1()				//单人画游戏时界面
{
	int i;
	for(i = 0; i <= 15; i++)	
	{
		SetColor(5);
		SetPos(i * 2, 0);
		cout << "■";
		SetPos(i * 2, 27);
		cout << "■";
	}
	
	for(i = 0; i < 27; i++) 
	{
		SetColor(5);
		SetPos(0, i);
		cout << "■";
		SetPos(15*2, i);
		cout << "■";
	}
	
	for(i = 16; i < 30; i++)		
	{
		SetColor(0);
		SetPos(i * 2, 0);
		cout << "☆";
		SetPos(i * 2, 10);
		cout << "☆";
	}
	
	for(i = 0; i <= 10; i++)	
	{
		SetColor(0);
		SetPos(32, i);
		cout << "☆";
		SetPos(60, i);
		cout << "☆";
	}
	
	SetPos(34, 2);
	cout << "分数: " << score; 
	SetPos(34, 5);
	cout << "下一图形:";
 } 

这是双人模式

void Tetris::DrawMap2()				//双人画游戏时界面
{
   int i;
   SetColor(0);
//第一个计分的人 
   for(i = 0; i < 13; i++)		//宽13格计分 
   {
   	SetColor(0);
   	SetPos(i * 2, 0);
   	cout << "☆";
   	SetPos(i * 2, 10);
   	cout << "☆";
   }
   
   for(i = 0; i <= 10; i++)		//高10格计分 
   {
   	SetPos(0, i);
   	cout << "☆";
   	SetPos(13*2, i);
   	cout << "☆";
   }
//第二个人计分的人 
   for(i = 43; i < 57; i++)		//宽13格计分 
   {
   	SetPos(i * 2, 0);
   	cout << "☆";
   	SetPos(i * 2, 10);
   	cout << "☆";
   }
   
   for(i = 0; i <= 10; i++)		//高10格计分 
   {
   	SetPos(43*2, i);
   	cout << "☆";
   	SetPos(57*2, i);
   	cout << "☆";
   }
//第一个人的界面 
   for(i = 14; i < 25; i++)		//宽13格计分 
   {
   	SetColor(5);
   	SetPos(i * 2, 21);
   	cout << "■";
   }
   for(i = 0; i <= 21; i++)		//高21格计分 
   {
   	SetColor(5);
   	SetPos(50, i);
   	cout << "■";
   	SetPos(28, i);
   	cout << "■";
   }
//第二个人的界面 
   for(i = 30; i < 42; i++)		//宽13格计分 
   {
   	SetColor(5);
   	SetPos(i * 2, 21);
   	cout << "■";
   }
   for(i = 0; i <21; i++)		//高21格计分 
   {
   	SetColor(5);
   	SetPos(60, i);
   	cout << "■";
   	SetPos(82, i);
   	cout << "■";
   }

   SetColor(3);
   //Input_score();
   SetPos(2, 2);
   cout << "分数: " << score; 
   SetPos(2, 5);
   cout << "下一图形:";
   SetPos(88, 2);
   cout << "分数: " << score; 
   SetPos(88, 5);
   cout << "下一图形:";

} 

这是用来画地图的光标移动!!

void SetPos(int i, int j)			//控制光标位置, 列, 行
{
  COORD pos={i,j};
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

一开始感觉绘图还有光标移动很难,发现自己动手操作起来就可以实现了,这也是我第一次写开发日记,第一次用markdown,有一点点不熟悉,然后就是我知道我自己的水平可能不怎么样,但是我会努力学习的!!我认为对于界面的设计,对称尤为重要,我反复尝试,终于设计出我认为还算满意的界面了,另外对于色彩的选择,也得达到赏心悦目的标准,整个游戏的渲染代码不多,主要在于设计。



廖智炫

2020.5.17

和 dalao 樱落三千讨论了一下午,在尽量满足框架的情况下,比较清晰地确定了玩家类(Player)的职能,以及玩家类与方块类(Squre)、游戏类(Game)的互动方式

目前初步确定了玩家类的属性和方法。将在第二天确定玩家类属性和方法的具体方案。


2020.5.18

和 dalao 樱落三千讨论,进一步细化了玩家类的属性和方法。确认了玩家类和方块类、游戏类的交互模式,以及玩家类具体实现的想法。确定了玩家类的属性与方法,并写为了文件 Player.h

其中包括以下成员变量与函数:

class Player {
private:
	int CountScore;//用于计分
	bool MapSqure[30][10];//描述地图
	bool GameOver;//判定是否游戏结束
	std::string Name;//设定选手昵称
	Brick NowBrick, NextBrick;//当前方块与下一方块

	bool isOverlap();//判断是否方块会与地图重叠
	bool carryCommand(int Direction);//执行指令,并返回是否执行成功
	bool touchBottom();//判断方块是否与地图(包括已经成为地图的方块)重叠
	bool touchCeiling();//判断方块放置后是否触碰到顶
	void addToMap();//将方块加入到地图中
	int delLine();//删除满的行,并返回删除行的数量

public:
	Player(bool StartGame=0);//初始化
	void setName(const std::string& Name_);//设置姓名
	void run(int Direction,int &CountRemoveLine);//运行指令
	void addLine(int CountLine);//增加行数
};

2020.5.19

实现了 Player.h 的部分方法。包括:判重、执行对方块的变化、判定是否触碰底部、删除目标行等

为了实现方便,添加入新的静态变量:

static int UP_LIM, DOWN_LIM, LEFT_LIM, RIGHT_LIM;

分别表示地图的边界

同时,使用暴力变换->判定重叠的方式来判定变换的合法性


2020.5.2

由于 Brick.h 的部分修改,修改了 Player.cpp 中的部分代码

同时,补充完了 Player.cpp 中的主体部分。目前 Player.cpp 部分仅剩余对游戏类提供的查询接口(可能考虑使用友元函数),以及测试

介于实现方便,对玩家类的描述改良为如下所示

class Player {
private:
	static int UP_LIM, DOWN_LIM, LEFT_LIM, RIGHT_LIM;
	int CountScore;
	bool MapSqure[31][11];
	bool GameOver;
	std::string Name;
	Brick NowBrick, NextBrick;

	bool isOverlap();
	bool carryCommand(int Direction);
	bool touchBottom();
	bool touchCeiling();
	void addToMap();
	int delLine();
	int renewBrick();

public:
	Player(bool StartGame=0);
	void setName(const std::string& Name_);
	int run(int Direction);
	int addLine(int CountLine);
};

2020.5.21

对代码进行了初步的调试,解决了构造函数中数组溢出的问题,并加入了对方块类的初始化

突然觉得我用英文给代码写注释是个错误。按我的英语水平,会不会导致别人根本看不懂我在注释什么鬼

posted @ 2020-05-21 16:12  JustinRochester  阅读(527)  评论(2编辑  收藏  举报