Qt平台下的精简版俄罗斯方块,代码80行(顺便散点分)

lxyppc 2012-03-05 01:03:51
代码虽小,五脏俱全。
之前写了一个90行版本的(90行版本),需要.h和main.cpp两个文件。现在用一个文件来实现了。
由于没有.h文件了,“借”用了一个Qt中原生的SLOT来响应timer事件
这个版本采用位运算来判定方块的合法性,使得代码更精简
P.S. 由于在ubuntu和windows下mono格式的颜色是反的, ubuntu下运行看起来不太习惯
#include <QtGui>
unsigned int p1 = 0, p2 = 0, score = 0;
#define EX(x) ((((x)&0xf000ull)>>12)|(((x)&0xf00ull)<<8)|(((x)&0xf0ull)<<28)|(((x)&0xfull)<<48))
quint64 pats[7*4] = {
EX(0x0660),EX(0x0660),EX(0x0660),EX(0x0660), EX(0x4460),EX(0x0740),EX(0x6220),EX(0x02e0),
EX(0x2260),EX(0x0470),EX(0x6440),EX(0x0e20), EX(0x0630),EX(0x2640),EX(0x0630),EX(0x2640),
EX(0x0360),EX(0x4620),EX(0x0360),EX(0x4620), EX(0x0720),EX(0x2620),EX(0x0270),EX(0x2320),
EX(0x4444),EX(0x0f00),EX(0x4444),EX(0x0f00),
};
quint16 map[28] = {0xffff,0xffff,0xffff,0xffff};
struct MainWindow : public QMainWindow {
MainWindow(QWidget *parent = 0) : QMainWindow(parent),timer(new QTimer(this)){
setGeometry(400,200,250,250);
connect(timer, SIGNAL(timeout()), this, SLOT(raise()));
}
virtual bool event ( QEvent * e ){
if(e->type() == QEvent::ZOrderChange)keyPressEvent(0);
return QMainWindow::event(e);
}
int blockDrop(bool real = true){
if(real)*(quint64*)&map[curpos.y()] |= (pats[p1%28]<<curpos.x());
for(int i=0;i<4 && real; i++)
if(map[i+curpos.y()] == 0xffff){
memmove(&map[5],&map[4], (i+curpos.y() - 4)*2);
map[4] = ~0x1ff8;
score++;
}
timer->setInterval(score<450 ? 500-(score/50)*50 : 50);
p1 = p2;
curpos = QPoint(6,0);
while(!isValid(curpos.x(),curpos.y()) && curpos.y()<6)curpos.ry()++;
if(curpos.y()>=6) timer->stop();
return p2 = qrand();
}
void paintEvent(QPaintEvent *){
QPainter painter(this);
painter.drawImage(5,5,QImage((uchar*)map,16,28,2,QImage::Format(2)).scaled(160,280),28,38,104,204);
QImage img = QImage((uchar*)&pats[p1%28],4,4,2,QImage::Format(2)).convertToFormat(QImage::Format(3));
painter.drawImage(curpos.x()*10-23,curpos.y()*10-33,(img.setColor(0,0),img.scaled(40,40)));
painter.drawImage(130,30,QImage((uchar*)&pats[p2%28],4,4,2,QImage::Format(2)).scaled(40,40));
painter.drawText(130,20,QString("score:%1").arg(score));
if(!timer->isActive())painter.drawText(130,85,QString("Game over"));
painter.drawText(130,100,80,140,0,"P-Restart\nW-Rotate\nA-Left\nD-Right\nS-Down\nSpace-Drop");
}
virtual void keyPressEvent ( QKeyEvent * e ){
if(!timer->isActive()){
if(e->key() == Qt::Key_P || e->key() == Qt::Key_Enter){
*(quint64*)&map[24] = 0xfffefffefffefffeull;
for(int i=4;i<24;i++) map[i] = ~0x1ff8;
qsrand(QTime::currentTime().msec());
score = 0;
p2 = qrand();
blockDrop(false);
timer->start();
}
}else if(!e || e->key() == Qt::Key_Down || e->key() == Qt::Key_S){
isValid(curpos.x(),curpos.y()+1) ? curpos.ry()++ : blockDrop();
}else if(e->key() == Qt::Key_Space){
while(isValid(curpos.x(),curpos.y()+1)) curpos.ry()++;
blockDrop();
}else if(e->key() == Qt::Key_Left || e->key() == Qt::Key_A){
if(isValid(curpos.x()-1,curpos.y())) curpos.rx()--;
}else if(e->key() == Qt::Key_Right || e->key() == Qt::Key_D){
if(isValid(curpos.x()+1,curpos.y())) curpos.rx()++;
}else if(e->key() == Qt::Key_Up || e->key() == Qt::Key_W){
p1 = ((p1&(~3)) | ((p1+1)&3));
if(!isValid(curpos.x(),curpos.y())) p1 = ((p1&(~3)) | ((p1-1)&3));
}
update();
}
bool isValid(int x, int y){ return !( (pats[p1%28]<<x) & *(quint64*)&map[y]); }
QTimer* timer;
QPoint curpos;
};
int main(int argc, char *argv[]){
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
...全文
624 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
haltwang 2013-03-02
  • 打赏
  • 举报
回复
引用 7 楼 lxyppc 的回复:
楼主位的代码在windows下运行会有点问题,改成下面的就ok了 C/C++ code?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475……
楼主的代码在winodws下看不见方块,落地后才能看见。 你的这个改动后的不错,但是堆到顶,也就是输了的时候会死掉,内存管理可能有问题。 不过两位都很牛x,代码值得学习。
lxyppc 2012-03-06
  • 打赏
  • 举报
回复
楼主位的代码在windows下运行会有点问题,改成下面的就ok了
#include <QtGui>
unsigned int p1 = 0, p2 = 0, score = 0;
#define EX(x) ((((x)&0xf000ull)>>12)|(((x)&0xf00ull)<<8)|(((x)&0xf0ull)<<28)|(((x)&0xfull)<<48))
quint64 pats[7*4] = {
EX(0x0660),EX(0x0660),EX(0x0660),EX(0x0660), EX(0x4460),EX(0x0740),EX(0x6220),EX(0x02e0),
EX(0x2260),EX(0x0470),EX(0x6440),EX(0x0e20), EX(0x0630),EX(0x2640),EX(0x0630),EX(0x2640),
EX(0x0360),EX(0x4620),EX(0x0360),EX(0x4620), EX(0x0720),EX(0x2620),EX(0x0270),EX(0x2320),
EX(0x4444),EX(0x0f00),EX(0x4444),EX(0x0f00),
};
quint16 map[28] = {0xffff,0xffff,0xffff,0xffff};
struct MainWindow : public QMainWindow {
MainWindow(QWidget *parent = 0) : QMainWindow(parent),timer(new QTimer(this)){
setGeometry(400,200,250,250);
connect(timer, SIGNAL(timeout()), this, SLOT(raise()));
}
virtual bool event ( QEvent * e ){
if(e->type() == QEvent::ZOrderChange)keyPressEvent(0);
return QMainWindow::event(e);
}
int blockDrop(bool real = true){
if(real)*(quint64*)&map[curpos.y()] |= (pats[p1%28]<<curpos.x());
for(int i=0;i<4 && real; i++)
if(map[i+curpos.y()] == 0xffff){
memmove(&map[5],&map[4], (i+curpos.y() - 4)*2);
map[4] = ~0x1ff8;
score++;
}
timer->setInterval(score<450 ? 500-(score/50)*50 : 50);
p1 = p2;
curpos = QPoint(6,0);
while(!isValid(curpos.x(),curpos.y()) && curpos.y()<6)curpos.ry()++;
if(curpos.y()>=6) timer->stop();
return p2 = qrand();
}
void paintEvent(QPaintEvent *){
QPainter painter(this);
painter.drawImage(5,5,QImage((uchar*)map,16,28,2,QImage::Format(2)).scaled(160,280),28,38,104,204);
QImage img = QImage((uchar*)&pats[p1%28],4,4,2,QImage::Format(2)).convertToFormat(QImage::Format(3));
img.setColorTable(QVector<QRgb>()<<0<<0xff000000);
painter.drawImage(curpos.x()*10-23,curpos.y()*10-33,img.scaled(40,40));
painter.drawImage(130,30,QImage((uchar*)&pats[p2%28],4,4,2,QImage::Format(2)).scaled(40,40));
painter.drawText(130,20,QString("score:%1").arg(score));
if(!timer->isActive())painter.drawText(130,85,QString("Game over"));
painter.drawText(130,100,80,140,0,"P-Restart\nW-Rotate\nA-Left\nD-Right\nS-Down\nSpace-Drop");
}
virtual void keyPressEvent ( QKeyEvent * e ){
if(!timer->isActive()){
if(e->key() == Qt::Key_P || e->key() == Qt::Key_Enter){
*(quint64*)&map[24] = 0xfffefffefffefffeull;
for(int i=4;i<24;i++) map[i] = ~0x1ff8;
qsrand(QTime::currentTime().msec());
score = 0;
p2 = qrand();
blockDrop(false);
timer->start();
}
}else if(!e || e->key() == Qt::Key_Down || e->key() == Qt::Key_S){
isValid(curpos.x(),curpos.y()+1) ? curpos.ry()++ : blockDrop();
}else if(e->key() == Qt::Key_Space){
while(isValid(curpos.x(),curpos.y()+1)) curpos.ry()++;
blockDrop();
}else if(e->key() == Qt::Key_Left || e->key() == Qt::Key_A){
if(isValid(curpos.x()-1,curpos.y())) curpos.rx()--;
}else if(e->key() == Qt::Key_Right || e->key() == Qt::Key_D){
if(isValid(curpos.x()+1,curpos.y())) curpos.rx()++;
}else if(e->key() == Qt::Key_Up || e->key() == Qt::Key_W){
p1 = ((p1&(~3)) | ((p1+1)&3));
if(!isValid(curpos.x(),curpos.y())) p1 = ((p1&(~3)) | ((p1-1)&3));
}
update();
}
bool isValid(int x, int y){ return !( (pats[p1%28]<<x) & *(quint64*)&map[y]); }
QTimer* timer;
QPoint curpos;
};
int main(int argc, char *argv[]){
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
hemiya 2012-03-06
  • 打赏
  • 举报
回复
念茜 2012-03-05
  • 打赏
  • 举报
回复
果真精简
lxyppc 2012-03-05
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 xinmuba 的回复:]

楼主,叼

这还有很多行的 俄罗斯方块呢
http://blog.csdn.net/xinmuba/article/details/7278177
[/Quote]
你的方块是面向对象的,我的方块没对象
jinling4388 2012-03-05
  • 打赏
  • 举报
回复
留个脚印!随便接分
赵自行 2012-03-05
  • 打赏
  • 举报
回复
我也用的ubuntu啊,接着分了!
moooxin 2012-03-05
  • 打赏
  • 举报
回复
楼主,叼

这还有很多行的 俄罗斯方块呢
http://blog.csdn.net/xinmuba/article/details/7278177

16,216

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