オセロを将棋にすり替える


アニメ『3月のライオン』
若き天才ってカッコいいですねえ。17歳ですか。心を閉ざす主人公が、3姉妹や周囲の人たちから暖かく接してもらい次第に心が開いていく様子に癒やされます。三姉妹の家はすごく癒やされます。特に猫。猫たちはいっつもお腹すいてるんですね。

GUIプログラムからCUIプログラムを使う(標準入出力)」で作ったオセロのGUIフロントエンドを、将棋でも使えるように変更してみます。
shogi.tclではなく、gameboard.tclとしたのは、マス目がある他のゲームにも対応するためです。

takk@deb83:~/scrap$ cp reversi.tcl gameboard.tcl

新しいGUIフロントエンドは、最初に初期化コマンドを受け取ることで、ボードのマス数と色を決めることにします。

初期化コマンドの書式は、
“INIT,桁数,行数,色”
で、
オセロの場合は、
“INIT,8,8,green”
将棋の場合は、
“INIT,9,9,yellow”
としました。

初期化コマンドの解析処理がこちらです。

    28	gets $pipe str
    29	set arr [split $str ","]
    30	set cmd [lindex $arr 0]
    31	if { $cmd == "INIT" } {
    32		set xmax [lindex $arr 1]
    33		set ymax [lindex $arr 2]
    34		set color [lindex $arr 3]
    35	}

