コアダンプの数だけ強くなれるよ

見習いエンジニアの備忘log

Javascriptでオセロ(その1)

HTML+JavaScriptでブラウザで動くオセロを実装してみる。
制限付き(*1)で動いたところまで。

ソースコードはほとんど参考(*2)のまま。

(*1) 機能制限
・AIなし(人間vs人間だけ)
・黒が先行
・パス不可
・勝利判定なし

ソースコード

html

othello.html

<html>
<head>
	<title>Othello</title>
	<link rel="stylesheet" type="text/css" href="css/board.css">
</head>

<body>
	<script type="text/javascript" src="js/othello.js"></script>
	
	<!-- 盤面の要素定義 -->
	<div style="display:none">
		<div id="cell" class="square"><div class="cell"></div></div>
		<div id="black" class="square"><img class="block" src="img/black.png"></img></div>
		<div id="white" class="square"><img class="block" src="img/white.png"></img></div>
	</div>

	<div id="board"></div>


</body>
</html>
javascript

othello.js

(function() {
    // 変数定義
    var BOARD_TYPE = {
        'WIDTH' :8,
        'HEIGHT':8,
    };

    var PIECE_TYPE = {
        'NONE'   : 0,
        'BLACK'  : 1,
        'WHITE'  : 2,
        'MAX'    : 3,
    };

    var stone;
    var board = [];

    var turn = PIECE_TYPE.BLACK;
    var checkTurnOver = function(x, y, flip) {
    
        var ret = 0;
        
        for (var dx = -1; dx <= 1; dx++) {
            for(var dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) {
                    continue;
                }
            
                var nx = x + dx;
                var ny = y + dy;
                var n = 0;
                while(board[nx][ny] == PIECE_TYPE.MAX - turn) {
                    n++;
                    nx += dx;
                    ny += dy;
                }
                
                if (n > 0 && board[nx][ny] == turn) {
                    ret += n;
                    
                    if (flip) {
                        nx = x + dx;
                        ny = y + dy;
                        
                        while(board[nx][ny] == PIECE_TYPE.MAX - turn) {
                            board[nx][ny] = turn;
                            nx += dx;
                            ny += dy;
                        }
                        
                        
                    }
                }
            }
        }
        
        return ret;
    };
    
    var showBoard = function() {
    
        var b = document.getElementById("board");
        
        while(b.firstChild) {
            b.removeChild(b.firstChild);
        }
        
        for(var y = 1; y <= BOARD_TYPE.HEIGHT; y++) {
            for(var x = 1; x <= BOARD_TYPE.WIDTH; x++) {
                var cell = stone[board[x][y]].cloneNode(true);
                
                cell.style.left = ((x - 1) * 31) + "px"; 
                cell.style.top = ((y - 1) * 31) + "px"; 
                b.appendChild(cell);
                
                if (board[x][y] == PIECE_TYPE.NONE) {
                    (function() {
                        var _x = x;
                        var _y = y;
                        //alert("break point")
                        cell.onclick = function() {
                            if (checkTurnOver(_x, _y, true) > 0) {
                                board[_x][_y] = turn;
                                showBoard();
                                turn = PIECE_TYPE.MAX - turn;
                            }
                            
                        };
                    })();
                }
            }
        }
        
    };

    onload = function() {
        
        // 0:石無し, 1:黒, 2:白
        stone = [
            document.getElementById("cell"),
            document.getElementById("black"),
            document.getElementById("white")
        ];
        
        // PIECE種別の凍結(念のため)
        Object.freeze(PIECE_TYPE);
        
        // 盤面を初期化
        for (var i = 0; i < 10; i++) {
            board[i] = [];
            for (var j = 0; j < 10; j++) {
                board[i][j] = PIECE_TYPE.NONE;
            }
        }
        
        // 黒白の初期配置
        board[4][5] = PIECE_TYPE.BLACK;
        board[5][4] = PIECE_TYPE.BLACK;
        board[4][4] = PIECE_TYPE.WHITE;
        board[5][5] = PIECE_TYPE.WHITE;
        
        // 盤面表示
        showBoard();
    };
})();
css
#board{
    position            : relative;
}

.cell
{
    position            : relative;
    top                 : 1px;
    left                : 1px;
    width               : 31px;
    height              : 31px;
    background-color    : #00ff00;
}

.square
{
    position            : absolute;
    width               : 33px;
    height              : 33px;
    background-color    : #000000;
}

.block
{
    display             : block;
    position            : relative;
    top                 : 1px;
    left                : 1px;
    width               : 31px;
    height              : 31px;
}
その他

black.png
f:id:segmentation-fault:20170320225002p:plain

white.png
f:id:segmentation-fault:20170320225005p:plain

実行結果

f:id:segmentation-fault:20170320225855p:plain


次回は下記を目標に作業。
・機能追加
・ソースコードをなるべく綺麗に直す
・GitHubにアップ&埋め込み。


www.segmentation-fault.xyz



(*2) 参考
【プログラミング】オセロを1時間で作ってみた【実況解説】 by t-kihira ニコニコ技術部/動画 - ニコニコ動画