俄罗斯方块代码存储

Tool.h

class Tool
{
protected:
	int_data[4][4];     //4*4的方块组数量
	int_type;           //俄罗斯方块的类型变量
private:
	void Make_1();
	void Make_2();
	void Make_3();
	void Make_4();
	void Make_5();
public:
	Tool(int type);//构造函数,本类没有使用动态分布,无需析构,类对象可直接复制、赋值
	const int GetTpe() const;                  //获取Tool的类型
	const int & ElementAt (int i,int j) const; //获取小方块的赋值
	Tool Roll();                               //对小方块进行形态变换
};

Tool.cpp

#include "Tool.h"
Tool::Tool(void)
{
	_type=type;
	for (int i=0;i<4;i++)
		for (int j=0;j<4;j++)
			_data[i][j]=0;
	switch (_type){
	case 1:Make_1();break;
	case 2:Make_2();break;
	case 3:Make_3();break;
	case 4:Make_4();break;
	case 5:Make_5();break;
	}
}

void Tool::Make_1()
{
	_data[1][0]=_data[1][1]=_data[1][2]=_data[1][3]=1;
}

void Tool::Make_2()
{
	_data[1][1]=_data[1][2]=_data[2][1]=_data[2][2]=2;
}

void Tool::Make_3()
{
	_data[1][1]=_data[1][2]=_data[2][1]=_data[3][1]=3;
}

void Tool::Make_4()
{
	_data[1][0]=_data[1][1]=_data[2][1]=_data[3][1]=4;
}

void Tool::Make_5()
{
	_data[1][0]=_data[1][1]=_data[2][1]=_data[2][2]=5;
}

const int & Tool::ElementAt(int i,int j)const{//获取小方块的元素数值
	return_data[i][j];
}
const int Toll::GetType()const{
	return_type;
}
//返回顺时针旋转90度后的俄罗斯方块
Tool Tool::Roll(){
	Tool toolRotated (*this);//复制一个俄罗斯方块
	for (int i=0;i<4;i++)
		for (int j=0;j<4;j++)
			toolRotated._data[i][j]=_data[3-j][i];
	return toolRotated;
}

Game.h

#pragma once

#include "Tool.h"
enum GAME_STATE {
	PAUSE,//暂停
	GO,  //工作
	STOP //停止
};

class Game
{
	friend class CMyBoxDlg;
private:
	GAME_STATE _state;			//游戏状态
	int *_bigNet;				//游戏主界面表示数组
	int *_bigNetAux;			//游戏主界面表示辅助数组
	int  _netWidth, _netHeight;	//主游戏界面的宽度、高度
	Tool _tool;					//当前游戏主界面正在下落的方块
	Tool _nextTool;				//下一个即将出现出现的下落方块
	int _iLocX, _iLocY;			//方块坐标,俄罗斯方块左上角位置

public:
	Game(int height, int width);
	~Game();
	void Start();					//开始游戏
	void Input(UINT nChar);			//键盘输入接收处理函数
	bool Go();						//运行一步
	void PauseOrContinue();			//暂停/继续键的控制函数

private:
	void NextTool();				//生成下一个方块
	bool CanMoveDown();				//方块是否可以向下移动
    //计算参数中的一维数组中不为0的元素数
	int  CountNoneZero(int * matrix, int Height, int Width);
	//将俄罗斯方块标记加入到指定主界面数组中
	void AddToolToAux(int *net, int iOffsetX, int iOffsetY, 
		const Tool &_tool);	
	void MoveDown();		//方块向下移动一格
	bool CanMoveLeft();		//方块是否可以向左移动
	bool CanMoveRight();	//方块是否可以向右移动
	void MoveLeft();		//方块向左移动一格
	void MoveRight();		//方块向右移动一格
	bool CanRoll();			//方块是否可以变换形态
	void Roll();			//变换方块形态
	void RemoveLines();		//移除行操作
	bool CanRemoveLine(int index);//是否可以移除一行
	void RemoveLine(int index);	//移除一行
	bool IsDead();				//游戏是否结束

};

Game.cpp

#include "stdafx.h"
#include "Game.h"

