其他分享
首页 > 其他分享> > 我罗斯方块最终篇

我罗斯方块最终篇

作者:互联网

 

本次作业要求    我罗斯作业要求
本次作业属于     2020面向对象程序设计
本次作业具体要求
  • 代码的 git 仓库链接
  • 运行截图/运行视频
  • 代码要点
  • 收获与心得
  • 依然存在的问题
本次作业目标
  • 基本实现我罗斯的正常运行
  • 发表博客
本次作业正文   https://www.cnblogs.com/smallgrape/p/13122112.html
小组成员

   031902534  陈妍羽

   031902541  许雅萍

代码仓库     完整代码

 

一.代码仓库

我罗斯代码仓库

二.运行截图/运行的视频

点击观看视频

游戏封面:

游戏开始:

 

游戏结束,可选择再来一局

三.代码要点

//游戏类
class Game
{
public:
    void Move();//每个玩家操作的大函数
    void SetWindow();//初始界面 
    void GameOver(Player& player, Player& opponent);//游戏结束再来一局的函数
    void GamePause();//游戏暂停
    int step2(Player& player1, Player& player2);//方块生命过程的第二个步骤
};
int Game::step2(Player& player1, Player& player2)//读取按键,进行相应方块变化的函数
{
    int flag = 0;
    if (_kbhit())
    {
        switch (_getch())
        {
        case 'w':case 'W':
            player1.BlockUp(player1.OriginX);
            break;
        case 'a':case 'A':
            player1.BlockLeft(player1.OriginX);
            break;
        case 'd':case 'D':
            player1.BlockRight(player1.OriginX);
            break;
        case 's':case 'S':
            switch (player1.BlockDown(player1.OriginY))
            {
            case 0:
                player1.check = false;
                break;
            case 1:
                player1.check = true;
                break;
            case 2:
                GameOver(player1, player2);
                flag = 1;
                //goto initial;
            }
            break;
        case 72:
            player2.BlockUp(player2.OriginX);
            break;
        case 75:
            player2.BlockLeft(player2.OriginX);
            break;
        case 77:
            player2.BlockRight(player2.OriginX);
            break;
        case 80:
            switch (player2.BlockDown(player2.OriginY))
            {
            case 0:
                player2.check = false;
                break;
            case 1:
                player2.check = true;
                break;
            case 2:
                GameOver(player2, player1);
                flag = 1;
                //goto initial;
            default:
                break;
            }
            break;
        case 32:
            GamePause();
            break;
        case 27:
            exit(0);
        default:
            break;
        }
    }
    return flag;
}
gameover函数:
void Game::GameOver(Player& player, Player& opponent)//gameover函数,一轮游戏的结束,可以敲击空格键再来一局
{
    SetConsoleTextAttribute(hOut, BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
    SetPos(player.x0 + 10, 8);
    cout << "LOSE";
    SetPos(48 - player.x0 + 10, 8);
    cout << "WIN";
    SetConsoleTextAttribute(hOut, BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
    SetPos(38, 22);
    cout << "空格键重新开始";
    SetPos(40, 23);
    cout << "Esc键退出";
    char key;
    while (true)
    {
        key = _getch();
        if (key == 32)
        {
            SetConsoleTextAttribute(hOut, BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
            player.PrintScreen();
            opponent.PrintScreen();
            return;
        }
        if (key == 27)
        {
            exit(0);
        }
    }
}

 

//玩家类
//随机生成,打印,清除方块的操作函数
{
void randBlock();
void printBlock(int block[4][4], int a, int b);//打印 
void clearBlock(int block[4][4], int a, int b);
}
//对运动中的方块的四种操作
{
int BlockDown(int y);
void BlockLeft(int x);
void BlockRight(int x);
void BlockUp(int x);

}
//检测碰撞,消行,加行的函数
{
void Eliminate_Row_Add_Row(int& val, int map2[21][12]);
bool Detect_Collision(int block[4][4], int x, int y);
}
//被大函数调用的两个步骤函数
{
bool step1(int& val, Player& opponent);
int step3();
}
//绘制玩家的游戏页面,初始化地图
{
void setMap();
void PrintScreen();//打印窗口
}
检测碰撞
bool Player::Detect_Collision(int block[4][4], int x, int y)
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if (x + i >= 0 && y + j >= 0 && map[x + i][y + j] && block[i][j] == 1)
            {

                return false;
            }
        }
    }

    return true;
}
增减行函数:
void Player::Eliminate_Row_Add_Row(int& val, int map2[21][12])//为玩家自己消一行,为对方增加一行
{
    int checking = 0;//判断是否需要消行
    SetConsoleTextAttribute(hOut, BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
    int i, j, m, n, x, f, k;
    for (i = 19; i >= 0; i--)
    {
        x = 0;
        for (j = 1; j < 11; j++)
        {
            x += map[i][j];
        }

        if (x == 10)
        {
            checking = 1;
            for (m = i; m > 0; m--)
            {
                for (n = 1; n < 11; n++)
                {
                    map[m][n] = map[m - 1][n];
                    SetPos(2 * (n + x0 / 2), y0 + m);
                    if (map[m][n] == 1)
                    {
                        cout << "█";
                    }
                    else
                    {
                        cout << "  ";
                    }
                }
            }
            i++;
        }
    }
    if (checking == 1)
    {
        for (i = 0; i < 20; i++)//寻找方块镇的首行
        {
            f = 0;
            for (j = 1; j < 11; j++)
            {
                if (map2[i][j] != 0)
                {
                    f = 1;
                }
                if (f == 1)
                    break;
            }
            if (f == 0)break;
        }
        int y = i;
        for (m = i; m < 19; m++)//地图向上平移
        {
            for (j = 1; j < 11; j++)
            {
                map2[m][j] = map2[m + 1][j];
            }
        }
        map2[19][1] = 1;//为了避免随机生成的凌乱的一行,全是方块,或全是空的
        map2[19][10] = 0;
        for (i = 2; i < 10; i++)
        {
            k = rand() % 2;
            map2[19][i] = k;
        }
        for (i = y; i < 20; i++)
        {
            for (j = 1; j < 11; j++)
            {
                SetPos(2 * (j + (48 - x0) / 2), y0 + i);
                if (map2[i][j] == 1)
                {
                    cout << "█";
                }
                else
                {
                    cout << "  ";
                }
            }
        }
    }

}
//实现双人游戏

网上查询到的资料,要实现两个玩家各玩各的,互不影响,要用双线程。双线程学了一些知识,也用了进去,但是有出现问题;了解到双线程,看起来是双人同时玩,但是实际上,同一个时刻其实还是只会执行其中一个玩家的代码,只不过是时间够短,“看不出来”;实际上,是错开时间执行两个玩家各自的代码,于是思考到了另外的方式,实现双人模式,就真的是两个玩家交替执行,实现还可以。

    player1.setMap();
    player2.setMap();
    srand((unsigned)time(NULL));
    player1.randBlock();
    player2.randBlock();
    while (true)
    {
        if (player1.step1(val, player2))
        {
            GameOver(player1, player2);
            goto initial;

        }

        player1.printBlock(player1.newblock, player1.OriginX, player1.OriginY);

        if (player2.step1(val, player1))
        {
            GameOver(player2, player1);
            goto initial;
        }

        player2.printBlock(player2.newblock, player2.OriginX, player2.OriginY);

        if (step2(player1, player2))
            goto initial;

        Sleep(20);
        if (!(--times))
        {
            if (player1.step3())
            {
                GameOver(player1, player2);
                goto initial;
            }

            if (player2.step3())
            {
                GameOver(player2, player1);
                goto initial;
            }

            times = val;
        }

    }
    cin.get();
双线程设计背景音乐与我罗斯游戏并行
void music()
{
    while (1)
    {
        PlaySound(LPWSTR(IDR_WAVE2), GetModuleHandle(NULL), SND_RESOURCE | SND_LOOP);
        PlaySound(LPWSTR(IDR_WAVE3), GetModuleHandle(NULL), SND_RESOURCE | SND_LOOP);
        PlaySound(LPWSTR(IDR_WAVE4), GetModuleHandle(NULL), SND_RESOURCE | SND_LOOP);
        PlaySound(LPWSTR(IDR_WAVE5), GetModuleHandle(NULL), SND_RESOURCE | SND_LOOP);
    }

}
int main()
{
    //    SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    Game game;
    game.SetWindow();
    initgraph(840, 560);

    IMAGE a;
    loadimage(&a, L"jpg", MAKEINTRESOURCE(IDB_BITMAP1));
    putimage(0, 0, &a);
    _getch();
    closegraph();
    //
    thread t1(music);
    thread t2((&Game::Move), game);
    t1.join();
    t2.join();
    return 0;
}

 

 

四.收获与心得

1、收获最大的肯定是找代码bug的能力,不得不说,最困难的事,本来以为是实现双人模式,但是实际上最困难的莫过于,修改优化代码后,出现的令人措手不及的一系列bug。最叫人难受的是,每次犯了一些搞笑的错误,比如该是玩家1的时候,写成了玩家2,导致游戏实现的乱七八糟,结果不停调试不停找,分析应该是哪里出现了错误,有时候找了几个钟头,最后猛然发现是某些惊为天人的愚蠢的错误。感觉有些时候,不知名地方的一个小错误,像是蝴蝶效应一样,会因为代码的庞大,函数之间,类之间错综复杂的关系,反映在看起来毫不相关的地方。果然,还是要努力打好基础,提升能力,才不会因为代码的越来越长,修改bug越来越吃力,费劲。

2、还有一点,要实现我罗斯,要学会了解好多东西,比如做界面的一系列函数,制作封面,设计背景音乐,时间的函数。要在短的时间,迅速掌握一些方法的使用,并不容易,尤其是网络上的信息真的太乱了,有时候开了几十个窗口,搜寻到的有效信息还是不足以实现相应的功能,要了解到有用的信息真是不容易。

3、最后一点,能实现这个游戏,在一开始知晓这个学习任务的时候,是没有料到会做成的,尤其是要实现双人模式,但是当那个夜晚,实现了双人玩耍,两只手玩着双人的俄罗斯的时候,原来我们真的可以做成,真是不可思议。后来我们还设计了一个封面,封面的图片是画出来的,还加了背景音乐,虽然,还有好多可以改进的地方,但是亲手做出来的东西,还是很喜欢的。

 

五.依然存在的问题

1、原设想是,我罗斯游戏的背景要设计成颜色丰富,更好看的样子,暂时还不会实现背景嵌套;

2、我罗斯的方块的下降速度,还没有设计成可以根据玩家自己的意愿更改速度,因为我们的游戏只分玩家胜负,没有限制玩一盘的时间,所以并不需要,分数,后续要改进成,即使两个玩家不分伯仲都可以保持方块不到顶,也要根据一轮游戏,有限的时间,分数的高低,来确定输赢的局面。

3、因为,使用的是检测按键的函数,再区分那个键是哪一种键,来实现方块的运动;所以当一个玩家长按某个键,另一个玩家的按键会失灵;

4、还没来得及,设计输入玩家的名字,或是直接固定玩家的名字(主要是还没想到理想的游戏玩家昵称);

5、因为双人模式就是从单人模式发展过来的,我罗斯是一个双人游戏,就没有设计单双人模式可供选择,任意切换,后期会尝试改进。

 

标签:case,break,罗斯,最终,player2,int,player1,void,方块
来源: https://www.cnblogs.com/smallgrape/p/13122112.html