linux環(huán)境下C++實(shí)現(xiàn)俄羅斯方塊
本文實(shí)例為大家分享了C++實(shí)現(xiàn)俄羅斯方塊的具體代碼,供大家參考,具體內(nèi)容如下
本程序的運(yùn)行環(huán)境是linux,用到了多線程。創(chuàng)建了一個(gè)用來(lái)繪圖的線程和一個(gè)獲取按鍵的線程。程序中有一些需要改善的地方,比如336-338行定義的全局變量以及聲明的對(duì)象。本來(lái)聲明的Block和Table對(duì)象應(yīng)該在main函數(shù)里面,然后將這兩個(gè)對(duì)象作為參數(shù)傳遞給線程函數(shù)getkey。但是好像只能傳遞一個(gè)對(duì)象參數(shù)給線程函數(shù)。希望高手能夠?qū)Τ绦蜻M(jìn)行改進(jìn)。
ps:由于用到了多線程,而pthread不是linux的默認(rèn)庫(kù),所以編譯的時(shí)候需要指定線程庫(kù)。即:g++ -o block -lpthread block.cpp
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <time.h>
#include<termios.h>
#include<fcntl.h>
#define TABLE_SIZE 20
#define BLOCK_SIZE 4
#define SLEEP_TIME 500
using namespace std;
struct grid{int x; int y;}; //坐標(biāo)
/////////////////////Block 類//////////////////////
class Block
{
public:
enum direct{UP, DOWN, LEFT, RIGHT}; //定義方向
grid g[BLOCK_SIZE]; //方塊的坐標(biāo)信息
void def_block(grid g1, grid g2, grid g3, grid g4); //定義方塊
void rotate(); //旋轉(zhuǎn)方塊
void move(int dir); //移動(dòng)方塊
void set_cen(grid g); //設(shè)置方塊旋轉(zhuǎn)中心
grid get_cen(); //獲取方塊旋轉(zhuǎn)中心
void set_type(int t); //設(shè)置方塊種類
int get_type(); //獲取方塊種類
void back(); //旋轉(zhuǎn)還原
void creat_block(int x, int y); //隨機(jī)生成方塊
private:
grid center; //方塊旋轉(zhuǎn)中心
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) { //隨機(jī)創(chuàng)建方塊
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() { //構(gòu)造棋盤
height=20; width=10; count=0;
init_table();
}
Table(int x, int y);
int set_block(Block bl); //安設(shè)方塊
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); //獲取棋盤上點(diǎn)信息
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<width; i++) {
for(j=0; j<height; 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<width; 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<width; 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<width+2; i++) cout<<"-"<<flush;
cout<<"\n"<<flush;
for(i=height-1; i>=0; i--) {
cout<<"|"<<flush;
for(j=0; j<width; j++) {
if(table[j][i]==0) cout<<" "<<flush;
else cout<<"▣"<<flush;
}
if(i==10)
cout<<"| 得分:"<<get_count()<<endl;
else if(i==7)
cout<<"| Press 'q' to quit!"<<endl;
else
cout<<"|"<<endl;
}
for(i=0; i<width+2; i++) cout<<"-"<<flush;
cout<<"\n"<<flush;
//cout<<"得分:"<<get_count()<<endl;
}
void Table::move_line(int y) {
int i, j;
for(i=y; i<height-1; i++) {
for(j=0; j<width; 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);//線程函數(shù)在類里面定義必須定義為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<<"can't create thread!"<<endl;
exit(0);
}
}
unsigned char flag=1,buf[2];//全局變量
Table tab(15, 20); //構(gòu)造一個(gè)15,20的棋盤
Block bl; //構(gòu)造一個(gè)落下方塊
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)//游戲結(jié)束或者用戶按下'q'鍵,則程序退出
{
tcsetattr(0,TCSANOW,&saveterm);
exit(0);
}
if(buf[0]<=68&&buf[0]>=65) flag=0;//如果按的鍵是方向鍵,則將標(biāo)志位置0并執(zhí)行相應(yīng)的處理.
if(flag==0)
{
if(buf[0]==65) {
//if(dir!=0) {
if(bl.get_type()==5) continue; //如果出現(xiàn)田字形則不作旋轉(zhuǎn)
tab.clr_block(bl); //清空方塊上一次位置
bl.rotate(); //開(kāi)始旋轉(zhuǎn)
if(!tab.set_block(bl)) { //將旋轉(zhuǎn)后的方塊寫在棋盤上
bl.back(); //如果寫失敗(例如到邊線了,或卡住了)則還原旋轉(zhuǎn)前位置
continue;
tab.set_block(bl);
}
}
//下(加速下落)
//dir=GetAsyncKeyState(VK_DOWN); //獲取向下
if(buf[0]==66) {
tab.clr_block(bl); //清空方塊上一次位置
bl.move(bl.DOWN); //向下移動(dòng)一步
if(!tab.set_block(bl)) { //將移動(dòng)后的方塊寫在棋盤上
bl.move(bl.UP); //如果失敗,則還原到移動(dòng)前的位置(即上移一步)
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);
}
////////////主函數(shù)部分///////////////////////
int main()
{
//Table tab(15, 20); //構(gòu)造一個(gè)15,20的棋盤
//Block bl; //構(gòu)造一個(gè)落下方塊
Mythread thread;
thread.init();
int dir,i,c;
while(true) {
//生成方塊
srand(time(0));
bl.creat_block(tab.get_w(), tab.get_h());
//判斷游戲是否結(jié)束
if( !tab.set_block(bl) ) {
system("clear");
cout<<"GAME OVER!"<<endl;
flag=2;
cout<<"PRESS ANY KEY TO CONTINUE!"<<endl;
while(1);
}
///////////行動(dòng)按鍵判定
while(true){
usleep(500000); //暫停500 MS
/////////////向下移動(dòng)一格
tab.clr_block(bl); //清空上一次方塊位置
bl.move(bl.DOWN); //向下移動(dòng)一步
if(!tab.set_block(bl)) { //是否觸底
bl.move(bl.UP); //如果觸底,還原觸底前位置
tab.set_block(bl);
break;
}
}
//如果滿行則消行
for(i=0; i<tab.get_h(); i++) {
if(tab.if_full(i)) { //是否滿行
tab.clr_line(i); //如果是,消行
tab.move_line(i); //將所消行的上面的棋盤信息下移
i--; //下移后,重新檢查這一行是否滿(可能出現(xiàn)幾行同時(shí)消去)
tab.set_count(100); //記錄得分
}
}
}
return 0;
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
欄 目:C語(yǔ)言
本文標(biāo)題:linux環(huán)境下C++實(shí)現(xiàn)俄羅斯方塊
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/770.html
您可能感興趣的文章
- 01-10APUE筆記之:進(jìn)程環(huán)境詳解
- 01-10大數(shù)(高精度數(shù))模板(分享)
- 01-10深入解析Linux下\r\n的問(wèn)題
- 01-10Linux線程管理必備:解析互斥量與條件變量的詳解
- 01-10Linux C 獲取進(jìn)程退出值的實(shí)現(xiàn)代碼
- 01-10解析Linux下的時(shí)間函數(shù):設(shè)置以及獲取時(shí)間的方法
- 01-10深入探討linux下進(jìn)程的最大線程數(shù)、進(jìn)程最大數(shù)、進(jìn)程打開(kāi)的文
- 01-10基于linux下獲取時(shí)間函數(shù)的詳解
- 01-10linux c 查找使用庫(kù)的cflags與libs的方法詳解
- 01-10深入sizeof的使用詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?


