オストルのGUIをJavaScriptで作成しました。
連続した駒をオス処理は再帰を使って記述しました。
こちらで遊べます。
千日手ルールは未実装です。遊ぶ人が気を付けてください。
ostle.html
<html><head><meta charset="Shift_JIS">
<title>Ostle</title><script>
<!--
var canvas; //オブジェクト
var ctx; //コンテキスト
var nametbl=[
"■","□","●"
];
var x1=[ 0, -1, 0, 1]; //移動量x
var y1=[-1, 0, 1, 0]; //移動量y
var movtbl=[
[ 1, 1, 1, 1 ], //0:■
[ 1, 1, 1, 1 ], //1:□
[ 1, 1, 1, 1 ], //2:●
];
var setup=[
[ 1, 1, 1, 1, 1],
[ -1, -1, -1, -1, -1],
[ -1, -1, 2, -1, -1],
[ -1, -1, -1, -1, -1],
[ 0, 0, 0, 0, 0],
];
var fontcolor=["black","maroon"]; //文字の色
var boxcolor=["LimeGreen","gray" ,"blue" ,"red"]; //線の色
var fillcolor=["LimeGreen","Khaki","white","LightPink"]; //盤面の色
var psize=32; //マスのピクセル数
var board=[]; //盤バッファ
var bw=7,bh=7; //盤バッファのサイズ
var ofsx=1,ofsy=1; //盤のオフセット座標
var turn=0; //0=先手/1=後手
var startx=-1,starty=-1; //選択した座標
var username=["ipad","iphone","android"]; //端末の名前
var playtbl=["先手","後手"];
var connect=0;
//盤の情報
function piece() {
this.id=-1; //駒の種類(-1=駒がない)
this.player=0; //駒の向き(0=先手/1=後手/2=穴)
this.movable=false; //移動可能フラグ
}
//初期化処理
function init(){
canvas=document.getElementById("world");
canvas.width=psize*bw;
canvas.height=psize*bh;
ctx=canvas.getContext('2d');
ctx.font="24px 'MS Pゴシック'";
user=window.navigator.userAgent.toLowerCase();
for(i=0; i<username.length; i++){
if(user.indexOf(username[i]) > 0)break;
}
if(i < username.length){
document.addEventListener("touchstart", touchstart);
}else{
document.addEventListener("mousedown", mousedown);
}
board=new Array(bh);
for(y=0; y<bh; y++){
board[y]=new Array(bw);
for(x=0; x<bw; x++){
board[y][x]=new piece(); //盤バッファの初期化
}
}
for(x=0; x<5; x++){
for(y=0; y<5; y++){
board[ofsy+y][ofsx+x].id=setup[y][x];
board[ofsy+y][ofsx+x].player=setup[y][x];
}
}
redraw(); //画面全体を再描画
}
//スマホ/タブレット用のタッチイベント
function touchstart(e){
if (e.targetTouches.length==1){
touch=e.targetTouches[0];
touchpiece(touch.pageX ,touch.pageY);
}
}
//PC用のクリックイベント
function mousedown(e){
touchpiece(e.clientX ,e.clientY);
}
//駒の移動処理
function touchpiece(tx,ty){
cx=Math.floor((tx-8)/psize);
cy=Math.floor((ty-8)/psize);
if(isinside(cx,cy,0,0,bw,bh)==false)return;
if(startx==-1){
movestart(cx,cy); //移動開始
}else{
moveend(cx,cy); //移動終了
startx=-1;
redraw(); //画面全体を再描画
}
}
//移動開始
function movestart(cx,cy){
id=board[cy][cx].id;
if(id==-1)return; //駒が存在しないと無効
player=board[cy][cx].player;
if(!(player==turn || player==2))return; //自分の駒と穴のみ動かせる
startx=cx;
starty=cy;
drawpiece(startx,starty,id,player,2); //駒を白色に
if(isinside(startx,starty,ofsx,ofsy,5,5)==false){
for(x=ofsx; x<(ofsx+5); x++){ //配置可能マスを描画
for(y=ofsx; y<(ofsx+5); y++){ //配置可能マスを描画
while(isinside(x,y,ofsx,ofsy,5,5)==true){
drawpiece(x,y,-1,0,3);
board[y][x].movable=true;
}
}
}
}
for(dir=0; dir<4; dir++){ //移動可能マスを描画
x=startx;
y=starty;
while(movtbl[id][dir] > 0){
x +=x1[dir];
y +=y1[dir];
id2=board[y][x].id;
player2=board[y][x].player;
if(isinside(x,y,ofsx,ofsy,5,5)==false) break; //盤の外へ
if((id==2) && (id2==0)) break;
if((id==2) && (id2==1)) break;
drawpiece(x,y,id2,player2,3); //盤面を赤色に
board[y][x].movable=true;
if(movtbl[id][dir]==1) break;
}
}
}
//移動終了
function moveend(endx,endy){
if(board[endy][endx].movable==false)return; //移動不可能
dx=endx - startx;
dy=endy - starty;
if(board[endy][endx].id==-1){ // 移動先が空白マスの場合
board[endy][endx].id=board[starty][startx].id;
board[endy][endx].player=board[starty][startx].player;
board[starty][startx].id=-1;
board[starty][startx].player=-1;
}else if(board[endy][endx].id==2){ // 移動先が穴の場合
board[starty][startx].id=-1;
board[starty][startx].player=-1;
}else if(isinside(endx,endy,ofsx,ofsy,5,5)==false){ // 移動先が盤外の場合
board[starty][startx].id=-1;
board[starty][startx].player=-1;
}else if((board[endy][endx].id==0) || (board[endy][endx].id==1)){ // 移動先に駒がある場合
// 1マス隣の駒を再帰処理する
moveend(endx+dx,endy+dy)
// 押した駒を1マス隣にずらす
board[endy][endx].id = board[starty][startx].id;
board[endy][endx].player = board[starty][startx].player;
// 押した駒があった場所を空白マスにする
board[starty][startx].id = -1;
board[starty][startx].player = -1;
}
turn ^=1; // プレイヤーの切り替え
}
//駒を描画
function drawpiece(x,y,id,player,color){
px=x*psize;
py=y*psize;
ctx.fillStyle=boxcolor[color];
ctx.fillRect(px, py, psize, psize);
ctx.fillStyle=fillcolor[color];
ctx.fillRect(px+1, py+1, psize-2, psize-2);
if(id==-1)return;
ctx.fillStyle=fontcolor[(id >> 3)& 1];
if(player){
px=-px-psize;
py=-py-psize;
ctx.rotate(Math.PI);
}
ctx.fillText(nametbl[id],px+4,py+24,300);
if(player)ctx.rotate(Math.PI);
}
//駒が範囲内に存在するか判定
function isinside(x,y,ax,ay,w,h){
if((x<ax)||(x>=(ax+w))||(y<ay)||(y>=(ay+h)))return(false);
return(true);
}
//画面全体を再描画
function redraw(){
for(y=0; y<bh; y++){
for(x=0; x<bw; x++){
if(isinside(x,y,ofsx,ofsy,5,5))c=1; else c=0;
id=board[y][x].id;
player=board[y][x].player;
drawpiece(x,y,id,player,c); //駒を描画
board[y][x].movable=false;
}
}
ctx.fillStyle=fontcolor[0];
ctx.fillText(playtbl[turn],80,(1-turn)*196+24,300);
}
//-->
</script></head><body onload="init()">
<canvas id="world"></canvas></body></html>