Stubborn 发表于 2021-5-12 16:14:36

C语言,2048游戏文字版,流程逻辑思路,代码详解(中)

本帖最后由 Stubborn 于 2021-5-12 18:01 编辑

C语言,2048游戏文字版,流程逻辑思路,代码详解(中)

上一篇已经实现了大部分的绘制函数,这部分开始实现游戏的逻辑函数
⑤bool GeneratingRandomNumbers(struct Game *);大致逻辑是,随机生成2或者4,都是1/2的概率,然后随机生成一个索引,在数据列表中为0的位置跟新
bool GeneratingRandomNumbers(struct Game *data){
    /**Generate a random number and place it in a random position where the data parameter is not 0。
   *If the modification is successful, return true; otherwise, return false。
   */
    srand(time(NULL));

    short value = ((const short []){2, 4});
    size_t randomIndex = (size_t) randint(data->length);
    data->score += value;
    data->move += 1;

    for (size_t rightIndex = randomIndex; rightIndex < data->length; ++rightIndex)
    {
      if (data->arr==0)
      {
            data->arr = value;
            return true;
      }

    }

    for (size_t leftIndex = randomIndex; leftIndex > 0; --leftIndex)
    {
      if (data->arr==0)
      {
            data->arr = value;
            return true;
      }
    }
    return false;

}

好了,写到这里,开始回顾一下,实现的什么功能,以及程序的运行流程。
1.程序运行,展示一个欢迎界面,并提供输入选择。
2.输入对应的选择会有对应的界面
3.选择开始游戏后,生成一个随机数,并且打印出游戏界面。
那么接下来,我们就应该编写监听键盘的输入的函数,并实现⑥数字的移动以及合并选择。
首先是监听键盘的输入的函数bool JudgmentInput(int, struct Game *);   
根据对应的键盘操作,调用不同的移动函数,当游戏可以发生移动,或者合并的时候,返回一个true。否则返回一个false。
其次当操作成功之后,在生成一个随机数,操作失败检测下当前游戏是不是可以结束,即当前游戏不能发生移动,合并的情况。
不管成功或者失败,都看下有没有到胜利条件,看下合成的数字有没有到2048。然后再次绘制游戏界面,跟新游戏状态。

函数bool JudgmentInput(int, struct Game *); 实现的逻辑是:
当键盘发生了上下左右的操作,调用对应的移动合并操作。
如果移动合并操作失败,或者发生其他的操作,检查游戏是不是结束,或者胜利。
再次打印游戏界面
bool JudgmentInput(int key, struct Game *data){
    bool flag = false;
    switch (key) {////LEFT = 75, UP = 72, RIGHT = 77, DOWN = 80, Esc=27
      case 72:
            flag = MoveUp(data);
            break;
      case 80:
            flag =MoveDown(data);
            break;
      case 75:
            flag =MoveLeft(data);
            break;
      case 77:
            flag =MoveRight(data);
            break;
      case 27:
            exit(0);
    }
    if (flag){
      GeneratingRandomNumbers(data);
    } else {
      DrawLoser(data);
    }
    DrawWin(*data);
    DrawTheGameBox(*data);
    return flag;
}


在void StartGame()函数里面死循环,监听键盘操作
void StartGame(){
    /**Start the game, run the logic of the game
   * */
    bool True = true;
    struct Game data= {16, {0}, 0, 0, 0, time(NULL)};
    struct Game *p = &data;
    GeneratingRandomNumbers(p);
    DrawTheGameBox(data);
    // 监听键盘
    while (True)
    {
      while (kbhit())
      {
            JudgmentInput(getch(), p);
      }
    }
}



现在开始实现⑥部分的数字合并部分,也是整个游戏的逻辑核心。首先看图。




首先看左侧,游戏往上移动。2048游戏的逻辑是什么?
数字向上移动,如果相邻的两个各自数字一样,则合并成一个新数字。

所以我们实现的逻辑是什么?具体如何实现?
我们需要实现数字移动,以及数字的合并。

怎么移动数字,一个最基本的逻辑 ,当遍历到数值为0的时候,那么表明这个位置可以被填充的,0下方的数字都可以移动。用编程表达就是这两个位置可以交换
arr = arr;
arr = 0;


注意,因为我这里使用的是一维数组,表达方式不一样。实际看个人的数据进行表达。一定要注意数组的越界,我们应该遍历到第三层就停止遍历。
当我们整个遍历一次后,会发生什么?可以移动的数字,全部往上移动了一层。那么我们重复这个步骤,那么就可以全部进行移动


