接触游戏有一段时间了,也写了一些东西,效果还不错,今天没事,我就把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 }
这个代码主要适用于打印二维数组的,逻辑不复杂,用于在控制台中显示移动效果。
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的核心算法,我发的代码都是经过测试的,大家可以拿过去直接使用,修改和测试。而且代码都很完整,所以我就没有把源码贴出来。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。