/****************************/ /*             */ /*  五目並べ   */ /*             */ /* 1997/10/19 宍戸 輝光 */ /*             */ /****************************/ import java.awt.*; import java.util.Random; public class gomoku extends java.applet.Applet implements Runnable { Image banmen; Graphics dr_ban; Choice sente,gote,lan; Font f; FontMetrics fm; Panel pn,pn2,pn3; Label siro,kuro,mes; Button bt,bt2; Checkbox speed; int i,i2,i3,j,n,waku_x,waku_y,turn=1,lastX,lastY,r,mesn; int koma[][]=new int [16][16]; /* 石の配置情報 */ int score[][]=new int [16][16]; int kuhakux[]=new int [6]; int kuhakuy[]=new int [6]; int kohox[]=new int [256]; int kohoy[]=new int [256]; boolean game=false,cpu=false,flg_paint,cpu_turn=false,waku=false; boolean cpuVScpu,draw,stopped; String st[]=new String[7]; /*メッセージ文字列*/ Color waku_color; Random rnd=new Random(); Thread runner=null; public void start(){ resize(420,400); banmen=createImage(256,256); /*部品作成*/ dr_ban=banmen.getGraphics(); sente=new Choice(); gote=new Choice(); lan=new Choice(); pn=new Panel(); pn2=new Panel(); pn3=new Panel(); siro=new Label(); kuro=new Label(); mes=new Label(); bt=new Button(); bt2=new Button(); speed=new Checkbox("cpu wait",null,false); speed.setBackground(Color.orange); f=new Font("TimesRoman",Font.PLAIN,12); /*ラベル・選択メニューFont*/ sente.setFont(f); gote.setFont(f); lan.setFont(f); siro.setFont(f); kuro.setFont(f); mes.setFont(f); sente.addItem("Human"); /*ラベル・選択メニューのテキスト定義*/ sente.addItem("Computer"); gote.addItem("Human"); gote.addItem("Computer"); gote.select(1); lan.addItem("Japanese"); lan.addItem("English"); kuro.setText("\u5148\u624b\uff08\u9ed2\uff09"); kuro.setBackground(Color.orange); siro.setText("\u5f8c\u624b\uff08\u767d\uff09"); siro.setBackground(Color.orange); st[0]= "\u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3\u3067\u958b\u59cb\u3067\u3059"; st[1]="\u9ed2\u306e\u756a\u3067\u3059"; st[2]="\u767d\u306e\u756a\u3067\u3059"; st[3]="\u9ed2\u306e\u52dd\u3061\uff01\uff01"; st[4]="\u767d\u306e\u52dd\u3061\uff01\uff01"; st[5]="\u5f15\u304d\u5206\u3051\uff01\uff01"; st[6]="\u66f4\u65b0\u3057\u3066\u304f\u3060\u3055\u3044"; mes.setText(st[0]); mes.setBackground(Color.orange); mesn=0; f=new Font("TimesRoman",Font.BOLD,16); /*ボタンの文字*/ bt.setFont(f); bt2.setFont(f); bt.setLabel("Start"); bt2.setLabel("Stop"); setBackground(Color.orange); /*アプレットの背景をオレンジにする*/ sente.setBackground(Color.white);/*選択メニューの背景を白にする*/ gote.setBackground(Color.white); lan.setBackground(Color.white); bt.setBackground(Color.lightGray); bt2.setBackground(Color.lightGray); this.setLayout((LayoutManager)null); /*部品を配置*/ add(pn); add(pn2); add(pn3); pn.reshape(0,8,400,48); pn2.reshape(0,328,400,32); pn3.reshape(32,368,240,24); pn.setLayout(new FlowLayout(FlowLayout.CENTER,4,4)); pn2.setLayout(new FlowLayout(FlowLayout.CENTER,16,3)); pn3.setLayout(new FlowLayout()); pn.add(kuro); pn.add(sente); pn.add(siro); pn.add(gote); pn2.add(bt); pn2.add(bt2); pn2.add(speed); pn2.add(lan); pn3.add(mes); bt2.enable(false); mesn=0; banmenClear();/*盤を描く*/ stopped=false; if (runner==null){ runner=new Thread(this); runner.start(); } } public void stop() { mes.setText(st[6]); /* 終了メッセージ表示 */ if (runner!=null) { /*終了時にスレッド破棄*/ runner.stop(); runner=null; } } public void banmenClear(){ int i,j; dr_ban.setColor(Color.green); /*盤面イメージをクリア*/ dr_ban.fillRect(0,0,256,256); dr_ban.setColor(Color.black); for (i=0;i<16;i++) /*碁盤の目を描く*/ dr_ban.drawLine(i*16+8,8,i*16+8,248); for (i=0;i<16;i++) dr_ban.drawLine(8,i*16+8,248,i*16+8); } public void ishi_haiti(int x,int y) { /*石を置く*/ koma[x][y]=turn; lastX=x; lastY=y; if (turn==1){ dr_ban.setColor(Color.black); dr_ban.fillOval(1+x*16,1+y*16,13,13); } if (turn==-1) { dr_ban.setColor(Color.white); dr_ban.fillOval(1+x*16,1+y*16,13,13); dr_ban.setColor(Color.gray); dr_ban.drawOval(1+x*16,1+y*16,13,13); } } public boolean mouseMove(Event evt,int x,int y){ int xx,yy; if (x<20 || x>275 ||y<68 ||y>319) /*マウスカーソルは盤面の中か?*/ return false; /*外なら何もしないでリターン*/ xx=(int)((x-20)/16); yy=(int)((y-68)/16); if (koma[xx][yy]==0 && game==true && !cpuVScpu) /*石を置ける状態か?*/ waku_color=Color.blue; /*おける状態なら枠の色は青*/ else waku_color=Color.red; /*そうでなければ赤*/ waku_x=18+xx*16; /*枠を描くアプレットの座標*/ waku_y=66+yy*16; waku=true; /*枠をアプレットに描く*/ repaint(); return true; } public boolean mouseDown(Event evt,int x,int y){ int xx,yy; if (x<20 || x>276 ||y<68 ||y>320 ||!game) /*カーソルは盤面の中か?*/ return false; /*外なら何もしないでリターン*/ if (cpu_turn || !flg_paint || cpuVScpu) /*石を置けない状態ならリターン*/ return false; xx=(int)((x-20)/16); /*マウスカーソルの位置を盤面の座標に変換*/ yy=(int)((y-68)/16); if (koma[xx][yy]==0) { /*カーソルの位置に石がなければ*/ ishi_haiti(xx,yy); /*石を置く*/ lastX=xx; lastY=yy; hantei(turn); /*もし勝負がついたならゲーム終了*/ turn=-turn; flg_paint=false; /*再描画フラグを設定*/ repaint(); if (cpu) cpu_turn=true; } return true; } public void run() { /*スレッド本体*/ while (runner!=null) { if (cpu_turn && flg_paint && !stopped) {/*対コンピュータなら*/ cpuTurn(); /*コンピュータが石を配置*/ hantei(turn); /*もし勝負がついたならゲーム終了*/ turn=-turn; repaint(); cpu_turn=false; /*コンピュータの番終了*/ } if (cpuVScpu && flg_paint &&!stopped) { cpuTurn(); hantei(turn); flg_paint=false; repaint(); turn=-turn; } } } public boolean action(Event evt,Object what) { int saki,ato; if (evt.target==bt){ /*スタートボタン*/ if (game) /*現在ゲーム中なら無効*/ return false; cpu=false; cpuVScpu=false; for (i=0;i<16;i++) /*石の配置情報をクリア*/ for (j=0;j<16;j++) koma[j][i]=0; banmenClear(); turn=1; saki=sente.getSelectedIndex(); ato=gote.getSelectedIndex(); if (saki==1 && ato==0){ /*コンピュータ先手*/ cpu=true; j=Math.abs(rnd.nextInt()) % 3+7; i=Math.abs(rnd.nextInt()) % 3+7; ishi_haiti(j,i); turn=-1; } if (saki==0 && ato==1) cpu=true; game=true; cpu_turn=false; bt.enable(false); bt2.enable(true); sente.enable(false); gote.enable(false); if (saki==1 && ato==1) cpuVScpu=true; repaint(); return true; } if (evt.target==bt2){ /*クリアボタン*/ game=false; cpuVScpu=false; turn=1; bt.enable(true); bt2.enable(false); sente.enable(true); gote.enable(true); mesn=0; repaint(); return true; } if (evt.target==lan) { /* 表示言語選択メニュー */ if (lan.getSelectedIndex()==0) { /* 日本語表示 */ st[0]="\u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3"; st[0]=st[0]+"\u3067\u958b\u59cb\u3067\u3059"; st[1]="\u9ed2\u306e\u756a\u3067\u3059"; st[2]="\u767d\u306e\u756a\u3067\u3059"; st[3]="\u9ed2\u306e\u52dd\u3061\uff01\uff01"; st[4]="\u767d\u306e\u52dd\u3061\uff01\uff01"; st[5]="\u5f15\u304d\u5206\u3051\uff01\uff01"; st[6]="\u66f4\u65b0\u3057\u3066\u304f\u3060\u3055\u3044"; kuro.setText("\u5148\u624b\uff08\u9ed2\uff09"); siro.setText("\u5f8c\u624b\uff08\u767d\uff09"); } else if (lan.getSelectedIndex()==1) { /* 英語表示 */ st[0]="Push Start Button!!"; st[1]="Black's Turn"; st[2]="White's Turn"; st[3]="Black Win!!"; st[4]="White Win!!"; st[5]="Draw!!"; st[6]="Please Reload!!"; kuro.setText("Black"); siro.setText("White"); } repaint(); return true; } return false; } public void sikou(int isi) { /*コンピュータの思考(盤面評価)*/ int n0,n1,aite; int kati=15000,hissi=1000,sanren=500,mittu=100,futatu=10; /*点数*/ int kati2=12000,hissi2=500,sanren2=200,mittu2=80,futatu2=10; for (i=0;i<16;i++) { /* 横に走査 */ for(i2=0;i2<12;i2++) { n1=0; n0=0; aite=0; for (j=i2;jmax) max=score[j][i]; n=0; for (i=0;i<16;i++) /*最高点の手を選択*/ for (j=0;j<16;j++) if (score[j][i]==max) { kohox[n]=j; kohoy[n]=i; n++; } if (n==0) return false; n=Math.abs(rnd.nextInt()) % n; ishi_haiti(kohox[n],kohoy[n]);/*最高点の中から1つを実行*/ return true; } public void hantei(int v){ /*石が5つ並んでいるかの判定*/ byte n1,n2,n3,n4; draw=true; for (i=0;i<16;i++) /* すべてのマスに石があれば引き分け */ for (j=0;j<16;j++) if (koma[j][i]==0) draw=false; if (draw) /* 引き分けならゲーム終了 */ game_end(); for (i=0;i<16;i++){ n1=0; for (j=0;j<15;j++){ if (koma[j][i]==v && koma[j+1][i]==v){ /*横方向*/ n1++; if (n1>=4) game_end(); } else n1=0; } } for (i=0;i<16;i++){ n2=0; n3=0; n4=0; for (j=0;j<15;j++){ if (koma[i][j]==v && koma[i][j+1]==v){ /*縦方向*/ n2++; if (n2>=4) game_end(); } else n2=0; if ((i+j)<15){ /*斜め右下方向*/ if (koma[i+j][j]==v && koma[i+j+1][j+1]==v) { n3++; if (n3>=4) game_end(); } else n3=0; if (koma[j][i+j]==v && koma[j+1][i+j+1]==v) { n4++; if (n4>=4) game_end(); } else n4=0; } } } for (i=15;i>3;i--) { /*斜め左下方向(横に走査)*/ n3=0; for (j=0;j<15;j++) if ((i-j)>0 && j<15) if (koma[i-j][j]==v && koma[i-j-1][j+1]==v) { n3++; if (n3>=4) game_end(); } else n3=0; } for (i=0;i<12;i++){ /*斜め左下方向(縦に走査)*/ n4=0; for (j=15;j>0;j--) if ((15-j+i)<15 && j>0) if (koma[j][15-j+i]==v && koma[j-1][15-j+i+1]==v) { n4++; if (n4>=4) game_end(); } else n4=0; } } public void game_end(){ /* ゲーム終了 */ game=false; cpuVScpu=false; bt.enable(true); sente.enable(true); gote.enable(true); if (turn==1) /*どちらが勝ったのか?*/ mesn=3; else mesn=4; if (draw) mesn=5; if (!draw){ dr_ban.setColor(Color.red); /*勝負がついた場所(石)を赤く囲む*/ dr_ban.fillRect(lastX*16,lastY*16,16,16); if (koma[lastX][lastY]==1) dr_ban.setColor(Color.black); if (koma[lastX][lastY]==-1) dr_ban.setColor(Color.white); dr_ban.fillOval(1+lastX*16,1+lastY*16,13,13); } bt2.enable(false); repaint(); } public void paint(Graphics g){ if (turn==1){ /*ターン表示*/ g.setColor(Color.black); if (game==true) mesn=1; } else { g.setColor(Color.white); if (game==true) mesn=2; } if (!game) g.setColor(Color.orange); g.fillOval(280,64,24,24); mes.setText(st[mesn]); /*メッセージ表示*/ g.drawImage(banmen,16,64,this); /*盤面イメージ表示*/ if (waku){ /* 盤面上のカーソル枠を表示 */ g.setColor(waku_color); g.drawRect(waku_x,waku_y,11,11); } flg_paint=true; } public void update(Graphics g){ paint(g); } }