1024(改进版)的控制代码(无界面)

最近自己动手写了一个1024小游戏的控制代码,没有界面,但是比起原始版本多了对角线方向可以滑动,设计思路如下:

[0]:控制数字滑动的模块,我将它写成一个类的成员函数.实现数字的滑动以及相同数字的合并.因为数字有8个方向滑动,因此我们需要将不同方向的数字比较的方向,开始的位置都记录下来,然后写出一个通用的框架来处理四个方向的滑动.

bool Game:: slide(string ms)
{
    auto &data = *matrix.get();
    auto de_i = get<0>(direction[ms]),de_j = get<1>(direction[ms]);//获取本次滑动的数字比较方向(eg: [x][y]向[x+de_i][y+de_j]移动)
    auto beg_row = get<2>(direction[ms]),beg_col = get<3>(direction[ms]);//获取本次滑动数字开始比较的位置(eg:从第[beg_row][beg_col]开始滑动)
    auto de_row = (beg_row==N-2) ? -1 : 1,de_col = (beg_col==N-2) ? -1 : 1;//获取应该处理的下一个数字[x+de_row][y+de_col]
    MyType isnewvalue(N);
    for (auto &it : isnewvalue) it.resize(N);
    bool valuechanged = false;
    for (size_t i = beg_row; isgood(i);i+=de_row)
    for (size_t j = beg_col; isgood(j); j+=de_col)
    {
        if (!data[i][j])
            continue;//当前数字不存在,直接处理下一个数字
        int temp_i = i, temp_j = j;
        if (!data[i + de_i][j + de_j])//当前方向没有数字,数字滑动
        {
            valuechanged = true;//数字将会移动,状态改变
            while (isgood(i + de_i) && isgood(j + de_j)&&!data[i + de_i][j + de_j] )
                i += de_i,j += de_j;

            data[i ][j] = data[temp_i][temp_j];
            data[temp_i][temp_j] = 0;
        }
        //数字移动后继续进行合并处理
        if (isgood(i+de_i)&&isgood(j+de_j)&&(data[i][j] == data[i + de_i][j + de_j])&&
            !isnewvalue[i+de_i][j+de_j])
        {   
            data[i][j] = 0;
            data[i + de_i][j + de_j] *= 2;
            isnewvalue[i + de_i][j + de_j] = 1;//标记为刚刚生成,后来的数字不能与刚才生成新数字合并
            --count;//数字个数少1
            valuechanged = true;//数字合并,状态改变
        }
        i = temp_i, j = temp_j;
    }
    return valuechanged;//返回矩阵状态是否改变过
}

[1]数字生成模块:每次滑动后都应该生成新的数字,需要判断能生成几个(0,1或2),以及相应位置必须是空的.

void Game:: generate()
{
        auto &data = *matrix.get();
        int x, y;
        srand(time(0));//产生随机数种子
        int n = 0;//产生的数字个数
        while (count != N*N&&n != 2)
        {
            do{
                x = rand() % N;
                y = rand() % N;
            } while (data[x][y]);
            data[x][y] = (count % 2) ? 2 : 4;
            ++count;//总个数加1
            ++n;//产生的数字个数加1
        }
}

[2]判断游戏是否结束:当竖直方向以及水平方向和对角线与反对角线方向都不会产生数字矩阵状态变化的可能,则游戏结束.所以这里需要slide函数的配合,在slide函数中记录状态是否变化.

bool Game::isfailed()
{
    Game temp = *this;
    bool ans = (count == N*N&&!temp.slide("up") && !temp.slide("right")
        &&!temp.slide("leftup")&&!temp.slide("rightup"));
    if (ans)
        cout << "game over";
    return ans;//返回是否失败
}

[3]:游戏类的设计

class Game
{
    #define isgood(x) ((x!=N&&x!=-1)?true:false)//判断坐标是否越界
    using MyType = vector<vector<int>>;
    using change = tuple<int, int, int, int>;
public:
    Game(int n) : matrix(make_shared<MyType>(n)),N(n){
        for (auto &it : *matrix) it.resize(N);
        direction.insert({ "up", change(-1, 0, 1, 0) });
        direction.insert({ "down", change(1, 0, N - 2, 0) });
        direction.insert({ "left", change(0,-1 , 0, 1) });
        direction.insert({ "right", change(0, 1, 0, N-2) });
        direction.insert({ "leftup", change(-1, -1, 1, 1) });
        direction.insert({ "rightdown", change(1, 1, N-2, N-2) });
        direction.insert({ "leftdown", change(1, -1, N-2, 1) });
        direction.insert({ "rightup", change(-1, 1, 1, N-2) });});

    }
    Game(const Game& g) :N(g.N), count(g.count), direction(g.direction) {
          matrix = make_shared<MyType>(*g.matrix.get());
    }
    void print();
    bool slide(string ms);
    void generate();    
    bool isfailed();

private:
    const size_t N;//表示矩阵的大小N*N
    size_t count;//表示存在的数字个数
    map<string, change>direction;
    shared_ptr<MyType> matrix;
};

[4]:print()函数

void Game:: print()
{
    auto &data = *matrix.get();
    cout << std::endl;
    for (auto row : data)
    {
        cout << std::endl;
        for (auto it : row)
            cout << it << "\t";
    }
}

[5]:主函数:设计了简单/困难两种模式,简单模式在游戏失败前每一次滑动都会产生新的数字,而困难模式则要求数字矩阵状态改变才会产生新数字.

int main()
{
    cout << "请选择简单/困难模式\n";
    string mode;//模式
    cin >> mode;
    Game game(4);
    game.generate();
    game.print();
    string ms;
    while (cin>>ms&&!game.isfailed())
    {
        auto changed = game.slide(ms);
        if (mode == "easy"||changed)
        game.generate();
        game.print();
    } 
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值