//ナンプレパズル スクリーン制御版 API使用 #include "stdafx.h" #include "stdlib.h" #include "conio.h" #include "time.h" #include "console.h" HANDLE g_h; int curX; int curY; int tb[9][9],ansTb[9][9],Q[9][9]; int multiCheck=0;int numAns=0; char WCH[][5]={"0","1","2","3","4","5","6","7","8","9"}; int rand9(){/*1から9の乱数*/ return (int)(((double)rand()/(RAND_MAX+1))*9+1); } int checkRand9(int ist,int jst, int R){ /*同じ数字がブロック中にないかを判定*/ for(int i=0; i<3;i ++)for(int j=0;j<3; j++)if(tb[i+ist][j+ist]==R) return R; return 0; } void setRand9(int ist,int jst){/*ブロックに数字を設定*/ for(int i=0; i<3;i ++)for(int j=0;j<3; j++){ int R; do R=rand9(); while(checkRand9(ist,ist, R)!=0); tb[ist+i][jst+j]=R; } } void initTb(){/*判定用テーブルにブロック単位の数字を設定*/ for(int i=0;i<9;i++ ) for(int j=0;j<9;j++) tb[i][j]=0; for(int i=0;i<9;i+=3) setRand9(i,i); } void printQ(){/*問題の表示*/ clearConsole(g_h);setCursorPosition(g_h,0,1);setColor(g_h,H_YELLOW,L_BLACK); printf("\n "); for(int i=1;i<10;i++) printf("%4d",i); for(int i=0;i<9;i++){ if ( i==0 ) printf("\n ┏━┯━┯━┳━┯━┯━┳━┯━┯━┓"); else if((i % 3)==0) printf("\n ┣━┿━┿━╋━┿━┿━╋━┿━┿━┫"); else printf("\n ┠─┼─┼─╂─┼─┼─╂─┼─┼─┨"); printf("\n %d ",i+1); for(int j=0;j<9;j++){ if((j % 3)==0) printf("┃"); else printf("│"); if(Q[i][j]==0) printf(" "); else { if(tb[i][j]==0) setColor(g_h,H_WHITE ,L_BLACK); else setColor(g_h,H_YELLOW,L_BLACK); printf("%s",WCH[Q[i][j]]); } } printf("┃"); } printf("\n ┗━┷━┷━┻━┷━┷━┻━┷━┷━┛"); } int numPre(); // 空白マスの試行関数のプロトタイプ宣言 int checkNumPre(int ix, int iy){ // ナンプレ条件判定関数 int kx=(ix / 3) * 3, ky=(iy / 3)*3, x=tb[ix][iy]; for(int i=0; i<3;i++) { for(int j=0; j<3; j++) if(((kx+i)!=ix ||(ky+j) !=iy) && (tb[kx+i][ky+j] == x)) return 0; } for(int i=0; i<9; i++) if((ix !=i) && (x == tb[i] [iy])) return 0; for(int i=0; i<9; i++) if((iy !=i) && (x == tb[ix][i] )) return 0; return numPre(); } int numPre(){ /*空白マスの試行関数*/ for(int i=0; i<9; i++)for(int j=0; j<9; j++){ if(tb[i][j]==0){ for(int k=1; k<10; k++){ tb[i][j]=k;if(checkNumPre(i,j)) return 1; } tb[i][j]=0; return 0; } } numAns++; /* 複数解チェックかつ解の個数 = 1 */ if(multiCheck && numAns==1) return 0; /* のとき,再試行 ( 失敗とみなす) */ return 1; /* 単一解 / 個数=2のとき終了(成功) */ } void copyAnsTb(){/* 判定用領域を解答領域に移す*/ for(int i=0;i<9;i++)for(int j=0;j<9;j++) ansTb[i][j]=tb[i][j]; } void copyfromQ(){/* 問題用領域を判定用領域に移す*/ for(int i=0;i<9;i++)for(int j=0;j<9;j++) tb[i][j]=Q[i][j]; } void clearQ(){ /* 問題用領域のクリア*/ for(int i=0;i<9;i++)for(int j=0; j<9; j++) tb[i][j]=0; } void genQ(int N){ // ランダムな位置のN個の値を解答領域から問題領域に移す int ix, iy; // これが問題生成となる for(int k=0; k < N; k++){ do{ ix = rand9(); iy = rand9();} while(Q[ix-1][iy-1] !=0); Q[ix-1][iy-1]=ansTb[ix-1][iy-1]; } } int makeTb(int NumRest){ /* ナンプレパズルの生成 */ initTb(); multiCheck=0;numAns=0;int R=numPre(); int N = NumRest; copyAnsTb(); clearQ(); do{ /*生成した問題に複数解があれば再生成*/ genQ(N); copyfromQ(); multiCheck=1; numAns=0; int R=numPre(); printQ(); if(numAns==1) return 0; printf("\n複数解があります。残す場所を何個増やしますか?"); scanf("%d",&N); } while(N !=0); for(int i=0;i<9;i++)for(int j=0;j<9;j++) tb[i][j]=Q[i][j]; return 0; } int notEnd(){ /*ゲーム終了でないかを判定*/ for(int i=0;i<9;i++) for(int j=0;j<9;j++) if(Q[i][j]==0) return 1; return 0; } void inDT(int *i, int *j, int *V){ int C; *V = 0; do{ setCursorPosition(g_h, 0,0); setColor(g_h,H_WHITE, H_BLUE); printf("\nマスの位置をカーソルで,値を数字で指定してください."); int Y=curY*2+4;int X=curX*4+5; setCursorPosition(g_h, X, Y); setColor(g_h,H_WHITE, H_RED); if(Q[curY][curX]==0) printf(" "); else printf("%s", WCH[Q[curY][curX]]); C=getch(); if(C==0xE0){ C=getch(); if(C>='1' && C<='9') *V= C - '0'; else{ setCursorPosition(g_h, X, Y); if(tb[curY][curX]==0) setColor(g_h,H_WHITE , L_BLACK);//入力した数字のとき白色 else setColor(g_h,H_YELLOW, L_BLACK);//元々の数字のとき黄色 if(Q[curY][curX]==0) printf(" "); else printf("%s",WCH[Q[curY][curX]]); if (C==0x48) {if(curY> 0) curY--;} // ↑ else if(C==0x50) {if(curY< 8) curY++;} // ↓ else if(C==0x4b) {if(curX> 0) curX--;} // ← else if(C==0x4d) {if(curX< 8) curX++;} // → } } else if(C>='1' && C<='9') *V= C - '0'; setColor(g_h,H_WHITE, L_BLACK); } while(*V<1 || *V>9); *i=curY; *j=curX; if(Q[curY][curX]!=0){ setColor(g_h,H_WHITE, L_BLACK);setCursorPosition(g_h, 0, 22); g_h, printf("\nそこは指定できません"); } } int _tmain(int argc, _TCHAR* argv[]) { int N,C; g_h=getOutConsole(); setCursorInfo(g_h,100,false); curX=0; curY=0; srand((short) time(NULL)); printf("\n表示するマスの数="); scanf("%d",&N); makeTb(N); printQ(); while(notEnd()){ int i, j, V; do{ do inDT(&i, &j, &V); while(Q[i][j]!=0); setColor(g_h,H_YELLOW, L_BLACK);setCursorPosition(g_h, 0, 22); if(V != ansTb[i][j]) printf("\n **不正解です** "); else printf("\n "); } while(V != ansTb[i][j]); Q[i][j]=V; //printQ(); //printf("\n表示するマスの数="); } printQ(); setColor(g_h,H_WHITE, L_BLACK);setCursorPosition(g_h, 0, 22); printf("\n 終了しました"); getchar();getchar(); return 0; }