俄罗斯方块----Ubuntu终端游戏

来源:互联网 发布:网络格斗游戏排行 编辑:程序博客网 时间:2024/05/16 06:08

我最近在看C++和linux,为了能够更加牢靠的掌握自己的学到的知识,所以采用写小游戏的方法来帮助自己巩固学习。在这篇代码中我用到的C++和linux知识有:
C++知识:
1. 类的创建
2. 内联函数
3. pthread线程
linux知识:
1. 进入root模式
2. 给文件增加权限
3. 查看和使用系统的外设

有三点要特别说明:
1. 本代码不适用于所有linux系统,如果照搬的话可能会运行失败。如果要保证此代码编译的程序能在另一台机器上运行,需要先查看该机器的键盘是对应哪一个event文件,并将代码中的打开event文件的名称改掉。
2. 因为打开event文件需要很高的权限,所以需要在root模式下运行
3. 要编译此程序需要在链接是加入pthread库,即编译时需要g++ -lpthread *.cpp

具体代码如下:

RussiaBlock.h#ifndef RUSSIA_BLOCK_H#define RUSSIA_BLOCK_H#include <iostream>#include <ctime>#include <stdexcept>#include <unistd.h>#include <pthread.h>#include <cstdlib>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/select.h>#include <errno.h>#include <linux/input.h>using namespace std;typedef struct Pos{    unsigned char x;    unsigned char y;} Pos;typedef struct Block{    Pos  pos[4];    bool Droping;    short shape;} Block;class RussiaBlock{    private:        enum {TIAN_BLOCK=0,L_BLOCK,T_BLOCK,FL_BLOCK,I_BLOCK,HI_BLOCK,Z_BLOCK,FZ_BLOCK};        bool    gameFail;        bool    dropToEnd;        bool    Rotating;        unsigned int score;        unsigned char screenWidth;        unsigned char screenHeight;        Block currentBlock;        Block nextBlock;        unsigned char map[100][100];    public:        void  GameStart(void);                                  //开始游戏        RussiaBlock(unsigned char, unsigned char = 80);    private:        Block TianBlock(void);          //田型方块        void  FailNotice(void);                             //游戏失败提示        Block LBlock(void);             //L型方块        void  KeyOperate(void);                         //按键操作        void  ShowScreen(void);                             //显示游戏区域        Block CreatNewBlock(void);                          //创建一个新的方块        void  ShowNextBlock(void);                          //显示下一个方块提示    private:        Block TBlock();                 //T型方块        Block FLBlock();                //反L型方块        Block IBlock();                 //I型方块        Block HIBlock();                //横I型方块        Block ZBlock();                 //Z型方块        Block FZBlock();                //反Z型方块        void  AutoDrop(void *);         //自动下降线程        static void *Thread_func(void *);        static void *Thread_Key(void *);        void   MoveRight();             //右移        void   MoveLeft();              //左移        void   DropEnd();               //下降到底        void   RotateBlock();           //旋转方块        void   DeleteLines();           //清除游戏区域内多行内容        bool   DropOneLine();           //下降一行        void   DeleteOneLine();         //删除一行        bool   AtTheEnd();              //判断是否在可降落的最低点        inline bool ThisLineIsFull(int index)        {            for(int i=0;i<screenWidth;i++)            {                if(map[i][index] == 0)                    return false;            }            return true;        }        inline void DeleteOneLine(int index)        {            for(int i=index;i>0;i--)            {                for(int j=0;j<screenWidth;j++)                {                    map[j][i] = map[j][i-1];                }            }            for(int j=0;j<screenWidth;j++)            {                map[j][0] = 0;            }        }};#endif
RussiaBlock.cpp#include "RussiaBlock.h"#include <iostream>using namespace std;RussiaBlock::RussiaBlock(unsigned char width, unsigned char height){    gameFail = false;    screenWidth = width;    screenHeight= height;    score       = 0;    for(int i=0;i != 100;i++)        for(int j=0;j!=100;j++)        {            map[i][j] = 0;        }    srand(time(0));    nextBlock = CreatNewBlock();    Rotating = false;}Block RussiaBlock::CreatNewBlock(void){    short blockShape = 0;    blockShape = (short)(rand()%8);    Block newBlock;    switch(blockShape)    {        case 0: newBlock = TianBlock();break;        case 1: newBlock = LBlock();break;        case 2: newBlock = TBlock();break;        case 3: newBlock = FLBlock();break;        case 4: newBlock = IBlock();break;        case 5: newBlock = HIBlock();break;        case 6: newBlock = ZBlock();break;        case 7: newBlock = FZBlock();break;    }    newBlock.shape = blockShape;    return newBlock;}void RussiaBlock::ShowScreen(){    system("clear");    for(int i=0;i<screenWidth+2;i++)        cout << "_";    cout <<endl;    for(int i(0);i<screenHeight;i++)    {        cout << "|";        for(int j(0);j<screenWidth;j++)        {            if(map[j][i] == 0) cout<<" ";            else if(map[j][i] == 1 || map[j][i] == 2) cout<<"#";            else cout<<map[j][i];        }        cout << "|";        cout<<endl;    }    for(int i=0;i<screenWidth+2;i++)        cout << "-" ;    cout << endl;    ShowNextBlock();    cout << "score:" << score<<endl;}void RussiaBlock::ShowNextBlock(void){    bool have = false;    for(int r=0;r<4;r++)    {        for(int c=0;c<4;c++)        {            have = false;            for(int blk=0;blk<4;blk++)            {                if(nextBlock.pos[blk].x == c&& nextBlock.pos[blk].y == r)                {                    have = true;                    cout << "#";                }            }            if(have==false) cout<<" ";        }        cout << endl;    }}void RussiaBlock::GameStart(void){    pthread_t id_auto,id_key;    try    {        int ret = pthread_create(&id_auto,NULL,&Thread_func,this);        if(ret != 0) throw runtime_error("start game fail");        ret = pthread_create(&id_key,NULL,&Thread_Key,this);        if(ret != 0) throw runtime_error("start game fail");    }    catch(runtime_error err)    {        cout << err.what() <<endl;        return;    }    gameFail = false;    while(!gameFail)    {        dropToEnd = false;        currentBlock = nextBlock;        nextBlock = CreatNewBlock();        for(int i=0;i<4;i++)        {            currentBlock.pos[i].x += (screenWidth/2);            map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1;        }        while(!dropToEnd)        {            if(AtTheEnd())            {                dropToEnd = true;                for(int i=0;i<4;i++)                    map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 2;                DeleteLines();            }        }        for(int i=0;i<screenWidth;i++)        {            if(map[i][0] == 2)            {                gameFail = true;                break;            }        }    }    pthread_join(id_auto,NULL);    pthread_join(id_key,NULL);    FailNotice();}bool RussiaBlock::AtTheEnd(void){    for(int i=0;i<4;i++)    {        if(map[currentBlock.pos[i].x][currentBlock.pos[i].y + 1] == 2|| currentBlock.pos[i].y ==screenHeight - 1)            return true;    }    return false;}void RussiaBlock::FailNotice(void){    string failStr("Game Over!");    for(int i=0;i!=failStr.size();i++)    {        map[i][screenHeight/2] = failStr[i];    }    ShowScreen();}void RussiaBlock::KeyOperate(void){    struct input_event ev_key;    int btn_fd = open("/dev/input/event3",O_RDWR);    if(btn_fd < 0)    {        cerr << btn_fd <<endl;        cerr << "Game initial fail!" << endl;        return;    }    while(!gameFail)    {        int count = read(btn_fd,&ev_key,sizeof(struct input_event));        //for(int i=0;i<(int)count/sizeof(struct input_event);i++)        if(EV_KEY == ev_key.type && ev_key.value == 1)        {            switch(ev_key.code)            {                case KEY_A:MoveLeft();break;                case KEY_S:DropEnd();break;                case KEY_D:MoveRight();break;                case KEY_W:RotateBlock();break;            }        }        ShowScreen();    }    close(btn_fd);}void RussiaBlock::DeleteLines(void){    for(int i=0;i<screenHeight;i++)    {        if(ThisLineIsFull(i))        {            DeleteOneLine(i);            score++;        }    }}void RussiaBlock::DropEnd(void){    bool getEnd = false;    while(1)    {        for(int i=0;i<4;i++)        {            if(map[currentBlock.pos[i].x][currentBlock.pos[i].y + 1] == 2|| currentBlock.pos[i].y ==screenHeight - 1)            {                getEnd = true;                break;            }        }        if(!getEnd)        {            for(int i=0;i<4;i++)            {                map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0;                currentBlock.pos[i].y++;                map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1;            }        }        else break;    }}void RussiaBlock::MoveRight(void){    for(int i=0;i<4;i++)    {        if(currentBlock.pos[i].x + 1 == screenWidth || map[currentBlock.pos[i].x+1][currentBlock.pos[i].y] == 2)        {            return ;        }    }    for(int i=0;i<4;i++)    {        map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0;        currentBlock.pos[i].x++;    }    for(int i=0;i<4;i++)        map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1;}void RussiaBlock::MoveLeft(void){    for(int i=0;i<4;i++)    {        if(currentBlock.pos[i].x - 1 < 0 || map[currentBlock.pos[i].x-1][currentBlock.pos[i].y] == 2)        {            return ;        }    }    for(int i=0;i<4;i++)    {        map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0;        currentBlock.pos[i].x--;        map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1;    }}void RussiaBlock::RotateBlock(void){    short blockShape = currentBlock.shape;    if(blockShape == TIAN_BLOCK) return;    if(blockShape == I_BLOCK)    {        Pos pos[4] = {0};        for(int i=0;i<4;i++)        {            pos[i].y = currentBlock.pos[2].y;            pos[i].x = currentBlock.pos[2].x + i-1;        }        for(int i=0;i<4;i++)        {            if(map[pos[i].x][pos[i].y] == 2 || pos[i].y >= screenHeight || pos[i].y < 0 || pos[i].x >= screenWidth || pos[i].x < 0) return ;        }        for(int i=0;i<4;i++)        {            map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0;            currentBlock.pos[i] = pos[i];            map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1;        }        currentBlock.shape = HI_BLOCK;        return ;    }    if(blockShape == HI_BLOCK)    {        Pos pos[4] = {0};        for(int i=0;i<4;i++)        {            pos[i].x = currentBlock.pos[1].x;            pos[i].y = currentBlock.pos[1].y + i-1;        }        for(int i=0;i<4;i++)        {            if(map[pos[i].x][pos[i].y] == 2 || pos[i].y >= screenHeight || pos[i].y < 0 || pos[i].x >= screenWidth || pos[i].x < 0) return ;        }        for(int i=0;i<4;i++)        {            map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0;            currentBlock.pos[i] = pos[i];            map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1;        }        currentBlock.shape = I_BLOCK;        return ;    }    unsigned char maxX = currentBlock.pos[0].x,maxY = currentBlock.pos[0].y,minX = currentBlock.pos[0].x, minY = currentBlock.pos[0].y;    for(int i=1;i<4;i++)    {        if(maxX < currentBlock.pos[i].x) maxX = currentBlock.pos[i].x;        if(minX > currentBlock.pos[i].x) minX = currentBlock.pos[i].x;        if(maxY < currentBlock.pos[i].y) maxY = currentBlock.pos[i].y;        if(minY > currentBlock.pos[i].y) minY = currentBlock.pos[i].y;    }    unsigned char X = ((maxX-minX) == 2)?maxX-1:maxX;               unsigned char Y = ((maxY-minY) == 2)?maxY-1:maxY;    unsigned char arr[3][3] = {0};    short arrX=0,arrY=0;    for(int i=Y-1;i<=Y+1;i++)    {        arrX = 0;        for(int j=X-1;j<=X+1;j++)        {            arr[arrX++][arrY] = map[j][i];            if(map[j][i] == 2) return ;        }        arrY++;    }    //转置并换行    for(int i=0;i<3;i++)    {        for(int j = 0;j<=i;j++)        {            unsigned char temp = arr[j][i];            arr[j][i] = arr[i][j];            arr[i][j] = temp;        }    }    for(int j=0;j<3;j++)    {        unsigned char temp = arr[j][0];        arr[j][0] = arr[j][2];        arr[j][2] = temp;    }    arrY = 0;    int index = 0;    for(int i=Y-1;i<=Y+1;i++)    {        arrX = 0;        for(int j=X-1;j<=X+1;j++)        {            map[j][i] = arr[arrX++][arrY];            if(map[j][i] == 1)            {                currentBlock.pos[index].x = j;                currentBlock.pos[index++].y = i;            }        }        arrY++;    }}Block RussiaBlock::TianBlock(void){    Block NewBlock = {0};    NewBlock.pos[0].x = 0;    NewBlock.pos[0].y = 0;    NewBlock.pos[1].x = 1;    NewBlock.pos[1].y = 0;    NewBlock.pos[2].x = 0;    NewBlock.pos[2].y = 1;    NewBlock.pos[3].x = 1;    NewBlock.pos[3].y = 1;    return NewBlock;}Block RussiaBlock::LBlock(void){    Block NewBlock = {0};    NewBlock.pos[0].x = 0;    NewBlock.pos[0].y = 0;    NewBlock.pos[1].x = 0;    NewBlock.pos[1].y = 1;    NewBlock.pos[2].x = 0;    NewBlock.pos[2].y = 2;    NewBlock.pos[3].x = 1;    NewBlock.pos[3].y = 2;    return NewBlock;}Block RussiaBlock::TBlock(void){    Block NewBlock = {0};    NewBlock.pos[0].x = 0;    NewBlock.pos[0].y = 0;    NewBlock.pos[1].x = 1;    NewBlock.pos[1].y = 0;    NewBlock.pos[2].x = 2;    NewBlock.pos[2].y = 0;    NewBlock.pos[3].x = 1;    NewBlock.pos[3].y = 1;    return NewBlock;}Block RussiaBlock::FLBlock(void){    Block NewBlock = {0};    NewBlock.pos[0].x = 0;    NewBlock.pos[0].y = 0;    NewBlock.pos[1].x = 1;    NewBlock.pos[1].y = 0;    NewBlock.pos[2].x = 2;    NewBlock.pos[2].y = 0;    NewBlock.pos[3].x = 2;    NewBlock.pos[3].y = 1;    return NewBlock;}Block RussiaBlock::IBlock(void){    Block NewBlock = {0};    NewBlock.pos[0].x = 0;    NewBlock.pos[0].y = 0;    NewBlock.pos[1].x = 0;    NewBlock.pos[1].y = 1;    NewBlock.pos[2].x = 0;    NewBlock.pos[2].y = 2;    NewBlock.pos[3].x = 0;    NewBlock.pos[3].y = 3;    return NewBlock;}Block RussiaBlock::HIBlock(void){    Block NewBlock = {0};    NewBlock.pos[0].x = 0;    NewBlock.pos[0].y = 0;    NewBlock.pos[1].x = 1;    NewBlock.pos[1].y = 0;    NewBlock.pos[2].x = 2;    NewBlock.pos[2].y = 0;    NewBlock.pos[3].x = 3;    NewBlock.pos[3].y = 0;    return NewBlock;}Block RussiaBlock::ZBlock(void){    Block NewBlock = {0};    NewBlock.pos[0].x = 0;    NewBlock.pos[0].y = 0;    NewBlock.pos[1].x = 1;    NewBlock.pos[1].y = 0;    NewBlock.pos[2].x = 1;    NewBlock.pos[2].y = 1;    NewBlock.pos[3].x = 2;    NewBlock.pos[3].y = 1;    return NewBlock;}Block RussiaBlock::FZBlock(void){    Block NewBlock = {0};    NewBlock.pos[0].x = 1;    NewBlock.pos[0].y = 0;    NewBlock.pos[1].x = 2;    NewBlock.pos[1].y = 0;    NewBlock.pos[2].x = 0;    NewBlock.pos[2].y = 1;    NewBlock.pos[3].x = 1;    NewBlock.pos[3].y = 1;    return NewBlock;}void *RussiaBlock::Thread_func(void *param){    RussiaBlock *p = (RussiaBlock *)param;    p->AutoDrop(NULL);}void RussiaBlock::AutoDrop(void *ptr){    while(!gameFail)    {        int tim = time(0);        while(tim == time(0)) ;        DropOneLine();        ShowScreen();    }}bool RussiaBlock::DropOneLine(void){    for(int i=0;i<4;i++)    {        if(map[currentBlock.pos[i].x][currentBlock.pos[i].y + 1] ==2 ||currentBlock.pos[i].y == screenHeight -1)        {            return false;        }    }    for(int i=0;i<4;i++)    {        map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0;        currentBlock.pos[i].y++;    }    for(int i=0;i<4;i++)        map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1;    return true;}void *RussiaBlock::Thread_Key(void *param){    RussiaBlock *p = (RussiaBlock *)param;    p->KeyOperate();}
main.cpp#include <iostream>#include "RussiaBlock.h"using namespace std;int main(){    RussiaBlock blk(10,10);    blk.GameStart();    return 0;}
makefileRussiaBlock: main.o RussiaBlock.o    g++ -lpthread main.o RussiaBlock.o -o RussiaBlockmain.o: main.cpp RussiaBlock.h    g++ -c main.cppRussiaBlock.o: RussiaBlock.cpp    g++ -c RussiaBlock.cpp

这里写图片描述
这里写图片描述
这里写图片描述

0 0
原创粉丝点击