//Game类的构造函数
Game::Game(int height, int width) : _tool(0), _nextTool(0)
{
	_netWidth = width;     //20
	_netHeight = height;   //9
	_bigNet = _bigNetAux = NULL;
	_state = STOP;

	// 分配游戏界面表示数组
	_bigNet = new int[_netHeight*_netWidth];   
	// 分配游戏界面表示辅助数组
	_bigNetAux = new int[_netHeight*_netWidth];	
	// 初始化游戏界面表示数组为0
	for (int i = 0; i < _netHeight; i++)	
		for (int j = 0; j < _netWidth; j++)
			_bigNet[i*_netWidth + j] = 0;
	// 随机数播种,产生俄罗斯方块形状随机数使用
	srand((unsigned int)time(0));				
}

//析构函数
Game::~Game(void)
{
	delete[] _bigNet;
	delete[] _bigNetAux;
}

//生成下一个方块,更换新的积木
void Game::NextTool()
{   
	//设置4*4方块所在的左上角坐标
	_IlocY=0;
	_iLocX = (_netWidth - 4) / 2;
	_tool = _nextTool;
	//更新下一个俄罗斯方块
	_nextTool = Tool(rand() % 5 + 1);
}

//开始游戏
void Game::Start()
{
	//初始化游戏主界面内的下落方块
	_tool=Tool(0);
	//初始化下一个方块
	_nextTool=Tool(0);
	// 初始化游戏状态为运行状态
	_state = GO;			
	// 初始化游戏界面表示数组为0
	for (int i = 0; i < _netHeight; i++)	
		for (int j = 0; j < _netWidth; j++)
			_bigNet[i*_netWidth + j] = 0;
	//	连续调用两次方块的产生
	NextTool();								
	NextTool();
}

//暂停/继续键的控制函数
void Game::HaltOrContinue()
{
	if (_state == HALT)
		_state = GO;
	else if (_state == GO)
		_state = HALT;
}

//键盘输入接收处理函数
void Game::Input(UINT nChar)
{
	switch (nChar) {
	case VK_UP: if (CanRoll())     Roll(); break;
	case VK_DOWN: if (CanMoveDown()) MoveDown(); break;
	case VK_LEFT: if (CanMoveLeft()) MoveLeft(); break;
	case VK_RIGHT: if (CanMoveRight()) MoveRight(); break;
	}
}

//方块是否可以向下移动
bool Game::CanMoveDown()
{
	int cnt1 = 4, cnt2 = 0;
	cnt1 += CountNoneZero(_bigNet, _netHeight, _netWidth);
	// 假设发生变换
	AddToolToAux(_bigNetAux, _iLocX, _iLocY + 1, _tool); 
	// 统计变换后方块数
	cnt2 = CountNoneZero(_bigNetAux, _netHeight, _netWidth);
	return cnt2 == cnt1;
}

//将俄罗斯方块标记加入到指定主界面数组中
void Game::AddToolToAux(int *net, int iOffsetX, int iOffsetY , const Tool &_tool)
{
	//必要时先复制主界面数组至指定数组
	if (net != _bigNet)   
		for (int i = 0; i < _netHeight; i++)
			for (int j = 0; j < _netWidth; j++)
				net[i*_netWidth+j]=_bigNet[i*_netWidth+j];
	int iType = _tool.GetType();
	if (iType != 0) {
		//合并俄罗斯方块数据
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < 4; j++) {
				if (i + iOffsetY >= 0 &&
					i + iOffsetY < _netHeight  &&
					j + iOffsetX >= 0 &&
					j + iOffsetX < _netWidth   &&
					_tool.ElementAt(i, j) != 0)
				net[(i+iOffsetY)*_netWidth+j+iOffsetX]=iType;
			}
	}
}

//计算数组中不为0的元素数
int Game::CountNoneZero(int *matrix, int Height, int Width)
{
	int cnt = 0;
	for (int i = 0; i < Height; i++)
		for (int j = 0; j < Width; j++) {
			if (matrix[i*Width + j] != 0)
				++cnt;
		}
	return cnt;
}

//方块向下移动一格
void Game::MoveDown()
{
	++_iLocY;
}

