C言語
C言語
どうぶつしょうぎ(https://ja.wikipedia.org/wiki/どうぶつしょうぎ )のシミュレーション課題
①ランダム戦略
・ルール内で全てランダムに戦略を決定する
・互いに着手可能な着手からランダムに一つ着手する
この戦略に従いシミュレーションを行い考察する
②人工知能戦略
・数手先に有利になるような手順を考える。一般的には評価地を定めて、その評価地が高くなるように戦略を考える。
人工知能的な戦略を考える。そしてその戦略に従いシミュレーションを行い考察する。
・ランダム戦略と人工知能戦略で戦わせる
・人工知能戦略同士戦わせる
・人工知能戦略と自分で戦う
①と②のソースプログラム、実行形式、プログラムの使い方(入出力等)、簡単な説明、分析+解説の5つを提出する。
①を至急提出しないといけないためどのようにコードを組めばよいかなど教えていただけないでょうか。
http://pr.cei.uec.ac.jp/kobo2015/index. ... 4%A6%A1%AA
このURLに載っているコードを基に作っています。
①ランダム戦略
・ルール内で全てランダムに戦略を決定する
・互いに着手可能な着手からランダムに一つ着手する
この戦略に従いシミュレーションを行い考察する
②人工知能戦略
・数手先に有利になるような手順を考える。一般的には評価地を定めて、その評価地が高くなるように戦略を考える。
人工知能的な戦略を考える。そしてその戦略に従いシミュレーションを行い考察する。
・ランダム戦略と人工知能戦略で戦わせる
・人工知能戦略同士戦わせる
・人工知能戦略と自分で戦う
①と②のソースプログラム、実行形式、プログラムの使い方(入出力等)、簡単な説明、分析+解説の5つを提出する。
①を至急提出しないといけないためどのようにコードを組めばよいかなど教えていただけないでょうか。
http://pr.cei.uec.ac.jp/kobo2015/index. ... 4%A6%A1%AA
このURLに載っているコードを基に作っています。
Re: C言語
質問内容は「①を至急提出しないといけないためどのようにコードを組めばよいかなど教えていただけないでょうか。」ですね。
とりあえず、①のサンプルコード的な物を超適当に試作してみましたので、いきなりガチガチに理解せずともロジック的な物を読み解いて頂ければと思います。
因みに、私はリンク先の説明とやらを殆ど読まずに、「どうぶつしょうぎ」のルールだけ見て適当にそれっぽく作っただけです。(それをちゃんと読んで作ったら、私が代わりに作っただけになりそうな気がして宜しくないと思ったので。)
仕様も含め全て私が勝手に決めたものですので、このままデッドコピーして提出した場合、怒られる可能性があると思いますので悪しからず。
また、早く仕上げる為にコピペと置換を使いまくって、適当にパッと見た感じ動いていそうに見えた段階で載せたコードですので、何処かにバグを含んでいる可能性が高いと考えて下さい。
それと、windows仕様です。
あと、sleep()関数に関しては、コンパイラに依っては存在しないと思うので、必要なら自作して下さい。
飽くまでも、とりあえず、ロジック的な物を質問者様に理解して貰う為に、それっぽく動けば良いという意図で作った程度のコードだという事は十分に認識して下さい。(とてもではないが、模範的な解答とは私自身も思っていないし、このコードを載せた後に偉い方々から色々指摘されそうに思えるコードです。)
ひらがな=先手=PLAYER
カタカナ=後手=ENEMY
とりあえず、①のサンプルコード的な物を超適当に試作してみましたので、いきなりガチガチに理解せずともロジック的な物を読み解いて頂ければと思います。
因みに、私はリンク先の説明とやらを殆ど読まずに、「どうぶつしょうぎ」のルールだけ見て適当にそれっぽく作っただけです。(それをちゃんと読んで作ったら、私が代わりに作っただけになりそうな気がして宜しくないと思ったので。)
仕様も含め全て私が勝手に決めたものですので、このままデッドコピーして提出した場合、怒られる可能性があると思いますので悪しからず。
また、早く仕上げる為にコピペと置換を使いまくって、適当にパッと見た感じ動いていそうに見えた段階で載せたコードですので、何処かにバグを含んでいる可能性が高いと考えて下さい。
それと、windows仕様です。
あと、sleep()関数に関しては、コンパイラに依っては存在しないと思うので、必要なら自作して下さい。
飽くまでも、とりあえず、ロジック的な物を質問者様に理解して貰う為に、それっぽく動けば良いという意図で作った程度のコードだという事は十分に認識して下さい。(とてもではないが、模範的な解答とは私自身も思っていないし、このコードを載せた後に偉い方々から色々指摘されそうに思えるコードです。)
ひらがな=先手=PLAYER
カタカナ=後手=ENEMY
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ID_LION 1
#define ID_ELEPHANT 2
#define ID_GIRAFFE 3
#define ID_CHICK 4
#define ID_CHICKEN 5
char LION[3][3];
char ELEPHANT[3][3];
char GIRAFFE[3][3];
char CHICK[3][3];
char CHICKEN[3][3];
char TABLE[4][3];
char STOCKS_ENEMY[8];
char STOCKS_PLAYER[8];
void init(void){
char i,j;
for(i=0;i<3;i++) for(j=0;j<3;j++) LION[i][j]=1;
LION[1][1]=0;
for(i=0;i<3;i++) for(j=0;j<3;j++) ELEPHANT[i][j]=1;
for(i=0;i<3;i++) ELEPHANT[1][i]=0;
for(i=0;i<3;i++) ELEPHANT[i][1]=0;
for(i=0;i<3;i++) for(j=0;j<3;j++) GIRAFFE[i][j]=1;
for(i=0,j=0;i<3;i++,j++) GIRAFFE[i][j]=0;
for(i=2,j=0;i>=0;i--,j++) GIRAFFE[i][j]=0;
for(i=0;i<3;i++) for(j=0;j<3;j++) CHICK[i][j]=0;
CHICK[0][1]=1;
for(i=0;i<3;i++) for(j=0;j<3;j++) CHICKEN[i][j]=1;
CHICKEN[1][1]=0;
CHICKEN[2][0]=0;
CHICKEN[2][2]=0;
for(i=0;i<4;i++) for(j=0;j<3;j++) TABLE[i][j]=0;
TABLE[0][0]=ID_GIRAFFE*-1;
TABLE[0][1]=ID_LION*-1;
TABLE[0][2]=ID_ELEPHANT*-1;
TABLE[1][1]=ID_CHICK*-1;
TABLE[2][1]=ID_CHICK;
TABLE[3][0]=ID_ELEPHANT;
TABLE[3][1]=ID_LION;
TABLE[3][2]=ID_GIRAFFE;
for(i=0;i<8;i++) STOCKS_ENEMY[i]=0;
for(i=0;i<8;i++) STOCKS_PLAYER[i]=0;
}
char get_winner(void){
char i;
for(i=0;i<8;i++) if(STOCKS_PLAYER[i]==ID_LION || STOCKS_PLAYER[i]==ID_LION*-1) return 1; //PLAYER IS WINNER.
for(i=0;i<8;i++) if(STOCKS_ENEMY[i]==ID_LION || STOCKS_ENEMY[i]==ID_LION*-1) return -1; //ENEMY IS WINNER.
return 0;
}
char get_enemys_military_power(void){
char i,j;
char sum=0;
for(i=0;i<4;i++) for(j=0;j<3;j++) if(TABLE[i][j]<0) sum++;
for(i=0;i<8;i++) if(STOCKS_ENEMY[i]!=0) sum++;
return sum;
}
char get_enemys_stocks(void){
char i,j;
char sum=0;
for(i=0;i<8;i++) if(STOCKS_ENEMY[i]!=0) sum++;
return sum;
}
char get_players_military_power(void){
char i,j;
char sum=0;
for(i=0;i<4;i++) for(j=0;j<3;j++) if(TABLE[i][j]>0) sum++;
for(i=0;i<8;i++) if(STOCKS_PLAYER[i]!=0) sum++;
return sum;
}
char get_players_stocks(void){
char i,j;
char sum=0;
for(i=0;i<8;i++) if(STOCKS_PLAYER[i]!=0) sum++;
return sum;
}
void draw(void){
char i,j;
system("CLS");
printf("ENEMY'S STOCKS:");
for(i=0;i<8;i++){
switch(STOCKS_ENEMY[i]){
case ID_LION:
case -ID_LION:
printf("ラ");
break;
case ID_ELEPHANT:
case -ID_ELEPHANT:
printf("ゾ");
break;
case ID_GIRAFFE:
case -ID_GIRAFFE:
printf("キ");
break;
case ID_CHICK:
case -ID_CHICK:
case ID_CHICKEN:
case -ID_CHICKEN:
printf("ヒ");
break;
default:
break;
}
}
printf("\n\n");
for(i=0;i<4;i++){
for(j=0;j<3;j++){
switch(TABLE[i][j]){
case ID_LION:
printf("ら");
break;
case ID_ELEPHANT:
printf("ぞ");
break;
case ID_GIRAFFE:
printf("き");
break;
case ID_CHICK:
printf("ひ");
break;
case ID_CHICKEN:
printf("に");
break;
case -ID_LION:
printf("ラ");
break;
case -ID_ELEPHANT:
printf("ゾ");
break;
case -ID_GIRAFFE:
printf("キ");
break;
case -ID_CHICK:
printf("ヒ");
break;
case -ID_CHICKEN:
printf("ニ");
break;
default:
printf("□");
break;
}
}
printf("\n");
}
printf("\n");
printf("PLAYER'S STOCKS:");
for(i=0;i<8;i++){
switch(STOCKS_PLAYER[i]){
case ID_LION:
case -ID_LION:
printf("ら");
break;
case ID_ELEPHANT:
case -ID_ELEPHANT:
printf("ぞ");
break;
case ID_GIRAFFE:
case -ID_GIRAFFE:
printf("き");
break;
case ID_CHICK:
case -ID_CHICK:
case ID_CHICKEN:
case -ID_CHICKEN:
printf("ひ");
break;
default:
break;
}
}
printf("\n");
}
int main(void){
int i,j,k;
int get1,get2;
system("CLS");
init();
for(i=0;i<3;i++){
for(j=0;j<3;j++) printf("%d,",CHICKEN[i][j]);
printf("\n");
}
srand(time(NULL));
draw();
while(get_winner()==0){
//PLAYERのターン
restart1:
if(get_players_military_power()<=0) return 1; //エラー
//相手から奪った駒を使用する場合
if(rand()%get_players_military_power()<get_players_stocks()){
for(get1=rand()%8;STOCKS_PLAYER[get1]==0;get1=rand()%8);
for(get2=rand()%12;TABLE[get2/3][get2%3]!=0;get2=rand()%12);
TABLE[get2/3][get2%3]=STOCKS_PLAYER[get1];
if(TABLE[get2/3][get2%3]<0) TABLE[get2/3][get2%3]*=-1;
if(TABLE[get2/3][get2%3]==ID_CHICKEN) TABLE[get2/3][get2%3]=ID_CHICK;
STOCKS_PLAYER[get1]=0;
}
//ボード上の駒を動かす場合
else{
for(get1=rand()%12;TABLE[get1/3][get1%3]<=0;get1=rand()%12);
switch(TABLE[get1/3][get1%3]){
case ID_LION:
for(i=rand()%3,j=rand()%3,k=0;LION[i][j]==0 || LION[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_LION;
break;
case ID_ELEPHANT:
for(i=rand()%3,j=rand()%3,k=0;ELEPHANT[i][j]==0 || ELEPHANT[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_ELEPHANT;
break;
case ID_GIRAFFE:
for(i=rand()%3,j=rand()%3,k=0;GIRAFFE[i][j]==0 || GIRAFFE[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_GIRAFFE;
break;
case ID_CHICK:
for(i=rand()%3,j=rand()%3,k=0;CHICK[i][j]==0 || CHICK[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_CHICK;
//成る場合
if(get1/3+i-1<2) TABLE[get1/3+i-1][get1%3+j-1]=ID_CHICKEN;
break;
case ID_CHICKEN:
for(i=rand()%3,j=rand()%3,k=0;CHICKEN[i][j]==0 || CHICKEN[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_CHICKEN;
break;
default:
break;
}
}
draw();
putchar('\a');
sleep(1);
if(get_winner()!=0) break;
//ENEMYのターン
restart2:
if(get_enemys_military_power()<=0) return 1; //エラー
//相手から奪った駒を使用する場合
if(rand()%get_enemys_military_power()<get_enemys_stocks()){
for(get1=rand()%8;STOCKS_ENEMY[get1]==0;get1=rand()%8);
for(get2=rand()%12;TABLE[get2/3][get2%3]!=0;get2=rand()%12);
TABLE[get2/3][get2%3]=STOCKS_ENEMY[get1];
if(TABLE[get2/3][get2%3]>0) TABLE[get2/3][get2%3]*=-1;
if(TABLE[get2/3][get2%3]==-ID_CHICKEN) TABLE[get2/3][get2%3]=-ID_CHICK;
STOCKS_ENEMY[get1]=0;
}
//ボード上の駒を動かす場合
else{
for(get1=rand()%12;TABLE[get1/3][get1%3]>=0;get1=rand()%12);
switch(TABLE[get1/3][get1%3]){
case -ID_LION:
for(i=rand()%3,j=rand()%3,k=0;LION[i][j]==0 || LION[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_LION;
break;
case -ID_ELEPHANT:
for(i=rand()%3,j=rand()%3,k=0;ELEPHANT[i][j]==0 || ELEPHANT[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_ELEPHANT;
break;
case -ID_GIRAFFE:
for(i=rand()%3,j=rand()%3,k=0;GIRAFFE[i][j]==0 || GIRAFFE[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_GIRAFFE;
break;
case -ID_CHICK:
for(i=rand()%3,j=rand()%3,k=0;CHICK[i][j]==0 || CHICK[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_CHICK;
//成る場合
if(get1/3+(i-1)*-1<2) TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_CHICKEN;
break;
case -ID_CHICKEN:
for(i=rand()%3,j=rand()%3,k=0;CHICKEN[i][j]==0 || CHICKEN[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_CHICKEN;
break;
default:
break;
}
}
draw();
putchar('\a');
sleep(1);
}
if(get_winner()>0) printf("\nPLAYER WIN.");
else printf("\nENEMY WIN.");
return 0;
}
Re: C言語
オフトピック
> ①を至急提出しないといけないためどのようにコードを組めばよいかなど教えていただけないでょうか。
(1)盤面を表現する方法を定める
(2)可能な手を列挙する手段を実装する
(3)(2)からランダムで手を選ぶ手段を実装する
(4)(3)で選んだ結果を盤面データに反映する手段を実装する
(5)終了判定(勝敗,引き分け)を実装する
といった感じでしょうか.
リンク先は 403 Forbidden で見れません.(学内専用とかかな?)
そこにあるとされるコードを基にしなくても良い話なのでしょうか? (課題の制約条件的な意味で)
(勝手な想像ですが,課題内容としては②の側が本番っぽいですし,
①については,ちょこっとコード追加すれば終わるくらいの状態のコードが用意されてるんじゃないかな? とか)
(1)盤面を表現する方法を定める
(2)可能な手を列挙する手段を実装する
(3)(2)からランダムで手を選ぶ手段を実装する
(4)(3)で選んだ結果を盤面データに反映する手段を実装する
(5)終了判定(勝敗,引き分け)を実装する
といった感じでしょうか.
リンク先は 403 Forbidden で見れません.(学内専用とかかな?)
そこにあるとされるコードを基にしなくても良い話なのでしょうか? (課題の制約条件的な意味で)
(勝手な想像ですが,課題内容としては②の側が本番っぽいですし,
①については,ちょこっとコード追加すれば終わるくらいの状態のコードが用意されてるんじゃないかな? とか)
Re: C言語
私が書いたコードは、大まかな流れを説明しようと思って、超適当に作っただけなので、私のコードを完成させる事に注力しない方が良いと思います。
私が書いた超適当なコードは、バグも含んでいるみたいですし、その様なコードを完成させる為に無駄な努力はしなくて良いと思います。
飽くまで、斜め読みして雰囲気を掴む程度に留めておいた方が良いと思います。
今見たら、usao氏が指摘している様に、既に大学の先生からベースとなるコードが提示されているみたいですね。
そちらに加筆・訂正をした方が宜しいかと思います。
リンク切れするらしいので、コード部分だけ引用して載せておきます。 (私はまだ読んでいません。)
↓ http://pr.cei.uec.ac.jp/kobo2015/index. ... bo2015.zip より引用。
header.h
board.c
io.c
search.c
main.c
私が書いた超適当なコードは、バグも含んでいるみたいですし、その様なコードを完成させる為に無駄な努力はしなくて良いと思います。
飽くまで、斜め読みして雰囲気を掴む程度に留めておいた方が良いと思います。
今見たら、usao氏が指摘している様に、既に大学の先生からベースとなるコードが提示されているみたいですね。
そちらに加筆・訂正をした方が宜しいかと思います。
リンク切れするらしいので、コード部分だけ引用して載せておきます。 (私はまだ読んでいません。)
↓ http://pr.cei.uec.ac.jp/kobo2015/index. ... bo2015.zip より引用。
header.h
#pragma once
#define DELIM " "
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
# define strtok_r strtok_s
#endif
#ifdef SRC_BOARD
#define BOARD_EXTERN
#else
#define BOARD_EXTERN extern
#endif
/* 便利定数 */
enum {
white = 0,
black = 1,
hand = -1, /* 駒台の番号 */
MOVE_NULL = 0, /* 着手無し */
};
/* 駒の種類 */
enum {
piyo = 1,
zou = 2,
kirin = 3,
lion = 4,
niwa = 5,
/* 先手(white)の駒の種類 */
white_piece = 0,
w_piyo = white_piece + piyo,
w_zou,
w_kirin,
w_lion,
w_niwa,
/* 後手(black)の駒の種類 */
black_piece = 8,
b_piyo = black_piece + piyo,
b_zou,
b_kirin,
b_lion,
b_niwa,
/* 全ての駒の数 */
all_piece_num,
/* 駒以外の情報 */
types_num = 5,
empty = 0,
wall = 15,
};
/* 局面を表す構造体 */
typedef struct tree {
int board[32]; /* 盤上の駒の情報 */
int whand[types_num]; /* 先手の持ち駒 */
int bhand[types_num]; /* 後手の持ち駒 */
int turn; /* 現在の手番 */
int ply; /* 現在の手数 */
} tree_t;
typedef struct move {
int to; /*動いた先のマスの番号 */
int from; /* 元のマスの番号。打った駒はhand(-1)番 */
int type; /* 指した、打った駒の種類 */
int catch_type; /* 取った駒の種類 */
int is_promote; /* 1なら成った */
} move_t;
/* ゲーム局面ーと移動の履歴を表す変数 */
BOARD_EXTERN tree_t game;
BOARD_EXTERN move_t history[512];
/* board.c */
void init_board();
void make_move(move_t move);
void unmake_move(move_t move);
int is_legal(move_t move);
int is_drop_legal(move_t move);
int is_move_legal(move_t move);
int attacks_to(int from, int to, int type);
int gen_legal(move_t moves[]);
/* io.c */
void show_turn();
void show_board();
void show_hand(int turn);
void show_position();
void manual_move(char **last);
int CSA2Internal(const char *str, move_t *move);
void back();
/* search.c */
int search_root(int depth);
int evaluate();
#define SRC_BOARD
#include "header.h"
int dir_index[8] = {
-6, -5, -4, -1, 1, 4, 5, 6 };
int direction[16][8] = { //各駒の利きの向き
{ 0 },
{ 0, 0, 0, 1, 0, 0, 0, 0 }, //W_PIYO
{ 1, 0, 1, 0, 0, 1, 0, 1 }, //W_ZOU
{ 0, 1, 0, 1, 1, 0, 1, 0 }, //W_KIRIN
{ 1, 1, 1, 1, 1, 1, 1, 1 }, //W_LION
{ 1, 1, 0, 1, 1, 1, 1, 0 }, //W_NIWA
{ 0 },
{ 0 },
{ 0 },
{ 0, 0, 0, 0, 1, 0, 0, 0 }, //B_PIYO
{ 1, 0, 1, 0, 0, 1, 0, 1 }, //B_ZOU
{ 0, 1, 0, 1, 1, 0, 1, 0 }, //B_KIRIN
{ 1, 1, 1, 1, 1, 1, 1, 1 }, //B_LION
{ 0, 1, 1, 1, 1, 0, 1, 1 }, //B_NIWA
};
int get_pro(int piece);
int get_nopro(int piece);
int drop_type(int piece);
void flip_turn();
/**
* 盤面を初期化する関数
*/
void init_board() {
int i;
for (i = 0; i <= 25; ++i) game.board[i] = wall;
game.board[6] = b_zou;
game.board[11] = b_lion;
game.board[16] = b_kirin;
game.board[12] = b_piyo;
game.board[19] = w_zou;
game.board[14] = w_lion;
game.board[9] = w_kirin;
game.board[13] = w_piyo;
game.board[7] = empty;
game.board[8] = empty;
game.board[17] = empty;
game.board[18] = empty;
for (i = 0; i<types_num; ++i) {
game.whand[i] = 0;
game.bhand[i] = 0;
}
game.ply = 1;
}
/**
* 移動処理を行う
*
* @param move 実行する移動の情報
*/
void make_move(move_t move) {
int type, captype;
int* myhand;
/* TODO: */
/** MEMO
* 1. 手番の処理
* 2. 持ち駒処理
* 1. 打つ駒を駒台から減らす
* 2. 打つ先に駒を置く
* 3. 駒を動かす指し手
* 1. (駒があれば)移動先の相手の駒を取る
* 2. 移動先に駒を置く。もし成るならば成った駒を置く
* 3. 移動元の駒を消す
* 4. 手番の移行処理
*/
}
/**
* 実行した移動を取り消す
*
* @param move 取り消す移動の情報
*/
void unmake_move(move_t move) {
int type, captype;
int* myhand;
/* TODO: */
/** MEMO
* 基本的に make_move() と逆の順番で処理をすれば良い。
* 但し、合法かどうかは判別しなくても良い(既に判定されたと考える)
*/
}
/**
* 成れる駒であれば成った後の駒を返す
*
* @param piece 成れる駒か判定する駒
*/
int get_pro(int piece) {
if (piece == w_piyo) return w_niwa;
if (piece == b_piyo) return b_niwa;
return piece;
}
/**
* 成駒であれば成る前の駒を返す
*
* @param piece 成り駒か判定する駒
*/
int get_nopro(int piece) {
if (piece == w_niwa) return w_piyo;
if (piece == b_niwa) return b_piyo;
return piece;
}
/**
* 駒台に置く駒の種類を取得する
*/
int drop_type(int piece) {
if (piece >= black_piece) return piece - black_piece;
return piece - white_piece;
}
/**
* 手番を入れ替える
*/
void flip_turn() {
/* 手番は 0=white, 1=black の2値表現 */
game.turn ^= 1;
}
/**
* 指し手が合法手であるか判別する
*
* @param move 判定する指し手情報
*/
int is_legal(move_t move) {
if (move.from == hand) return is_drop_legal(move);
else return is_move_legal(move);
}
/**
* 置駒手が合法手であるか判別する
*
* @param move 判定する置駒情報
*/
int is_drop_legal(move_t move) {
/*移動先に駒があれば打てない*/
/* TODO: */
/*持っていない駒は打てない*/
/* TODO: */
return 1;
}
/**
* 移動手が合法手であるか判別する
*
* @param move 判定する移動情報
*/
int is_move_legal(move_t move) {
int type;
/* TODO: */
/** MEMO
* 1. 移動元の駒の種類が着手と一致しているか
* 2. 成れない位置で成っていないか
先手が成れるのは,最上段の6, 11, 16
後手が成れるのは,最下段の9, 14, 19
* 3. 移動元の駒の利きでない場所ではないか
* 4. 移動先に自分の駒はないか
* 5. 移動先は壁ではないか
*/
/* */
return 1;
}
/**
* 駒の利きを判定する
*
* @param from 駒の移動前の位置
* @param to 駒の移動後の位置
* @param type 駒の種類
*/
int attacks_to(int from, int to, int type) {
int dir, i;
dir = to - from;
/* 利きのリストに含まれる方向への移動か */
/* TODO: */
/* 移動先は利きに含まれていない */
/* TODO: */
return 1;
}
/**
* 合法手を生成する関数
*
* @param moves 移動情報を格納する配列
*/
int gen_legal(move_t moves[]) {
int nmove = 0;
if (game.turn == white) {
/* ライオンが取られていたら合法手無し */
if (game.bhand[lion] == 1) return 0;
/* 駒を打つ合法手を生成 */
nmove = gen_legalhand_w(moves, nmove);
/* 駒を動かす合法手を生成 */
nmove = gen_legalmove_w(moves, nmove);
}
else {
/* ライオンが取られていたら合法手無し */
if (game.whand[lion] == 1) return 0;
/* 駒を打つ合法手を生成 */
nmove = gen_legalhand_b(moves, nmove);
/* 駒を動かす合法手を生成 */
nmove = gen_legalmove_b(moves, nmove);
}
return nmove;
}
int gen_legalhand_w(move_t moves[], int nmove) {
int i, j;
move_t move;
/* 初期化 */
move.from = hand; move.is_promote = 0; move.catch_type = 0;
/* 駒を打てる場所それぞれに対して合法手を生成 */
/* TODO: */
return nmove;
}
int gen_legalhand_b(move_t moves[], int nmove) {
int i, j;
move_t move;
/* 初期化 */
move.from = hand; move.is_promote = 0; move.catch_type = 0;
/* 駒を打てる場所それぞれに対して合法手を生成 */
/* TODO: 上と同様に実装する */
return nmove;
}
int gen_legalmove_w(move_t moves[], int nmove) {
int i, j;
move_t move;
/* 盤上の自分の駒それぞれに対して合法手を生成 */
/* TODO: */
/* MEMO:
* 1. 1駒ずつ合法手を生成していく
* 2. 利きの先が移動できない場所なら無視
* 3. 移動する指し手を生成
* 4. 最奥ならば成る手も生成
*/
return nmove;
}
int gen_legalmove_b(move_t moves[], int nmove) {
int i, j;
move_t move;
/* 盤上の自分の駒それぞれに対して合法手を生成 */
/* TODO: 上と同様に実装する */
return nmove;
}
#include "header.h"
#include <stdio.h>
#include <string.h>
/** 表示に関する関数群 **************/
/* 持ち駒として駒の種類を表示する為のテキストデータ */
const char *ch_piece[16] = {
"--", "ひ", "ぞ", "き", "ら",
"--", "に", "--", "--", "--" };
/* 盤上の駒を表示する為のテキストデータ */
const char *ch_piece2[16] = {
" ", "^ひ", "^ぞ", "^き",
"^ら", "^に", "---", "---",
" ", "vひ", "vぞ", "vき",
"vら", "vに", "---", "---" };
const char *ch_piece_csa[16] = {
"--", "HI", "ZO", "KI", "RA",
"--", "NI", "--", "--", "--", };
/* 持ち駒の表示 */
void show_turn() {
char sturn[2][8] = { "先手", "後手" };
printf("%sの番です。\n", sturn[game.turn]);
}
/* 盤面とその上の駒を表示 */
void show_board() {
int i, j, type;
/* 列表示 */
printf(" A B C\n");
for (i = 0; i<4; ++i) {
/* 横線と段表示 */
printf(" -------------\n");
printf("%d |", i + 1);
for (j = 0; j<3; ++j) { /* 駒の種類を特定してそれぞれ表示 */
type = game.board[16 - 5 * j + i];
printf("%s|", ch_piece2[type]);
}
/* 1段分の出力が終了 */
printf("\n");
}
/* 盤面の一番下の線 */
printf(" -------------\n");
}
/* 持ち駒の表示 */
void show_hand(int turn) {
int i, *hand;
/* 指定された手番の持ち駒の配列を取得 */
if (turn == white) hand = game.whand;
else hand = game.bhand;
/* 指定された手番の持ち駒を、あるものだけ表示 */
for (i = 1; i <= 4; ++i) {
if (hand[i] > 0)
printf(" %s%d", ch_piece[i], hand[i]);
}
printf("\n");
}
void show_legalmove() {
int i, nmove = 0;
move_t moves[64];
/* gen_legal() 実装後、これを利用して合法手を表示 */
for (i = 0; i<nmove; ++i) {
printf("%d>%d[%s], ", moves[i].from, moves[i].to, ch_piece_csa[moves[i].type % 8]);
}
printf("\n");
}
void show_position() {
show_turn();
show_hand(black);
show_board();
show_hand(white);
show_legalmove();
}
/** 入力に関する関数群 **************/
void manual_move(char **last) {
move_t move;
/* lastから着手部分を切り出す。
第一引数にNULLを入れ、前回切り出したlastからスタート */
const char *p = strtok_r(NULL, DELIM, last);
/* 着手の解析 */
printf("move: %s\n", p);
if (p == NULL || CSA2Internal(p, &move) == -1) {
printf("Invalid Move\n");
printf("Example: 2221HI+\n");
return;
}
/* 合法手の判定 */
if (is_legal(move) != 1) {
printf("Illegal Move\n");
return;
}
/* 着手の実行 */
make_move(move);
/* 盤面の更新 */
show_position();
}
/* CSA形式の表現を内部の指し手表現に変換する */
int CSA2Internal(const char *str, move_t *move) {
int fromX, fromY, toX, toY, i;
char buf[8] = { 0 }, *p;
/* 初期化 */
move->is_promote = 0; move->catch_type = 0;
strncpy(buf, str, strlen(str) + 1);
/* 文字列の形式によるガード */
if (str == NULL) return -1;
else if (strlen(str) != 6){
if (strlen(str) == 7 && str[6] == '+') {
move->is_promote = 1;
/* 成り情報を抽出したので捨てる */
buf[6] = '\0';
}
else return -1;
}
/* コマンドの解析
移動情報を読み出し */
fromX = str[0] - '0';
fromY = str[1] - '0';
toX = str[2] - '0';
toY = str[3] - '0';
/* xy座標系から添え字に変換 */
move->from = (21 - fromX * 5) + fromY - 1;
move->to = (21 - toX * 5) + toY - 1;
/* コマンドから駒の種類を読み出し */
p = buf + 4;
for (i = 0; i<10; ++i) {
/* 一致した手番付き駒種類を取得 */
if (!strcmp(p, ch_piece_csa[i])) {
move->type = (game.turn == white) ? i : i + 8;
break;
}
}
/* 該当する駒無し */
if (i == 10) return -1;
/* 持ち駒を打つ指し手 */
if (fromX == 0 && fromY == 0) {
move->from = hand;
return 0;
}
/* 駒を動かす指し手
取る駒を計算 */
if (move->from<0 || move->from>25 || move->to<0 || move->to >25) return -1;
move->catch_type = game.board[move->to];
return 0;
}
void back() {
if (game.ply == 1) return;
/* ひとつ前の手数の着手を取ってきてunmake_moveする。 */
unmake_move(history[game.ply - 1]);
/* 状態を書き換えたら新しい盤面を表示する。 */
show_position();
}
#include "header.h"
/**
* 探索関数のルート関数
*
* @param depth 読む手の深さ
*/
int search_root(int depth) {
int nmove, i, best, max, val;
move_t moves[64];
max = -999999;
/* TODO: */
/* MEMO:
* ここでは search() と同様に探索した後に最善手を選ぶ処理を入れる
*/
return max;
}
/**
* 探索関数の再帰関数
*
* @param depth 読む手の深さ
*/
int search(int depth) {
int i, val, max, nmove;
move_t moves[64];
max = -9999999;
// TODO:
return max;
}
/**
* 駒の評価関数
*/
int evaluate_piece() {
int i;
int score = 0;
/* TODO: */
return game.turn == white ? score : -score;
}
/**
* 盤面全体の評価関数
*/
int evaluate() {
int i;
/* TODO: */
return 0;
}
#include "header.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEFAULT_DEPTH 7
int cmd_prompt();
int main(void) {
init_board();
show_position();
while (cmd_prompt() == 0);
return 0;
}
/* コマンド入力を受け付ける
返り値が0のとき正常。1のとき異常 */
int cmd_prompt() {
char buf[256];
const char *token;
char *last;
/* 初期化 */
memset(buf, 0, sizeof(buf));
/* 現在の状態を表示 */
if (game.turn == black) printf("Black %d> ", game.ply);
else printf("White %d> ", game.ply);
//コマンド入力の受付. 空なら無視
fgets(buf, sizeof(buf), stdin);
if (!strcmp(buf, "\n"))
return 0;
//文字列の最後(改行文字)を空文字にして文字列扱いに。
buf[strlen(buf) - 1] = '\0';
/* コマンドと引数を切り出し */
token = strtok_r(buf, DELIM, &last);
if (token == NULL)
return 0;
/* コマンドに対応した関数の呼び出し */
if (!strcmp(token, "quit"))
return -1;
else if (!strcmp(token, "board"))
show_position();
else if (!strcmp(token, "new")) {
init_board();
show_position();
}
else if (!strcmp(token, "move"))
manual_move(&last);
else if (!strcmp(token, "back"))
back();
/* 該当コマンドが無い場合の例外処理 */
else {
printf("Invalid Command [%s]\n", token);
}
return 0;
}
Re: C言語
お二人の方返信ありがとうございます。
自分が載せたURLのサイトに先ほど白い恋人さんが載せてくださったソースコードと、抜けている部分を埋めるためのdocxファイルがあるのですがそこに載っている課題も解けないもので。そこに載っている課題を載せますと
・make_move() 内に追加せよ。move_tの配列を用意し,make_moveされるたびに現在の手数の位置に格納していけば良い。
・入力されたコマンドをmake_moveする前に,その着手が非合法手ならばIllegal Moveと表示して着手を破棄するように、is_legal関数を用いてmanual_moveを修正する。
・gen_legalの動作確認とインタフェースの改善を兼ねて,局面を表示するときに現局面の合法手のリストを表示する機能を実装する。
・ここでは簡単な評価項目を用いているが、実際にはより複雑で正確な評価を行える必要がある。例えば上の例ではライオンがタッチダウンを行うことを目的としているが、その他にもライオンが中央のラインに居るだけでも効果的であるし、きりんとぞうであればどちらを持っていた方が有利であるか、など様々な点が考えられる。ここではあなたが実際にどうぶつしょうぎを指してみて、良いと思った戦術、駒の配置に基づいて評価関数を作成せよ。実装例としては上の例のように特定の条件に一致しているか判断することも考えられるが、他にも各駒が居るマスに応じて評価する方法などが考えられる。どのような方法を用いても良いので様々な評価を実装してみること。
上記の4つになります。
自分が載せたURLのサイトに先ほど白い恋人さんが載せてくださったソースコードと、抜けている部分を埋めるためのdocxファイルがあるのですがそこに載っている課題も解けないもので。そこに載っている課題を載せますと
・make_move() 内に追加せよ。move_tの配列を用意し,make_moveされるたびに現在の手数の位置に格納していけば良い。
・入力されたコマンドをmake_moveする前に,その着手が非合法手ならばIllegal Moveと表示して着手を破棄するように、is_legal関数を用いてmanual_moveを修正する。
・gen_legalの動作確認とインタフェースの改善を兼ねて,局面を表示するときに現局面の合法手のリストを表示する機能を実装する。
・ここでは簡単な評価項目を用いているが、実際にはより複雑で正確な評価を行える必要がある。例えば上の例ではライオンがタッチダウンを行うことを目的としているが、その他にもライオンが中央のラインに居るだけでも効果的であるし、きりんとぞうであればどちらを持っていた方が有利であるか、など様々な点が考えられる。ここではあなたが実際にどうぶつしょうぎを指してみて、良いと思った戦術、駒の配置に基づいて評価関数を作成せよ。実装例としては上の例のように特定の条件に一致しているか判断することも考えられるが、他にも各駒が居るマスに応じて評価する方法などが考えられる。どのような方法を用いても良いので様々な評価を実装してみること。
上記の4つになります。
Re: C言語
責任を感じたので、指摘を受けた箇所だけ軽くバグフィックスしてみました。
置換のし忘れと、ルールの認識ミスが有ったようです。
ただ、飽くまでも、それっぽく動いている様に見える程度に修正しただけなので、まだバグが潜んでいる可能性も否定できないので悪しからず。
置換のし忘れと、ルールの認識ミスが有ったようです。
ただ、飽くまでも、それっぽく動いている様に見える程度に修正しただけなので、まだバグが潜んでいる可能性も否定できないので悪しからず。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//下記値×-1は敵の駒を表す
#define ID_LION 1
#define ID_ELEPHANT 2
#define ID_GIRAFFE 3
#define ID_CHICK 4
#define ID_CHICKEN 5
//各駒の移動可能な場所を定義した配列。(1が移動可能な場所)
char LION[3][3];
char ELEPHANT[3][3];
char GIRAFFE[3][3];
char CHICK[3][3];
char CHICKEN[3][3];
char TABLE[4][3]; //盤面の状態をを記録する配列
char STOCKS_ENEMY[8]; //敵が保有する捕虜を保存する配列
char STOCKS_PLAYER[8]; //プレイヤーが保有する捕虜を保存する配列
//初期化処理
void init(void){
char i,j;
for(i=0;i<3;i++) for(j=0;j<3;j++) LION[i][j]=1;
LION[1][1]=0;
for(i=0;i<3;i++) for(j=0;j<3;j++) ELEPHANT[i][j]=1;
for(i=0;i<3;i++) ELEPHANT[1][i]=0;
for(i=0;i<3;i++) ELEPHANT[i][1]=0;
for(i=0;i<3;i++) for(j=0;j<3;j++) GIRAFFE[i][j]=1;
for(i=0,j=0;i<3;i++,j++) GIRAFFE[i][j]=0;
for(i=2,j=0;i>=0;i--,j++) GIRAFFE[i][j]=0;
for(i=0;i<3;i++) for(j=0;j<3;j++) CHICK[i][j]=0;
CHICK[0][1]=1;
for(i=0;i<3;i++) for(j=0;j<3;j++) CHICKEN[i][j]=1;
CHICKEN[1][1]=0;
CHICKEN[2][0]=0;
CHICKEN[2][2]=0;
for(i=0;i<4;i++) for(j=0;j<3;j++) TABLE[i][j]=0;
TABLE[0][0]=ID_GIRAFFE*-1;
TABLE[0][1]=ID_LION*-1;
TABLE[0][2]=ID_ELEPHANT*-1;
TABLE[1][1]=ID_CHICK*-1;
TABLE[2][1]=ID_CHICK;
TABLE[3][0]=ID_ELEPHANT;
TABLE[3][1]=ID_LION;
TABLE[3][2]=ID_GIRAFFE;
for(i=0;i<8;i++) STOCKS_ENEMY[i]=0;
for(i=0;i<8;i++) STOCKS_PLAYER[i]=0;
}
//勝者の算出
char get_winner(void){
char i;
for(i=0;i<8;i++) if(STOCKS_PLAYER[i]==ID_LION || STOCKS_PLAYER[i]==ID_LION*-1) return 1; //PLAYER IS WINNER.
for(i=0;i<8;i++) if(STOCKS_ENEMY[i]==ID_LION || STOCKS_ENEMY[i]==ID_LION*-1) return -1; //ENEMY IS WINNER.
return 0;
}
//敵が持つ盤面上の駒+捕虜の総数の算出
char get_enemys_military_power(void){
char i,j;
char sum=0;
for(i=0;i<4;i++) for(j=0;j<3;j++) if(TABLE[i][j]<0) sum++;
for(i=0;i<8;i++) if(STOCKS_ENEMY[i]!=0) sum++;
return sum;
}
//敵が持つ捕虜の総数の算出
char get_enemys_stocks(void){
char i,j;
char sum=0;
for(i=0;i<8;i++) if(STOCKS_ENEMY[i]!=0) sum++;
return sum;
}
//プレイヤーが持つ盤面上の駒+捕虜の総数の算出
char get_players_military_power(void){
char i,j;
char sum=0;
for(i=0;i<4;i++) for(j=0;j<3;j++) if(TABLE[i][j]>0) sum++;
for(i=0;i<8;i++) if(STOCKS_PLAYER[i]!=0) sum++;
return sum;
}
//プレイヤーが持つ捕虜の総数の算出
char get_players_stocks(void){
char i,j;
char sum=0;
for(i=0;i<8;i++) if(STOCKS_PLAYER[i]!=0) sum++;
return sum;
}
//描画処理
void draw(void){
char i,j;
system("CLS");
printf("ENEMY'S STOCKS:");
for(i=0;i<8;i++){
switch(STOCKS_ENEMY[i]){
case ID_LION:
case -ID_LION:
printf("ラ");
break;
case ID_ELEPHANT:
case -ID_ELEPHANT:
printf("ゾ");
break;
case ID_GIRAFFE:
case -ID_GIRAFFE:
printf("キ");
break;
case ID_CHICK:
case -ID_CHICK:
case ID_CHICKEN:
case -ID_CHICKEN:
printf("ヒ");
break;
default:
break;
}
}
printf("\n\n");
for(i=0;i<4;i++){
for(j=0;j<3;j++){
switch(TABLE[i][j]){
case ID_LION:
printf("ら");
break;
case ID_ELEPHANT:
printf("ぞ");
break;
case ID_GIRAFFE:
printf("き");
break;
case ID_CHICK:
printf("ひ");
break;
case ID_CHICKEN:
printf("に");
break;
case -ID_LION:
printf("ラ");
break;
case -ID_ELEPHANT:
printf("ゾ");
break;
case -ID_GIRAFFE:
printf("キ");
break;
case -ID_CHICK:
printf("ヒ");
break;
case -ID_CHICKEN:
printf("ニ");
break;
default:
printf("□");
break;
}
}
printf("\n");
}
printf("\n");
printf("PLAYER'S STOCKS:");
for(i=0;i<8;i++){
switch(STOCKS_PLAYER[i]){
case ID_LION:
case -ID_LION:
printf("ら");
break;
case ID_ELEPHANT:
case -ID_ELEPHANT:
printf("ぞ");
break;
case ID_GIRAFFE:
case -ID_GIRAFFE:
printf("き");
break;
case ID_CHICK:
case -ID_CHICK:
case ID_CHICKEN:
case -ID_CHICKEN:
printf("ひ");
break;
default:
break;
}
}
printf("\n");
}
int main(void){
int i,j,k;
int get1,get2;
init(); //初期化処理
srand(time(NULL)); //疑似乱数生成器の種の初期化
draw(); //盤面の描画
sleep(1);
while(get_winner()==0){
//PLAYERのターン
restart1:
if(get_players_military_power()<=0) return 1; //エラー
//相手から奪った駒を使用する場合
if(rand()%get_players_military_power()<get_players_stocks()){
for(get1=rand()%8;STOCKS_PLAYER[get1]==0;get1=rand()%8); //保有している捕虜からランダムに選定
for(get2=rand()%12;TABLE[get2/3][get2%3]!=0;get2=rand()%12); //置ける場所の探索
//配置処理
TABLE[get2/3][get2%3]=STOCKS_PLAYER[get1];
if(TABLE[get2/3][get2%3]<0) TABLE[get2/3][get2%3]*=-1;
if(TABLE[get2/3][get2%3]==ID_CHICKEN) TABLE[get2/3][get2%3]=ID_CHICK;
STOCKS_PLAYER[get1]=0;
}
//ボード上の駒を動かす場合
else{
//移動する駒の選定
for(get1=rand()%12;TABLE[get1/3][get1%3]<=0;get1=rand()%12);
switch(TABLE[get1/3][get1%3]){
case ID_LION:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;LION[i][j]==0 || LION[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_LION;
break;
case ID_ELEPHANT:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;ELEPHANT[i][j]==0 || ELEPHANT[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_ELEPHANT;
break;
case ID_GIRAFFE:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;GIRAFFE[i][j]==0 || GIRAFFE[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_GIRAFFE;
break;
case ID_CHICK:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;CHICK[i][j]==0 || CHICK[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_CHICK;
//成る場合
if(get1/3+i-1<1) TABLE[get1/3+i-1][get1%3+j-1]=ID_CHICKEN;
break;
case ID_CHICKEN:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;CHICKEN[i][j]==0 || CHICKEN[i][j]==1 && (get1/3+i-1<0 || get1/3+i-1>=4 || get1%3+j-1<0 || get1%3+j-1>=3 || TABLE[get1/3+i-1][get1%3+j-1]>0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart1;
//捕虜の入手
if(TABLE[get1/3+i-1][get1%3+j-1]<0){
for(k=0;STOCKS_PLAYER[k]!=0;k++);
STOCKS_PLAYER[k]=TABLE[get1/3+i-1][get1%3+j-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+i-1][get1%3+j-1]=ID_CHICKEN;
break;
default:
break;
}
}
draw();
putchar('\a');
sleep(1);
if(get_winner()!=0) break;
//ENEMYのターン
restart2:
if(get_enemys_military_power()<=0) return 1; //エラー
//相手から奪った駒を使用する場合
if(rand()%get_enemys_military_power()<get_enemys_stocks()){
for(get1=rand()%8;STOCKS_ENEMY[get1]==0;get1=rand()%8); //保有している捕虜からランダムに選定
for(get2=rand()%12;TABLE[get2/3][get2%3]!=0;get2=rand()%12); //置ける場所の探索
//配置処理
TABLE[get2/3][get2%3]=STOCKS_ENEMY[get1];
if(TABLE[get2/3][get2%3]>0) TABLE[get2/3][get2%3]*=-1;
if(TABLE[get2/3][get2%3]==-ID_CHICKEN) TABLE[get2/3][get2%3]=-ID_CHICK;
STOCKS_ENEMY[get1]=0;
}
//ボード上の駒を動かす場合
else{
//移動する駒の選定
for(get1=rand()%12;TABLE[get1/3][get1%3]>=0;get1=rand()%12);
switch(TABLE[get1/3][get1%3]){
case -ID_LION:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;LION[i][j]==0 || LION[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_LION;
break;
case -ID_ELEPHANT:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;ELEPHANT[i][j]==0 || ELEPHANT[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_ELEPHANT;
break;
case -ID_GIRAFFE:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;GIRAFFE[i][j]==0 || GIRAFFE[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_GIRAFFE;
break;
case -ID_CHICK:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;CHICK[i][j]==0 || CHICK[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_CHICK;
//成る場合
if(get1/3+(i-1)*-1>=3) TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_CHICKEN;
break;
case -ID_CHICKEN:
//移動先の決定
for(i=rand()%3,j=rand()%3,k=0;CHICKEN[i][j]==0 || CHICKEN[i][j]==1 && (get1/3+(i-1)*-1<0 || get1/3+(i-1)*-1>=4 || get1%3+(j-1)*-1<0 || get1%3+(j-1)*-1>=3 || TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]<0);i=rand()%3,j=rand()%3,k++) if(k>=10) goto restart2;
//捕虜の入手
if(TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]>0){
for(k=0;STOCKS_ENEMY[k]!=0;k++);
STOCKS_ENEMY[k]=TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1];
}
//駒の移動
TABLE[get1/3][get1%3]=0;
TABLE[get1/3+(i-1)*-1][get1%3+(j-1)*-1]=-ID_CHICKEN;
break;
default:
break;
}
}
draw();
putchar('\a');
sleep(1);
}
if(get_winner()>0) printf("\nPLAYER WIN.");
else printf("\nENEMY WIN.");
return 0;
}