俄罗斯方块(c++,vs2013,亲测可用)

一、参考文章

兔老大的文章

二、源代码

#include<iostream>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
#include<conio.h>
using namespace std;

#define A1 0//A代表长条型,B为方块,C为L型,D为闪电型(实在无法描述那个形状)
#define A2 1

#define B 2

#define C11 3
#define C12 4
#define C13 5
#define C14 6

#define C21 7
#define C22 8
#define C23 9
#define C24 10

#define D11 11
#define D12 12

#define D21 13
#define D22 14

void SetPos(short i, short j)//设定光标位置
{
	COORD pos = { i, j };
	HANDLE Out = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(Out, pos);
}

int sharp[15][8] =
{
	{ 0, 0, 1, 0, 2, 0, 3, 0 }, { 0, 0, 0, 1, 0, 2, 0, 3 },
	{ 0, 0, 1, 0, 0, 1, 1, 1 },
	{ 0, 0, 1, 0, 1, 1, 1, 2 }, { 0, 1, 1, 1, 2, 0, 2, 1 }, { 0, 0, 0, 1, 0, 2, 1, 2 }, { 0, 0, 0, 1, 1, 0, 2, 0 },
	{ 1, 0, 1, 1, 1, 2, 0, 2 }, { 0, 0, 0, 1, 1, 1, 2, 1 }, { 0, 0, 0, 1, 0, 2, 1, 0 }, { 0, 0, 1, 0, 2, 0, 2, 1 },
	{ 0, 0, 0, 1, 1, 1, 1, 2 }, { 0, 1, 1, 0, 1, 1, 2, 0 },
	{ 0, 1, 0, 2, 1, 0, 1, 1 }, { 0, 0, 1, 0, 1, 1, 2, 1 }
};//这个2维数组是用来保存各个形状位置的

int high[15] = { 4, 1, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3 };//这个数组是用来保存各个形状高度的

class Box//俄罗斯方块类
{
private:
	int map[23][12];//画面坐标
	int hotpoint[2];//热点(即当前活动的点,所有图形都是相当此点绘制的)
	int top;//当前最高位置
	int point;//分数
	int level;//等级
	int ID;//当前活动图形的ID号
public:
	Box()//初始化
	{
		int i, j;
		for (i = 0; i<23; i++)
			for (j = 0; j<12; j++)
				map[i][j] = 0;
		hotpoint[0] = 0;
		hotpoint[1] = 5;
		point = 0;
		level = 1;
		top = 99;
		ID = 0;
	}
	void DrawMap();//画界面
	int Judge(int x, int y);//判断当前位置能否绘制图形
	void Welcome();//欢迎界面
	void DrawBox(int x, int y, int num);//绘制图形
	void Redraw(int x, int y, int num);//擦除图形
	void Run();//运行
	void Turn();//转动方块
	void UpdataMap();//更新画面
};

void Box::DrawMap()//画界面
{
	int i;

	for (i = 0; i<14; i++)
	{
		SetPos(i * 2, 0);
		cout << "■";
	}
	for (i = 1; i <= 24; i++)
	{
		SetPos(0, i);
		cout << "■";
		SetPos(13 * 2, i);
		cout << "■";
	}
	for (i = 0; i<14; i++)
	{
		SetPos(i * 2, 24);
		cout << "■";
	}

	i = 15;
	for (i = 15; i <= 25; i++)
	{
		SetPos(i * 2, 0);
		cout << "■";
	}
	for (i = 1; i <= 8; i++)
	{
		SetPos(15 * 2, i);
		cout << "■";
		SetPos(25 * 2, i);
		cout << "■";
	}
	for (i = 15; i <= 25; i++)
	{
		SetPos(i * 2, 9);
		cout << "■";
	}

	SetPos(16 * 2, 16);
	cout << "俄罗斯方块";
	SetPos(16 * 2, 17);
	cout << "分数:" << point;
	SetPos(16 * 2, 18);
	cout << "等级:" << level;
}

void Box::DrawBox(int x, int y, int num)//绘制图形
{
	int i;
	int nx, ny;
	for (i = 0; i<4; i++)
	{
		nx = x + sharp[num][i * 2];
		ny = y + sharp[num][i * 2 + 1];
		SetPos((ny + 1) * 2, nx + 1);//利用sharp数组相对于点x,y绘制形状
		cout << "■";
	}
}

void Box::Redraw(int x, int y, int num)//擦除图形,原理同上
{
	int i;
	int nx, ny;
	for (i = 0; i<4; i++)
	{
		nx = x + sharp[num][i * 2];
		ny = y + sharp[num][i * 2 + 1];
		SetPos((ny + 1) * 2, nx + 1);
		cout << " ";
	}
}

