GithubHelp home page GithubHelp logo

red2048blog's Introduction

今天来谈一下如何使用red制作2048.

1 制作界面

1.1 绘制格子

首先在面板上画出格子,这里使用base来当作格子。

1.png

1.2 创立二维block

那接下来使用什么存储格式来存储格子中的数据呢,答案肯定是二维的block。

使用grid-block来存储原始的二维数组,要知道2048游戏起始的时候都是有两个2在窗口中的,这里使用的固定的2048起始数组,如果想要得到随机的2048起始数组,也可以使用嵌套循环调用random方法得到。grid-block的主要作用是存储数据并且和1.1中的方格一一对应。

1.3 连接格子与二维block

既然已经得到了方格图形界面和所对应的二维数组,那接下来的工作就是将这二者连接在一起。

如何将二维数组与图形界面连接在一起呢?

主要操作是遍历整个二维block,并且给每一个方格赋予其对应的二维block中的值就可以了。 grid-world/pane/:l/text: form grid-block/:i/:j,注意在遍历的同时,还需要将不为“0”的元素的visible?属性置为true,将为“0”的元素的visible?属性置为false即可。在遍历的同时还可以给每一个数字(即2,4,8,16...)赋予不同的颜色,主要操作color属性就可以了。

2.png

2 2048游戏逻辑

2.1 方格移动或重合逻辑

2.1.1 单行方格移动和重合逻辑

试想以下在玩2048的过程中,假如操作方向向左,所有方格都会向左平移,当右边的方格遇到与靠其左的方格值一样的情况,两者就会重合相加。若方格的左边有空,则方格及其靠右的方格集体向左平移。

实现逻辑,方格移动有上下左右四个方向,可以先做向左的方法,又因为整体窗体是一个4x4的方格,所以又可以先实现操作一行。

  1. 根据上面所观察到的情况,应该先做相加操作,此时应该遍历整行的元素,从第一个元素开始,若其为“0”则可以直接跳过,若其不为零则判断其与其右边的元素是否相等,若相等则将相加的结果保存到该元素值中,并将靠其右边的元素置为“0”,依次向右类推就可以完成重合相加操作。(注意这里操作的对象应该是二维block中的元素)

  2. 接下来就是平移操作,试想一下,平移的基本操作便是判断一个元素是否为“0”,若为“0”则跳过到其右边的元素,若不为零则判断靠其左的元素是否为“0”:若为“0”则用该元素替代其靠左的元素,其元素本来的位置置为“0”;若不为“0”则无操作。那么现在要考虑的便是循环次数的问题,试想一下最右边的元素,若是其左边都为“0”,那么进行向左操作的之后结果是不是移动到了最左边,可以把这个过程想象成一个"冒泡排序",那么这个循环就是一个每次循环次数四次的一级嵌套循环。若变成一级循环则一共的次数为4x4=16次。

2.1.2 四行方格移动重合逻辑

既然上面已经实现了单行方格移动和重合逻辑,若要实现四行则进行一个循环就可以了(这里把实现了该逻辑的方法称为move-left)。

g1.gif

以上gif便是实现了放个移动或重合逻辑后向左操作的结果。

2.2 加入新元素

2.2.1 何时加入

仔细想想在玩2048的过程中,当有元素重合(例如2与2相加之后为4)或整体元素移动的的时候(例如整体从左向右移动),只要窗体中还有空格剩余的时候都会新加入元素2或4。

  1. 从以上可以得到,若元素重合(相加)时会加入新元素,在元素移动时会加入新元素。故而可以在方格移动重合逻辑的方法中加入modified变量来监视是否有改动,若有改动则返回true即可。

  2. 接下来时空格剩余的条件,只需要遍历一遍4x4的窗口中的格子即可,若有“0”则返回true给empty。

综合以上两点,若modified和empty同时为true则可以加入新的元素。因为之前2.1.2中已经写好了move-left的方法,所以可以将这些判断加入到move-left方法中,在移动操作后进行判断。

2.2.2 如何加入

