将棋の局面をPHPで再現してみた

記事
IT・テクノロジー
お久しぶりです。sqrt27です。
約半年前に投稿したサービスに関してですが、ココナラのルール違反で下書きに戻されましたが、長考の末この記事を書きだした始めた日に自分で削除しました。よって現在出品コンテンツはひとつもありません。

本題ですが、将棋という日本の伝統的なボードゲームをご存知でしょうか。ルールを知らない方でも知っている有名な棋士に羽生善治九段や藤井聡太竜王などがあげられるものです。(肩書は当ブログを書きだした当時)

将棋の「指し手」をURLパラメータに入れて各指し手ごとに局面を再現するプログラムをPHPにしました。
棋譜の著作権の関係でプロの棋譜は安易に載せられないのですが、今までにプロアマ問わず何万局と指されてる定跡手くらいなら著作権も何もないと思うので、指し手の一例として相掛かりの定跡の一種である1▲2六歩~11▲2六飛までのパラメータを載せておきます。

?kifu=position%20startpos%20moves%202g2f%208c8d%202f2e%208d8e%206i7h%204a3b%202e2d%202c2d%202h2d%20P%2a2c%202d2f%20

そして以下にコードの一部を載せておきます。なお諸事情により指し手の解説部分や手を進める動作のリンク部分等は省略させて頂きます。

