加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

游戏2048的核心算法c#版本的实现

发布时间:2020-12-16 01:17:27 所属栏目:百科 来源:网络整理
导读:接触游戏有一段时间了,也写了一些东西,效果还不错,今天没事,我就把2048 c# 版本的实现贴出来,代码已经测试过,可以正常、完美运行。当然了,在网上有很多有关2048的实现方法,但是没有提出到类里面,只是写的测试代码,我在这里已经完全提到类里面,核

    接触游戏有一段时间了,也写了一些东西,效果还不错,今天没事,我就把2048 c# 版本的实现贴出来,代码已经测试过,可以正常、完美运行。当然了,在网上有很多有关2048的实现方法,但是没有提出到类里面,只是写的测试代码,我在这里已经完全提到类里面,核心类和核心方法都经过测试,没有问题。由于本人学习有漏,或者不足,也请大家批评指正,大家共同进步。

   ?? 该文章分为三个部分,我们分门别类说的,大家也会很清楚。目录如下:

    第一部分:图片展示,最开始,我还是先把程序的运行效果贴出来,大家有一个初步感受。

    第二部分:代码的前端部分,因为我这个程序就是一个在控制台中运行的程序,没有界面。但是有些操作需要在控制台中操作,这部分代码在控制台中。

    第三部分:2048核心的类和辅助类型,所有核心算法和实现都在这里,都已经封装了方法,直接调用就可以。

    其实这三个部分很简单,每个部分都有自己的职责,废话不多说了,直接上代码。

    一、2048 在控制台中的运行效果(主要以贴图为主。)

      1、数据初始化

        


      这是程序第一次执行的效果,数据刚刚完成初始化。

      2、操作开始,点击键盘的 a 字母代表向做移动,分为两张图,移动前和移动后的效果。

        左移前
        

        左移后
        



       3、点击键盘的 D 字符代表向右移动,分为两个图片,分别是移动前和移动后。

          移动前
          


          移动后
          



        4、点击键盘的 w 字符代表向上移动,分为两个图片,分别是移动前和移动后。
          移动前

          

          移动后
          



        5、点击键盘的 s 字符代表向下移动,分为两个图片,分别是移动前和移动后。
          移动前

          

          移动后
          



    二、在控制台中控制逻辑和一些辅助方法,逻辑很简单,就不多说了,直接上代码。

