鱼C论坛

 找回密码
 立即注册
查看: 1754|回复: 0

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

[复制链接]
发表于 2021-5-12 16:14:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

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


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

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

  10.     for (size_t rightIndex = randomIndex; rightIndex < data->length; ++rightIndex)
  11.     {
  12.         if (data->arr[rightIndex]==0)
  13.         {
  14.             data->arr[rightIndex] = value;
  15.             return true;
  16.         }

  17.     }

  18.     for (size_t leftIndex = randomIndex; leftIndex > 0; --leftIndex)
  19.     {
  20.         if (data->arr[leftIndex]==0)
  21.         {
  22.             data->arr[leftIndex] = value;
  23.             return true;
  24.         }
  25.     }
  26.     return false;

  27. }
复制代码


好了,写到这里,开始回顾一下,实现的什么功能,以及程序的运行流程。
1.程序运行,展示一个欢迎界面,并提供输入选择。
2.输入对应的选择会有对应的界面
3.选择开始游戏后,生成一个随机数,并且打印出游戏界面。
那么接下来,我们就应该编写监听键盘的输入的函数,并实现⑥数字的移动以及合并选择。

首先是监听键盘的输入的函数bool JudgmentInput(int, struct Game *);   
根据对应的键盘操作,调用不同的移动函数,当游戏可以发生移动,或者合并的时候,返回一个true。否则返回一个false。
其次当操作成功之后,在生成一个随机数,操作失败检测下当前游戏是不是可以结束,即当前游戏不能发生移动,合并的情况。
不管成功或者失败,都看下有没有到胜利条件,看下合成的数字有没有到2048。然后再次绘制游戏界面,跟新游戏状态。

函数bool JudgmentInput(int, struct Game *); 实现的逻辑是:
当键盘发生了上下左右的操作,调用对应的移动合并操作。
如果移动合并操作失败,或者发生其他的操作,检查游戏是不是结束,或者胜利。
再次打印游戏界面

  1. bool JudgmentInput(int key, struct Game *data){
  2.     bool flag = false;
  3.     switch (key) {  ////LEFT = 75, UP = 72, RIGHT = 77, DOWN = 80, Esc=27
  4.         case 72:
  5.             flag = MoveUp(data);
  6.             break;
  7.         case 80:
  8.             flag =  MoveDown(data);
  9.             break;
  10.         case 75:
  11.             flag =  MoveLeft(data);
  12.             break;
  13.         case 77:
  14.             flag =  MoveRight(data);
  15.             break;
  16.         case 27:
  17.             exit(0);
  18.     }
  19.     if (flag){
  20.         GeneratingRandomNumbers(data);
  21.     } else {
  22.         DrawLoser(data);
  23.     }
  24.     DrawWin(*data);
  25.     DrawTheGameBox(*data);
  26.     return flag;
  27. }
复制代码



在void StartGame()函数里面死循环,监听键盘操作
  1. void StartGame(){
  2.     /**Start the game, run the logic of the game
  3.      * */
  4.     bool True = true;
  5.     struct Game data= {16, {0}, 0, 0, 0, time(NULL)};
  6.     struct Game *p = &data;
  7.     GeneratingRandomNumbers(p);
  8.     DrawTheGameBox(data);
  9.     // 监听键盘
  10.     while (True)
  11.     {
  12.         while (kbhit())
  13.         {
  14.             JudgmentInput(getch(), p);
  15.         }
  16.     }
  17. }
复制代码




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

移动合并.png


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

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

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


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


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



