游戏2048的核心算法c#版本的实现
接触游戏有一段时间了,也写了一些东西,效果还不错,今天没事,我就把2048 c# 版本的实现贴出来,代码已经测试过,可以正常、完美运行。当然了,在网上有很多有关2048的实现方法,但是没有提出到类里面,只是写的测试代码,我在这里已经完全提到类里面,核心类和核心方法都经过测试,没有问题。由于本人学习有漏,或者不足,也请大家批评指正,大家共同进步。
该文章分为三个部分,我们分门别类说的,大家也会很清楚。目录如下:
第一部分:图片展示,最开始,我还是先把程序的运行效果贴出来,大家有一个初步感受。
第二部分:代码的前端部分,因为我这个程序就是一个在控制台中运行的程序,没有界面。但是有些操作需要在控制台中操作,这部分代码在控制台中。
第三部分:2048核心的类和辅助类型,所有核心算法和实现都在这里,都已经封装了方法,直接调用就可以。
其实这三个部分很简单,每个部分都有自己的职责,废话不多说了,直接上代码。
一、2048 在控制台中的运行效果(主要以贴图为主。)
1、数据初始化
这是程序第一次执行的效果,数据刚刚完成初始化。
2、操作开始,点击键盘的 a 字母代表向做移动,分为两张图,移动前和移动后的效果。
左移前
左移后
3、点击键盘的 D 字符代表向右移动,分为两个图片,分别是移动前和移动后。
移动前
移动后
4、点击键盘的 w 字符代表向上移动,分为两个图片,分别是移动前和移动后。
移动前
移动后
5、点击键盘的 s 字符代表向下移动,分为两个图片,分别是移动前和移动后。
移动前
移动后
二、在控制台中控制逻辑和一些辅助方法,逻辑很简单,就不多说了,直接上代码。
GameCoreManager game = new GameCoreManager(5); game.Initail(); Console.WriteLine("原始数组:");
PrintArray(game.DataContainer);
Console.WriteLine(); while (true)
{
if (game.CalculateEmptyElements(game.DataContainer).Count <= 0)
{
Console.WriteLine("游戏结束");
break;
}
switch (Console.ReadLine())
{
case "w":
game.Move(Direction.Up);
break;
case "s":
game.Move(Direction.Down);
break;
case "a":
game.Move(Direction.Left);
break;
case "d":
game.Move(Direction.Right);
break;
case "exit":
break;
}
if (game.IsChange)
{
game.GenerateRandomNumber();
PrintArray(game.DataContainer);
}
}
以上代码就是放在控制台的 Main 方法中药执行的代码。
/// <summary>
/// 打印二维数组在控制台上。
/// </summary>
/// <param name="array">要打印数据的数组。</param>
private static void PrintArray(int[,] array)
{
Console.Clear();
if (array == null || array.Length <= 0)
{
Console.WriteLine("没有任何元素可以打印。");
} for (int row = 0; row < array.GetLength(0); row++)
{
for (int column = 0; column < array.GetLength(1); column++)
{
Console.Write(array[row,column]+"\t");
}
Console.WriteLine();
}
}
这个代码主要适用于打印二维数组的,逻辑不复杂,用于在控制台中显示移动效果。
在控制台中的代码就是这些,是不是很简单,其实不是很复杂,接下来我们看看核心类的实现。
三、2048 核心类 GameCoreManager 的实现,里面有完整的备注,所以我就不多说了。大家可以直接使用,测试。
/// <summary>
/// 游戏核心算法的管理器类型,该类型定义 2048 游戏的核心算法。
/// </summary>
public sealed class GameCoreManager
{
#region 实例字段 private int[,] _dataContainer; #endregion #region 构造函数 /// <summary>
/// 初始化 GameCoreManager 类型的新实例,数据容器维度默认值:4.
/// </summary>
public GameCoreManager() : this(4) { } /// <summary>
/// 通过制定的数据维度初始化 GameCoreManager 类型的新实例。
/// </summary>
/// <param name="capacity">数据容量。</param>
public GameCoreManager(int capacity)
{
if (capacity <= 0 || capacity >= 32)
{
throw new ArgumentNullException("dimensional is null.");
}
DataContainer = new int[capacity, capacity];
} #endregion #region 实例属性 /// <summary>
/// 获取数据
/// </summary>
public int[,] DataContainer { get => _dataContainer; private set => _dataContainer = value; } #endregion #region 实例接口方法 /// <summary>
/// 初始化游戏数据。
/// </summary>
public void Initail()
{
int length = DataContainer.GetLength(0) / 2 + DataContainer.GetLength(0) % 2;
for (int i = 0; i < length; i++)
{
GenerateRandomNumber();
}
} /// <summary>
/// 数据移动。
/// </summary>
/// <param name="direction">要移动的方向</param>
public void Move(Direction direction)
{
//判断原数组是否发生了变化。
//记录原数组。
int[,] destinationArray = new int[DataContainer.GetLength(0), DataContainer.GetLength(1)];
Array.Copy(DataContainer, destinationArray, DataContainer.Length);
IsChange = false; switch (direction)
{
case Direction.Up:
MoveUp();
break;
case Direction.Down:
MoveDown();
break;
case Direction.Left:
MoveLeft();
break;
case Direction.Right:
MoveRight();
break;
} //比较现在的数组和以前的数组比较
for (int row = 0; row < DataContainer.GetLength(0); row++)
{
for (int column = 0; column < DataContainer.GetLength(1); column++)
{
if (DataContainer[row, column] != destinationArray[row, column])
{
IsChange = true;
return;
}
}
}
} /// <summary>
/// 获取或者设置数组元素是否发生变动。true 表示发生变动,false 表示没有变动。
/// </summary>
public bool IsChange { get; private set; } /// <summary>
/// 计算空元素的个数,并保存元素的索引位置。
/// </summary>
/// <param name="sourceArray">要处理的二维数组。</param>
/// <returns>返回保存空元素索引位置的列表对象。</returns>
public IList<Position> CalculateEmptyElements(int[,] sourceArray)
{
IList<Position> elements = new List<Position>(DataContainer.GetLength(0) * DataContainer.GetLength(1));
if (sourceArray == null || sourceArray.Length <= 0)
{
return elements;
} for (int row = 0; row < sourceArray.GetLength(0); row++)
{
for (int column = 0; column < sourceArray.GetLength(1); column++)
{
if (sourceArray[row, column] == 0)
{
elements.Add(new Position(row, column));
}
}
}
return elements;
} /// <summary>
/// 随机生成数字元素填充空的数组元素。
/// </summary>
public void GenerateRandomNumber()
{
var list = CalculateEmptyElements(this.DataContainer);
if (list.Count > 0)
{
Random random = new Random();
var position = list[random.Next(0, list.Count)];
DataContainer[position.Row, position.Column] = random.Next(0, 10) == 4 ? 4 : 2;
}
} #endregion #region 实例私有方法(核心算法) /// <summary>
/// 将数组中的为 0 的元素移动到数组最后面。[1,0,0,2],结果为【1,2,0,0】
/// </summary>
/// <param name="array">要处理的数组。</param>
private void MoveZeroToLast(int[] array)
{
if (array == null || array.Length <= 0)
{
return;
} int[] myarray = new int[array.Length]; int index = 0;
for (int i = 0; i < array.Length; i++)
{
if (array[i] != 0)
{
myarray[index++] = array[i];
}
}
//通过引用修改元素才可以,修改引用对外界没有影响。
myarray.CopyTo(array, 0);
} /// <summary>
/// 合并数组中相邻相同的数字元素,后一个元素清零。[2,2,0,2],结果为【4,2,0,0】
/// </summary>
/// <param name="array">要处理的数组。</param>
private void MergeSameNumber(int[] array)
{
if (array == null || array.Length <= 0)
{
return;
} MoveZeroToLast(array);//2,2,2,0 for (int i = 0; i < array.Length - 1; i++)
{
if (array[i] != 0 && array[i] == array[i + 1])
{
array[i] += array[i + 1];
array[i + 1] = 0;
}
} //4,0,2,0 MoveZeroToLast(array);//4,2,0,0
} /// <summary>
/// 向上移动数据。
/// </summary>
private void MoveUp()
{
//从上往下取数据。
if (DataContainer == null || DataContainer.Length <= 0)
{
return;
} int[] tempArray = new int[DataContainer.GetLength(0)]; for (int column = 0; column < DataContainer.GetLength(1); column++)
{
for (int row = 0; row < DataContainer.GetLength(0); row++)
{
tempArray[row] = DataContainer[row, column];
} MergeSameNumber(tempArray); for (int row = 0; row < DataContainer.GetLength(0); row++)
{
DataContainer[row, column] = tempArray[row];
}
}
} /// <summary>
/// 向下移动数据。
/// </summary>
private void MoveDown()
{
//从下往上取
if (DataContainer == null || DataContainer.Length <= 0)
{
return;
} int[] tempArray = new int[DataContainer.GetLength(0)]; for (int column = 0; column < DataContainer.GetLength(1); column++)
{
for (int row = DataContainer.GetLength(0) - 1; row >= 0; row--)
{
tempArray[DataContainer.GetLength(0) - 1 - row] = DataContainer[row, column];
} MergeSameNumber(tempArray); for (int row = DataContainer.GetLength(0) - 1; row >= 0; row--)
{
DataContainer[row, column] = tempArray[DataContainer.GetLength(0) - 1 - row];
}
}
} /// <summary>
/// 向左移动数据。
/// </summary>
private void MoveLeft()
{
if (DataContainer == null || DataContainer.Length <= 0)
{
return;
}
//从左往右 int[] tempArray = new int[DataContainer.GetLength(1)]; for (int i = 0; i < DataContainer.GetLength(0); i++)
{
for (int j = 0; j < DataContainer.GetLength(1); j++)
{
tempArray[j] = DataContainer[i, j];
} MergeSameNumber(tempArray); for (int j = 0; j < DataContainer.GetLength(1); j++)
{
DataContainer[i, j] = tempArray[j];
}
}
} /// <summary>
/// 向右移动数据。
/// </summary>
private void MoveRight()
{
if (DataContainer == null || DataContainer.Length <= 0)
{
return;
} //从右向左取 //{ 2,2,4,8 },0,4,4,8
//{ 2,4,4,4 },
//{ 0,8,4,0 },
//{ 2,4,0,4 } int[] tempArray = new int[DataContainer.GetLength(1)]; for (int i = 0; i < DataContainer.GetLength(1); i++)
{
for (int j = DataContainer.GetLength(1) - 1; j >= 0; j--)
{
//8,4,2,2
tempArray[DataContainer.GetLength(1) - 1 - j] = DataContainer[i, j];
} //8,4,4,0
MergeSameNumber(tempArray); for (int j = DataContainer.GetLength(1) - 1; j >= 0; j--)
{
DataContainer[i, j] = tempArray[DataContainer.GetLength(1) - 1 - j];
}
}
} #endregion
}
这就是2048 核心类的实现,代码都有备注,其实,逻辑也不复杂,大家看也是可以看得懂的,只是需要点耐心。
文章就到此为止了,这是有关2028的核心算法,我发的代码都是经过测试的,大家可以拿过去直接使用,修改和测试。而且代码都很完整,所以我就没有把源码贴出来。
游戏2048的核心算法c#版本的实现的更多相关文章
- Unity3D_(游戏)甜品消消乐02_游戏核心算法
甜品消消乐01_游戏基础界面 传送门 甜品消消乐02_游戏核心算法 传送门 甜品消消乐03_游戏UI设计 传送门 GameManager脚本上修改Fill Time可以改变消消乐移动速度 实现过 ...
- 游戏2048源代码 - C语言控制台界面版
一.游戏介绍 <2048>是最近比较流行的一款数字游戏.原版2048首先在github上发布,原作者是Gabriele Cirulli.它是基于<1024>和<小3传奇& ...
- Android 带你玩转实现游戏2048 其实2048只是个普通的控件(转)
1.概述 博主本想踏入游戏开放行业,无奈水太深,不会游泳:于是乎,只能继续开发应用,但是原生Android也能开发游戏么,2048.像素鸟.别踩什么来着:今天给大家带来一篇2048的开发篇,别怕不分上 ...
- Android 带你玩转实现游戏2048 其实2048只是个普通的控件
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40020137,本文出自:[张鸿洋的博客] 1.概述 博主本想踏入游戏开放行业,无 ...
- 游戏数值——LOL篇 以LOL为起点-说游戏数值设计核心思路
附 文 文档在今年三月份我动笔写了一小部分,但当时思路凌乱,行文梗阻,于是丢在一边构思了半年,现在又回过头来慢慢写,希望能写好写完吧,初衷是希望即时萌新也能看懂,但是好像并不能行——本 ...
- 开源游戏“2048”IOS移植版
简介: 这个游戏是我在今年(2014/05)课余时闲着无聊做的一个益智类小游戏,总共花了4个工作日才完成,为了游戏的效率,做了很多优化,目前在IE5以上浏览器能够流畅运行,运行时如果屏幕分辨率不兼容, ...
- SQL关键字转换大写核心算法实现
1 不跟你多废话 上代码! /// <summary> /// SQL关键字转换器 /// </summary> public class SqlConverter : IKe ...
- 用Java实现MVPtree——MVPtree核心算法代码的搭建
项目需要,需要把MVPtree这种冷门的数据结构写入Java,然网上没有成形的Java实现,虽说C++看惯了不过对C++实现复杂结构也是看得蒙蔽,幸好客户给了个github上job什么的人用Java写 ...
- x264代码剖析(十三):核心算法之帧间预測函数x264_mb_analyse_inter_*()
x264代码剖析(十三):核心算法之帧间预測函数x264_mb_analyse_inter_*() 帧间预測是指利用视频时间域相关性,使用临近已编码图像像素预測当前图像的像素,以达到有效去除视频时域冗 ...
随机推荐
- [Python]在当前目录下创建三个目录
import os os.mkdir("2018-03-16-b018") os.mkdir("2019-03-16-b019") os.mkdir(" ...
- 在Oracle Sql Developer/Sql Plus中查看oracle版本
输入select * from v$version; 执行即可. 此法在Sql plus中执行效果: SQL> select * from v$version; BANNER --------- ...
- 2019UNCTF
Easyshellcode: 不说了,都是没有工具的血泪史,直接上exp: from pwn import * from numbers import * from ae64 import AE64 ...
- -webkit-line-clamp下多行文字溢出点点点...
限制在一个块元素显示的文本的行数. -webkit-line-clamp 是一个 不规范的属性(unsupported WebKit property),它没有出现在 CSS 规范草案中. 为了实现该 ...
- Keepalived之高可用LVS集群
前文我们聊了下keepalived的邮件通知相关配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13645163.html:今天我们来说说keepalive ...
- Minimizing maximizer(POJ 1769)
原题如下: Minimizing maximizer Time Limit: 5000MS Memory Limit: 30000K Total Submissions: 5104 Accep ...
- python修改excel内容
前提:安装pip install xlutils和xlrd 思路:xlrd用来读数据,xlutils用来修改数据:先打开excel——读到原来的sheet页——生成可以修改的excel和sheet页— ...
- Unit3:控件\布局
控件 TextView <TextView android:layout_width="match_parent" android:layout_height="w ...
- Cloudera Manager和CDH安装部署
本次安装采用离线安装的方式,需要提前下载好需要的包. 1. 准备工作 1.1 环境说明 操作系统:RedHat企业级Linux6.5 64-bit Cloudera Manager:5.8.4 CDH ...
- 关于java基础_方法的简单习题
package day05; import java.util.Arrays; /** * 方法作业 * @author ASUS * */ public class Demo6 { /* * 1.定 ...