AURA 株式会社アウラ

RECRUIT急募!採用エントリー
アルゴリズムを考えるのが楽しい!JavaScriptで将棋を作ろう

スタッフブログ

Staff Blog
  1. ホームページ制作はアウラ:ホーム
  2. スタッフブログ
  3. アルゴリズムを考えるのが楽しい!JavaScriptで将棋を作ろう

アルゴリズムを考えるのが楽しい!JavaScriptで将棋を作ろう

アルゴリズムを考えるのが楽しい!JavaScriptで将棋を作ろう

こんにちは。先日入社した周(シュウ)です。
趣味は山登りで、休みの日は、緑の多い山で森林の匂いを嗅ぐのが好きです。
よろしくお願い致します。

「プログラミングの楽しさって何?」
と聞かれたら、やはり多種多様の手段です。
そのアルゴリズムを考え、悩みながら、答案を掘り出すことに楽しさがあります。

アルゴリズムを考えることで、
クリエイターにとって必要不可欠の思考力を鍛えることが期待できます。
特に、日本の伝統ゲームである「将棋」を再現するためのアルゴリズムは競い合いも出るほど、
プログラム学習者に人気があります。

同じ言語を使用しても、100人が記述したら、100通りの可能性が出てきます。

今回、私はJavaScriptを使って、将棋のアルゴリズムに挑戦してみました。

HTMLタグを使った将棋の盤の組み方とは?

先に将棋のボードの形から考えます。
将棋のボードは9マス×9マスのグリッドです。マスの中に駒が一個ずつ並びます。
そして上から3行と下から3行は敵陣と自分の陣になります。

行単位で気軽に管理できるタグと言えば、「table」が考えられます。
行を表す「tr」タグにクラス名を付けると、敵と味方の陣を判別することが出来ます。

リストの「ul」タグを使うのも1つですが、ボードを組み出すため、連続81個の「li」タグを使わなければなりません。
後ほど、駒を動かしたり、反転したりするときに、その先のマスを計算することが困難になります。
そこで、「table」を使うことで計算が圧倒的にしやすくなります。

ピンポイント:マス目の交点の付け方

将棋ボードのマス目交点に四つの黒い点が付いています。
どのようにCSSを使って再現するのでしょうか。
私はまず黒い点に隣接するマスを探し出しました。
そして疑似要素「after」で小さい円を作り、positionで位置を指定します。

div .board tr:nth-child(3) td:nth-child(3)::after,
div .board tr:nth-child(3) td:nth-child(6)::after,
div .board tr:nth-child(6) td:nth-child(3)::after,
div .board tr:nth-child(6) td:nth-child(6)::after {
  content: '';
  position: absolute;
  right: -0.3rem;
  bottom: -0.3rem;
  width: 0.6rem;
  height: 0.6rem;
  background: #333;
  border-radius: 50%;
}

敵と味方の判別方法

将棋のボードを作る際に、味方の陣と敵の陣が収まる「tr」タグに、
それぞれのクラス名を付けました。
しかし、それだけでは、敵と味方を完全に見分けることはできません。

自分の駒が相手の陣に入ると、自分の駒か、相手の駒か、判別しにくくなります。
見た目上は、三角の指し方向で一目で分かりますが、プログラミング上で判別しやすくするために、
駒にもクラスを付けるか「alt」属性を活用する必要があるのではないかと考え、今回はalt属性を使って駒の状態を把握することにしました。

ここでは、「飛車」を例にします。

NhisyaA

頭に付いている「N」は、成り駒であるかどうかを示します。
そして最後に付いている「A」を用いて、自分の駒か相手の駒かを判別します。

駒の動かし方

将棋では駒によって「動かし方」が違ってきます。
駒ごとに「動かし方」の関数を作成するのも1つの手です。

駒によっては動かし方に共通点があると気づきました。
概して言えば、上下左右と右上・左上・右下・左下になります。
その上、移動できるマス数も、何マスでも移動できるパターンと、一マスしか移動できないパターンに分れます。