?

 1 GameCoreManager game = new GameCoreManager(5);
 2 
 3             game.Initail();
 4 
 5             Console.WriteLine("原始数组:" 6             PrintArray(game.DataContainer);
 7             Console.WriteLine();
 8 
 9             while (true)
10             {
11                 if (game.CalculateEmptyElements(game.DataContainer).Count <= 012                 {
13                     Console.WriteLine(游戏结束14                     break;
15                 }
16                 switch (Console.ReadLine())
17 18                     case w:
19                         game.Move(Direction.Up);
20                         21                     s22                         game.Move(Direction.Down);
23                         24                     a25                         game.Move(Direction.Left);
26                         27                     d28                         game.Move(Direction.Right);
29                         30                     exit31                         32 33                 if (game.IsChange)
34 35                     game.GenerateRandomNumber();
36                     PrintArray(game.DataContainer);
37 38             }


?        以上代码就是放在控制台的 Main 方法中药执行的代码。

?        这个代码主要适用于打印二维数组的,逻辑不复杂,用于在控制台中显示移动效果。
        

 1 /// <summary>
 2         /// 打印二维数组在控制台上。
 3         </summary>
 4         <param name="array">要打印数据的数组。</param>
 5         private static void PrintArray(int[,] array)
        {
            Console.Clear();
 8             if (array == null || array.Length <=  9 10                 Console.WriteLine(没有任何元素可以打印。11             }
12 
13             for (int row = 0; row < array.GetLength(0); row++14 15                 int column = 0; column < array.GetLength(1); column++16 17                     Console.Write(array[row,column]+t18                 Console.WriteLine();
20 21         }


        在控制台中的代码就是这些,是不是很简单,其实不是很复杂,接下来我们看看核心类的实现。


    三、2048 核心类 GameCoreManager 的实现,里面有完整的备注,所以我就不多说了。大家可以直接使用,测试。
      

  1   2      游戏核心算法的管理器类型,该类型定义 2048 游戏的核心算法。
  3       4     public sealed class GameCoreManager
  5     {
  6         #region 实例字段
  7 
  8           9 
 10         #endregion
 11 
 12         #region 构造函数
 13 
 14          15          初始化 GameCoreManager 类型的新实例,数据容器维度默认值:4.
 16          17         public GameCoreManager() : this(4) { }
 18 
 19          20          通过制定的数据维度初始化 GameCoreManager 类型的新实例。
 21          22         <param name="capacity">数据容量。 23         public GameCoreManager( capacity)
 24  25             if (capacity <= 0 || capacity >= 32 26  27                 throw new ArgumentNullException(dimensional is null. 28  29             DataContainer = new [capacity,capacity];
 30         }
 31 
 32          33 
 34         #region 实例属性
 35 
 36          37          获取数据
 38          39         int[,] DataContainer { get => _dataContainer; set => _dataContainer = value; }
 40 
 41          42 
 43         #region 实例接口方法
 44 
 45          46          初始化游戏数据。
 47          48         void Initail()
 49  50             int length = DataContainer.GetLength(0) / 2 + DataContainer.GetLength(0) % 2 51             int i = 0; i < length; i++ 52  53                 GenerateRandomNumber();
 54  55  56 
 57          58          数据移动。
 59          60         <param name="direction">要移动的方向 61          Move(Direction direction)
 62  63             //判断原数组是否发生了变化。
 64             记录原数组。
 65             int[DataContainer.GetLength(0),DataContainer.GetLength(1)];
 66             Array.Copy(DataContainer,destinationArray,DataContainer.Length);
 67             IsChange = false 68 
 69              (direction)
 70  71                 case Direction.Up:
 72                     MoveUp();
 73                      74                  Direction.Down:
 75                     MoveDown();
 76                      77                  Direction.Left:
 78                     MoveLeft();
 79                      80                  Direction.Right:
 81                     MoveRight();
 82                      83  84 
 85             比较现在的数组和以前的数组比较
 86             0; row < DataContainer.GetLength( 87  88                 0; column < DataContainer.GetLength( 89  90                     if (DataContainer[row,column] != destinationArray[row,column])
 91                     {
 92                         IsChange =  93                         return 94                     }
 95  96  97  98 
 99         100          获取或者设置数组元素是否发生变动。true 表示发生变动,false 表示没有变动。
101         102         bool IsChange { get; set; }
103 
104         105          计算空元素的个数,并保存元素的索引位置。
106         107         <param name="sourceArray">要处理的二维数组。108         <returns>返回保存空元素索引位置的列表对象。</returns>
109         public IList<Position> CalculateEmptyElements(110 111             IList<Position> elements = new List<Position>(DataContainer.GetLength(0) * DataContainer.GetLength());
112             if (sourceArray == null || sourceArray.Length <= 113 114                  elements;
115 116 
117             0; row < sourceArray.GetLength(118 119                 0; column < sourceArray.GetLength(120 121                     if (sourceArray[row,column] == 122 123                         elements.Add(new Position(row,column));
124 125 126 127             128 129 
130         131          随机生成数字元素填充空的数组元素。
132         133          GenerateRandomNumber()
134 135             var list = CalculateEmptyElements(this.DataContainer);
136             if (list.Count > 137 138                 Random random =  Random();
139                 var position = list[random.Next(,list.Count)];
140                 DataContainer[position.Row,position.Column] = random.Next(0,10) == 4 ? 4 : 141 142 143 
144         145 
146         #region 实例私有方法(核心算法)
147 
148         149          将数组中的为 0 的元素移动到数组最后面。[1,2],结果为【1,2,0】
150         151         要处理的数组。152         void MoveZeroToLast([] array)
153 154             155 156                 157 158 
159             int[] myarray = [array.Length];
160 
161             int index = 162             0; i < array.Length; i++163 164                 if (array[i] != 165 166                     myarray[index++] = array[i];
167 168 169             通过引用修改元素才可以,修改引用对外界没有影响。
170             myarray.CopyTo(array,1)">171 172 
173         174          合并数组中相邻相同的数字元素,后一个元素清零。[2,2],结果为【4,1)">175         176         177         void MergeSameNumber(178 179             180 181                 182 183 
184             MoveZeroToLast(array);2,0
185 
186             0; i < array.Length - 1; i++187 188                 0 && array[i] == array[i + ])
189 190                     array[i] += array[i + ];
191                     array[i + 1] = 192 193 194 
195             4,1)">196 
197             MoveZeroToLast(array);198 199 
200         201          向上移动数据。
202         203          MoveUp()
204 205             从上往下取数据。
206             if (DataContainer == null || DataContainer.Length <= 207 208                 209 210 
211             int[] tempArray = 212 
213             214 215                 216 217                     tempArray[row] = DataContainer[row,column];
218 219 
220                 MergeSameNumber(tempArray);
221 
222                 223 224                     DataContainer[row,column] = tempArray[row];
225 226 227 228 
229         230          向下移动数据。
231         232          MoveDown()
233 234             从下往上取
235             236 237                 238 239 
240             241 
242             243 244                 int row = DataContainer.GetLength(0) - 1; row >= 0; row--245 246                     tempArray[DataContainer.GetLength(1 - row] =247 248 
249 250 
251                 252 253                     DataContainer[row,column] = tempArray[DataContainer.GetLength(1 - row];
254 255 256 257 
258         259          向左移动数据。
260         261          MoveLeft()
262 263             264 265                 266 267             从左往右
268 
269             270 
271             0; i < DataContainer.GetLength(0); i++272 273                 int j = 0; j < DataContainer.GetLength(1); j++274 275                     tempArray[j] = DataContainer[i,j];
276 277 
278 279 
280                 281 282                     DataContainer[i,j] = tempArray[j];
283 284 285 286 
287         288          向右移动数据。
289         290          MoveRight()
291 292             293 294                 295 296 
297             从右向左取
298 
299             { 2,4,8 },8
300             301             { 0,8,0 },1)">302             303 
304             305 
306             1); i++307 308                 int j = DataContainer.GetLength(1) - 1; j >= 0; j--309 310                     8,2
311                     tempArray[DataContainer.GetLength(1 - j] =312 313 
314                 315 316 
317                 318 319                     DataContainer[i,j] = tempArray[DataContainer.GetLength( j];
320 321 322         }        
323 
324         325     }

?

?    另外,还有两个枚举类型,代码很简单,直接贴代码了。

 1      2      元素的坐标位置。
 3      4     struct Position
 5  6          7          获取或者设置元素的行坐标。
 8          9         int Row { 10 
11         12          获取或者设置元素的列坐标。
13         14         int Column { 15 
16         17          通过行坐标、列坐标初始化 Position 对象实例。
18         19         <param name="row">元素的行坐标。20         <param name="column">元素的列坐标。21         public Position(int row, column)
23             if (row >= 0 && column >= 24 25                 this.Row = row;
26                 this.Column = column;
27 28             else
29 30                 parameter is null.31 33     }
34 
35     36      移动的方向。
37     38     enum Direction
39 40         41          向上移动
42         43         Up,1)">44 
45         46          向下移动
47         48         Down,1)">49 
50         51          向左移动
52         53         Left,1)">54 
55         56          向右移动
57         58         Right
59     }

?


    这就是2048 核心类的实现,代码都有备注,其实,逻辑也不复杂,大家看也是可以看得懂的,只是需要点耐心。

    文章就到此为止了,这是有关2028的核心算法,我发的代码都是经过测试的,大家可以拿过去直接使用,修改和测试。而且代码都很完整,所以我就没有把源码贴出来。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读