<html>
<head><meta charset="utf-8">
<title>将棋研究</title>
<link rel="stylesheet" href="../indexstyle.css" type="text/css">
<link rel="shortcut icon" href="./icon.ico">
<style type="text/css">
body {
    margin-left: 12px;
    margin-right: 12px;
}
table {
 margin: auto;
 border-collapse: collapse;
}
table.sashiteselect td {
    width:108px;
    height:24px;
    border: solid 3px #000000;
    text-align: center;
    font-size:16px;
}
table.shogiban td {
    width:20px;
    height:20px;
    border: solid 3px #000000;
    text-align: center;
    font-size:16px;
}
td.sashite {
    background-color:#ffff00;
}
td.nari {
    color:#ff0000;
}
td.w {
    transform: rotate( 180deg );
}
a {
    text-decoration: none;
}
</style>
</head>
<body>
<div id="header">
<h1>将棋研究</h1>
<div id="hbline">
|&nbsp;<a href="../">TOP</a>&nbsp;|&nbsp;<a href="./index.php">開始局面へ戻る</a>&nbsp;|&nbsp;<a href="javascript:history.back();">一つ前へ戻る</a>&nbsp;|
</div>
</div>
<div id="contents" style="width:90%; margin:auto;">
<table class="shogiban">
<?php
/*
 将棋の平手における局面を再現するプログラム
 作:sqrt27
 棋譜の形式:SFEN
 サーバの処理方法:GETによるURLパラメータ形式
 指し手エラー:非対応
 後手番目線:非対応
 その他詳細はプログラム内コメント参照
 ※指し手エラー...二歩や王手放置などの反則手が現れた場合の処理のこと
*/
//URLパラメータにsfen形式の棋譜が入力されていれば
if(isset($_GET['kifu'])) {
    //棋譜データを$kifuに代入
    $kifu = $_GET['kifu'];
    echo "<script type=\"text/javascript\">console.log(\"".$kifu."\");</script>";
}else {
    //そうでなければ開始局面を$kifuに代入
    $kifu = "position startpos moves ";
    echo "<script type=\"text/javascript\">console.log(\"".$kifu."\");</script>";
}
//ここから平手初期配置
$mochigoma['b']==" ";
$mochigoma['w']==" ";
$ban['1a']=w_n_l();
$ban['1b']=b_nul();
$ban['1c']=w_n_p();
$ban['1d']=b_nul();
$ban['1e']=b_nul();
$ban['1f']=b_nul();
$ban['1g']=b_n_p();
$ban['1h']=b_nul();
$ban['1i']=b_n_l();
$ban['2a']=w_n_n();
$ban['2b']=w_n_b();
$ban['2c']=w_n_p();
$ban['2d']=b_nul();
$ban['2e']=b_nul();
$ban['2f']=b_nul();
$ban['2g']=b_n_p();
$ban['2h']=b_n_r();
$ban['2i']=b_n_n();
$ban['3a']=w_n_s();
$ban['3b']=b_nul();
$ban['3c']=w_n_p();
$ban['3d']=b_nul();
$ban['3e']=b_nul();
$ban['3f']=b_nul();
$ban['3g']=b_n_p();
$ban['3h']=b_nul();
$ban['3i']=b_n_s();
$ban['4a']=w_n_g();
$ban['4b']=b_nul();
$ban['4c']=w_n_p();
$ban['4d']=b_nul();
$ban['4e']=b_nul();
$ban['4f']=b_nul();
$ban['4g']=b_n_p();
$ban['4h']=b_nul();
$ban['4i']=b_n_g();
$ban['5a']=w_n_k();
$ban['5b']=b_nul();
$ban['5c']=w_n_p();
$ban['5d']=b_nul();
$ban['5e']=b_nul();
$ban['5f']=b_nul();
$ban['5g']=b_n_p();
$ban['5h']=b_nul();
$ban['5i']=b_n_k();
$ban['6a']=w_n_g();
$ban['6b']=b_nul();
$ban['6c']=w_n_p();
$ban['6d']=b_nul();
$ban['6e']=b_nul();
$ban['6f']=b_nul();
$ban['6g']=b_n_p();
$ban['6h']=b_nul();
$ban['6i']=B_n_g();
$ban['7a']=w_n_s();
$ban['7b']=b_nul();
$ban['7c']=w_n_p();
$ban['7d']=b_nul();
$ban['7e']=b_nul();
$ban['7f']=b_nul();
$ban['7g']=b_n_p();
$ban['7h']=b_nul();
$ban['7i']=b_n_s();
$ban['8a']=w_n_n();
$ban['8b']=w_n_r();
$ban['8c']=w_n_p();
$ban['8d']=b_nul();
$ban['8e']=b_nul();
$ban['8f']=b_nul();
$ban['8g']=b_n_p();
$ban['8h']=b_n_b();
$ban['8i']=b_n_n();
$ban['9a']=w_n_l();
$ban['9b']=b_nul();
$ban['9c']=w_n_p();
$ban['9d']=b_nul();
$ban['9e']=b_nul();
$ban['9f']=b_nul();
$ban['9g']=b_n_p();
$ban['9h']=b_nul();
$ban['9i']=b_n_l();
//ここまで平手初期配置
$i=24; //URLパラメータの何文字目かを取得(0手なら最後の空白入れて24文字)
$tekazu=0; //開始局面は0手目
while($i < strlen($kifu)) {
    //最後空白を入れないと解説なし
    $moto=substr($kifu,$i,2); //移動元座標または持ち駒の種類
    $saki=substr($kifu,$i+2,2); //移動先座標
    //以下駒を取る処理
    if($ban[$saki]!="<td> </td>") {
        //駒を取ったのが先手のとき
        if($tekazu%2==0) {
            $kariv=mb_substr($ban[$saki],-6,1);
            //成り駒なら元に戻して
            if($kariv=="と") {
                $kariv="歩";
            }else if($kariv=="杏") {
                $kariv="香";
            }else if($kariv=="圭") {
                $kariv="桂";
            }else if($kariv=="全") {
                $kariv="銀";
            }else if($kariv=="馬") {
                $kariv="角";
            }else if($kariv=="龍") {
                $kariv="飛";
            }
            //持ち駒に追加する
            $mochigoma['b']=$mochigoma['b'].$kariv;
        //駒を取ったのが後手のとき
        }else {
            $kariv=mb_substr($ban[$saki],-6,1);
            //成り駒なら元に戻して
            if($kariv=="と") {
                $kariv="歩";
            }else if($kariv=="杏") {
                $kariv="香";
            }else if($kariv=="圭") {
                $kariv="桂";
            }else if($kariv=="全") {
                $kariv="銀";
            }else if($kariv=="馬") {
                $kariv="角";
            }else if($kariv=="龍") {
                $kariv="飛";
            }
            //持ち駒に追加する
            $mochigoma['w']=$mochigoma['w'].$kariv;
        }
    }
    //以下駒打
    if(substr($kifu,$i+1,1)=="*") {
        //駒の種類毎に処理
        if(substr($kifu,$i,1)=="P") {
            if($tekazu%2==0) {
                $ban[$moto]=b_n_p();
                //歩を打ったら持ち駒の歩をひとつ取る(後手も同様)
                $mochigoma['b']=preg_replace("/歩/", "", $mochigoma['b'],1);
            }else {
                $ban[$moto]=w_n_p();
                $mochigoma['w']=preg_replace("/歩/", "", $mochigoma['w'],1);
            }
        }else if(substr($kifu,$i,1)=="L") {
            if($tekazu%2==0) {
                $ban[$moto]=b_n_l();
                //香車を打ったら持ち駒の香車をひとつ取る(後手も同様)
                $mochigoma['b']=preg_replace("/香/", "", $mochigoma['b'],1);
            }else {
                $ban[$moto]=w_n_l();
                $mochigoma['w']=preg_replace("/香/", "", $mochigoma['w'],1);
            }
        }else if(substr($kifu,$i,1)=="N") {
            if($tekazu%2==0) {
                $ban[$moto]=b_n_n();
                //桂馬を打ったら持ち駒の桂馬をひとつ取る(後手も同様)
                $mochigoma['b']=preg_replace("/桂/", "", $mochigoma['b'],1);
             }else {
                $ban[$moto]=w_n_n();
                $mochigoma['w']=preg_replace("/桂/", "", $mochigoma['w'],1);
            }
        }else if(substr($kifu,$i,1)=="S") {
            if($tekazu%2==0) {
                $ban[$moto]=b_n_s();
                //銀を打ったら持ち駒の銀をひとつ取る(後手も同様)
                $mochigoma['b']=preg_replace("/銀/", "", $mochigoma['b'],1);
             }else {
                $ban[$moto]=w_n_s();
                $mochigoma['w']=preg_replace("/銀/", "", $mochigoma['w'],1);
            }
        }else if(substr($kifu,$i,1)=="B") {
            if($tekazu%2==0) {
                $ban[$moto]=b_n_b();
                //角を打ったら持ち駒の角をひとつ取る(後手も同様)
                $mochigoma['b']=preg_replace("/角/", "", $mochigoma['b'],1);
             }else {
                $ban[$moto]=w_n_b();
                $mochigoma['w']=preg_replace("/角/", "", $mochigoma['w'],1);
            }
        }else if(substr($kifu,$i,1)=="R") {
            if($tekazu%2==0) {
                $ban[$moto]=b_n_r();
                //飛車を打ったら持ち駒の飛車をひとつ取る(後手も同様)
                $mochigoma['b']=preg_replace("/飛/", "", $mochigoma['b'],1);
             }else {
                $ban[$moto]=w_n_r();
                $mochigoma['w']=preg_replace("/飛/", "", $mochigoma['w'],1);
            }
        }else if(substr($kifu,$i,1)=="G") {
            if($tekazu%2==0) {
                $ban[$moto]=b_n_g();
                //金を打ったら持ち駒の金をひとつ取る(後手も同様)
                $mochigoma['b']=preg_replace("/金/", "", $mochigoma['b'],1);
             }else {
                $ban[$moto]=w_n_g();
                $mochigoma['w']=preg_replace("/金/", "", $mochigoma['w'],1);
            }
        }//玉を取る操作はルール上実現し得ないので省略
    }
    //駒の移動
    $ban[$saki]=$ban[$moto];
    $ban[$moto]=b_nul();
    //成る操作
    if(substr($kifu,$i+4,1)=="+") {
        if($ban[$saki]=="<td>歩</td>") {
            $ban[$saki]=b_npp();
        }else if($ban[$saki]=="<td>香</td>") {
            $ban[$saki]=b_npl();
        }else if($ban[$saki]=="<td>桂</td>") {
            $ban[$saki]=b_npn();
        }else if($ban[$saki]=="<td>銀</td>") {
            $ban[$saki]=b_nps();
        }else if($ban[$saki]=="<td>角</td>") {
            $ban[$saki]=b_npb();
        }else if($ban[$saki]=="<td>飛</td>") {
            $ban[$saki]=b_npr();
        }else if($ban[$saki]=="<td class=\"w\">歩</td>") {
            $ban[$saki]=w_npp();
        }else if($ban[$saki]=="<td class=\"w\">香</td>") {
            $ban[$saki]=w_npl();
        }else if($ban[$saki]=="<td class=\"w\">桂</td>") {
            $ban[$saki]=w_npn();
        }else if($ban[$saki]=="<td class=\"w\">銀</td>") {
            $ban[$saki]=w_nps();
        }else if($ban[$saki]=="<td class=\"w\">角</td>") {
            $ban[$saki]=w_npb();
        }else if($ban[$saki]=="<td class=\"w\">飛</td>") {
            $ban[$saki]=w_npr();
        }
        $i=$i+1; //文字数カウントを1足す
    }
    $i=$i+5; //指し手は空白を含めて5文字なので文字数カウントを1足す
    $tekazu=$tekazu+1; //手数を1足す
    //という操作を最終手まで繰り返す
}
//tableを表示
echo "<table class=\"shogiban\">";
//局面がどこまで動いたか
echo "<caption>";
if($tekazu==0) {
    echo "開始局面";
}else if($tekazu%2==1) {
    //先手
    echo $tekazu."▲";
}else {
    //後手
    echo $tekazu."△";
}
/*最終手で成る操作をした場合は
  今後の処理に影響を来さないように
  文字数カウントに1を引く*/
