×

关注微信公众号

免备案网站空间虚拟主机双线空间域名查询PS数码后期
photoshop互助课堂数百G视频教程下载英语培训机构初中英语如何学随时随地聆听大师开讲/课堂
路径专辑手绘教程抠图教程酷素材photoshop cs3视频教程
查看: 5733|回复: 1

[教程] as3版俄罗斯方块AI③@张志晨as3实例教程91

[复制链接]
发表于 2014-3-25 18:20:57 | 显示全部楼层 |阅读模式
本帖最后由 dqxxx 于 2014-4-7 12:38 编辑

as3版俄罗斯方块AI③@张志晨as3实例教程91

这是真正的Ai代码:
是核心代码
主要评估函数在此

  1. package as3{
  2.         import flash.geom.Rectangle;
  3.         import flash.geom.Point;
  4.         import flash.display.MovieClip;

  5.         public class Ai {
  6.                 public static const LEFT:int=-1;//左移一格
  7.                 public static const RIGHT:int=1;
  8.                 public static const DOWN:int=12;//下移一行
  9.                 const ONE:String="1";//此处已放有小正方形
  10.                 var area:Rectangle=new Rectangle(1,4,10,20);//游戏区域:从1列4行起,共10列20行
  11.                 var width:int;//地图的宽度
  12.                 var height:int;//地图的高度
  13.                 var _maps:Array=[];//虚拟地图
  14.                 var four:Array=[];//记忆方块,内有四个小正方形
  15.                 var four2:Array=[];//记忆方块,内有四个小正方形
  16.                 var best:Array;//[id,c,……] 评估后的返回值 最佳方案:谁从第几列下落,评分,地图样式,停止时的位置等……
  17.                 var tmp:Array=[];//临时地图


  18.                 public function Ai(_width:int=12,_height:int=25) {
  19.                         width=_width;
  20.                         height=_height;
  21.                 }

  22.                 //----获取外部地图副本--深复制----------------------
  23.                 public function getMap(map:Array):String {
  24.                         //变成字符串,方便复制(因为数组--引用对象,字符--引用值)
  25.                         return map.join("");
  26.                 }

  27.                 //----复制地图------------深复制------------
  28.                 public function copyMap(mapStr:String):Array {
  29.                         return mapStr.split("")
  30.                 }

  31.                 //=======移动------------------------------------------------
  32.                 public function isMove(dir:int):Boolean {//dir=1|-1|12
  33.                         for (var i:int =0; i<4; i++) {
  34.                                 var id:int=four[i]+dir;//虚拟移动
  35.                                 if (_maps[id]==ONE) {//只要四个小正方形其中一个的前方有障碍就不能移动了
  36.                                         return false;
  37.                                 }
  38.                         }
  39.                         return true;
  40.                 }

  41.                 public function move(dir:int) {//dir=1|-1|12
  42.                         for (var i:int =0; i<4; i++) {
  43.                                 four[i]+=dir;//真实移动
  44.                         }
  45.                 }

  46.                 public function moveX(column:int):Boolean {//平移到指定的列,用于演示
  47.                         //方块的左边位置
  48.                         var px:int=left();
  49.                         //无需平移,可直接下落:
  50.                         if (px==column) {
  51.                                 return true;
  52.                         }
  53.                         //平移:
  54.                         var f:int=px<column?1:-1;
  55.                         for (var i:int =px; i!=column; i+=f) {
  56.                                 if (isMove(f)) {
  57.                                         move(f);
  58.                                 } else {
  59.                                         //不能平移到指定列
  60.                                         return false;
  61.                                 }
  62.                         }
  63.                         //完成平移,可以下落了
  64.                         return true;
  65.                 }
  66.                 //速落:
  67.                 public function moveY() {
  68.                         while (isMove(DOWN)) {//能落
  69.                                 move(DOWN);//就落
  70.                         }
  71.                 }


  72.                 //===========旋转------------------------------------
  73.                 public function getBL():Point {
  74.                         //旋转空间的左下角坐标
  75.                         var xx:int=four[3]%width;//这里用到了标志,就是旋转中心 得到它的列
  76.                         var yy:int=(four[3]/width)>>0;//得到它的行,// >>0是取整
  77.                         return (new Point(xx-1,yy+1));//返回的是这个方块的左下角坐标
  78.                 }

  79.                 function isRota():Boolean {
  80.                         //田不参与旋转
  81.                         if (Tetris.id==0) {
  82.                                 return false;
  83.                         }

  84.                         var sx:int,sy:int,tx:int,ty:int;
  85.                         if (Tetris.id==1) {//横 旋转空间4*4=16格
  86.                                 sx=0,tx=3;
  87.                                 sy=-2,ty=1;
  88.                         } else if (Tetris.id==2) {//竖 旋转空间4*4=16格
  89.                                 sx=-1,tx=2;
  90.                                 sy=-3,ty=0;
  91.                         } else {//其它为九宫格
  92.                                 sx=0,tx=2;
  93.                                 sy=0,ty=-2;
  94.                         }
  95.                         var p:Point=getBL();//以下以方块的左下角坐标为标准,得到旋转所需要的空间
  96.                         for (var r:int =p.y+sy; r<=p.y+ty; r++) {
  97.                                 for (var c:int =p.x+sx; c<=p.x+tx; c++) {
  98.                                         var _id:int=r*width+c;
  99.                                         if (_maps[_id]==ONE) {//旋转空间内只要一个静止的方块
  100.                                                 return false;//则不能旋转
  101.                                         }
  102.                                 }
  103.                         }
  104.                         return true;
  105.                 }
  106.                 public function rotation() {//实现旋转
  107.                         if (isRota()) {//调用上面的函数
  108.                                 var id:int=Tetris.id;
  109.                                 var offset:Array=Tetris.offset();
  110.                                 for (var i:int =0; i<4; i++) {
  111.                                         four[i]+=offset[i];//通过偏移量实现旋转
  112.                                 }
  113.                                 Tetris.change();

  114.                         } else {
  115.                                 trace("旋转空间不足");
  116.                         }
  117.                 }

  118.                 //---落地--------------------------------------------------------
  119.                 public function stop() {
  120.                         for (var i:int =0; i<4; i++) {
  121.                                 _maps[four[i]]=ONE;//改变虚拟地图的值,记忆此处有一个小正方形
  122.                         }
  123.                 }
  124.                 //可否消行、调用消行函数,消去哪些行
  125.                 public function delLine():Array {
  126.                         //过滤看行号相同的项
  127.                         var sqY:Array=[];
  128.                         //sqY[0]=getY(four[0]);
  129.                         for (var k=0; k<4; k++) {
  130.                                 var yy:int=getY(four[k]);
  131.                                 if (sqY.indexOf(yy)==-1) {
  132.                                         sqY.push(yy);
  133.                                 }
  134.                         }
  135.                         //因小方块并不是从小到大排列的,排序后,
  136.                         //保证从上到下的顺序消行
  137.                         sqY.sort(Array.NUMERIC);
  138.                         var leng:int=sqY.length;
  139.                         var n:Array=[];
  140.                         //四个小方块停在哪些行就检测哪些行能否消行:
  141.                         for (var r:int=0; r<leng; r++) {
  142.                                 var isTen:Boolean=true;
  143.                                 var _id:int=sqY[r]*width;
  144.                                 for (var c:int=area.left; c<area.right; c++) {
  145.                                         if (_maps[_id+c]!=ONE) {//一行中只要有一个空格
  146.                                                 isTen=false;
  147.                                                 break;
  148.                                         }
  149.                                 }
  150.                                 if (isTen) {//消行,记录行号
  151.                                         clear(sqY[r]);
  152.                                         n.push(sqY[r]);
  153.                                 }
  154.                         }
  155.                         //返回所有被消行号:
  156.                         return (n);
  157.                 }

  158.                 //计算局面高度。方便消行,因为此高度以上没有方块,不用操作
  159.                 public function tallest():int {
  160.                         //先行后列,第一个不为0的格,就是最高的
  161.                         for (var r:int =area.top; r<area.bottom; r++) {
  162.                                 var _id:int=r*width;
  163.                                 for (var c:int =area.left; c<area.right; c++) {
  164.                                         if (_maps[_id+c]==ONE) {
  165.                                                 return (r);
  166.                                         }
  167.                                 }
  168.                         }
  169.                         return area.bottom;
  170.                 }
  171.                 //消行
  172.                 function clear(row:int) {
  173.                         var c:int;
  174.                         var r:int;
  175.                         if (row==4) {//如果消去的是顶行:
  176.                                 for (c=49; c<59; c++) {
  177.                                         _maps[c]="0";
  178.                                 }
  179.                                 return;
  180.                         }
  181.                         var tall:int=tallest();//最高行,调用上面的函数
  182.                         for (r=row; r>tall-1; r--) {
  183.                                 for (c =area.left; c<area.right; c++) {
  184.                                         var _id:int=r*width+c;
  185.                                         _maps[_id]=_maps[_id-width];//上行内容下移一行
  186.                                 }
  187.                         }
  188.                         if (tall==4) {//很少用到 落下一个块后,高度到顶了:
  189.                                 for (c=49; c<59; c++) {
  190.                                         _maps[c]="0";
  191.                                 }
  192.                         }
  193.                 }

  194.                 //=========================评估--------------------------------------
  195.                 public function assess(map:Array,delLine1:int,delLine2:int=0):int {
  196.                         var top:int=1024;
  197.                         var space:int=0;
  198.                         var topLast:int=0;
  199.                         var topLLast:int=0;
  200.                         var deep:int=0;
  201.                         var alp:int=0;
  202.                         var diff:int=0;
  203.                         var topAvg:Number=0;

  204.                         var h:int=0;
  205.                         var r:int;
  206.                         var c:int;

  207.                         var _id:int;
  208.                         for (c=area.left; c<area.right; c++) {
  209.                                 topLLast=topLast;//上上一列高度
  210.                                 topLast=h;//上一列高度
  211.                                 for (h=area.top; h<area.bottom; h++) {
  212.                                         //本列高度h
  213.                                         _id=h*width+c;
  214.                                         if (map[_id]==ONE) {//本列最上面的方块
  215.                                                 break;
  216.                                         }
  217.                                 }

  218.                                 //本列在全局是否最高(就是行号最小):
  219.                                 if (h<top) {
  220.                                         top=h;
  221.                                 }
  222.                                 //本列有多少个 洞
  223.                                 for (r=h+1; r<area.bottom; r++) {
  224.                                         _id=r*width+c;
  225.                                         if (map[_id]!=ONE) {
  226.                                                 space++;
  227.                                         }
  228.                                 }

  229.                                 var h1:int=topLast-topLLast;
  230.                                 var h2:int=topLast-h;
  231.                                 if (h1>1&&h2>1) {//凹
  232.                                         ++deep;
  233.                                 } else if (h1<-1&&h2<-1) {//凸
  234.                                         ++alp;
  235.                                 }
  236.                                 diff+=Math.abs(h2);//累积坡度
  237.                                 topAvg+=h;//累积高度

  238.                         }
  239.                         topAvg/=10;//平均高度
  240.                         if (h2<-1) {//挨着右界的坑
  241.                                 deep++;
  242.                         }
  243.                         return top*19+topAvg*15+delLine1*2+delLine2-space*7-deep*4-alp*2-diff;
  244.                 }

  245.                 public function Evaluate(mapStr:String) {//参数是实际地图的复本
  246.                         //有几种变形
  247.                         var more:int;
  248.                         if (Tetris.id==0) {
  249.                                 more=1;//田只一种
  250.                         } else if (Tetris.id<7) {
  251.                                 more=2;
  252.                         } else {
  253.                                 more=4;
  254.                         }

  255.                         tmp=[];
  256.                         for (var r:int =0; r<more; r++) {//变形 0-3种
  257.                                 if (r>0) {
  258.                                         //变形(相当于旋转)
  259.                                         Tetris.change();
  260.                                 }
  261.                                 for (var c:int =area.left; c<area.right; c++) {//一列一列的尝试
  262.                                         _maps=copyMap(mapStr);//地图副本
  263.                                         getTetris();//直接放在地图第4行  four获得并改变值

  264.                                         if (moveX(c)) {//平移到c列
  265.                                                 moveY();//下落
  266.                                                 stop();//停靠
  267.                                                 var hang:Array=delLine();//消行情况
  268.                                                 //保存局面:
  269.                                                 //------0       1      2          3         4           5
  270.                                                 //[tmp[ id,     x,   delLine,  mapStr,    bottom,      four]
  271.                                                 //-----方块号 下落列号 消行情况 消行后地图  方块停靠行号 方块落地位置
  272.                                                 tmp.push([Tetris.id,c,hang,_maps.join(""),bottom(),four.join(",")]);
  273.                                         }
  274.                                 }
  275.                         }

  276.                         //下落第二个方块,并评估:
  277.                         all=0;
  278.                         best=[0,0,0,0,0,0,0];
  279.                         var leng:int=tmp.length;
  280.                         for (var i:int=0; i<leng; i++) {
  281.                                 Tetris.id=Tetris.id2;
  282.                                 Evaluate2(tmp[i]);//此函数给best数组赋值
  283.                         }
  284.                         //best只保存最佳方案    [id,x,h[],map,bottom,four,value]
  285.                         //枚举49-1600种情况      0  1  2   3   4      5     6
  286.                         //返回第一个方块的信息:[形, 列,消, 图, 底,    位,  分]
  287.                         Global.root.trys.text=all+"";
  288.                         return best;
  289.                 }

  290.                 var all:int=0;
  291.                 function Evaluate2(tmp:Array ) {
  292.                         //有几种变形
  293.                         var more:int;
  294.                         if (Tetris.id==0) {
  295.                                 more=1;
  296.                         } else if (Tetris.id<7) {
  297.                                 more=2;
  298.                         } else {
  299.                                 more=4;
  300.                         }

  301.                         for (var r:int =0; r<more; r++) {
  302.                                 if (r>0) {
  303.                                         //变形(相当于旋转)
  304.                                         Tetris.change();
  305.                                 }
  306.                                 for (var c:int =area.left; c<area.right; c++) {//一列一列的尝试
  307.                                         _maps=copyMap(tmp[3]);//地图副本
  308.                                         getTetris();//直接放在地图第4行

  309.                                         if (moveX(c)) {//平移到c列
  310.                                                 moveY();//下落
  311.                                                 stop();//停止

  312.                                                 var hang2:int=delLine().length;//消行并返回行数

  313.                                                 var value:int=assess(_maps,tmp[2].length,hang2);//评估
  314.                                                 if (value>best[6]) {//记忆最佳值
  315.                                                         best[0]=tmp[0];
  316.                                                         best[1]=tmp[1];
  317.                                                         best[2]=tmp[2];
  318.                                                         best[3]=tmp[3];
  319.                                                         best[4]=tmp[4];
  320.                                                         best[5]=tmp[5];
  321.                                                         best[6]=value;
  322.                                                 }
  323.                                                 all++;
  324.                                         }
  325.                                 }
  326.                         }
  327.                 }


  328.                 //---得到当前方块-----------------------------------
  329.                 public function getTetris() {
  330.                         //谁需要下移行数d,以便直接显示在游戏区
  331.                         var d:int=0;
  332.                         if (Tetris.id==1) {
  333.                                 d=2;
  334.                         } else if (Tetris.id==2) {
  335.                                 d=4;
  336.                         } else {
  337.                                 d=3;
  338.                         }
  339.                         for (var i:int =0; i<4; i++) {
  340.                                 four[i]=Tetris.square[Tetris.id][i]+d*12;
  341.                         }
  342.                 }
  343.                 //小块坐标,用于判断可否下落
  344.                 public static function getX(id:int=0) {
  345.                         return id%12;
  346.                 }
  347.                 public static function getY(id:int=0) {
  348.                         return (id/12)>>0;
  349.                 }

  350.                 //一个方块的四置
  351.                 public function left() {
  352.                         var i:int=Number("0000211200210220200".charAt(Tetris.id));
  353. //0000211200210220200 标明四个小正方形中第几个能代表整个方块的左边框位置,下同
  354. //另外可以用循环得到四个小正方形谁最靠左,再获取它的坐标,这也是可以的
  355.                         return four[i]%width;
  356.                 }
  357.                 public function bottom() {
  358.                         var i:int=Number("2002212102212212101".charAt(Tetris.id));
  359.                         var b:int =(four[i]/width)>>0;
  360.                         return b;
  361.                 }/*
  362.                 public function top() {
  363.                 var i:int=Number("0020101220120020020".charAt(Tetris.id));
  364.                 return (four[i]/width)>>0;
  365.                 }
  366.                 public function right() {
  367.                 var i:int=Number("2202102122122011012".charAt(Tetris.id));
  368.                 return four[i]%width;
  369.                 }
  370.                 */

  371.         }


  372. }
复制代码
as3版俄罗斯方块AI①@张志晨as3实例教程91
as3版俄罗斯方块AI②@张志晨as3实例教程91
as3版俄罗斯方块AI③@张志晨as3实例教程91

as3版俄罗斯方块AI④@张志晨as3实例教程91
as3版俄罗斯方块AI⑤@张志晨as3实例教程91
本帖的地址:http://bbs.jcwcn.com/forum.php?mod=viewthread&tid=539506
跟着教程做一遍,做完的图要到这里评论交作业,教程有看不懂的地方,可以在贴子下面评论
发表于 2015-1-4 08:57:37 | 显示全部楼层
酷素材
强烈支持楼主。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | [立即注册]

本版积分规则

2345