マスのボタンを生成するfor文のネストが固定で8となっていた箇所は、初期化コマンドで受けた桁数行数によって
回すように変更ということになります。

    38	for {set i 1} {$i <= $xmax} {incr i} {
    39		for {set j 1} {$j <= $ymax} {incr j} {

また、コマンドで、オセロの石だけでなく、将棋の駒も処理できるように、
各コマンドを増やしました。

    13			if {$bw == "B"} { .b$xy configure -text "●"  -fg black }
    14			if {$bw == "W"} { .b$xy configure -text "●"  -fg white }
    15			if {$bw == "f"} { .b$xy configure -text "歩"  -fg black }
    16			if {$bw == "o"} { .b$xy configure -text "王"  -fg black }
    17			if {$bw == "a"} { .b$xy configure -text "金"  -fg black }
    18			if {$bw == "g"} { .b$xy configure -text "銀"  -fg black }
    19			if {$bw == "u"} { .b$xy configure -text "桂"  -fg black }
    20			if {$bw == "s"} { .b$xy configure -text "香"  -fg black }
    21			if {$bw == "t"} { .b$xy configure -text "飛"  -fg black }
    22			if {$bw == "x"} { .b$xy configure -text "角"  -fg black }

最終的にこうなりました。

takk@deb83:~/scrap$ cat -n gameboard.tcl
     1	proc update_board { pipe } {
     2		while {[gets $pipe str] >= 0} {
     3			set first_char [string range $str 0 0]
     4	
     5			if { $first_char == "Y" } {	;# Y in YOU
     6				break
     7			}	
     8	
     9			set arr [split $str ","]
    10			set xy [lindex $arr 0]
    11			set bw [lindex $arr 1]
    12	
    13			if {$bw == "B"} { .b$xy configure -text "●"  -fg black }
    14			if {$bw == "W"} { .b$xy configure -text "●"  -fg white }
    15			if {$bw == "f"} { .b$xy configure -text "歩"  -fg black }
    16			if {$bw == "o"} { .b$xy configure -text "王"  -fg black }
    17			if {$bw == "a"} { .b$xy configure -text "金"  -fg black }
    18			if {$bw == "g"} { .b$xy configure -text "銀"  -fg black }
    19			if {$bw == "u"} { .b$xy configure -text "桂"  -fg black }
    20			if {$bw == "s"} { .b$xy configure -text "香"  -fg black }
    21			if {$bw == "t"} { .b$xy configure -text "飛"  -fg black }
    22			if {$bw == "x"} { .b$xy configure -text "角"  -fg black }
    23		}
    24	}
    25	
    26	set pipe [open "| ./a.out" r+]
    27	
    28	gets $pipe str
    29	set arr [split $str ","]
    30	set cmd [lindex $arr 0]
    31	if { $cmd == "INIT" } {
    32		set xmax [lindex $arr 1]
    33		set ymax [lindex $arr 2]
    34		set color [lindex $arr 3]
    35	}
    36	
    37	set turnsw 0
    38	for {set i 1} {$i <= $xmax} {incr i} {
    39		for {set j 1} {$j <= $ymax} {incr j} {
    40			button .b$i$j -font {FreeMono 40 bold} -bg $color -activebackground yellow -activeforeground red
    41			grid .b$i$j -in . -row $j -column $i -sticky nsew
    42			grid columnconfigure . all -weight 1 -minsize 60
    43			grid rowconfigure . all -weight 1 -minsize 60
    44	
    45			bind .b$i$j <Button> {
    46				set x [string range %W 2 2]
    47				set y [string range %W 3 3]
    48				puts $pipe "$x,$y\n";flush $pipe
    49	
    50				update_board $pipe
    51	
    52				set turnsw [expr 1 - $turnsw]
    53			}
    54		}
    55	}
    56	
    57	update_board $pipe

次はオセロ用エンジンをコピーして将棋用エンジンを作ります。将棋以外にも使うので単純にgame.cとしました。

takk@deb83:~/scrap$ cp reversi.c game.c

今回は将棋ロジックは含めず、並べて表示するところまでのソースとします。
まず配列。将棋の9×9に対応するため拡張します。関連するfor文も本定数に置き換えます。

     4	#define XMAX 9
     5	#define YMAX 9
     6	char bd[YMAX+2][XMAX+2];

将棋の駒を布陣します。GUIフロントエンドはオセロと共通なので、コマンド名がかぶらないように、
オセロはBとWというように大文字を使い、将棋は小文字にしています。

    59		printf("INIT,9,9,yellow\n");
    60		for(i=1;i<=9;i++){
    61			bd[7][i]='f';
    62		}
    63		bd[8][8]='t';
    64		bd[8][2]='x';
    65		bd[9][1]='s';
    66		bd[9][2]='u';
    67		bd[9][3]='g';
    68		bd[9][4]='a';
    69		bd[9][5]='o';
    70		bd[9][6]='a';
    71		bd[9][7]='g';
    72		bd[9][8]='u';
    73		bd[9][9]='s';

角がxに飛車はt、金はaにしました。

全ソースはこのとおりです。

     1	#include <stdio.h>
     2	#include <string.h>
     3	
     4	#define XMAX 9
     5	#define YMAX 9
     6	char bd[YMAX+2][XMAX+2];
     7	
     8	void disp()
     9	{
    10		int x,y;
    11		for(y = 1; y <= YMAX; y++)
    12			for(x = 1; x <= XMAX; x++)
    13				if(bd[y][x] != 0 )
    14					printf("%d%d,%c\n",x,y,bd[y][x]);
    15	}
    16	
    17	int check(int x, int y, int xx, int yy, char bw, int first);
    18	
    19	int check(int x, int y, int xx, int yy, char bw, int first)
    20	{
    21		int my_x = x + xx;
    22		int my_y = y + yy;
    23	
    24		if(bd[my_y][my_x] == bw)
    25			if(first == 1)
    26				return 0;
    27			else
    28				return 1;
    29	
    30		switch(bd[my_y][my_x]){
    31		case	0:
    32			return 0;	
    33		}
    34	
    35		if(!check(my_x,my_y, xx,yy, bw, 0) )
    36			return 0;
    37	
    38		bd[my_y][my_x] = bw;
    39		return 1;
    40	}
    41	
    42	int main(int argc, char* argv[])
    43	{
    44		int i;
    45		char disc;
    46		int xx[]={-1,-1, 0, 1, 1, 1, 0, -1};
    47		int yy[]={ 0,-1,-1,-1, 0, 1, 1,  1};
    48		int x,y,turn=0,t,turnend_flag;
    49		char c;
    50	
    51		memset(bd,0,sizeof(bd));
    52	
    53	#ifdef REVERSI
    54		printf("INIT,8,8,green\n");
    55		bd[4][4]='W'; bd[5][4]='B';
    56		bd[4][5]='B'; bd[5][5]='W';
    57	
    58	#else
    59		printf("INIT,9,9,yellow\n");
    60		for(i=1;i<=9;i++){
    61			bd[i][7]='f';
    62		}
    63		bd[8][8]='t';
    64		bd[8][2]='x';
    65		bd[9][1]='s';
    66		bd[9][2]='u';
    67		bd[9][3]='g';
    68		bd[9][4]='a';
    69		bd[9][5]='o';
    70		bd[9][6]='a';
    71		bd[9][7]='g';
    72		bd[9][8]='u';
    73		bd[9][9]='s';
    74	#endif
    75		fflush(stdout);
    76	
    77		for(;;){
    78			disp();
    79			disc = turn==0?'B':'W';
    80			printf("YOU=%c\n",disc);
    81			fflush(stdout);
    82			x=0;y=0;
    83			scanf("%d,%d",&x,&y);
    84			if(x>XMAX || y>YMAX || x<1 || y<1 )continue;
    85			turnend_flag = 0;
    86			if(bd[y][x] == 0)
    87				for(i=0;i<8;i++)
    88					if(check(x,y, xx[i],yy[i], disc, 1)){
    89						bd[y][x] = disc;
    90						turnend_flag = 1;
    91					}
    92			if(turnend_flag)
    93				turn = 1 - turn;
    94		}
    95	
    96		return 0;
    97	}

将棋盤を表示してみましょう。

takk@deb83:~$ git clone https://github.com/takkete/scrap.git
takk@deb83:~/scrap$ gcc game.c
takk@deb83:~/scrap$ wish gameboard.tcl

このように表示されます。エンジン次第で、いろんなゲームに変わりますね。
shogi-001

コメント

  1. […] ← オセロを将棋にすり替える […]

タイトルとURLをコピーしました