パターンごとに、「動かし方」の関数を作って、その関数をそれぞれの駒に与えれば、コードの短縮に繋がるのではないかと閃きました。

1)クリックした駒が今所在するマスの座標を取得します。

//駒の位置
row = $(game).closest('tr').index()+1;
col = $(game).parent();
col = col.index()+1;

(2)取得したマスの座標を元に移動先の座標を算出します。

//上
let up_check_one=()=>{
    let gomaNow = $(`tr:nth-child(${row-1})>td:nth-child(${col})`);
    if(spaceCheck(user,gomaNow)=="1"){
        $(gomaNow).addClass("option");
    }else if(spaceCheck(user,gomaNow)=="2"){
        $(gomaNow).addClass("option");
    }
}

(3)それぞれの駒に、移動できる方向の関数を与えます。

//歩兵 先手・裏面
if(gomaName == "Nfuhe"){
    up_check_one();
    down_check_one();
    left_check_one();
    right_check_one();
    upright_check_one();
    upleft_check_one();
}//if

//歩兵 先手・表面
if(gomaName == "fuhe"){
    up_check_one();
}//if

成るかどうか?プログラムで判断!

将棋では、駒を相手の陣に移動させると、成り駒へと変化させることができます。
ただし、成るかどうかは対局者の判断によります。

まず、親の「tr」タグに相手の陣を示すクラス名が付いているかどうかを「hasClass」で確認します。もしクラス名が付いていれば、「naru_flag」にtrueを与えます。

if(user=="userBGoma"){
    if(_click_td.parents("tr").hasClass("userAArea")){
        naru_flag=true;
    }
}else{
    if(_click_td.parents("tr").hasClass("userBArea")){
        naru_flag=true;
    } 
}

もし成ることが可能であれば、ポップアップウインドウで「なりますか?」と対局者に聞きます
対局者が「ok」を押した場合、「switch」文を使って、各駒を成り駒に入れ替える処理を行います。

if(naru_flag){
    let result = confirm('なりますか');
    if(result){
        switch(gomaName){
            case "hisya":
                $(goma).attr('alt','Nhisya');
                $(goma).attr('src','img/hisyaB.svg');
                break;
            case "hisyaA":
                $(goma).attr('alt','NhisyaA');
                $(goma).attr('src','img/hisyaB.svg');
                break;
            ...
        }
    }
}

相手の駒はどう取る?

まず、指定する移動先のマスに駒が入っているかどうかを判断します。
もし駒が入っていれば、flagに「2」を与えます

if(_click_td.children().hasClass("userBGoma")){
    flag=2;
}

flagは2の場合、相手の駒を取得するプログラムを実行します。

//持ち駒の入れ箱
if(flag==2){
	let use = $(".useArea li");
	for(let i=0;i<use.length;i++){
	    if($(use[i]).hasClass($(event.target).children().attr('alt'))){
	        //取得した駒を自分の入れ箱に入れます
	        $(use[i]).append($(event.target).children());
	        //動かしている駒を移動先のマスに入れます
	        _click_td.append(goma);
	    }
	}
}

最後に、もし移動先のマスにある駒が玉将であれば、勝負の処理に入ります。

if(attr('alt')=='owuA'){
	//結果を表示します
}

まとめ

以上、私が考えたJavaScriptで再現する将棋のアルゴリズムでした。

日常生活で生じる悩みを解決することと同じく、機能をどのように再現していくかは、
多数の方法があります。
自分なりの方法を掘り下げていくと、プログラミングが楽しくなります。
みなさんも是非プログラミングで将棋を作ってみてください。

 

お電話でのお問い合わせはこちら:06-6292-8577。受付時間は平日9:30~18:30 インターネットからは24時間受付中!お問い合わせフォームはこちら
RECRUIT急募!採用エントリー