linux俄罗斯方块程序,linux环境下C++实现俄罗斯方块
本文实例为大家分享了C++实现俄罗斯方块的具体代码,供大家参考,具体内容如下
本程序的运行环境是linux,用到了多线程。创建了一个用来绘图的线程和一个获取按键的线程。程序中有一些需要改善的地方,比如336-338行定义的全局变量以及声明的对象。本来声明的Block和Table对象应该在main函数里面,然后将这两个对象作为参数传递给线程函数getkey。但是好像只能传递一个对象参数给线程函数。希望高手能够对程序进行改进。
ps:由于用到了多线程,而pthread不是linux的默认库,所以编译的时候需要指定线程库。即:g++ -o block -lpthread block.cpp
#include
#include
#include
#include
#include
#include
#define TABLE_SIZE 20
#define BLOCK_SIZE 4
#define SLEEP_TIME 500
using namespace std;
struct grid{int x; int y;}; //坐标
/Block 类//
class Block
{
public:
enum direct{UP, DOWN, LEFT, RIGHT}; //定义方向
grid g[BLOCK_SIZE]; //方块的坐标信息
void def_block(grid g1, grid g2, grid g3, grid g4); //定义方块
void rotate(); //旋转方块
void move(int dir); //移动方块
void set_cen(grid g); //设置方块旋转中心
grid get_cen(); //获取方块旋转中心
void set_type(int t); //设置方块种类
int get_type(); //获取方块种类
void back(); //旋转还原
void creat_block(int x, int y); //随机生成方块
private:
grid center; //方块旋转中心
int type; //方块类型
};
void Block::def_block(grid g1, grid g2, grid g3, grid g4) {
g[0]=g1; g[1]=g2; g[2]=g3; g[3]=g4;
}
void Block::rotate() {
int x, y, i=0;
for(i; i<=3; i++) {
x=g[i].x-center.x; y=g[i].y-center.y;
g[i].x=center.x+y; g[i].y=center.y-x;
}
}
void Block::move(int dir) {
int d=dir, i=0;
switch(d) {
case UP: {
for(i; i<=3; i++) g[i].y++;
center.y++; break;
}
case DOWN: {
for(i; i<=3; i++) g[i].y--;
center.y--; break;
}
case LEFT: {
for(i; i<=3; i++) g[i].x--;
center.x--; break;
}
case RIGHT: {
for(i; i<=3; i++) g[i].x++;
center.x++; break;
}
}
}
void Block::set_cen(grid g) {
center=g;
}
grid Block::get_cen() {
return center;
}
void Block::set_type(int t) {
type=t;
}
int Block::get_type() {
return type;
}
void Block::back() {
int x, y, i=0;
for(i; i<=3; i++) {
x=g[i].x-center.x; y=g[i].y-center.y;
g[i].x=center.x-y; g[i].y=center.y+x;
}
}
void Block::creat_block(int x, int y) { //随机创建方块
int ran;
grid g[BLOCK_SIZE];
ran=1+rand()%7;
switch(ran) {
//L
case 1: {
g[0].x=x/2; g[0].y=y-3;
g[1].x=g[0].x; g[1].y=g[0].y+1;
g[2].x=g[0].x; g[2].y=g[0].y+2;
g[3].x=g[0].x+1; g[3].y=g[0].y;
set_cen(g[0]); set_type(1); break;
}
//反L
case 2: {
g[0].x=x/2; g[0].y=y-3;
g[1].x=g[0].x; g[1].y=g[0].y+1;
g[2].x=g[0].x; g[2].y=g[0].y+2;
g[3].x=g[0].x-1; g[3].y=g[0].y;
set_cen(g[0]); set_type(2); break;
}
//Z
case 3: {
g[0].x=x/2; g[0].y=y-2;
g[1].x=g[0].x; g[1].y=g[0].y+1;
g[2].x=g[0].x+1; g[2].y=g[0].y+1;
g[3].x=g[0].x-1; g[3].y=g[0].y;
set_cen(g[0]); set_type(3); break;
}
//反Z
case 4: {
g[0].x=x/2; g[0].y=y-2;
g[1].x=g[0].x; g[1].y=g[0].y+1;
g[2].x=g[0].x+1; g[2].y=g[0].y+1;
g[3].x=g[0].x-1; g[3].y=g[0].y;
set_cen(g[0]); set_type(4); break;
}
//田
case 5: {
g[0].x=x/2; g[0].y=y-2;
g[1].x=g[0].x; g[1].y=g[0].y+1;
g[2].x=g[0].x+1; g[2].y=g[0].y+1;
g[3].x=g[0].x+1; g[3].y=g[0].y;
set_cen(g[0]); set_type(5); break;
}
//1
case 6: {
g[0].x=x/2; g[0].y=y-3;
g[1].x=g[0].x; g[1].y=g[0].y+1;
g[2].x=g[0].x; g[2].y=g[0].y+2;
g[3].x=g[0].x; g[3].y=g[0].y-1;
set_cen(g[0]); set_type(6); break;
}
//山
case 7: {
g[0].x=x/2; g[0].y=y-2;
g[1].x=g[0].x; g[1].y=g[0].y+1;
g[2].x=g[0].x-1; g[2].y=g[0].y;
g[3].x=g[0].x+1; g[3].y=g[0].y;
set_cen(g[0]); set_type(7); break;
}
default: ;
}
def_block(g[0], g[1], g[2], g[3]);
}
/
Table 类//
class Table
{
public:
Table() { //构造棋盘
height=20; width=10; count=0;
init_table();
}
Table(int x, int y);
int set_block(Block bl); //安设方块
void clr_block(Block bl); //清除方块
int clr_line(int y); //消行
int get_h(); //获取棋盘高度
int get_w(); //获取棋盘宽度
int if_full(int y); //判定是否满行
int get_table(int x, int y); //获取棋盘上点信息
void paint(); //绘制棋盘
void move_line(int y); //整行下移
void set_count(int c); //记录得分
int get_count(); //获取得分
private:
int table[TABLE_SIZE][TABLE_SIZE];//棋盘
int height, width; //棋盘的高和宽
int count; //得分
void init_table(); //棋盘初始化
};
void Table::init_table() {
int i=0, j=0;
for(i; i
for(j=0; j
table[i][j]=0;
}
}
}
Table::Table(int x, int y) {
height=y; width=x; count=0;
init_table();
}
int Table::set_block(Block bl) {
int x, y;
int i;
for(i=0; i<=3; i++) {
x=bl.g[i].x; y=bl.g[i].y;
if(table[x][y]!=0 || x>=width || x<0 || y>=height || y<0) {
return 0;
}
}
for(i=0; i<=3; i++) {
x=bl.g[i].x; y=bl.g[i].y;
table[x][y]=1;
}
return 1;
}
void Table::clr_block(Block bl) {
int x, y;
for(int i=0; i<=3; i++) {
x=bl.g[i].x; y=bl.g[i].y;
table[x][y]=0;
}
}
int Table::clr_line(int y) {
if(y<0 || y>=height) return 0;
for(int i=0; i
table[i][y]=0;
}
return 1;
}
int Table::get_h() {
return height;
}
int Table::get_w() {
return width;
}
int Table::if_full(int y) {
int i=0;
for(i; i
if(table[i][y]==0) return 0;
}
return 1;
}
int Table::get_table(int x, int y) {
return table[x][y];
}
void Table::paint() {
int i, j;
for(i=0; i
cout<
for(i=height-1; i>=0; i--) {
cout<
for(j=0; j
if(table[j][i]==0) cout<
else cout<
}
if(i==10)
cout<
else if(i==7)
cout<
else
cout<
}
for(i=0; i
cout<
//cout<
}
void Table::move_line(int y) {
int i, j;
for(i=y; i
for(j=0; j
table[j][i]=table[j][i+1];
}
}
}
void Table::set_count(int c) {
count+=c;
}
int Table::get_count() {
return count;
}
///
class Mythread
{
public:
void init();
static void *getkey(void *arg);//线程函数在类里面定义必须定义为static型,以去除类指针。
static void *paint_loop(void *arg);
};
void Mythread::init()
{
pthread_t ntid,ntid2;
int err,err2;
err = pthread_create(&ntid,NULL,getkey,NULL);
err2 = pthread_create(&ntid2,NULL,paint_loop,NULL);
if(err != 0 || err2 != 0){
cout<
exit(0);
}
}
unsigned char flag=1,buf[2];//全局变量
Table tab(15, 20); //构造一个15,20的棋盘
Block bl; //构造一个落下方块
void* Mythread::paint_loop(void *arg)
{
while(1)
{
system("clear");
tab.paint();
usleep(50000); //暂停50 MS
}
}
void* Mythread::getkey(void *arg)
{
struct termios saveterm,nt;
fd_set rfds,rs;
struct timeval tv;
int i=0,q,r,fd=0;
tcgetattr(fd,&saveterm);
nt=saveterm;
nt.c_lflag &= ~ECHO;
nt.c_lflag &= ~ISIG;
nt.c_lflag &= ~ICANON;
tcsetattr(fd,TCSANOW,&nt);
FD_ZERO(&rs);
FD_SET(fd,&rs);
tv.tv_sec=0;
tv.tv_usec=0;
while(1)
{
read(0,buf,1);
r=select(fd+1,&rfds,NULL,NULL,&tv);
if(r<0)
{
write(1,"select() error.\n",16);
}
rfds=rs;
if(flag==2||buf[0]==113)//游戏结束或者用户按下'q'键,则程序退出
{
tcsetattr(0,TCSANOW,&saveterm);
exit(0);
}
if(buf[0]<=68&&buf[0]>=65) flag=0;//如果按的键是方向键,则将标志位置0并执行相应的处理.
if(flag==0)
{
if(buf[0]==65) {
//if(dir!=0) {
if(bl.get_type()==5) continue; //如果出现田字形则不作旋转
tab.clr_block(bl); //清空方块上一次位置
bl.rotate(); //开始旋转
if(!tab.set_block(bl)) { //将旋转后的方块写在棋盘上
bl.back(); //如果写失败(例如到边线了,或卡住了)则还原旋转前位置
continue;
tab.set_block(bl);
}
}
//下(加速下落)
//dir=GetAsyncKeyState(VK_DOWN); //获取向下
if(buf[0]==66) {
tab.clr_block(bl); //清空方块上一次位置
bl.move(bl.DOWN); //向下移动一步
if(!tab.set_block(bl)) { //将移动后的方块写在棋盘上
bl.move(bl.UP); //如果失败,则还原到移动前的位置(即上移一步)
tab.set_block(bl);
}
}
//左(左移)
//dir=GetAsyncKeyState(VK_LEFT);
if(buf[0]==68) {
tab.clr_block(bl);
bl.move(bl.LEFT);
if(!tab.set_block(bl)) {
bl.move(bl.RIGHT);
tab.set_block(bl);
}
}
//右(右移)
//dir=GetAsyncKeyState(VK_RIGHT);
if(buf[0]==67) {
tab.clr_block(bl);
bl.move(bl.RIGHT);
if(!tab.set_block(bl)) {
bl.move(bl.LEFT);
tab.set_block(bl);
}
}
flag=1;
}
}
tcsetattr(0,TCSANOW,&saveterm);
}
主函数部分///
int main()
{
//Table tab(15, 20); //构造一个15,20的棋盘
//Block bl; //构造一个落下方块
Mythread thread;
thread.init();
int dir,i,c;
while(true) {
//生成方块
srand(time(0));
bl.creat_block(tab.get_w(), tab.get_h());
//判断游戏是否结束
if( !tab.set_block(bl) ) {
system("clear");
cout<
flag=2;
cout<
while(1);
}
///行动按键判定
while(true){
usleep(500000); //暂停500 MS
/向下移动一格
tab.clr_block(bl); //清空上一次方块位置
bl.move(bl.DOWN); //向下移动一步
if(!tab.set_block(bl)) { //是否触底
bl.move(bl.UP); //如果触底,还原触底前位置
tab.set_block(bl);
break;
}
}
//如果满行则消行
for(i=0; i
if(tab.if_full(i)) { //是否满行
tab.clr_line(i); //如果是,消行
tab.move_line(i); //将所消行的上面的棋盘信息下移
i--; //下移后,重新检查这一行是否满(可能出现几行同时消去)
tab.set_count(100); //记录得分
}
}
}
return 0;
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
linux俄罗斯方块程序,linux环境下C++实现俄罗斯方块相关推荐
- arm linux 2.6下载,ARM+LINUX(montavista2.6.x)环境下SIMCOM5218使用
ARM+LINUX(montavista2.6.x)环境下 SIMCOM5218使用 http://blog.sina.com.cn/s/blog_4c796ed20100hpxg.html 一. 系 ...
- Nginx在Linux(centos7)环境下的下载与安装
Nginx在Linux(centos7)环境下的下载与安装 一.下载Nginx 1.免费的开源版本官方网址 2.选择需要下载的版本 二.安装Nginx 1.安装前准备(需要安装相关依赖库) 2.安装N ...
- Windows下ARM Linux应用程序开发环境搭建说明
这是因为工作写的一个文档,主要是我们开发人员都不会Linux不会vi也不会命令行,于是研究了一下Windows系统调试ARM Linux程序的办法,在这共享一下. 1. 概述 嵌入式Linux系统的应 ...
- linux(ubuntu)环境下安装及配置JDK
安装完IDEA之后遇到了问题,发现jdk安装完之后配置环境变量好困难,下面总结一下我的安装及配置方式: JDK下载链接:http://download.oracle.com/otn-pub/java/ ...
- linux centos7 mysql_Linux centos7环境下安装MySQL的步骤详解
Linux centos7环境下安装MySQL的步骤详解 安装MySQL mysql 有两个跟windows不同的地方 1).my.ini 保存到/etc/my.ini 2).用户权限,单独用户执行 ...
- 桂电在linux、Mac OS环境下使用出校器(支持2.14)
这是guetsec学长在三院科协学长所抓包逆向分析1.81版出校器的基础上,用python写的一款为Mac和linux环境开发的出校器. 最后我做了略微修改,支持暂时最新版本2.14.下面有直接从源码 ...
- Linux挖坑脚本,Windows环境下写Linux sh脚本的一次挖坑和填坑
最近在研究Docker集群和安装的时候,需要准备若干台机器.所以我为节约时间,打算批量复制VM机器,然后用sh脚本命令执行机器名称和IP等基础配置信息的修改. 具体操作:我在windows环境下,用N ...
- 在linux+nginx+mysql+php环境下安装 phpmyadmin
环境 1, CentOS 7 2, nginx1.12.2 (Linux 利用yum源安装nginx) 3, php7.0 (Linux 利用yum源安装php7.0+nginx) 4, mysql5 ...
- linux sublime nodejs,Windows环境下sublime的Nodejs插件详细安装图解
前面的话 搜索了好多文档后,才成功在Windows环境下安装了sublime text3的nodejs插件.为了存档,也为了方便有同样需求的朋友,将其安装过程详细记录如下 安装nodejs 虽然nod ...
- Linux/unix不同shell环境下数值运算的处理
在阅读本文前,您需要对变量替换.命令替换和数值替换有一点认识. 阅读完本文,您应该获得解决下列问题的信息: 不同shell(bash,csh,ksh)下如何处理数值的运算 常用来数值运算的命令 关于运 ...
最新文章
- 用c语言编写通讯录程序,学C三个月了,学了文件,用C语言写了个通讯录程序
- Java JDK 11:现在可以使用所有新功能
- gradle多工程打包冲突问题
- 微信验证以及登录流程
- Ubuntu16.04安装NVIDIA显卡(RTX20系列)驱动+CUDA10.0+cudnn+Pytorch1.1.0
- Python输出中文乱码问题
- 晨风机器人对接php_php封装实现钉钉机器人报警接口的示例代码
- tomcat内存设置
- PHP 开发者如何做代码审查?
- ios开发之切换RootViewController
- Hilditch细化算法
- 1.3 anaconda的安装和使用
- 首发 华为Mate7青春版拆机换电池
- HI3516DV300 GPIO操作
- Python|每日一练|素数对|优化算法|素数|素数对:找出素数对
- 计算机如何取消自动关机,电脑怎么取消自动关机【处理形式】
- 数据库学习笔记(一) | 数据(Data)的定义
- 虚拟数字人遇上ChatGPT,好看的皮囊和有趣的灵魂?
- 鸟哥的Linux私房菜(服务器)- 第二十二章、邮件服务器: Postfix
- 软件测试面试题整理出炉附(附答案)
热门文章
- 微星迷你服务器开机无任何显示,合肥微星笔记本维修「请问 微星电脑 突然黑屏 电源 和cpu亮着 就是开不了机 怎么办?」...
- 贴吧无耻爆粉引流秘密-游戏公司都在偷偷的玩他
- python爬取b站用户_python爬取b站排行榜
- linux 格式化磁盘
- 房住不炒、买股被套!焦虑的中产们,这次瞄准了茅台?
- Apace组态设计器-制作风车
- SCSI、DeviceIoControl、SCSI_PASS_THROUGH、CDB
- 单例模式之饿汉模式懒汉模式
- AP与BB(应用处理器和基带处理器)
- 香港银行和科技公司竞争已经打响