void Box::Turn()//转动图形,单纯的该ID而已
{
	switch (ID)
	{
	case A1: ID = A2; break;
	case A2: ID = A1; break;

	case B: ID = B; break;

	case C11: ID = C12; break;
	case C12: ID = C13; break;
	case C13: ID = C14; break;
	case C14: ID = C11; break;

	case C21: ID = C22; break;
	case C22: ID = C23; break;
	case C23: ID = C24; break;
	case C24: ID = C21; break;

	case D11: ID = D12; break;
	case D12: ID = D11; break;

	case D21: ID = D22; break;
	case D22: ID = D21; break;
	}

}

void Box::Welcome()//欢迎界面
{
	char x;
	while (1)
	{
		system("cls");
		cout << "■■■■■■■■■■■■■■■■■■■" << endl;
		cout << "■    俄罗斯方块控制台版(不闪屏)  ■" << endl;
		cout << "■■■■■■■■■■■■■■■■■■■" << endl;
		cout << "■     A,D左右移动  S向下加速       ■" << endl;
		cout << "■        空格键转动方块            ■" << endl;
		cout << "■■■■■■■■■■■■■■■■■■■" << endl;
		cout << "■                                  ■" << endl;
		cout << "■           测试版                 ■" << endl;
		cout << "■                                  ■" << endl;
		cout << "■        按1-9选择等级!!         ■" << endl;
		cout << "■                                  ■" << endl;
		cout << "■                                  ■" << endl;
		cout << "■■■■■■■■■■■■■■■■■■■" << endl;
		SetPos(8, 10);
		x = getch();
		if (x <= '9'&&x >= '1')//设置等级
		{
			level = x - '0';
			break;
		}
	}
}

void Box::UpdataMap()//更新画面(关键)
{
	int clear;
	int i, j, k;
	int nx, ny;
	int flag;
	for (i = 0; i<4; i++)//更新map数组的信息
	{
		nx = hotpoint[0] + sharp[ID][i * 2];
		ny = hotpoint[1] + sharp[ID][i * 2 + 1];
		map[nx][ny] = 1;
	}
	if (hotpoint[0]<top)//如果热点高于顶点则更新顶点
		top = hotpoint[0];
	clear = 0;//消除的格数
	for (i = hotpoint[0]; i<hotpoint[0] + high[ID]; i++)
	{
		flag = 0;
		for (j = 0; j<12; j++)//检测是否可以消除此行
		{
			if (map[i][j] == 0)
			{
				flag = 1;
				break;
			}
		}
		if (flag == 0)//可以消除
		{
			for (k = i; k >= top; k--)//从当前位置向上所有的点下移一行
			{
				if (k == 0)//最高点特殊处理
					for (j = 0; j<12; j++)
					{
					map[k][j] = 0;
					SetPos((j + 1) * 2, k + 1);
					cout << " ";
					}
				else
				{
					for (j = 0; j<12; j++)
					{
						map[k][j] = map[k - 1][j];
						SetPos((j + 1) * 2, k + 1);
						if (map[k][j] == 0)
							cout << " ";
						else
							cout << "■";
					}
				}

			}
			top++;//消除成功,最高点下移
			clear++;
			point += clear * 100;
		}
	}

	SetPos(16 * 2, 17);
	cout << "分数:" << point;
}

