Ks-Product.com

前回のテトリスがかなり甘い作りで動作が不安定だったので、そこだけ注意してオセロを作ってみました。前作のように徐々に処理が重くなっていくってことは無いと思います。制作時間は丁度1日くらいでカンニングは基本的にしてません。

感想としてやっぱ色々と冗長な感じは否めませんね。アクセス修飾子も特別意識して指定してないです。CPUルーチンもランダムに置くだけという手抜き間満載です。
ちなみにドキュメントクラスに「Othello」と指定すれば前作同様それだけで動作しますが、一応zipでも配布します。

Download Files ファイルをダウンロードする
オセロサンプル ソースファイル
オセロのソースファイルです。最小限の機能のみ。
ライセンス: 営利・非営利問わず自由(改変など)に使えます。
ただし、このファイル自体を販売する行為などは禁じます。
アプリケーション: Adobe Flash CS4、FlashDevelop(不要です)
ActionScript バージョン: 3.0

package  
{
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.geom.Point;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;
    import flash.utils.Timer;
    /**
     * ...
     * @author Ks-Product.com
     */
    public class Othello extends Sprite
    {
        public const EMPTY = 0;
        public const WHITE = 1;
        public const BLACK = 2;
        public static const CELL_RADIUS = 15;
        public static var self:Othello;
        public var b:Board;
        public var canceler:Sprite
        public var boardArray:Array;
        public var currentColor:uint;
        public var explanation:TextField;
        public var phaseText:TextField;
        public var scoreText:TextField;
        
        public function Othello() 
        {
            initialize();
        }
        
        private function initialize():void
        {
            self = this;
            b = new Board();
            boardArray = b.board;
            b.x = 10;
            b.y = 10;
            addChild(b);
            
            canceler = new Sprite();
            canceler.graphics.beginFill(0x000000, 0);
            canceler.graphics.drawRect(b.x, b.y, b.width, b.height);
            canceler.graphics.endFill();

            
            var min:uint = 1;
            var max:uint = 3;
            currentColor = Math.floor(Math.random() * (max - min) + min);
            
            var f:TextFormat = new TextFormat();
            f.font = "_sans";
            f.color = 0x000000;

            var f2:TextFormat = new TextFormat();
            f2.font = "_sans";
            f2.color = 0xCCCCCC;

            phaseText = new TextField();
            phaseText.text = (currentColor == WHITE)? "白の番です" : "黒の番です";
            phaseText.x = 280;
            phaseText.y = 110;
            phaseText.setTextFormat(f);
            phaseText.autoSize = TextFieldAutoSize.LEFT;
            addChild(phaseText);
            
            scoreText = new TextField();
            scoreText.text = "白 : 0 , 黒 : 0";
            scoreText.x = 280;
            scoreText.y = 140;
            scoreText.setTextFormat(f);
            scoreText.autoSize = TextFieldAutoSize.LEFT;
            addChild(scoreText);
                    
            explanation = new TextField();
            explanation.text = "※プレイヤーは白、CPUは黒固定です";
            explanation.x = 280;
            explanation.y = 230;
            explanation.setTextFormat(f2);
            explanation.autoSize = TextFieldAutoSize.LEFT;
            addChild(explanation);
            initializePiece();
            startGame();
        }
        
        public static function _setPiece(pos:Object):void {
            var rPos:Array = self.getFlipPiece(pos);
            if (rPos.length) {
                self.setPiece(self.currentColor, pos);
                for (var i:uint = 0; i < rPos.length; i++) {
                    self.turnPiece(rPos[i]);
                }
                
                var blackNum:uint = 0;
                var whiteNum:uint = 0;
                for ( i = 0; i < self.boardArray.length; i++) {
                //集計
                    for (var j:uint = 0; j < self.boardArray[i].length; j++) {
                        if (self.boardArray[i][j] == self.WHITE) {
                            whiteNum++
                        }else if (self.boardArray[i][j] == self.BLACK) {
                            blackNum++
                        }
                    }
                }
                
                self.scoreText.text = "白 : " + whiteNum + " , 黒 : " + blackNum;
                self.currentColor = (self.currentColor == 1)?2:1;
                self.phaseText.text = (self.currentColor == self.WHITE)? "白の番です" : "黒の番です";
                
                if (!self.checkPiece()) {
                    //置ける場所がない場合の処理
                    var pass:String = (self.currentColor == self.WHITE)? "白がパスをしました。" : "黒がパスをしました。";
                    self.currentColor = (self.currentColor == 1)?2:1;
                    self.phaseText.text = (self.currentColor == self.WHITE)? pass + "白の番です" : pass + "黒の番です";
                    
                    if (!self.checkPiece()) {
                    //両者置けない場合は終了
                        var result:String;
                        if (whiteNum > blackNum) {
                            result = "白の勝利です。";
                        }else if (whiteNum < blackNum) {
                            result = "黒の勝利です。";
                        }else {
                            result = "引き分けです。";
                        }
                        self.phaseText.text = "ゲームが終了しました。" + result;
                        return;
                    }
                }
                if (self.currentColor == self.BLACK) self.moveCPU();
            }
        }
        
        /**
         * ピースの初期配置
         */
        private function initializePiece():void
        {
            setPiece(WHITE, { x:3, y:3 } );
            setPiece(BLACK, { x:4, y:3 } );
            setPiece(BLACK, { x:3, y:4 } );
            setPiece(WHITE, { x:4, y:4 } );
        }
        
        /**
         * ゲームスタート
         */
        private function startGame():void
        {
            checkPiece();
            if (currentColor == BLACK) moveCPU();
        }
        
        /**
         * CPUがピースを置きます。
         */
        public function moveCPU():void
        {
            addChild(canceler);
            
            var t:Timer = new Timer(500, 1);//擬似的思考時間
            t.addEventListener(TimerEvent.TIMER_COMPLETE, function() {
                var candidate:Array = [];
                for (var i:uint = 0; i <= 7; i++) {
                    for (var j:uint = 0; j <= 7; j++) {
                        if(b.cell[i][j].active) candidate.push(b.cell[i][j].pos)
                        
                    }
                }
                
                var rnd:uint = Math.floor(Math.random()*candidate.length);
                Othello._setPiece(candidate[rnd]);
                removeChild(canceler);
            } );
            t.start();
        }
        
        /**
         * 置けるセルを調べてアクティブ化
         * @return sucess
         */
        private function checkPiece():Boolean
        {
            var success:Boolean = false;
            var pos:Object = { x:0, y:0 };
            
            for (pos.x = 0; pos.x <= 7; pos.x++) {
            for (pos.y = 0; pos.y <= 7; pos.y++) {
                var flg:Boolean = flg = false;
                if (!boardArray[pos.y][pos.x])
                {
                    var filpPos:Array = checkFlipDirection(pos);
                    
                    if (filpPos.length) {
                        success = true;
                        b.cell[pos.y][pos.x].active = true
                    }else {
                        b.cell[pos.y][pos.x].active = false;
                    }
                }else {
                    b.cell[pos.y][pos.x].active = false;
                }
            }
            }
            return success;
        }

        /**
         * 裏返すピースを取得
         * @param    pos
         * @return  裏返すピース
         */
        private function getFlipPiece(pos:Object):Array
        {
            var filpPos:Array = [];
            if (boardArray[pos.y][pos.x]) return filpPos;
            return checkFlipDirection(pos);
        }
                
        /**
         * 指定座標から8方向へ裏返すことの出来るピースを検索
         * @param pos
         * @return 
         */
        private function checkFlipDirection(pos:Object):Array
        {
            var filpPos:Array = [];
            var rc:uint = (currentColor == WHITE)?BLACK:WHITE;

            for (var i:int = pos.x -1; i <= pos.x + 1; i++) {
                for (var j:int = pos.y -1; j <= pos.y + 1; j++) {
                    if (i >= 0 && j >= 0 && i <= 7 && j <= 7) {
                        if (boardArray[j][i] == rc) {
                            //反転可能な色であればその方向を調べる
                            var tmpPos:Array = [];
                            var dx:uint = i - pos.x;
                            var dy:uint = j - pos.y;
                            var nx:uint = i;
                            var ny:uint = j;
                            while (nx >= 0 && ny >= 0 && nx <= 7 && ny <= 7) {
                                tmpPos.push( { x:nx, y:ny } );
                                if (boardArray[ny][nx] == currentColor) {
                                    filpPos.push(tmpPos);
                                    break;
                                }else if (boardArray[ny][nx] == EMPTY) {
                                    break;
                                }
                                nx += dx;
                                ny += dy;
                            }
                        }
                    }
                }
            }
            return filpPos;
        }

        /**
         * ピースをボードに配置
         * @param    color
         * @param    pos
         */
        private function setPiece(color:uint,pos:Object):void
        {
            boardArray[pos.y][pos.x] = color;
            
            var p:Piece = new Piece(color);
            p.x = b.cell[pos.y][pos.x].x + CELL_RADIUS + b.x;
            p.y = b.cell[pos.y][pos.x].y + CELL_RADIUS + b.y;
            b.cell[pos.y][pos.x].piece = p;
            addChild(p);
        }
        
        /**
         * ピースを反転させる
         * @param    start
         * @param    end
         */
        private function turnPiece(pos:Array):void
        {
            for (var i in pos) {
                boardArray[pos[i].y][pos[i].x] = currentColor;
                b.cell[pos[i].y][pos[i].x].piece.color = currentColor;
            }
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
class Board extends Sprite
{
    public var board:Array;    
    public var cell:Array;
    function Board()
    {
        create();
    }
    
    private function create():void
    {
        board = [[0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0]];
        cell = [[0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0]];
        
        for (var i:uint = 0; i < board.length; i++ ) {
            for (var j:uint = 0; j < board[i].length; j++) {
                var c:Cell = new Cell();
                
                c.x = i * c.width;
                c.y = j * c.height;
                addChild(c);
                cell[j][i] = c;
                cell[j][i].pos = { x:i, y:j };
            }
        }
    }
}

class Cell extends Sprite
{
    public static const CLICK = "cellclick";
    public var ct:ColorTransform;
    public var pos:Object;
    public var piece:Piece;
    private var _active:Boolean;
    function Cell()
    {
        ct = new ColorTransform();
        create();
        
        addEventListener(MouseEvent.MOUSE_OVER, onRollOver);
        addEventListener(MouseEvent.MOUSE_OUT, onRollOut);
    }
    
    private function create():void
    {
        graphics.lineStyle(1);
        graphics.beginFill(0x009900, 1);
        graphics.drawRect(0, 0, Othello.CELL_RADIUS*2, Othello.CELL_RADIUS*2);
        graphics.endFill();
    }
    
    public function onRollOver(e:Event):void
    {
        ct.redOffset = ct.greenOffset = ct.blueOffset = 50;
        transform.colorTransform = ct;
    }
    
    public function onRollOut(e:Event):void
    {
        if (active) {
            ct.redOffset = 150;
            ct.greenOffset = ct.blueOffset = 0;
        }else{
            ct.redOffset = ct.greenOffset = ct.blueOffset = 0;
        }
        transform.colorTransform = ct;
    }
    
    public function set active(value:Boolean):void 
    {
        if (value) {
            ct.redOffset = 150;
            ct.greenOffset = ct.blueOffset = 0;
            buttonMode = true;
            addEventListener(MouseEvent.CLICK, onClick);
        }else {
            ct.redOffset = 0;
            buttonMode = false;
            removeEventListener(MouseEvent.CLICK,onClick);
        }
        transform.colorTransform = ct;
        _active = value;
    }
    
    private function onClick(e:MouseEvent):void 
    {
        Othello._setPiece(pos);
    }
    
    public function get active():Boolean { return _active; }
}

class Piece extends Sprite
{
    private var _color:uint;
    function Piece(_color:uint)
    {
        color = _color;
        create();
        mouseEnabled = false;
    }
    
    private function create():void
    {
        var c:uint;
        if (color == 1) {
            c = 0xFFFFFF;
        }else if (color == 2) {
            c = 0x000000;
        }else {
            throw new Error("Pieceクラスのコンストラクタには1,2以外の数値を指定できません"); 
            return;
        }
        graphics.lineStyle(1);
        graphics.beginFill(c, 1);
        graphics.drawCircle(0, 0, Othello.CELL_RADIUS-4);
        graphics.endFill();
    }
    
    public function get color():uint { return _color; }
    
    public function set color(value:uint):void 
    {
        _color = value;
        create();
    }
}

コメント(0)

コメントが存在しません。

コメントを投稿する

※投稿されたコメントは管理人が承認するまで反映されません。
またHTMLタグはご利用できません。コメント上にHTMLタグを表示させたい場合は全角でご入力ください。

お名前
サイトURL
コメント
  • Home
  • > オセロ(リバーシ)作ってみた。
名前:
kakeruニコ動twitter
職業:
neet(転職活動中)
生年月日:
1983年4月19日

Flash(ActionScript)で食っていけたらなと思う今日この頃…とりあえず、年末年始にかけて転職活動できるようにごにょごにょ…

Powered by Movable Type.

ご覧の環境ではこのコンテンツはご利用できません。
最新のFlashPlayerをダウンロードしてからご利用ください。
Get Adobe Flash player