合并之后,又会出现 0 的空位,此时我们再次调用移动函数,进行移动即可完成一次的移动操作
  1. bool _MoveUp(struct Game *data){
  2.     bool flag = false;
  3.     for (size_t _index = 4; _index < data->length; _index+=4)
  4.     {
  5.         for (size_t index = 4; index < data->length; ++index)
  6.         {
  7.             if (data->arr[index-4] == 0 && data->arr[index] !=0)
  8.             {
  9.                 data->arr[index-4] = data->arr[index];
  10.                 data->arr[index] = 0;
  11.                 flag = true;
  12.             }
  13.         }
  14.     }
  15.     return flag;
  16. }

  17. bool MoveUp(struct Game *data){
  18.     // 上移操作,需要实现的逻辑有,数字的移动以及合并,是否是有效的移动
  19.     bool flag = false;
  20.     flag = _MoveUp(data);
  21.     for (size_t index = 0; index < data->length-4; ++index) {
  22.         if (data->arr[index] == data->arr[index+4] && data->arr[index] != 0)
  23.         {
  24.             data->arr[index] *= 2;
  25.             if (data->arr[index] > data->max){
  26.                 data->max = data->arr[index];
  27.             }
  28.             data->arr[index+4] = 0;
  29.             flag = true;
  30.         }
  31.     }
  32.     _MoveUp(data);
  33.     return flag;
  34. }

  35. bool _MoveLeft(struct Game *data)
  36. {
  37.     bool flag = false;
  38.     for (size_t _index = 4; _index < data->length; _index+=4)
  39.     {
  40.         for (size_t index = 0; index < data->length; index+=4)
  41.         {
  42.             for (size_t i = 0; i < 4 - 1; ++i)
  43.             {
  44.                 if (data->arr[index + i] == 0 && data->arr[index+i+1] != 0)
  45.                 {
  46.                     data->arr[index+i] = data->arr[index+i+1];
  47.                     data->arr[index+i+1] = 0;
  48.                     flag = true;
  49.                 }
  50.             }
  51.         }
  52.     }
  53.     return flag;

  54. }

  55. bool MoveLeft(struct Game *data)
  56. {
  57.     bool flag = false;
  58.     flag = _MoveLeft(data);
  59.     for (size_t index = 0; index < data->length; index+=4)
  60.     {
  61.         for (size_t i = 0; i < 4 - 1; ++i)
  62.         {
  63.             if (data->arr[index + i] == data->arr[index + i + 1] && data->arr[index + i]  != 0)
  64.             {
  65.                 data->arr[index+i] *= 2;
  66.                 if (data->arr[index+i] > data->max){
  67.                     data->max = data->arr[index+i];
  68.                 }
  69.                 data->arr[index+i+1] = 0;
  70.                 flag = true;
  71.             }
  72.         }
  73.     }
  74.     _MoveLeft(data);
  75.     return flag;

  76. }

  77. bool _MoveRight(struct Game *data)
  78. {
  79.     bool flag = false;
  80.     for (size_t _index = 4; _index < data->length; _index+=4)
  81.     {
  82.         for (size_t index = 3; index < data->length; index+=4) // 3  7  11 15
  83.         {
  84.             for (size_t i = 0; i < 4 - 1; ++i)
  85.             {
  86.                 if (data->arr[index - i] == 0 && data->arr[index-i-1] != 0)
  87.                 {
  88.                     data->arr[index - i] = data->arr[index-i-1];
  89.                     data->arr[index- i -1] = 0;
  90.                     flag = true;
  91.                 }
  92.             }
  93.         }
  94.     }
  95.     return flag;
  96. }

  97. bool MoveRight(struct Game *data)
  98. {
  99.     bool flag = false;
  100.     flag = _MoveRight(data);
  101.     for (size_t index = 3; index < data->length; index+=4) // 3  7  11 15
  102.     {
  103.         for (size_t i = 0; i < 4 - 1; ++i)
  104.         {
  105.             if (data->arr[index - i] == data->arr[index- i -1] && data->arr[index- i -1] != 0) // 0 1 2
  106.             {
  107.                 data->arr[index - i] *= 2;
  108.                 if (data->arr[index-i] > data->max){
  109.                     data->max = data->arr[index-i];
  110.                 }
  111.                 data->arr[index- i -1] = 0;
  112.                 flag = true;
  113.             }
  114.         }
  115.     }
  116.     _MoveRight(data);
  117.     return flag;

  118. }

  119. bool _MoveDown(struct Game *data)
  120. {
  121.     bool flag = false;
  122.     for (size_t _index = 4; _index < data->length; _index+=4)
  123.     {
  124.         for (size_t index = data->length - 1; index >= 4; --index)
  125.         {
  126.             if (data->arr[index] == 0 && data->arr[index-4] !=0)
  127.             {
  128.                 data->arr[index] = data->arr[index-4];
  129.                 data->arr[index-4] = 0;
  130.                 flag = true;
  131.             }
  132.         }
  133.     }
  134.     return flag;
  135. }

  136. bool MoveDown(struct Game *data)
  137. {
  138.     bool flag = false;
  139.     flag = _MoveDown(data);
  140.     for (size_t index = data->length - 1; index >= 4; --index)
  141.     {
  142.         if (data->arr[index] == data->arr[index-4] && data->arr[index-4] !=0)
  143.         {
  144.             data->arr[index] *=2 ;
  145.             if (data->arr[index] > data->max){
  146.                 data->max = data->arr[index];
  147.             }
  148.             data->arr[index-4] = 0;
  149.             flag = true;
  150.         }
  151.     }
  152.     _MoveDown(data);
  153.     return flag;
  154. }
复制代码





小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-29 10:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表