怎么进行数字的合并。和移动数字的逻辑差不多,当遍历数组的时候,发现当前遍历的索引index 和 index + 4 值一样,即上下两个值一样,就可以进行合并。用编程表达就是这两个位置发生改变:
arr *= 2;
arr = 0;



合并之后,又会出现 0 的空位,此时我们再次调用移动函数,进行移动即可完成一次的移动操作
bool _MoveUp(struct Game *data){
    bool flag = false;
    for (size_t _index = 4; _index < data->length; _index+=4)
    {
      for (size_t index = 4; index < data->length; ++index)
      {
            if (data->arr == 0 && data->arr !=0)
            {
                data->arr = data->arr;
                data->arr = 0;
                flag = true;
            }
      }
    }
    return flag;
}

bool MoveUp(struct Game *data){
    // 上移操作,需要实现的逻辑有,数字的移动以及合并,是否是有效的移动
    bool flag = false;
    flag = _MoveUp(data);
    for (size_t index = 0; index < data->length-4; ++index) {
      if (data->arr == data->arr && data->arr != 0)
      {
            data->arr *= 2;
            if (data->arr > data->max){
                data->max = data->arr;
            }
            data->arr = 0;
            flag = true;
      }
    }
    _MoveUp(data);
    return flag;
}

bool _MoveLeft(struct Game *data)
{
    bool flag = false;
    for (size_t _index = 4; _index < data->length; _index+=4)
    {
      for (size_t index = 0; index < data->length; index+=4)
      {
            for (size_t i = 0; i < 4 - 1; ++i)
            {
                if (data->arr == 0 && data->arr != 0)
                {
                  data->arr = data->arr;
                  data->arr = 0;
                  flag = true;
                }
            }
      }
    }
    return flag;

}

bool MoveLeft(struct Game *data)
{
    bool flag = false;
    flag = _MoveLeft(data);
    for (size_t index = 0; index < data->length; index+=4)
    {
      for (size_t i = 0; i < 4 - 1; ++i)
      {
            if (data->arr == data->arr && data->arr!= 0)
            {
                data->arr *= 2;
                if (data->arr > data->max){
                  data->max = data->arr;
                }
                data->arr = 0;
                flag = true;
            }
      }
    }
    _MoveLeft(data);
    return flag;

}

bool _MoveRight(struct Game *data)
{
    bool flag = false;
    for (size_t _index = 4; _index < data->length; _index+=4)
    {
      for (size_t index = 3; index < data->length; index+=4) // 3711 15
      {
            for (size_t i = 0; i < 4 - 1; ++i)
            {
                if (data->arr == 0 && data->arr != 0)
                {
                  data->arr = data->arr;
                  data->arr = 0;
                  flag = true;
                }
            }
      }
    }
    return flag;
}

bool MoveRight(struct Game *data)
{
    bool flag = false;
    flag = _MoveRight(data);
    for (size_t index = 3; index < data->length; index+=4) // 3711 15
    {
      for (size_t i = 0; i < 4 - 1; ++i)
      {
            if (data->arr == data->arr && data->arr != 0) // 0 1 2
            {
                data->arr *= 2;
                if (data->arr > data->max){
                  data->max = data->arr;
                }
                data->arr = 0;
                flag = true;
            }
      }
    }
    _MoveRight(data);
    return flag;

}

bool _MoveDown(struct Game *data)
{
    bool flag = false;
    for (size_t _index = 4; _index < data->length; _index+=4)
    {
      for (size_t index = data->length - 1; index >= 4; --index)
      {
            if (data->arr == 0 && data->arr !=0)
            {
                data->arr = data->arr;
                data->arr = 0;
                flag = true;
            }
      }
    }
    return flag;
}

bool MoveDown(struct Game *data)
{
    bool flag = false;
    flag = _MoveDown(data);
    for (size_t index = data->length - 1; index >= 4; --index)
    {
      if (data->arr == data->arr && data->arr !=0)
      {
            data->arr *=2 ;
            if (data->arr > data->max){
                data->max = data->arr;
            }
            data->arr = 0;
            flag = true;
      }
    }
    _MoveDown(data);
    return flag;
}




页: [1]
查看完整版本: C语言,2048游戏文字版,流程逻辑思路,代码详解(中)