//方块是否可以向左移动
bool Game::CanMoveLeft()
{
	int cnt1 = 4, cnt2 = 0;
	cnt1 += CountNoneZero(_bigNet, _netHeight, _netWidth);
	// 假设发生变换
	AddToolToAux(_bigNetAux, _iLocX - 1, _iLocY, _tool); 
	// 统计变换后方块数
	cnt2 = CountNoneZero(_bigNetAux, _netHeight, _netWidth);
	return cnt2 == cnt1;
}

//方块是否可以向右移动
bool Game::CanMoveRight()
{
	int cnt1 = 4, cnt2 = 0;
	cnt1 += CountNoneZero(_bigNet, _netHeight, _netWidth);
	// 假设发生变换
	AddToolToAux(_bigNetAux, _iLocX + 1, _iLocY, _tool); 
	// 统计变换后方块数
	cnt2 = CountNoneZero(_bigNetAux, _netHeight, _netWidth);
	return cnt2 == cnt1;
}

//方块向左移动一格
void Game::MoveLeft()
{
	--_iLocX;
}

//方块向右移动一格
void Game::MoveRight()
{
	++_iLocX;
}

//方块是否可以变换形态
bool Game::CanRoll()
{
	int cnt1 = 4, cnt2 = 0;
	cnt1 += CountNoneZero(_bigNet, _netHeight, _netWidth);
	// 假设发生变换
	Tool  toolRotated = _tool.Roll();
	AddToolToAux(_bigNetAux, _iLocX, _iLocY, toolRotated); 
	// 统计变换后方块数
	cnt2 = CountNoneZero(_bigNetAux, _netHeight, _netWidth);
	return cnt2 == cnt1;
}

//变换方块形态
void Game::Roll() 
{
	//用旋转后俄罗斯方块代替
	_tool = _tool.Roll(); 
}


//运行一步
bool Game::Go()
{
	if (CanMoveDown()) {	//判断是否可以向下移动一格
		MoveDown();			//向下移动一格
		return true;
	}
	else {
		//将方块加到游戏主界面数组中
		AddToolToAux(_bigNet, _iLocX, _iLocY, _tool); 
		RemoveLines();		//移除满行
		NextTool();			//向界面中加入下一个方块
		if (IsDead()) {
			_state = STOP;	//设置游戏状态为停止
			return false;
		}
		return true;
	}
}

//移除行操作
void Game::RemoveLines()
{
	for (int i = _netHeight - 1; i >= 0; i--)
		while (CanRemoveLine(i)) 
			RemoveLine(i);  //可消除本行时,消除本行
}

//是否可以移除一行
bool Game::CanRemoveLine(int index)
{
	int count = 0;
	for (int i = 0; i < _netWidth; i++)
		if (_bigNet[index*_netWidth + i] != 0)
			count++;
	//小方块数量等于主界面宽度时本行可消除
	return count == _netWidth; 
}

//移除一行
void Game::RemoveLine(int index)
{
	for (int i = index; i > 0; i--) //前面所有行下移一行
		for (int j = 0; j < _netWidth; j++)
			_bigNet[i*_netWidth+j]=_bigNet[(i-1)*_netWidth+j];
	for (int j = 0; j < _netWidth; j++) 
		_bigNet[j] = 0; //第1行清0
}

//游戏是否结束
bool Game::IsDead()
{
	int cnt1 = 4, cnt2 = 0;
	cnt1 += CountNoneZero(_bigNet, _netHeight, _netWidth);
	// 假设发生变换
	AddToolToAux(_bigNetAux, _iLocX, _iLocY, _tool); 
	// 统计加入俄罗斯方块后小方块数
	cnt2 = CountNoneZero(_bigNetAux, _netHeight, _netWidth);
	//不等就是有重叠的情况发生,代表Dead
	return cnt2 != cnt1; 	
}

//获取游戏状态值
GAME_STATE Game::GetState(){
	return state;
}

在MyBoxDlg头文件中加入

private;
	Game game;
	void DrawNet();
	void DrawBigNet();
	void DrawSmallNet();
	void OnKeyDown(UINT nChar);

以及

#include"Game.h"

MyBoxDlg.cpp文件的实现

构造长宽高

修改其中MyBoxDlg的构造函数为

CMyBoxDlg::CMyBoxDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CMyBoxDlg::IDD, pParent),_game(20,9)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

开始按钮

点击MyBoxDlg,右键选择其中的类向导,选择

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值