Linux系统上Iptables实现端口转发的过程
2012-03-29 14:17
441 查看
前一阵子为了练手,写了一个连连看的小游戏,主要的设计为棋盘类,位置类,棋子类,核心算法包,一些自定义事件和资源类。我称连连看中被点击的按钮为棋子,下面那个看不见的布局要用的东西我成为棋盘。这样设计一个小游戏主要也是为了降低耦合性,每个部分可以比较独立的变化而不影响其他的部分。比如,棋子随意变,棋盘也可以变为圆形,甚至五角星的,只要改变一个字段就可以方便的更改棋子的皮肤或者音乐。
核心算法主要写了一个随机分配的算法,就是保证每次玩的时候最后都要正好能全部消灭。连连看的死局这里暂时没有考虑。还有一个就是把判断两个棋子是否可以消除,我没有用网上介绍的递归算法,我用的“十字通路法”,我自己起的名字哈。我想这样来解释会清楚一些:
十字通路:
每个棋子拥有一个十字通路,就是它可以到达的上下左右,可以到达的意思就是路过的位置是空的或者是不可见的,类似一个十字一样。当然也可能不是“十”字,或者是个"T",总之就是遍历上下左右,碰壁为止,并整理记录下来X轴通路和Y轴通路。
判断两个棋子是否可以消除的条件:
1.两个棋子的图案必须要相同。
2.两个棋子最多通过两次“拐弯”可以到达。理解成我所谓的十字通路就是两个棋子的X(Y)轴通路可以直线相连。
以下是我用来测试的代码
附件是测试对应的.swf,资源都内嵌了
核心算法主要写了一个随机分配的算法,就是保证每次玩的时候最后都要正好能全部消灭。连连看的死局这里暂时没有考虑。还有一个就是把判断两个棋子是否可以消除,我没有用网上介绍的递归算法,我用的“十字通路法”,我自己起的名字哈。我想这样来解释会清楚一些:
十字通路:
每个棋子拥有一个十字通路,就是它可以到达的上下左右,可以到达的意思就是路过的位置是空的或者是不可见的,类似一个十字一样。当然也可能不是“十”字,或者是个"T",总之就是遍历上下左右,碰壁为止,并整理记录下来X轴通路和Y轴通路。
判断两个棋子是否可以消除的条件:
1.两个棋子的图案必须要相同。
2.两个棋子最多通过两次“拐弯”可以到达。理解成我所谓的十字通路就是两个棋子的X(Y)轴通路可以直线相连。
以下是我用来测试的代码
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()" layout="vertical" width="100%" height="100%" backgroundGradientAlphas="[0.8, 0.9]" backgroundGradientColors="[#736D6D, #070707]" xmlns:ns1="*" xmlns:ns2="com.chess.*" xmlns:ns3="com.board.*"> <mx:Style source="myCSS.css"/> <mx:Script> <![CDATA[ import mx.events.CloseEvent; import mx.core.UIComponent; import mx.controls.Alert; import com.coreAlg.CheckBoard; import com.coreAlg.connect.Connect; import com.coreAlg.connect.GetCross; import embed.embedImage.EtImage; import com.board.Board; import com.chess.Chess; import mx.containers.HBox; import MyEvent.MyClickEvent; import com.position.Position; import mx.containers.Canvas; import embed.embedSound.HappySound; //private var position:Position; private var board:Board=new Board(); public var eee:EtImage=EtImage.getInstance(); //图片资源类 //程序里有个缓冲区 private var firstImageSource:Class=null; //上一个棋子的图片源 private var firstX:int=-1; //上一个棋子的X坐标 private var firstY:int=-1; //上一个棋子的Y坐标 private var tempImageSource:Class=null; //储存刚刚点击棋子的图片源 private var tempX:int=-1; //储存刚刚点击棋子的X坐标 private var tempY:int=-1; //储存刚刚点击棋子的Y坐标 private var getc:GetCross=GetCross.getInstance(); private var conn:Connect=Connect.getInstance(); private var check:CheckBoard=CheckBoard.getInstance(); private var pan:UIComponent=new UIComponent(); //画路径的画笔 private var sound:HappySound=HappySound.getInstance(); private var pathArray:Array; private var pathPan:UIComponent=new UIComponent(); private var pathTimer:Timer=new Timer(50); private var myTimer:Timer=new Timer(1000); private var totalTime:int=0; private var xN:int = 6; private var yN:int = 5; //private var board:Board; private function init():void { board.xNum=xN; //宽 board.yNum=yN; //高 board.nkind=5; //图案种数 board.x=0; board.y=0; myCanvas.addChild(board); myCanvas.addChild(pan); MyClickEvent.dispatcher.addEventListener(MyClickEvent.CLICK_IMAGE, clickHandler); this.addEventListener(MyClickEvent.CLICK_IMAGE, clickHandler); myTimer.start(); myTimer.addEventListener(TimerEvent.TIMER, onTimer); } private function onTimer(event:TimerEvent):void { totalTime++; } private function alertClickHandler(event:CloseEvent):Boolean { if (event.detail == Alert.OK) { xN += 2; yN += 2; if(xN > 10) { Alert.show('thank u 4 play~!'); return false; } myTimer.stop(); myTimer.start(); myCanvas.removeChild(board); board=new Board(); trace('board.chessCompleted:'+board.chessCompleted); board.xNum=xN; //宽 board.yNum=yN; //高 board.nkind=xN; //图案种数 board.x=0; board.y=0; myCanvas.addChild(board); return true; } return true; } private function clickHandler(event:MyClickEvent):void { tempX=event.x; tempY=event.y; var firPosition:Position=new Position(firstX, firstY); var secPosition:Position=new Position(tempX, tempY); //查看当前点击的通路数组 /* trace('xCross:'); var tttArray:Array=(getc.getCross((board.chessArray[event.y][event.x] as Chess), board)).getItemAt(0) as Array; for (var ttt:int=0; ttt < tttArray.length; ttt++) { trace((tttArray[ttt] as Position).xPosition + ' ' + (tttArray[ttt] as Position).yPosition); } tttArray=(getc.getCross((board.chessArray[event.y][event.x] as Chess), board)).getItemAt(1) as Array; trace('yCross:'); for (ttt=0; ttt < tttArray.length; ttt++) { trace((tttArray[ttt] as Position).xPosition + ' ' + (tttArray[ttt] as Position).yPosition); } */ tempImageSource=(board.chessArray[event.y][event.x] as Chess).imageSource; //如果缓存ID不为空 且 缓存ID和点击的目标不是同一个 且 缓存ID和目标ID有通路 if ((isValidPosition(firstX, firstY)) && (!equalPosition(tempX, tempY, firstX, firstY)) && (conn.connect(board, firPosition, secPosition))) { //画出路径,并消除那两个棋子,再清空路径数组 clearIcons.play([this]); (board.chessArray[tempY][tempX] as Chess).disAppearState(); (board.chessArray[firstY][firstX] as Chess).disAppearState(); board.chessCompleted += 2; drawPath(); //清空缓存 firstX=-1; firstY=-1; firstImageSource=null; board.pathArray=new Array(); //清空path if (check.checkComplete(board)) { mx.controls.Alert.show("congratulations~,难度"+xN+'乘以'+yN+" 一共用时" + totalTime+'秒', '', Alert.OK, this, alertClickHandler); } } else { //trace('最终匹配不成功'); //trace('*************************************************'); //没有匹配成功刷新缓存 if (firstX != -1 && !equalPosition(tempX, tempY, firstX, firstY)) { (board.chessArray[firstY][firstX] as Chess).normalState(); } firstImageSource=tempImageSource; firstX=tempX; firstY=tempY; // } } } private function equalImageSource(tm:Class, fir:Class):Boolean { if (tm == fir) { //trace('图片相等'); return true; } //trace('图片不相等'); return false; } private function isValidPosition(tx:int, ty:int):Boolean { if (tx >= 0 && ty >= 0) { //trace('横纵坐标都大于0'); return true; } //trace('坐标小于0'); //trace('firstX:'+firstX+' '+'firstY:'+firstY); return false; } private function equalPosition(tx:int, ty:int, firx:int, firy:int):Boolean { if (tx == firx && ty == firy) { //trace('坐标相等'); return true; } //trace('坐标不相等'); return false; } private function drawPath():void { trace('board.pathArray.length:' + board.pathArray.length); pathTimer.start(); pathArray=board.pathArray; board.pathArray=null; var step:Position=pathArray.shift() as Position; trace('path.length:' + pathArray.length); myCanvas.addChild(pathPan); pathPan.graphics.clear(); pathPan.graphics.lineStyle(2, 0xFF0000); pathPan.graphics.moveTo(board.x + board.leftGap + (step.xPosition + 1) * (board.chessWidth + 2) - board.chessWidth / 2, board.y + board.topGap + (step.yPosition + 1) * (board.chessHeight + 2) - board.chessHeight / 2); pathTimer.addEventListener(TimerEvent.TIMER, drawLine) //pathPan.addEventListener(Event.ENTER_FRAME,drawLine); } private function drawLine(event:Event):void { if (pathArray.length > 0) { var step:Position=pathArray.shift() as Position; pathPan.graphics.lineTo(board.x + board.leftGap + (step.xPosition + 1) * (board.chessWidth + 2) - board.chessWidth / 2, board.y + board.topGap + (step.yPosition + 1) * (board.chessHeight + 2) - board.chessHeight / 2); } else { pathTimer.stop(); //pathPan.removeEventListener(Event.ENTER_FRAME,drawLine); myCanvas.removeChild(pathPan); } } ]]> </mx:Script> <mx:Canvas id="myCanvas" width="100%" height="100%"> </mx:Canvas> <mx:SoundEffect id="clearIcons" duration="2000" source="{sound.clearSound}"/> </mx:Application>
附件是测试对应的.swf,资源都内嵌了
相关文章推荐
- iptables实现端口转发的过程
- iptables实现端口转发的过程
- Iptables实现端口转发的过程(修改版)
- 通过iptables实现端口转发和内网共享上网
- iptables实现端口转发
- 用iptables 实现本地端口转发(不错)
- Linux系统非ROOT用户80端口不能启动tomcat问题的变通办法——通过Iptables端口转发
- 配置iptables实现双机间端口转发
- 配置iptables实现端口转发
- 用IPTABLES的端口转发功能实现访问位于内网的MYSQL服务器
- centos6.5 iptables实现端口转发
- 配置iptables实现本地端口转发的方法详解
- 用iptables 实现本地端口转发
- 配置iptables实现端口转发
- IPtables 实现端口转发
- 用iptables 实现本地端口转发
- LVS + iptables 实现端口转发(DR模式)
- 配置iptables NAT端口转发 实现内网服务器端口提供公网接入
- 通过iptables实现端口转发和内网共享上网
- CentOS6.5基于iptables实现单网卡端口转发