首先来谈一下最基本的方案,加入新元素的逻辑就是通过一次嵌套循环遍历每一个元素判断该元素是否为“0”,若为“0”则可以将这个元素的值改为2或者4(可以通过either 1 <> random 4 [2][4]来进行概率的分配 ),调用完加入新元素的方法后将整体显示在窗口中即可。

g2.gif

以上gif便是完成了2.1中逻辑后加入新元素的现象。

2.3 其他方向的操作

实现了向左整体的代码之后,可以思考一下如何向上,向右,向下,可以将其他方向的操作参照向左操作重写,但是观察一下可以发现,向上操作无疑是将向左操作顺时针旋转了90度,所以在实现向上操作的时候可以先将整个二维block首先逆时针旋转90度,之后进行正常的向左格子偏移和相加操作,操作完成之后再将结果逆时针旋转270度即可回到原来的方向。

所以重点就在于逆时针旋转角度的方法的编写了。

  1. 简单的方法是首先编写一个将二维block逆时针旋转90度的方法,主要将二维block里面的元素进行旋转前后的位置的映射就可以了,之后若逆时针旋转180度甚至270度则直接重复调用这个方法就可以了。
  2. 第二种方法相对于前一种稍稍复杂一些,每次给旋转方法提供角度,利用三角函数和差公式来计算指定元素再角度偏移后的元素位置:
rotation: func [angle [integer!] /local offsetX offsetY sin cos rx ry][
	offsetX: offsetY: 5
	if 90 = angle [offsetY: 0]
	if 270 = angle [offsetX: 0]
	sin: to-integer sine angle
	cos: to-integer cosine angle 
	fake-block: copy/deep grid-block
	repeat x 4 [
		repeat y 4 [
			rx: x * cos - (y * sin) + offsetX
			ry: y * cos + (x * sin) + offsetY
			grid-block/:rx/:ry: fake-block/:x/:y
		]
	]
]

值得注意的是主要的元素只要存储在二维的grid-block中,而当角度进行偏转的时候,必须要使用一个中转的block来存储grid-block(若不用中转block来进行存储,只有grid-block的话,在角度旋转之后得到的结果不会准确)。这里使用了fake-block来存储操作之前的grid-block。

完成了rotation方法后,试想一下向下操作若是要转换为想做操作的话,是不是先要逆时针旋转270度,调用向左操作完毕后,再逆时针旋转90度即可。如下:

move-down: function [][
	rotation 270
	move-left 
	rotation 90 
]

其他方向以此类推。

g3.gif

以上gif是分别使用向左向上向右向下操作后的结果。

2.4 窗口填满后逻辑

试想一下窗口填满之后是否真的就游戏结束了呢?当然不一定,若是两个相邻的方块相等的话,还是可以继续游戏的。

判断逻辑是,当empty不再返回true的时,即所有格子都被填满的时候,需要检查一下每个元素是否和其相邻的元素是否相等,具体算法是从左上角开始判断,每次与靠其右和靠其下边的元素比较看是否相等(可以使用初始化一个logic!变量为false,这里假设使用canmove变量来存储):若相等则可以直接退出循环,将canmove置为true;若不等则以其靠右的元素为基准继续进行如上判断。以此类推遍历整个4x4窗口即可。

g4.gif

以上gif便是窗口填满后,向上操作两次得到的结果。

2.5 胜利失败逻辑

2.5.1 失败判断逻辑

从2.4中可以得出,若当窗口填满后而且不能移动,则canmove变量为false,这时候即可判定游戏失败,制作一个游戏窗口再此时弹出即可。

3.png

2.5.2 胜利判断逻辑

当窗口中的方格出现了2048则可表示胜利,所以判定胜利的方法就是遍历整个4x4窗口,若是有2048存在则弹出胜利窗口即可。

4.png

3 游戏完成

这样一来使用red语言制作2048已经完成了,可以参考源码 https://github.com/hyzwhu/red-2048/blob/master/2048.red

red2048blog's People

Contributors

hyzwhu avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.