void Box::Run()//运行游戏
{
	int i = 0;
	char x;
	int Count;//计数器
	int tempID;
	int temp;
	srand((int)time(0));
	ID = rand() % 15;//随机生成ID和下一个ID
	tempID = rand() % 15;
	DrawBox(hotpoint[0], hotpoint[1], ID);//绘制图形
	DrawBox(3, 17, tempID);
	Count = 1000 - level * 100;//等级决定计数
	while (1)
	{
		if (i >= Count)//时间到
		{
			i = 0;//计数器清零
			if (Judge(hotpoint[0] + 1, hotpoint[1]))//如果下个位置无效(即到底)
			{
				UpdataMap();//更新画面
				ID = tempID;//生成新ID,用原等待ID替换为当前ID
				hotpoint[0] = 0;//热点更新
				hotpoint[1] = 5;
				Redraw(3, 17, tempID);
				tempID = rand() % 15;
				DrawBox(hotpoint[0], hotpoint[1], ID);
				DrawBox(3, 17, tempID);
				if (Judge(hotpoint[0], hotpoint[1]))//无法绘制开始图形,游戏结束
				{
					system("cls");
					SetPos(25, 15);
					cout << "游戏结束!!!最终得分为:" << point << endl;
					system("pause");
					exit(0);
				}

			}
			else
			{
				Redraw(hotpoint[0], hotpoint[1], ID);//没有到底,方块下移一位
				hotpoint[0]++;//热点下移
				DrawBox(hotpoint[0], hotpoint[1], ID);
			}

		}
		if (kbhit())//读取键盘信息
		{
			x = getch();
			if (x == 'a' || x == 'A')//左移
			{
				if (Judge(hotpoint[0], hotpoint[1] - 1) == 0)
				{
					Redraw(hotpoint[0], hotpoint[1], ID);
					hotpoint[1] -= 1;
					DrawBox(hotpoint[0], hotpoint[1], ID);
				}
			}
			if (x == 'd' || x == 'D')//右移
			{
				if (Judge(hotpoint[0], hotpoint[1] + 1) == 0)
				{
					Redraw(hotpoint[0], hotpoint[1], ID);
					hotpoint[1] += 1;
					DrawBox(hotpoint[0], hotpoint[1], ID);
				}
			}
			if (x == 's' || x == 'S')//向下加速
			{
				if (Judge(hotpoint[0] + 1, hotpoint[1]) == 0)
				{
					Redraw(hotpoint[0], hotpoint[1], ID);
					hotpoint[0] += 1;
					DrawBox(hotpoint[0], hotpoint[1], ID);
				}
			}
			if (x == ' ')//转动方块
			{
				temp = ID;
				Turn();
				if (Judge(hotpoint[0], hotpoint[1]) == 0)
				{
					Redraw(hotpoint[0], hotpoint[1], temp);
					DrawBox(hotpoint[0], hotpoint[1], ID);
				}
				else
					ID = temp;
			}
			while (kbhit())//读掉剩下的键盘信息
				getch();
		}
		Sleep(1);//等待1毫秒
		i++;//计数器加1
	}
}

int Box::Judge(int x, int y)//判断当前是否可以绘制方块
{
	int i;
	int nx, ny;
	for (i = 0; i<4; i++)
	{
		nx = x + sharp[ID][i * 2];
		ny = y + sharp[ID][i * 2 + 1];
		if (nx<0 || nx >= 23 || ny<0 || ny >= 12 || map[nx][ny] == 1)//不能,返回1
			return 1;
	}
	return 0;
}

int main()//主函数
{
	Box game;
	game.Welcome();
	system("cls");
	game.DrawMap();
	game.Run();
	system("pause");
}

三、报错解决

一般在vs2012版本以前是不会出现错误的,在vs2012版本以后会出现如下的错误。

错误 1 error C4996: ‘getch’: The POSIX name for this item is deprecated. Instead, use the ISO C++ conf

解决方法如下:

第一种方法添加预处理

项目->属性->配置属性->C/C+±>预处理器->预处理器定义->编辑中添加

_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE

在这里插入图片描述

第二种方法:

将getch()函数更换为_getch()函数即可

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
系统运行环境: 1.硬件配置 CPU: Pentium III 600以上; 内存:128M以上。 2.软件环境 Windows 98以上操作系统; MS SQL Server 2000; Viual Studio.Net 2003; MS Access 2000及以上。 系统配置环境: 1.运行Viual Studio.Net。 2.依次单击【文件】|【新建】|【空白解决方案】,打开新建项目对话框, 在【项目类型】中选择【Visual Studio解决方案】,填写合适的名称和位置, 单击确定按钮,建立一个空白解决方案。 3.在【解决方案资源管理器】中,右击建立的解决方案,单击【添加】 |【新建项目】,打开添加新项目对话框,在左侧的【项目类型】中选择 【Visual C#项目】,在右侧的【模板】中选择【Windows应用程序】,填写合 适的名称,单击确定按钮,就建立了一个新的项目。 数据库配置环境: 本书中数据库分为两种:SQL Server 和 MS Access。 1.Access数据库操作方便,配置简单,只需要把数据库文件放置到bin 目录下的Debug文件夹下即可。 2.SQL Server数据库配置相对复杂一点,打开SQL Server企业管理器,单 击控制台前面的加号按钮,直到出现数据库,然后在数据库上单击鼠标右键, 从弹出式菜单选择【所有任务】|【附加数据库】,然后单击【...】按钮, 选择本章源代码中的DataBase文件夹下的RentManage.mdf文件,其他采用默认 设置,然后单击【确定】按钮。 3.以Access数据库的连接为例。首先在VS.net的工具箱的【数据】项中选择 OleDbConnection,选择所建立的数据库连接oleDbConnection1,在他的属性中 选择ConnectionString的新建连接,在数据库链接属性对话框的【提供程序】 选择项中选择【Microsoft OLE DB Provider for ODBC Drivers】,然后单击 【下一步】,在【连接】选择项中的【选择或输入服务器名称】下拉框中选择 【MS Access Database】,在【输入要使用的初始目录中】填写你所创建的数 据库所在的目录。最后单击【确定】按钮。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@菜鸟一枚

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值