オセロで取得できる最大の枚数を出力する。
オセロのプログラムを作っていて、毎回取得できる最大の枚数を出力しようとしていますが、上手くいきません。
実際に取得できた枚数はすぐ出せたのですが、どこがおかしいか全く分からないのでよろしくお願いします。
#include<iomanip.h>
#include<iostream.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
const int Max_tate=8; //縦の最大座標
const int Max_yoko=8; //横の最大座標
//状態を定義
const int None=0;
const int kuro=1;
const int shiro=2;
int human, cpu; //ターンプレイヤーの定義
int difficulty; //難易度
int field[Max_tate][Max_yoko];
int turn;
int turnplayer; //コンピューターか人間かの判断
int flipno;
int vec;
int flip_max;
int flip_plus;
int realflip;
void disp(void){
cout<<" ";
for(int i = 0 ; i < Max_yoko;i++){
cout<<" "<<i + 1;
}
cout<<endl;
for(int i=0;i<Max_tate;i++){
cout<<i+1<<"0";
for(int l=0;l<Max_yoko;l++){
if(field[i][l]==0){
cout<<"+";
}else if(field[i][l]==1){
cout<<"●";
}else if(field[i][l]==2){
cout<<"○";
}
}
cout<<endl;
}
}
//向きごとの移動量
vec_tate[] = {-1,-1,0,1,1,1,0,-1};
vec_yoko[] = {0,1,1,1,0,-1,-1,-1};
//vecで指定された向きについてひっくり返るコマがあるか確認する
int checkFlip(int y,int x,int turn,int vec){
int flag = 0;
while(1){
y += vec_tate[vec];
x += vec_yoko[vec];
//盤面の外に出ていたら終了
if( x < 0 || y < 0 || x > Max_tate-1 || y > Max_yoko-1) return 0;
//空きマスだったら終了
if(field[y][x] == None) return 0;
//相手のコマがあったらフラグを立てる
if(field[y][x] == (turn ? kuro : shiro)){
flag = 1;
continue;
}
//もしフラグがたっていればループ脱出。いなければ終了
if(flag == 1) break;
return 0;
}
return 1;
}
//その場所に置くことができるかを確認する関数
int check(int y,int x,int turn){
//どれか一方向でもひっくり返るか確認
for(vec = 0 ; vec < 8 ;vec++){
if(checkFlip(y,x,turn,vec) == 1) return 1;
}
return 0;
}
//実際に裏返す関数
void flip(int y,int x,int turn,int vec){
while(1){
y += vec_tate[vec];
x += vec_yoko[vec];
//自分のコマがあったら終了
if(field[y][x] == (turn ? shiro : kuro)){
break;
}
//それ以外なら自分のコマで塗りつぶす
field[y][x] = (turn ? shiro : kuro);
realflip++; //実際に裏返した枚数
}
}
//入力を受けて裏返せるか確かめる関数
int put(int y,int x,int turn){
int vec,flag=0;
//空白でなければ終了
if(field[y][x] != None) return 0;
//全方向について確認
for(vec=0 ; vec < 8 ; vec++){
if(checkFlip(y,x,turn,vec) == 1){
//裏返す
flip(y,x,turn,vec);
flag = 1;
}
}
if(flag == 1){
//この場所にコマを置く
field[y][x] = (turn ? shiro : kuro);
return 1;
}
return 0;
}
//裏返せる枚数を計算する
void number(int y,int x,int turn,int vec){
flipno=0;
while(1){
y += vec_tate[vec];
x += vec_yoko[vec];
//自分のコマがあったら終了
if(field[y][x] == (turn ? shiro : kuro)){
break;
}else{
//それ以外なら自分のコマで塗りつぶす
flipno++;
}
}if(flipno>flip_max){
flip_max=flipno;
}
}
//上の準備段階
int reverse(int y,int x,int turn){
for(int i=0;i<Max_tate;i++){
for(int l=0;l<Max_yoko;l++){
//空白でなければ終了
if(field[i][l] != None){
return 0;
}
//全方向について確認
for(vec=0 ; vec < 8 ; vec++){
if(checkFlip(y,x,turn,vec) == 1){
//裏返す個数
number(y,x,turn,vec);
}
}
}
}
return 0;
}
//入力関数
void input(int turn){
realflip =0;
flip_max=0;
for(int i=0;i<Max_tate;i++){
for(int l=0;l<Max_yoko;l++){
if(reverse(i-1,l-1,turn) == 1){
break;
}}}
cout<<flip_max<<"個取れます"<<endl;
int place = 0,y,x;
while(1){
//入力する
if(turnplayer==human){
cout<<"どこに置きますか?";
cin>>place;
}else{
place=rand()%89;
}
if(place == 0){
//数値がとれなかったらバッファをクリアする
if(turnplayer==human){
cout<<"その入力は行えません";
}continue;
}
//数値が範囲内か確認
if(place < 11 || place > 88){
if(turnplayer==human){
cout<<"そこには置けません"<<endl;
continue;
}place = 0;
}
y = place / 10;
x = place % 10;
//もう少し詳しく確認
if( x < 1 || y < 1 || x > 8 || y > 8){
if(turnplayer==human){
cout<<"input"<<place<<"error"<<endl;
place = 0;
continue;
}}
if(put(y-1,x-1,turn) == 1){
break;
}else{
if(turnplayer==human){
cout<<"裏返す駒がありません"<<place<<endl;
}place = 0;
}
}
}
int checkEnd(int turn){
//置ける場所があるか確認
for(int i = 0 ; i <Max_tate ; i++){
for(int j = 0 ; j < Max_yoko ; j++){
//あれば普通に続行
if(field[i][j] == None && check(i,j,turn) == 1) return 0;
}
}
//場所が無かったので交替して探す
turn = (turn + 1) % 2;
for(int i = 0 ; i < Max_tate; i++){
for(int j = 0 ; j < Max_yoko; j++){
//あればpassして続行
if(field[i][j] == None && check(i,j,turn) == 1) return 1;
}
}
//なかったのでゲーム終了
return 2;
}
//勝者判定
void checkWinner(){
int b=0,w=0;
//コマを数え上げる
for(int i = 0 ; i < Max_tate ; i++){
for(int j = 0 ; j <Max_yoko ; j++){
if(field[i][j]==kuro){
b++;
}else if(field[i][j]==shiro){
w++;
}
}
}
//最後に盤面表示
disp();
//勝者を表示
cout<<"黒"<<b<<":白"<<w<<endl;
if(b > w){
cout<<"●の勝利です!\n";
}else if(b < w) {
cout<<"○の勝利です";
}else{
cout<<"引き分けです";
}
}
int main(){
//ゲームの準備
cout<<"オセロ"<<endl;
if(rand()%2==0){
cout<<"あなたは先行(●)です"<<endl;
human=0,cpu=1;
}else{
cout<<"あなたは後攻(○)です"<<endl;
cpu=0,human=1;
}
for(int i=0;i<Max_tate;i++){
for(int l=0;l<Max_yoko;l++){
field[i][l]=None;
}
}
field[Max_tate/2-1][Max_yoko/2-1]=kuro;
field[Max_tate/2-1][Max_yoko/2]=shiro;
field[Max_tate/2][Max_yoko/2-1]=shiro;
field[Max_tate/2][Max_yoko/2]=kuro;
//ゲームのメインループ
while(turn < 2){
//どちらの手番か表示
if(turn == 0){
cout<<"turn:●\n";
}else{
cout<<"turn:○\n";
}
//盤面表示
disp();
//fliper(Max_tate,Max_yoko,turn,Max_tate);
//入力
input(turn);
//手番交替
turn = (turn + 1) % 2;
//CPUか人かを変える
if(turnplayer==human){
turnplayer=cpu;
}else{
turnplayer = human;
}
cout<<realflip<<"枚めくられました";
//終了判定
switch(checkEnd(turn)){
case 1:
cout<<"取れる駒がありません"<<endl;
cout<<"手番をパスします"<<endl;
turn = (turn + 1) % 2;
break;
case 2:
cout<<"ゲームを終了します"<<endl;
turn = 2;
checkWinner();
break;
default:
break;
}
}
return 0;
}
実行例:
オセロ
あなたは先行(●)です
turn:●
1 2 3 4 5 6 7 8
10++++++++
20++++++++
30++++++++
40+++●○+++
50+++○●+++
60++++++++
70++++++++
80++++++++
1個取れます
どこに置きますか?64
1枚めくられましたturn:○
1 2 3 4 5 6 7 8
10++++++++
20++++++++
30++++++++
40+++●○+++
50+++●●+++
60+++●++++
70++++++++
80++++++++
1個取れます
1枚めくられましたturn:●
1 2 3 4 5 6 7 8
10++++++++
20++++++++
30++++++++
40+++●○+++
50+++●○+++
60+++●○+++
70++++++++
80++++++++
1個取れます
どこに置きますか?66
2枚めくられましたturn:○(1個とれますと書いてあるが、みての通り66に置くと2個取得できる)
1 2 3 4 5 6 7 8
10++++++++
20++++++++
30++++++++
40+++●○+++
50+++●●+++
60+++●●●++
70++++++++
80++++++++
2個取れます
1枚めくられましたturn:●
1 2 3 4 5 6 7 8
10++++++++
20++++++++
30++++++++
40+++●○+++
50+++○●+++
60++○●●●++
70++++++++
80++++++++
1個取れます
どこに置きますか?