ただのリバーシ

by shohei909 forked from flex ボタンイベントのテスト (diff: 769)
♥5 | Line 577 | Modified 2010-03-28 22:52:52 | MIT License
play

ActionScript3 source code

/**
 * Copyright shohei909 ( http://wonderfl.net/user/shohei909 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/86fL
 */

<?xml version="1.0" encoding="utf-8"?><!-- forked from shohei909's flex ボタンイベントのテスト -->
<!--
	ただのリバーシです。
	
	
	とりあえず完成。
	
	
	
	
	
	
	
	AI対戦ができます。
	強さはレベル3でそこそこ。
	
	だれかにもっと強いAIをつくてほしいけど、
	こんな汚いコードじゃだれもつくってくれないだろうか?
	
	
	
	
	
	
	
	
	
	
	それにしてもサムネイルがひどい・・・
	errorなんて出てたらクリックする人がいなくなるよね。
	なんとかならないのかな~。
-->
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
	height="465" width="465"
	
	verticalAlign="middle" 
	horizontalAlign="center" 
	applicationComplete="onLoad();"  
    >
    
    <!-- エフェクトとフィルター -->
    <mx:Blur id="EffectIn" duration="300"/>
    <mx:Fade id="EffectOut" duration="150"/>
    
	<mx:GlowFilter id="glow" color="0xFF6600" />
	<mx:BlurFilter id="blur" blurX="2" blurY="2"/>
	

    
    


	
	
    <mx:Script><![CDATA[	
    
    		import flash.display.*;
		import mx.containers.*;
		import mx.core.*;
		import mx.controls.Alert;
		import mx.events.CloseEvent;


		public var nowTurn:uint;
		public var yourTurn:uint;
		public var finish:Boolean;
		
		public var timer:uint;
		
		public var othelloSize:uint = 8;
		
		
		public var rand:Number;
		public var rand2:Number;
		public var passNumber:uint;
		
		public var blackNumber:uint;
		public var whiteNumber:uint;
		
		
		
		public var page:Array;
		public var nowPage:int;
		public var lastPage:int;
		
		public var player:Vector.<uint>=new Vector.<uint>();
		public var size:uint = 40;
 		public var alert:Alert = new Alert();
		public var reversiMap:Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>(othelloSize);
    		
    		 
    		public var vbox:Vector.<VBox> = new Vector.<VBox>(othelloSize); 
  		public var cell:Vector.<Vector.<ViewStack>> = new Vector.<Vector.<ViewStack>>(othelloSize); 

  		public var stone:Vector.<Vector.<Vector.<UIComponent>>> = new Vector.<Vector.<Vector.<UIComponent>>>(othelloSize); 

  		public var map:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>(othelloSize); 

        
        
        
        	public function onLoad():void{
	    		for(var x:uint=0;x<8;x++){ 
 
 	  	  		vbox[x] = new VBox();
 	  	  		cell[x] = new Vector.<ViewStack>(othelloSize);
 	  	  		
  				stone[x] = new Vector.<Vector.<UIComponent>>(othelloSize);
  				reversiMap[x] = new Vector.<uint>(othelloSize);
 	  	  		
 	  	  		vbox[x].setStyle("verticalGap","0");
 	  	  		
 	  	  		map[x] = new Vector.<Number>(othelloSize); 

  					
  				field.addEventListener(MouseEvent.CLICK,click);
				field.addChild(vbox[x]);
				
      			for(var y:uint=0;y<8;y++){			
  					stone[x][y] = new Vector.<UIComponent>(3);
 	  	  			cell[x][y] = new ViewStack(); 
 	  	  			reversiMap[x][y] = 0;
 	  	  			map[x][y] = 0;
 	  	  			
 	  	  			
  					stone[x][y][0] = new Canvas();
  					stone[x][y][1] = new Canvas();
  					stone[x][y][2] = new Canvas();
  					
  					
  					
  					
  					stone[x][y][1].setStyle("showEffect",EffectIn);
  					stone[x][y][2].setStyle("showEffect",EffectIn);
  					
  					stone[x][y][1].setStyle("hideEffect",EffectOut);
  					stone[x][y][2].setStyle("hideEffect",EffectOut);
  					
  					
 					stone[x][y][1].graphics.beginFill (0x000000, 1.0);	// 面のスタイル設定
					stone[x][y][1].graphics.lineStyle (2, 0x000000, 1.0);	// 線のスタイル指定
					stone[x][y][1].graphics.drawCircle (size/2-1, size/2-1 , size/2.2);

					stone[x][y][2].graphics.beginFill (0xFFFFFF, 1.0);	// 面のスタイル設定
					stone[x][y][2].graphics.lineStyle (2, 0x000000, 1.0);	// 線のスタイル指定
					stone[x][y][2].graphics.drawCircle (size/2-1, size/2-1 , size/2.2);

  					
 	  	  		
 	  	  			
 	  	  			cell[x][y].width=size;
 	  	  			cell[x][y].height=size;
 	  	  			
  					
 	  	  			cell[x][y].setStyle("borderStyle","solid"); 
 	  	  			cell[x][y].setStyle("borderColor","0x333333");
 	  	  			
 	  	  			cell[x][y].addChild(stone[x][y][0]);
 	  	  			cell[x][y].addChild(stone[x][y][1]);
 	  	  			cell[x][y].addChild(stone[x][y][2]);
 	  	  			
 	  	  			
 	  	  			
 	  	  			vbox[x].addChild(cell[x][y]);
 	  	  			


     			}
	    		}
	    			    		
 	  	  	Alert.cancelLabel="キャンセル";
 	  	  	Alert.buttonWidth=80;
	    		alert = Alert.show("", "リバーシ", (Alert.OK), this, alertListener);

        		alert.addChildAt(config,0);
 	  	  	alert.width=300;
 	  	  	alert.height=250;
     	}
     	private function alertListener(e:CloseEvent):void {
     		if(e.detail == Alert.OK){
     			nowTurn = 1;
        			passNumber=0;
        			finish = false;
        			page = new Array();
        			nowPage = 0;
        			lastPage = 0;
			
				yourTurn = selectTurn.selectedValue.valueOf();

     			player[0]=null; player[1]=0; player[2]=0;
				player[yourTurn]=0;
				player[3-yourTurn] = player2.selectedValue.valueOf();
        			removeEventListener(Event.ENTER_FRAME,cp);
				if(player[3-yourTurn] > 0){
					addEventListener(Event.ENTER_FRAME,cp);
				}
				
    				for(var x:uint=0;x<8;x++){
    					for(var y:uint=0;y<8;y++){
    						cell[x][y].selectedIndex=0;
    						reversiMap[x][y] = 0;			
    					}
    				}
    				
				undoButton.enabled=false;
				redoButton.enabled=false;
			
    				cell[3][3].selectedIndex=2;
    				cell[4][3].selectedIndex=1;
    				cell[3][4].selectedIndex=1;
    				cell[4][4].selectedIndex=2;
				reversiMap[3][3] = 2;
				reversiMap[4][3] = 1;
				reversiMap[3][4] = 1;
				reversiMap[4][4] = 2;
        			passButton.enabled = true;
    				rand = Math.random();
    				
    				output();
    			}
        	}
        private function newGame():void{
	    		alert = Alert.show("", "リバーシ", (Alert.OK | Alert.CANCEL), this, alertListener);

        		alert.addChildAt(config,0);
 	  	  	alert.width=300;
 	  	  	alert.height=250;
        }
     	
     	
     	
     	
		private function addNewPage():void{
			page[nowPage] = new Array();		
			for(var x:uint=0;x<8;x++){
				page[nowPage][x] = new Array();
				for(var y:uint=0;y<8;y++){
					page[nowPage][x][y] = reversiMap[x][y];		
   				}
   			}
			
			nowPage++;
			lastPage = nowPage;
			undoButton.enabled=true;
			redoButton.enabled=false;
		}
		private function undo():void{
			if(nowPage == lastPage){
				page[nowPage] = new Array();		
				for(var x:uint=0;x<8;x++){
					page[nowPage][x] = new Array();
					for(var y:uint=0;y<8;y++){
						page[nowPage][x][y] = reversiMap[x][y];		
	   				}
	   			}
			}
			nowPage--;
			redoButton.enabled=true;
			if(nowPage == 0){
				undoButton.enabled=false;
			}
			gotoNowPage();
		}
		private function redo():void{
			nowPage++;
			undoButton.enabled=true;
			if(nowPage == lastPage){
				redoButton.enabled=false;
			}
			gotoNowPage();
		}
		private function gotoNowPage():void{
			for(var x:uint=0;x<8;x++){
				for(var y:uint=0;y<8;y++){
					reversiMap[x][y] = page[nowPage][x][y];		
   				}
   			}
			setField();
		}
		
		
        private function click(e:MouseEvent):void{
        		var x:int = e.localX / size;
        		var y:int = e.localY / size;
        		
        		if(x>=0 && x<othelloSize && y>=0 && y<othelloSize && player[nowTurn]==0){ 
        			if(placable(x,y,nowTurn,reversiMap)){
        				addNewPage();
        				place(x,y);
        			}
        		}
        }
        
        
        
		
		//reversiMapのデータをfieldに反映
		private function setField():void{
			for(var x:uint=0;x<8;x++){
				for(var y:uint=0;y<8;y++){
					cell[x][y].selectedIndex = reversiMap[x][y];			
    				}
    			}
		}
		
		


        
        

        
	    //(x,y)に石を置いたとき何が起こるかを返す。
	 	private function placeData(x:uint,y:uint,t:uint,mapData:Vector.<Vector.<uint>>):Object{

			var object:Object = new Object();
			object.mapData =new Vector.<Vector.<uint>>(8);		
			for(var ax:uint=0;ax<8;ax++){
				object.mapData[ax] = new Vector.<uint>(8);
				for(var ay:uint=0;ay<8;ay++){
					object.mapData[ax][ay] = mapData[ax][ay];		
	   			}
	   		}

			object.counter = 0;
			
			if(finish || cell[x][y].selectedIndex != 0){
        			return object;
        		}
        		
        		for(var dx:int = -1; dx <= 1; dx++){
        			for(var dy:int = -1; dy <= 1; dy++){
					
					var sx:int = x;
					var sy:int = y;
					
					var count:uint=0;
					while(true){
						sx+=dx; sy+=dy;
						
						if(sx<0 || sx>=othelloSize || sy<0 || sy>=othelloSize || mapData[sx][sy] == 0){
							count=0;
							break;
						}else if(mapData[sx][sy] == t){
							break;
						}
						count++;
					}
					if(count > 0){
						sx = x; 
						sy = y;
						for(var i:int = 0;i<=count;i++){
							object.counter++;
							object.mapData[sx][sy] = t;
							sx+=dx; sy+=dy;
						}
					}
        			}
        		}
        		return object;
        	}
        
        
        	private function place(x:uint,y:uint):void{
        		var next:Object = placeData(x,y,nowTurn,reversiMap);
        		if(next.counter > 0){
        			nowTurn = 3 - nowTurn;
        			passNumber=0;
        			reversiMap = next.mapData;
        			setField();
        			output();
        		}
        	}
        
        
		private function placable(x:uint,y:uint,t:int,mapData:Vector.<Vector.<uint>>):Boolean{
        		if(mapData[x][y] != 0){ return false; }
        		for(var dx:int = -1; dx <= 1; dx++){
        			for(var dy:int = -1; dy <= 1; dy++){
					
					var sx:int = x;
					var sy:int = y;
					var count:uint=0;

					while(true){
						sx+=dx; sy+=dy;
						if(sx<0 || sx>=othelloSize || sy<0 || sy>=othelloSize || mapData[sx][sy] == 0){
							count=0;
							break;
						}else if(mapData[sx][sy] == t){
							break;
						}
						count++;
					}
		
					if(count > 0){
						return true;
					}
				}
	        	}
			return false;
		}
        	
        	
        	
        	
		private function passable():Boolean{
	    		for(var x:uint=0;x<8;x++){
	    			for(var y:uint=0;y<8;y++){
	    				if(placable(x,y,nowTurn,reversiMap)){ return false; }
	    			}
	    		}
			return true;
		}
        
        
        

		
		
		
		private function pass():void{
			if(passable()){
        			passNumber++;
				nowTurn = 3 - nowTurn;
        			output();
				Alert.show("パスしました", "パス", (Alert.OK), this);
			}else{
				Alert.show("まだ打てるところがあります。\nパスはできません", "パス", (Alert.OK), this);
			}
		}
        
        private function output():void{
        		blackNumber=0;
        		whiteNumber=0;
        		timer = 0;
        		finish = true;
        		
			for(var x:uint=0;x<8;x++){
				for(var y:uint=0;y<8;y++){
					if(cell[x][y].selectedIndex == 1){
						blackNumber++;
					}else if(cell[x][y].selectedIndex == 2){
						whiteNumber++;
					}else if(cell[x][y].selectedIndex == 0 && finish){
						if(placable(x,y,1,reversiMap) || placable(x,y,2,reversiMap)){
							finish = false;
						}
					}
				}
			}
			
			
			if(player[1]==0){
					if(yourTurn == 1){
						blackLabel.text="あなた";
					}else if(yourTurn == 2){
						blackLabel.text="相手";
					}
			}else if(0<player[1] && player[1]<10){
					blackLabel.text="COM";
			}
			
			
			if(player[2]==0){
					if(yourTurn == 2){
						whiteLabel.text="あなた";
					}else if(yourTurn == 1){
						whiteLabel.text="相手";
					}
			}else if(0<player[2] && player[2]<10){
					whiteLabel.text="COM";
			}
			
			blackLabel.text += " :" + blackNumber;
			whiteLabel.text += " :" + whiteNumber;
			
			if(nowTurn == 1){
				blackCanvas.filters = [glow];
				whiteCanvas.filters = [blur];
			}else if(nowTurn == 2){
				whiteCanvas.filters = [glow];
				blackCanvas.filters = [blur];
			}
			
			if(finish == true){
				gameOver();
			}
        }
        
        private function gameOver():void{
        		var s:String = blackNumber +":"+ whiteNumber+" ";
        		if((yourTurn == 1) == (blackNumber > whiteNumber) ){
        			s += "あなたの勝ちです。";
        		}else if((yourTurn == 2) == (blackNumber > whiteNumber) ){
        			s += "あなたの負けです。";
        		}else{
        			s += "引き分けです";
        		}
        		Alert.show(s,"GAME OVER");
        		
        		passButton.enabled = false;
        		removeEventListener(Event.ENTER_FRAME,cp);
        }
        
        
        
        private function cp(e:Event):void{
     		if(nowTurn != yourTurn && finish==false){
     			if(timer > 20){
     				switch(player[nowTurn]){
     					case 1:
     						easyAI();
							timer=0;
     						break;
     					case 2:
     						normalAI();
							timer=0;
     						break;
     					case 3:
     						hardAI();
							timer=0;
     						break;
     					case 4:
     						veryhardAI();
							timer=0;
     						break;
     					case 5:
     						hardestAI();
							timer=0;
     						break;
     				}
     			}
     			timer++;
     		}else{
	     		timer = 0;
	     	}
     	}
     	
        
        
        
        	private function easyAI():void{
        		if(passable()){
        			pass();
        			return;
        		}
        		
        		var max:int = 0;
        		var maxY:uint = 0;
        		var maxX:uint = 0;
        		
			for(var x:uint=0;x<8;x++){
				for(var y:uint=0;y<8;y++){
					var next:Object = placeData(x,y,nowTurn,reversiMap);
					var point:int = next.counter;
					if(point > 0){
						if(((x<2||5<x)&&(y<2||5<y))==false){
								point+=100;
						}
						if(x==0 || 7==x){
							if(y==0 ||7==y){
								point +=200;
							}
						}
					}
					if(max < point){
						max = point;
						maxX = x;
						maxY = y;
					}else if(max == point){
						var r:Number = rand*(nowPage+1);
						r = r - Math.floor(r);
						if(r < 0.5){
							maxX = x;
							maxY = y;
						}
					}
				}
			}
			place(maxX,maxY);
        	}
        
		private function normalAI():void{
        		if(passable()){
        			pass();
        			return;
        		}
        		
        		var max:int = 0;
        		var maxY:uint = 0;
        		var maxX:uint = 0;
			for(var x:uint=0;x<8;x++){
				for(var y:uint=0;y<8;y++){
					var next:Object = placeData(x,y,nowTurn,reversiMap);
					var point:int = next.counter;
					if(point > 0){
						if(((x<2||5<x)&&(y<2||5<y))==false){
								point =100-point;
						}
						if(x==0 || 7==x){
							if(y==0 ||7==y){
								point +=200;
							}
						}
					}
					
					if(max < point){
						max = point;
						maxX = x;
						maxY = y;
					}else if(max == point){
						var r:Number =rand*(nowPage+1);
						r = r - Math.floor(r);
						if(r < 0.5){
							maxX = x;
							maxY = y;
						}
					}
				}
			}
			place(maxX,maxY);
        	}
        	
        	private function hardAI():void{
        		if(passable()){
        			pass();
        		}

        		if(passable()){
        			pass();
        			return;
        		}
        		var max:int = 0;
        		var maxY:uint = 0;
        		var maxX:uint = 0;
			for(var x:uint=0;x<8;x++){
				for(var y:uint=0;y<8;y++){
					var next:Object = placeData(x,y,nowTurn,reversiMap);
					var point:int = next.counter;
					if(point > 0){
						if(((x<2||5<x)&&(y<2||5<y))==false){
								point =1000-point;
						}else{
								point +=900;
						}
						if(x==0 || 7==x){
							if(y==0 ||7==y){
								point +=1500;
							}
						}

						for(var ax:uint=0;ax<8;ax++){
							for(var ay:uint=0;ay<8;ay++){
								if(placable(ax,ay,nowTurn,next.mapData)){
									point+=3;
								}
								if(placable(ax,ay,3-nowTurn,next.mapData)){
									point-=6;
								}
							}
						}
					}
					if(max < point){
						max = point;
						maxX = x;
						maxY = y;
					}else if(max == point){
						var r:Number =rand*(nowPage+1);
						r = r - Math.floor(r);
						if(r < 0.5){
							maxX = x;
							maxY = y;
						}
					}
				}
			}
			place(maxX,maxY);
        	}
        
        
        
        
        //だれかがつくるかもしれないAI
		private function veryhardAI():void{
        		//if(passable()){pass();return;}
			//place(.......);
        	}
        private function hardestAI():void{
        		//if(passable()){pass();return;}
			//place(.......);
        	}
        
    ]]></mx:Script>
    
    
    
    




 
    <!-- Alert用のBox -->   
    <mx:Box id="config" includeInLayout="false" horizontalAlign="left" height="100%"  width="100%" 
    				paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" >  
    		<mx:Label text="対戦相手の設定"/>
    		<mx:HBox>
    			<mx:RadioButtonGroup id="player2" selectedValue="1"/>
    		    <mx:RadioButton groupName="player2" value="0" label="人"/>
    		    <mx:RadioButton groupName="player2" value="1" label="COMレベル1"/>
    		</mx:HBox>
    		<mx:HBox>
    		    <mx:RadioButton groupName="player2" value="2" label="COMレベル2" />
    		    <mx:RadioButton groupName="player2" value="3" label="COMレベル3" />
		</mx:HBox>
    		
    		<!--
    			<mx:HBox>
    			    <mx:RadioButton groupName="player2" value="4" label="COMレベル4" />
   	 		    <mx:RadioButton groupName="player2" value="5" label="COMレベル5" />
			</mx:HBox>
		-->
    		
    		<mx:Spacer height="10"/>
    		<mx:Label text="あなたの手順"/>
    		<mx:HBox >
    			<mx:RadioButtonGroup id="selectTurn" selectedValue="1"/>
    		    <mx:RadioButton groupName="selectTurn" value="1" label="先手"/>
    		    <mx:RadioButton groupName="selectTurn" value="2" label="後手"/>
    		</mx:HBox>
    </mx:Box>
    
    
    
    
    
    
    
	
    <!-- 盤面 -->
    	<mx:HBox id="field" borderStyle="solid" horizontalGap="0" borderColor="0x000000" backgroundColor="0x00CC00"  	/>

    	
    <mx:HBox horizontalGap="2" width="85%" horizontalAlign="center" >
    		<mx:Button label="新しいゲーム"	height="30" 	click="newGame();"/>
    		<mx:Spacer width="20"/>
    		<mx:Button id="passButton" label="パス"  		height="30" 	click="pass();"/>
    		<mx:Spacer width="20"/>
    		<mx:Button id="undoButton" label="一つ戻る"  	enabled="false" height="30" 	click="undo();"	/>
    		<mx:Button id="redoButton" label="やり直し"  	enabled="false" height="30" 	click="redo();"	/>
    	</mx:HBox>
    	
    <mx:HBox horizontalGap="2" width="85%">   
     		
	    <mx:Canvas id="blackCanvas" borderStyle="solid" borderColor="0x222222" backgroundColor="0x00CC00">
	    		<mx:UIComponent id="black" height="30" width="30" 
	    					creationComplete="	black.graphics.beginFill (0x000000, 1.0);	
											black.graphics.lineStyle (2, 0x000000, 1.0);
											black.graphics.drawCircle (15, 15, 14);" />					
    		</mx:Canvas>
    		
	 	<mx:Label id="blackLabel" text="" height="30" fontSize="20"/>
    		<mx:Spacer width="100%"/>
      	<mx:Label id="whiteLabel" text="" height="30" fontSize="20"/>
  		
    		<mx:Canvas id="whiteCanvas"  borderStyle="solid" borderColor="0x222222" backgroundColor="0x00CC00">
	    		<mx:UIComponent id="white" height="30" width="30"
	    					creationComplete="	white.graphics.beginFill (0xFFFFFF, 1.0);	
											white.graphics.lineStyle (2, 0x000000, 1.0);
											white.graphics.drawCircle (15, 15, 14);" />
											
    		</mx:Canvas>
    		
    	</mx:HBox>
</mx:Application>

Forked