関数版(ptr_castF) とクラス版(ptr_castC) を作った。
関数版のテンプレート引数は2つあるが、使う時は1つしか指定していない。
VC++ では動くが、どうなのだろう?
#include <cstring>
#include <cstdio>
class COthello {
public:
enum Stat {Sp = 0, Wh = 1, Bl = 2};
private:
int m_no; // 何手目か
Stat m_ban[10][10]; // 盤の状態
bool m_bComp[2]; // プレイヤーがコンピュータかどうか
// py,px から i,j 方向の長さ
int RevLen(int py,int px,int i,int j)const;
static bool IsRange(int py,int px)
{return py >= 1 && py <= 8 && px >= 1 && px <= 8;}
public:
void Reset();
COthello(){Reset();}
int SaveFile(const char* nam)const;
int LoadFile(const char* nam);
int SetPlayer();
void Show()const;
int CanPut(int py,int px,Stat s)const;
bool CanPut(Stat s)const;
int Count(Stat s)const;
void Think(Stat s,int* py,int* px)const;
void Put(int py,int px,Stat s);
void StartGame();
};
void COthello::Reset()
{
int i,j;
for (i=0;i<10;++i) for (j=0;j<10;++j)
m_ban[i][j] = Sp;
m_ban[4][4] = m_ban[5][5] = Wh;
m_ban[5][4] = m_ban[4][5] = Bl;
m_bComp[0] = m_bComp[1] = false;
m_no = 0;
}
int COthello::SaveFile(const char* nam)const
{
FILE* f = fopen(nam,"w");
if (!f) return 1;
fprintf(f,"%d %d %d\n",m_no,m_bComp[0]?1:0,m_bComp[1]?1:0);
int i,j;
for (i=1;i<=8;++i) {
for (j=1;j<=8;++j)
fprintf(f," %d",static_cast<int>(m_ban[i][j]));
fprintf(f,"\n");
}
fclose(f);
return 0;
}
int COthello::LoadFile(const char* nam)
{
FILE* f = fopen(nam,"r");
if (!f) return 1;
char buf[80];
int i,j,k;
fgets(buf,sizeof(buf),f);
sscanf(buf,"%d %d %d",&m_no,&i,&j);
m_bComp[0] = i != 0;
m_bComp[1] = j != 0;
for (i=1;i<=8;++i) {
for (j=1;j<=8;++j) {
fscanf(f,"%d",&k);
m_ban[i][j] = static_cast<Stat>(k);
}
}
fclose(f);
return 0;
}
int COthello::SetPlayer()
{
char buf[80];
do {
printf("Is 1st Player comp ? (y/n) ");
if (!fgets(buf,sizeof(buf),stdin)) return 1;
} while (*buf != 'y' && *buf != 'n');
m_bComp[0] = *buf == 'y';
do {
printf("Is 2nd Player comp ? (y/n) ");
if (!fgets(buf,sizeof(buf),stdin)) return 1;
} while (*buf != 'y' && *buf != 'n');
m_bComp[1] = *buf == 'y';
return 0;
}
void COthello::Show()const
{
int i,j;
char* k[] = {" ","○","●"};
printf("%2d 1 2 3 4 5 6 7 8\n",m_no);
printf(" ┌─┬─┬─┬─┬─┬─┬─┬─┐\n");
for (i=1;i<=8;++i) {
printf("%d",i);
for (j=1;j<=8;++j)
printf("│%s",k[static_cast<int>(m_ban[i][j])]);
printf("│\n");
if (i<8) printf(" ├─┼─┼─┼─┼─┼─┼─┼─┤\n");
else printf(" └─┴─┴─┴─┴─┴─┴─┴─┘\n");
}
}
int COthello::RevLen(int py,int px,int i,int j)const
{
int res = 2;
Stat s = m_ban[py+i][px+j], t = s == Wh ? Bl : Wh;
while (m_ban[py+i*res][px+j*res] == s) ++res;
if (m_ban[py+i*res][px+j*res] != t) return 0;
return res-1;
}
int COthello::CanPut(int py,int px,Stat s)const
{
if (!IsRange(px,py)) return 0;
if (m_ban[py][px] != Sp || s == Sp) return 0;
int i,j,k, res = 0;
Stat t = s == Wh ? Bl : Wh;
for (i=-1;i<=1;++i) for (j=-1;j<=1;++j) {
if (i == 0 && j == 0) continue;
if (m_ban[py+i][px+j] == t && (k = RevLen(py,px,i,j)) > 0)
res += k;
}
return res;
}
bool COthello::CanPut(Stat s)const
{
int i,j;
for (i=1;i<=8;++i) for (j=1;j<=8;++j)
if (CanPut(i,j,s)) return true;
return false;
}
int COthello::Count(Stat s)const
{
int i,j, res = 0;
for (i=1;i<=8;++i) for (j=1;j<=8;++j)
if (m_ban[i][j] == s) ++res;
return res;
}
void COthello::Think(Stat s,int* py,int* px)const
{
static int chk[][8] = {{1,8,2,3,3,2,8,1},{8,9,6,7,7,6,9,8},
{2,6,4,5,5,4,6,2},{3,7,5,0,0,5,7,3},{3,7,5,0,0,5,7,3},
{2,6,4,5,5,4,6,2},{8,9,6,7,7,6,9,8},{1,8,2,3,3,2,8,1}};
int i,j,k,l,i1,j1,mx;
for (k=1;k<=9;++k) {
mx = 0;
for (i=1;i<=8;++i) for (j=1;j<=8;++j) if (chk[i-1][j-1] == k) {
l = CanPut(i,j,s);
if (l > mx) {
mx = l; i1 = i; j1 = j;
}
}
if (mx > 0) {
*py = i1; *px = j1;
break;
}
}
}
void COthello::Put(int py,int px,Stat s)
{
int i,j,k;
Stat t = s == Wh ? Bl : Wh;
if (!CanPut(py,px,s)) return;
m_ban[py][px] = s;
for (i=-1;i<=1;++i) for (j=-1;j<=1;++j) {
if (i == 0 && j == 0) continue;
if (m_ban[py+i][px+j] != t || !(k = RevLen(py,px,i,j)))
continue;
while (m_ban[py+i*k][px+j*k] = s, --k) ;
}
}
void COthello::StartGame()
{
char buf[80];
int i,px,py;
Stat st, dt[] = {Bl,Wh};
if (m_no == 0) {
Reset();
if (SetPlayer()) {
fprintf(stderr,"Can't set player\n");
return;
}
}
Show();
while (true) {
st = dt[m_no%2];
if (m_bComp[m_no%2]) {
Think(st,&py,&px);
} else {
printf("%s 縦横 or S(ave) or Q(uit) ? ",m_no%2 ? "○" : "●");
fgets(buf,sizeof(buf),stdin);
if (*buf == 'Q') return;
if (*buf == 'S') {
while (true) {
printf("file name ? ");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
if (!SaveFile(buf)) break;
}
return;
}
if (sscanf(buf,"%1d%1d",&py,&px) != 2) continue;
if (!CanPut(py,px,st)) continue;
}
++m_no;
Put(py,px,st);
Show();
if (m_no == 60) {
i = Count(st);
if (i == 32) printf("Draw.\n");
else printf("Player %d win!\n",(i<32?m_no:m_no+1)%2 + 1);
break;
} else if (!CanPut(dt[m_no%2])) {
printf("Player %d win!\n",2-m_no%2);
break;
}
}
}
int main(int argc,char** argv)
{
COthello c;
if (argc > 1) c.LoadFile(argv[1]);
c.StartGame();
}
|
#include <cstring>
#include <cstdio>
#include <conio.h>
class COthello {
public:
enum Stat {Sp = 0, Wh = 1, Bl = 2};
enum Dir {DirUp,DirLeft,DirRight,DirDown};
private:
int m_no; // 何手目か
Stat m_ban[10][10]; // 盤の状態
bool m_bComp[2]; // プレイヤーがコンピュータかどうか
int m_y,m_x; // プロンプト
// py,px から i,j 方向の長さ
int RevLen(int py,int px,int i,int j)const;
static bool IsRange(int py,int px)
{return py >= 1 && py <= 8 && px >= 1 && px <= 8;}
public:
void Reset();
COthello(){Reset();}
int SaveFile(const char* nam)const;
int LoadFile(const char* nam);
int SetPlayer();
void Show()const;
int CanPut(int py,int px,Stat s)const;
bool CanPut(Stat s)const;
int Count(Stat s)const;
void Think(Stat s,int* py,int* px)const;
void Put(int py,int px,Stat s);
void StartGame();
void PromptMove(Dir d,Stat s);
};
void COthello::Reset()
{
int i,j;
for (i=0;i<10;++i) for (j=0;j<10;++j)
m_ban[i][j] = Sp;
m_ban[4][4] = m_ban[5][5] = Wh;
m_ban[5][4] = m_ban[4][5] = Bl;
m_bComp[0] = m_bComp[1] = false;
m_no = 0;
m_y = m_x = 0;
}
int COthello::SaveFile(const char* nam)const
{
FILE* f = fopen(nam,"w");
if (!f) return 1;
fprintf(f,"%d %d %d\n",m_no,m_bComp[0]?1:0,m_bComp[1]?1:0);
int i,j;
for (i=1;i<=8;++i) {
for (j=1;j<=8;++j)
fprintf(f," %d",static_cast<int>(m_ban[i][j]));
fprintf(f,"\n");
}
fclose(f);
return 0;
}
int COthello::LoadFile(const char* nam)
{
FILE* f = fopen(nam,"r");
if (!f) return 1;
char buf[80];
int i,j,k;
fgets(buf,sizeof(buf),f);
sscanf(buf,"%d %d %d",&m_no,&i,&j);
m_bComp[0] = i != 0;
m_bComp[1] = j != 0;
for (i=1;i<=8;++i) {
for (j=1;j<=8;++j) {
fscanf(f,"%d",&k);
m_ban[i][j] = static_cast<Stat>(k);
}
}
fclose(f);
return 0;
}
int COthello::SetPlayer()
{
char buf[80];
do {
printf("Is 1st Player comp ? (y/n) ");
if (!fgets(buf,sizeof(buf),stdin)) return 1;
} while (*buf != 'y' && *buf != 'n');
m_bComp[0] = *buf == 'y';
do {
printf("Is 2nd Player comp ? (y/n) ");
if (!fgets(buf,sizeof(buf),stdin)) return 1;
} while (*buf != 'y' && *buf != 'n');
m_bComp[1] = *buf == 'y';
return 0;
}
void COthello::Show()const
{
int i,j;
char* k[] = {" ","○","●"};
printf("\033[H\033[J%2d 1 2 3 4 5 6 7 8 \n",m_no);
printf(" ┌─┬─┬─┬─┬─┬─┬─┬─┐\n");
for (i=1;i<=8;++i) {
printf("%d",i);
for (j=1;j<=8;++j) {
if (m_y == i && m_x == j && m_ban[i][j] == Sp)
printf("│◎");
else printf("│%s",k[static_cast<int>(m_ban[i][j])]);
}
printf("│\n");
if (i<8) printf(" ├─┼─┼─┼─┼─┼─┼─┼─┤\n");
else printf(" └─┴─┴─┴─┴─┴─┴─┴─┘\n");
}
printf("矢印で移動、スペースで決定\n");
}
int COthello::RevLen(int py,int px,int i,int j)const
{
int res = 2;
Stat s = m_ban[py+i][px+j], t = s == Wh ? Bl : Wh;
while (m_ban[py+i*res][px+j*res] == s) ++res;
if (m_ban[py+i*res][px+j*res] != t) return 0;
return res-1;
}
int COthello::CanPut(int py,int px,Stat s)const
{
if (!IsRange(px,py)) return 0;
if (m_ban[py][px] != Sp || s == Sp) return 0;
int i,j,k, res = 0;
Stat t = s == Wh ? Bl : Wh;
for (i=-1;i<=1;++i) for (j=-1;j<=1;++j) {
if (i == 0 && j == 0) continue;
if (m_ban[py+i][px+j] == t && (k = RevLen(py,px,i,j)) > 0)
res += k;
}
return res;
}
bool COthello::CanPut(Stat s)const
{
int i,j;
for (i=1;i<=8;++i) for (j=1;j<=8;++j)
if (CanPut(i,j,s)) return true;
return false;
}
int COthello::Count(Stat s)const
{
int i,j, res = 0;
for (i=1;i<=8;++i) for (j=1;j<=8;++j)
if (m_ban[i][j] == s) ++res;
return res;
}
void COthello::Think(Stat s,int* py,int* px)const
{
int i,j,l,i1,j1,mx;
mx = 0;
for (i=1;i<=8;++i) for (j=1;j<=8;++j) {
l = CanPut(i,j,s);
if (l > mx) {
mx = l; i1 = i; j1 = j;
}
}
*py = i1; *px = j1;
}
void COthello::Put(int py,int px,Stat s)
{
int i,j,k;
Stat t = s == Wh ? Bl : Wh;
if (!CanPut(py,px,s)) return;
m_ban[py][px] = s;
for (i=-1;i<=1;++i) for (j=-1;j<=1;++j) {
if (i == 0 && j == 0) continue;
if (m_ban[py+i][px+j] != t || !(k = RevLen(py,px,i,j)))
continue;
while (m_ban[py+i*k][px+j*k] = s, --k) ;
}
}
void COthello::StartGame()
{
int i,px,py;
Stat st, dt[] = {Bl,Wh};
if (m_no == 0) {
Reset();
if (SetPlayer()) {
fprintf(stderr,"Can't set player\n");
return;
}
}
while (true) {
st = dt[m_no%2];
if (m_bComp[m_no%2]) {
Think(st,&py,&px);
} else {
m_y = m_x = 1; PromptMove(DirDown,st);
while (true) {
Show();
i = getch();
if (i == 'Q') return;
if (i == 'S') {
SaveFile("a.txt");
printf("Save a.txt\n");
return;
}
if (i == ' ') {
py = m_y;
px = m_x;
break;
}
if (i == 0xE0) {
i = getch();
switch (i) {
case 'H': PromptMove(DirUp,st); break;
case 'K': PromptMove(DirLeft,st); break;
case 'M': PromptMove(DirRight,st); break;
case 'P': PromptMove(DirDown,st); break;
}
}
}
}
++m_no;
Put(py,px,st);
m_y = m_x = 0;
if (m_no == 60) {
Show();
i = Count(st);
if (i == 32) printf("Draw.\n");
else printf("Player %d win!\n",(i<32?m_no:m_no+1)%2 + 1);
break;
} else if (!CanPut(dt[m_no%2])) {
Show();
printf("Player %d win!\n",2-m_no%2);
break;
}
}
}
void COthello::PromptMove(Dir d,Stat s)
{
int dir[][4] = {{0,-1,-1,8},{-1,0,8,-1},{1,0,-8,1},{0,1,1,-8}};
int i,j, k = static_cast<int>(d), *dr = dir[k];
i = m_y; j = m_x;
while (true) {
i += dr[0];
j += dr[1];
if (!IsRange(i,j)) {
i += dr[2];
j += dr[3];
}
if (!IsRange(i,j)) break;
if (CanPut(i,j,s)) {
m_y = i; m_x = j;
break;
}
}
}
int main(int argc,char** argv)
{
COthello c;
if (argc > 1) c.LoadFile(argv[1]);
c.StartGame();
}
|