异星工厂吧 关注:63,119贴子:407,930
  • 13回复贴,共1

【电路展示】电路游戏:贪吃蛇

取消只看楼主收藏回复

视频来自:百度贴吧


1楼2017-02-02 19:57回复
    【摘要】提供电路控制灯,来模拟简单的游戏---贪吃蛇.
    通过丢弃物品到传送带来控制蛇的移动.
    【关键字词】电路;游戏;贪吃蛇;显示屏;信号读存
    【参考文献】
    http://tieba.baidu.com/p/4765827788
    【电路概述】
    整个电路由显示屏、”显卡”、”CPU”、随机数生成器、控制器五部分组成.(名字只是方便理解不等同于实际功能.)
    显示屏大小28*28,减去配电器占去的16格,共768格移动区域.
    显示屏基于二进制进行控制,电信号的处理基于时间顺序.
    在蛇头超出显示屏或碰到配电站所处格或碰到自身即为游戏失败,整个电路会重置.(可取消失败重置)



    5楼2017-02-02 20:15
    收起回复
      2025-11-03 08:53:46
      广告
      不感兴趣
      开通SVIP免广告
      此楼备用


      6楼2017-02-02 20:20
      收起回复
        本来准备正好大年初一的时候发的,结果工期没赶上,因为过年事情比较多最后拖到了现在.其实我只是想熟悉一下写篇教程出来,结果沉迷电路不可自拔


        20楼2017-02-03 11:11
        回复
          第一部分 电路操作





          22楼2017-02-03 12:04
          收起回复
            第二部分 电路基本组成与逻辑


            “CPU”
            功能: 对电路初始设置;响应玩家的控制;对蛇头坐标进行处理;判断是否碰撞或吃到食物.
            可输入信号:方向信号;刷新信号;食物坐标信号;
            可输出信号:蛇头坐标信号;增加蛇长信号;随机数生成信号;蛇头越界信号
            储存元件:储存当前蛇头坐标(每局重置); 储存当前食物坐标.
            主要处理耗时: 刷新信号送入→计算新坐标→判断合法→坐标送出至存储器:5 tick
            刷新信号送入→新坐标送至”显卡”:14 t
            (tick将简称t,处理中间过程将省略)


            24楼2017-02-03 14:08
            回复
              存储器
              功能:通过储存蛇头坐标记录蛇的移动轨迹,并依此计算蛇尾坐标.
              可输入信号:蛇头坐标:增加蛇长信号
              可输出信号:蛇尾坐标信号
              储存元件:储存当前蛇长(每局重置);储存当前存入数据的指针;储存所有蛇头坐标(每局重置)
              主要处理耗时:蛇头坐标送人→蛇头坐标存入:10 t
              蛇头坐标送入→蛇尾坐标送出至”显卡”: 25 t
              “显卡”
              功能:点亮/熄灭指定坐标的灯,查询指定坐标灯的状态.
              可输入信号:蛇头坐标:蛇尾坐标:随机数信号;蛇头越界信号
              可输出信号:重置信号(重置储存元件,结束游戏)
              储存元件:储存当前图像信息数据(每局重置)
              主要处理耗时: 坐标送入→点亮/熄灭灯:4 t
              坐标送入→坐标查询结果:5 t
              随机数生成
              功能:生成一个随机数,并检查是否在指定区域.
              可输入信号:随机数生成信号
              可输出信号:随机数信号(坐标)
              主要处理耗时:要求生成→随机数送出: 6 t


              25楼2017-02-03 14:11
              回复
                第三部分组件结构与逻辑
                (由于时间与精力的原因,只说明结构与实现原理,不叙述具体过程.)
                第一节“CPU”
                “CPU”设计图纸如下

                ps:所有设计图纸原照片(包含一些放大图):http://pan.baidu.com/s/1c06atw
                ps2:所有设计稿是为了对整个电路进行重构而画(测试的时候摆的太乱了QAQ).在重构后进行了一些小调整,最终的电路以存档实际电路为准.
                实际电路图如下:

                “CPU”共8个信号输入输出口(大部分各对应一个远程输电塔,棕色序号),8个功能区.
                信号:
                1.开始信号输入.
                2.刷新信号输入
                3.方向信号输入
                4.重置信号输入
                5.越界信号输出
                6.蛇头坐标输出
                7.食物坐标输入
                8.蛇头坐标值输出;蛇长增加信号;生成随机数信号
                (8号标错了,在11号的左边有一个输电塔,应该标那个)
                功能区
                9.得到刷新信号时,根据方向信号和当前蛇头坐标值计算出新的蛇头坐标值.
                输入来自:1、2、3、11.输出至10
                10.检查新坐标值是否越界(超出28*28外或到配电站所占区域),越界则拦截坐标值信号并发送越界信号到”显卡”,不越界将坐标值送给11、15、存储器
                输入来自:10输出至11、15、存储器或 5
                11.储存当前蛇头坐标值,并交给9号等待处理.在得到4号重置信号输入时,重置储存.
                输入来自: 4、11、14.输出至9
                12.译码器,将食物坐标译为坐标值.如坐标(C,9)→(12,9) →(9*32+12=300).译为值方便计算处理.
                输入来自: 7输出至13
                13.储存当前食物坐标值,并交给15号等待比较.
                输入来自: 12输出至15
                14.得到开始信号时给出初始值,给出初始坐标值(Z,462).设置蛇长为1并要求生成随机数.
                输入来自: 1输出至8、11、16
                15.判断新坐标值与食物坐标值是否相同.相同则拦截新坐标值,并送出蛇长+1信号和生成随机数信号,不相同将新坐标值送至16.
                输入来自: 10、13输出至16
                16.译码器,将蛇头坐标值译为坐标信号,如(Z,462) →(462=14*32+14)→(14,14) →(E,14)
                总结与吐槽:
                “CPU”只是繁杂,设计的难度并不大,差不多是我设计最快的一个,也是发现bug最少的一个.整个组件的速度被译码严重拖慢,如果对其他组件的信号接口进行重设,还是有很大提速空间.
                设计整个电路我最大的感受是我真是把能走的弯路走完了,”CPU”最初的设计思路就有问题,我竟然在完全建好后才发现,最后直接推到重来了(分享里有份原图纸).


                27楼2017-02-03 16:06
                收起回复
                  2025-11-03 08:47:46
                  广告
                  不感兴趣
                  开通SVIP免广告
                  第二节存储器
                  存储器存入逻辑图:

                  存储器读出逻辑图:


                  存储器存入原理:
                  “显卡”接收的是坐标信号,如输入(C,17),”显卡”会对第C行(第12行)第17列的灯进行操作.
                  但坐标信号对于储存和计算都是比较麻烦的.因此会将坐标信号转换为坐标值信号在进行操作.转换方法为(列数*32+行数).如(C,17)会被转换为(Z,556).(一般用Z信号记录值)
                  转换后的值正好可以用10位二进制记录(2^10=1024=32*32,这也正是为什么转换时要乘32的原因).
                  一个信号值的范围是-2 147 483 648~2 147 483 648(-2^31~2^31),这显然是一个整型变量的范围.为了方便,我们只取正数,再舍一位备用.也就是说一种信号可以存储30位二进制,正好可以存储3个坐标信息.
                  存储的原理便是基于此.用两个指针标识存储的位置,Y表示存储在该信号的第几个二进制位,X表示存储在第几个信号中
                  举个例子,当前指针为(X,60),(Y,10),要求将数据(Z,556)储存.
                  收到数据后Y先+10(如果大于30则会”进位”到X),指针为(X,60),(Y,20).
                  第60个信号为”内燃机车”,(X,60)将转换为(内燃机车,1)
                  至于第60个信号是什么这个是由自己定的,我在常量箱里对210种信号进行了编号.
                  要从第20位储存,数据需要乘以1048576(2^20,同理,从第十位乘以2^10)
                  (Z,556)将转换为(Z,583008256).
                  最后将Z的值赋给”内燃机车”得到(内燃机车,583008256).输入到存储器完成储存.


                  32楼2017-02-04 17:32
                  回复
                    数据的读出使用相同的原理.
                    举个例子,当前指针(X,90),(Y,20),蛇长为7
                    (90*3+20/10)-7=265, 265/3=88余1,得到蛇尾坐标储存在(X,88),(Y,10)
                    (实际电路操作过程不等同于上式,电路比想象中的麻烦一些)
                    第88个信号为”灯”,从存储器中将”灯”信号的值取出.
                    使用辗转相除法将”灯”信号储存的3个坐标取出,
                    由(Y,10)将第2个坐标取出.
                    将第2个坐标译码为坐标信号,输入到”显卡”.完成.
                    总结与吐槽:
                    存储器是整个电路中最麻烦,设计耗时最长,处理耗时最长,bug最多,维护性最差的组件.
                    是整个电路的最短板.写之前还发现一个bug,简直无情.如果不是时间实在不够,我都想重新设计.
                    最初还有两个设计思路,一是一种信号储存1个坐标,前8位储存信号种类后22位储存信号值,这是一种通配型的思路,设计相对简单,而且适用多种需求.但感觉比较浪费储存空间,一种信号明明可以储存3个坐标的.二是一种信号储存15个方向信号.蛇的移动只有上下左右这4种,只需要记录蛇是怎么移动的就可以由蛇头坐标算出蛇尾坐标.这个方法虽然储存空间少但更麻烦,还有很多问题,比如蛇长200,那算出蛇尾坐标需要多少时间?
                    最后选择了这个偏中间的思路,建完才发现我为什么要这么在意储存空间?选第一个不好吗?又是一个弯路,.


                    34楼2017-02-04 17:37
                    回复
                      第三节随机数生成器
                      随机数生成器就思路有点难找,确定思路后很容易就建好了.
                      随机数生成的原理是多个脉冲相互影响接入计数器,使计数器的值快速变动且不具备明显的规律,以产生不确定性.当要求产生随机数时将当前计数器的值取出即可.玩家行为的不确定导致取出随机数的时间不确定.而产生的真正的随机性.其思想跟编程语言通过当前时间算出随机数大同小异.
                      具体实现是使用4个不同周期的脉冲信号输出器相互交叉接入到4个计数器, 计数器在叠加到一个值后会重置.其中两个计数器的值相加,另两个计数器再相加得到两个范围在1~28的数,这两个数就是坐标值
                      这个4个脉冲信号输出器分别是:非门脉冲;黄带脉冲(4格,循环,内圈);红带脉冲;蓝带脉冲
                      至于为什么用这几个脉冲?怎样交叉?计数器叠加到多少重置?等等.这个......完全看我感觉和心情.好吧,不开玩笑了,其实是结果.
                      在周期性的要求产生随机数的情况下,以下是我采用不同设置时随机数生成的情况.





                      如果产生的结果让我感觉不随机,我就会更改设置,改一下交叉啊,改一下重置值什么的,实在不行我还会改脉冲改结构.上面只放了几个不同阶段的结果图,我没那么快就找到正确的设置的.
                      最后一张图已经呈现明显的随机性了(至少是没有盲区了),核验了一下也没问题,于是就使用了当时进行的设置.
                      因为按这个方法获取的随机数是具有周期性的,只要次数足够,一定会发现重复.我做的这些乱七八糟的设置就是为延长周期的长度,减少周期内的小段重复.但我又不可能计算这个周期是多少,所以只能一点点的试,以结果为准.
                      在随机数获取后还有一个过程,检查随机数代表的坐标是否在配电站的区域(这个配电站真是碍事),如果在,会拦截随机数,并重新获取.


                      35楼2017-02-04 18:44
                      回复
                        第四节“显卡”
                        “显卡”的原理是@d4217621的通过二进制进行显示控制,我只进行了一些改动.这里就不过多阐述了
                        从坐标到显示有关键的一环,就是计算次方值.
                        比如(C,8)转换为(C,2^8)→(C,256),就可以直接送到存储器进行显示了.
                        计算次方值不是什么难事,2^8只需要八遍*2就行了,但实际中不能这样用.八遍*2需要8t时间,并且在这8t时间中不能有新的坐标输入.如果是2^28就是28t的时间了.这个过程显然是需要变通的.
                        我采用的是取数法计算次方值,先将结果直接储存在常量箱,在得到信号时直接将结果取出.
                        整个过程共耗时4t.但占地比较大.
                        “显卡”的查询功能是对原理的反向使用,这个也不难理解.
                        “显卡”的电路逻辑比较简单,就具体说明了.
                        值得一提的是,由于判定是否碰撞到蛇身只能通过显卡的查询功能完成,因此重置信号的判定处理也在显卡中完成了.其逻辑为:在显示屏存在图像时(这说明游戏正在进行),输出(X,1),CPU判断越界后会发出(X,1),在显卡判断碰到蛇身时也会发出(X,1),当X=2时,发出重置信号.在控制器,可以使在显示屏存在图像时不发出(X,1)这样重置信号就无法发出.


                        37楼2017-02-04 21:15
                        收起回复
                          第四部分电路的优化与问题.
                          发布的150号存档,已知存在以下bug.
                          1.在存储器指针X<10时,(10只是大概的数)无法取出对应编号的信号,其原因推测是电路元件一次只能处理200个左右的信号.在最新的154号档已经解决,解决的方法是添加新的比较器去处理超出的信号.
                          2.在存储器指针X重置时,存储器无法工作.其原因是指针会被重置为0,然而并没有编号为0的信号(也做不到).这个bug未被解决,我使指针重置为1,但这个bug没有那么简单,由于一些原因”下游”的信号仍然存在错误,两个多小时的测试还是没找清原因.理论上可行的解决方法是在指针前加一个运算器进行+1,但这个运算器会改变存储器的时序,这更麻烦.
                          抱歉,暂时不能解决这个bug
                          3.存储器共能储存210*3=630个坐标,这意味着蛇长最多为629.
                          所有的bug都出在存储器,真的好绝望.
                          发布的150档目前有以下的优化思路:
                          1.按一个信号储存一个坐标的思路重新设计存储器.
                          2.仿照”显卡”,坐标值译码到坐标的过程使用取数的方法.这个过程并不简单,毕竟不能搞几百个进行取数,再考虑到需要比较器实现大于a小于b的功能,可能还要结果叠加的方法.简单推算一下,使用的元件八成要过百的.最后可以将6t缩减为1~4t,典型的用数量换取时间.
                          3.前置计算思想.也是用数量+精力换取时间,由于玩家的下个操作只有3种情况(贪吃蛇不能向自己身后移动,方便计算还是按4种吧),在玩家操作之前就计算出向右的情况下新的坐标是什么.应该给显卡什么信号,给存储器什么信号等等,然后是左上下各个方向的结果,在玩家操作时取出对应方向的结果直接就能显示了.有点像把整个电路复制了四份.理论上可以把响应时间缩短为5t以下.讲真,一个贪吃蛇有必要这么高端吗?


                          38楼2017-02-04 22:28
                          收起回复
                            第五部分最后说两句
                            电路这种东西,我感觉多人合作玩起来更有趣也更有效率.可惜现在小伙伴们还不太多,等游戏热门起来可以组个”工作室”一起玩的.
                            时间原因对电路的分析不够详细,如果小伙伴有疑问的话可以@ 我,我会进行解答的.
                            接下来,我还想建个俄罗斯方块的,不过考虑到我还有教程没写完,还有一些事情要做,最后看情况吧,不一定会发.
                            完结撒花.


                            39楼2017-02-04 23:06
                            回复