関数版(ptr_castF) とクラス版(ptr_castC) を作った。 関数版のテンプレート引数は2つあるが、使う時は1つしか指定していない。 VC++ では動くが、どうなのだろう?
#include <iostream> using namespace std; template <typename T,typename U> T ptr_castF(U u) { T t = dynamic_cast<T>(u); if (!t) throw bad_cast(); return t; } template <typename T> class ptr_castC { T t; public: template <typename U> ptr_castC(U u) : t(dynamic_cast<T>(u)) {} operator T(){if (!t) throw bad_cast(); return t;} }; struct Base {virtual ~Base(){}}; struct Derived : Base {}; struct Bad {}; int main() { Derived d; Base* p0 = &d; Derived* p1 = ptr_castF<Derived*>(p0); try { Bad* p2 = ptr_castF<Bad*>(p0); } catch (bad_cast) { cout << "err F\n"; } Derived* p3 = ptr_castC<Derived*>(p0); try { Bad* p4 = ptr_castC<Bad*>(p0); } catch (bad_cast) { cout << "err C\n"; } } |
#include <iostream> using namespace std; struct Base { Base(){cout << "In Base cons : " << typeid(*this).name() << endl;} virtual ~Base(){cout << "In Base dest : " << typeid(*this).name() << endl;} void f(){cout << "In f : " << typeid(*this).name() << endl;} }; struct Middle : Base { Middle(){cout << "In Middle cons : " << typeid(*this).name() << endl;} ~Middle(){cout << "In Middle dest : " << typeid(*this).name() << endl;} void g(){cout << "In g : " << typeid(*this).name() << endl;} }; struct Low : Middle { Low(){cout << "In Low cons : " << typeid(*this).name() << endl;} ~Low(){cout << "In Low dest : " << typeid(*this).name() << endl;} void h(){cout << "In h : " << typeid(*this).name() << endl;} }; int main() { Low l; l.f(); l.g(); l.h(); } |
#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(); } |