if(substr($kifu,$i-2,1)=="+") {
    $i=$i-1;
}
//直前の指し手と座標が同じなら「同 」それ以外なら座標を表示
if(substr($kifu,$i-3,2)==substr($kifu,$i-8,2)||substr($kifu,$i-3,2)==substr($kifu,$i-9,2)) {
    echo "同 ";
}else {
    if(substr($kifu,$i-3,1)=="1") {
        echo "1";
    }else if(substr($kifu,$i-3,1)=="2") {
        echo "2";
    }else if(substr($kifu,$i-3,1)=="3") {
        echo "3";
    }else if(substr($kifu,$i-3,1)=="4") {
        echo "4";
    }else if(substr($kifu,$i-3,1)=="5") {
        echo "5";
    }else if(substr($kifu,$i-3,1)=="6") {
        echo "6";
    }else if(substr($kifu,$i-3,1)=="7") {
        echo "7";
    }else if(substr($kifu,$i-3,1)=="8") {
        echo "8";
    }else if(substr($kifu,$i-3,1)=="9") {
        echo "9";
    }
    if(substr($kifu,$i-2,1)=="a") {
        echo "一";
    }else if(substr($kifu,$i-2,1)=="b") {
        echo "二";
    }else if(substr($kifu,$i-2,1)=="c") {
        echo "三";
    }else if(substr($kifu,$i-2,1)=="d") {
        echo "四";
    }else if(substr($kifu,$i-2,1)=="e") {
        echo "五";
    }else if(substr($kifu,$i-2,1)=="f") {
        echo "六";
    }else if(substr($kifu,$i-2,1)=="g") {
        echo "七";
    }else if(substr($kifu,$i-2,1)=="h") {
        echo "八";
    }else if(substr($kifu,$i-2,1)=="i") {
        echo "九";
    }
}
//駒名を表示
if($ban[$saki]=="<td>歩</td>"||$ban[$saki]=="<td class=\"w\">歩</td>") {
    echo "歩";
}else if($ban[$saki]=="<td>香</td>"||$ban[$saki]=="<td class=\"w\">香</td>") {
    echo "香";
}else if($ban[$saki]=="<td>桂</td>"||$ban[$saki]=="<td class=\"w\">桂</td>") {
    echo "桂";
}else if($ban[$saki]=="<td>銀</td>"||$ban[$saki]=="<td class=\"w\">銀</td>") {
    echo "銀";
}else if($ban[$saki]=="<td>角</td>"||$ban[$saki]=="<td class=\"w\">角</td>") {
    echo "角";
}else if($ban[$saki]=="<td>飛</td>"||$ban[$saki]=="<td class=\"w\">飛</td>") {
    echo "飛";
}else if($ban[$saki]=="<td>金</td>"||$ban[$saki]=="<td class=\"w\">金</td>") {
    echo "金";
}else if($ban[$saki]=="<td>玉</td>"||$ban[$saki]=="<td class=\"w\">王</td>") {
    echo "玉";
}else if($ban[$saki]=="<td class=\"nari\">と</td>"||$ban[$saki]=="<td class=\"w nari\">と</td>") {
    //成り駒の場合は成ったばかりかそうでないかを判定する
    if(substr($kifu,$i-1,1)=="+") {
        echo "歩成";
    }else {
        echo "と";
    }
}else if($ban[$saki]=="<td class=\"nari\">杏</td>"||$ban[$saki]=="<td class=\"w nari\">杏</td>") {
    if(substr($kifu,$i-1,1)=="+") {
        echo "香成";
    }else {
        echo "成香";
    }
}else if($ban[$saki]=="<td class=\"nari\">圭</td>"||$ban[$saki]=="<td class=\"w nari\">圭</td>") {
    if(substr($kifu,$i-1,1)=="+") {
        echo "桂成";
    }else {
        echo "成桂";
    }
}else if($ban[$saki]=="<td class=\"nari\">全</td>"||$ban[$saki]=="<td class=\"w nari\">全</td>") {
    if(substr($kifu,$i-1,1)=="+") {
        echo "銀成";
    }else {
        echo "成銀";
    }
}else if($ban[$saki]=="<td class=\"nari\">馬</td>"||$ban[$saki]=="<td class=\"w nari\">馬</td>") {
    if(substr($kifu,$i-1,1)=="+") {
        echo "角成";
    }else {
        echo "馬";
    }
}else if($ban[$saki]=="<td class=\"nari\">龍</td>"||$ban[$saki]=="<td class=\"w nari\">龍</td>") {
    if(substr($kifu,$i-1,1)=="+") {
        echo "飛成";
    }else {
        echo "龍";
    }
}
//kif形式の表記に基づいて表記するので「打」や移動元座標を表示
if($tekazu!=0) {
if(substr($kifu,$i-4,1)=="*") {
    echo "打";
}else {
    echo "(";
    echo substr($kifu,$i-5,1);
    if(substr($kifu,$i-4,1)=="a") {
        echo "1";
    }else if(substr($kifu,$i-4,1)=="b") {
        echo "2";
    }else if(substr($kifu,$i-4,1)=="c") {
        echo "3";
    }else if(substr($kifu,$i-4,1)=="d") {
        echo "4";
    }else if(substr($kifu,$i-4,1)=="e") {
        echo "5";
    }else if(substr($kifu,$i-4,1)=="f") {
        echo "6";
    }else if(substr($kifu,$i-4,1)=="g") {
        echo "7";
    }else if(substr($kifu,$i-4,1)=="h") {
        echo "8";
    }else if(substr($kifu,$i-4,1)=="i") {
        echo "9";
    }
    echo ")";
}
echo "迄</caption>";
}
//指し手をハイライトする処理
if(substr($ban[$saki],0,9)=="<td class") {
    if(substr($ban[$saki],11,6)=="w nari") {
        $ban[$saki] = preg_replace("/w nari/", "w nari sashite", $ban[$saki],1);
    }else if(substr($ban[$saki],11,2)=="w\"") {
        $ban[$saki] = preg_replace("/w\">/", "w sashite\">", $ban[$saki],1);
    }else if(substr($ban[$saki],11,4)=="nari") {
        $ban[$saki] = preg_replace("/nari/", "nari sashite", $ban[$saki],1);
    }
}else {
    $ban[$saki] = preg_replace("/<td>/", "<td class=\"sashite\">", $ban[$saki],1);
}
//盤面再現処理
echo "<tr><td colspan=10 class='w'>".$mochigoma['w']."</td></tr>";
echo "<tr><td>9</td><td>8</td><td>7</td><td>6</td><td>5</td><td>4</td><td>3</td><td>2</td><td>1</td><td>/</td></tr>";
echo "<tr>".$ban['9a'].$ban['8a'].$ban['7a'].$ban['6a'].$ban['5a'].$ban['4a'].$ban['3a'].$ban['2a'].$ban['1a']."<td>一</td></tr>";
echo "<tr>".$ban['9b'].$ban['8b'].$ban['7b'].$ban['6b'].$ban['5b'].$ban['4b'].$ban['3b'].$ban['2b'].$ban['1b']."<td>二</td></tr>";
echo "<tr>".$ban['9c'].$ban['8c'].$ban['7c'].$ban['6c'].$ban['5c'].$ban['4c'].$ban['3c'].$ban['2c'].$ban['1c']."<td>三</td></tr>";
echo "<tr>".$ban['9d'].$ban['8d'].$ban['7d'].$ban['6d'].$ban['5d'].$ban['4d'].$ban['3d'].$ban['2d'].$ban['1d']."<td>四</td></tr>";
echo "<tr>".$ban['9e'].$ban['8e'].$ban['7e'].$ban['6e'].$ban['5e'].$ban['4e'].$ban['3e'].$ban['2e'].$ban['1e']."<td>五</td></tr>";
echo "<tr>".$ban['9f'].$ban['8f'].$ban['7f'].$ban['6f'].$ban['5f'].$ban['4f'].$ban['3f'].$ban['2f'].$ban['1f']."<td>六</td></tr>";
echo "<tr>".$ban['9g'].$ban['8g'].$ban['7g'].$ban['6g'].$ban['5g'].$ban['4g'].$ban['3g'].$ban['2g'].$ban['1g']."<td>七</td></tr>";
echo "<tr>".$ban['9h'].$ban['8h'].$ban['7h'].$ban['6h'].$ban['5h'].$ban['4h'].$ban['3h'].$ban['2h'].$ban['1h']."<td>八</td></tr>";
echo "<tr>".$ban['9i'].$ban['8i'].$ban['7i'].$ban['6i'].$ban['5i'].$ban['4i'].$ban['3i'].$ban['2i'].$ban['1i']."<td>九</td></tr>";
echo "<tr><td colspan=10>".$mochigoma['b']."</td></tr>";
echo "</table>";
//ここから呼び出し用関数
//煩雑化防止策
function b_nul() {
    return "<td> </td>";
}
function b_n_p() {
    return "<td>歩</td>";
}
function b_n_l() {
    return "<td>香</td>";
}
function b_n_n() {
    return "<td>桂</td>";
}
function b_n_s() {
    return "<td>銀</td>";
}
function b_n_b() {
    return "<td>角</td>";
}
function b_n_r() {
    return "<td>飛</td>";
}
function b_n_g() {
    return "<td>金</td>";
}
function b_n_k() {
    return "<td>玉</td>";
}
function b_npp() {
    return "<td class=\"nari\">と</td>";
}
function b_npl() {
    return "<td class=\"nari\">杏</td>";
}
function b_npn() {
    return "<td class=\"nari\">圭</td>";
}
function b_nps() {
    return "<td class=\"nari\">全</td>";
}
function b_npb() {
    return "<td class=\"nari\">馬</td>";
}
function b_npr() {
    return "<td class=\"nari\">龍</td>";
}
function w_n_p() {
    return "<td class=\"w\">歩</td>";
}
function w_n_l() {
    return "<td class=\"w\">香</td>";
}
function w_n_n() {
    return "<td class=\"w\">桂</td>";
}
function w_n_s() {
    return "<td class=\"w\">銀</td>";
}
function w_n_b() {
    return "<td class=\"w\">角</td>";
}
function w_n_r() {
    return "<td class=\"w\">飛</td>";
}
function w_n_g() {
    return "<td class=\"w\">金</td>";
}
function w_n_k() {
    return "<td class=\"w\">王</td>";
}
function w_npp() {
    return "<td class=\"w nari\">と</td>";
}
function w_npl() {
    return "<td class=\"w nari\">杏</td>";
}
function w_npn() {
    return "<td class=\"w nari\">圭</td>";
}
function w_nps() {
    return "<td class=\"w nari\">全</td>";
}
function w_npb() {
    return "<td class=\"w nari\">馬</td>";
}
function w_npr() {
    return "<td class=\"w nari\">龍</td>";
}
//ここまで呼び出し用関数
?>
</table>
<hr>
<?php
//この欄は指し手の解説欄なので諸事情により省略
?>
<hr>
</div>
<div id="footer">
&copy;&nbsp;2017-2022&nbsp;sqrt27
</div>
</body>
</html>

途中見苦しい部分があると思いますが、これ以上簡略化されたコードの場合、後手の向きがおかしくなることや成り駒の視認性が劣るという事象が発生し得るのでご了承ください。
ということでこのコードに先程のパラメータを渡すと以下の図になります。なお諸事情により指し手の解説部分はコード省略&画像もモザイクにしてあります。
今後の課題として、伝統形式表記に対応することや、後手番目線の表示、平手以外の開始局面に対応などが挙げられますが、今のところこれで大丈夫とみて当方のサイトに実際の公開してありますので、興味があれば探してみて下さい。

shogipage.png


いかがでしょうか。ではまた。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す