部品として再利用し易いゲームアルゴリズムを書いてみるテスト。
ただの15パズルなんですが。
プログラマに対する動的な操作を許容して、
且つモジュール内部は隠蔽しつつ、関数・変数間のやり取りを無理なく記述するには
マルチプルインスタンスの概念を用いるのが無難だという結論に。
15パズルごときといえばそのとおりですが。
ゲーム盤面をプログラム中に可変出来るようにしたとき
こうする方が無理ないコードで書けると思えたのです。
THE 15 PUZZLE
Sbp (Sliding Block Puzzle) module test
main.c
/*--------------------------------------------------------------------------------- THE 15 PUZZLE Sbp (Sliding Block Puzzle) module test version 0.01 May 03, 2010 By REGEKATSU ---------------------------------------------------------------------------------*/ #include <stdio.h> #include <time.h> #include <nds.h> #include "Sbp.h" #define SHUFFLE_NUM 100 #define PIECE_X 4 #define PIECE_Y 4 void showPanel(SbpObject sbp_obj); //--------------------------------------------------------------------------------- int main(void) { //--------------------------------------------------------------------------------- SbpObject sbp; consoleDemoInit(); printf("THE 15 PUZZLE\nSbp (Sliding Block Puzzle)\n module test\n\nversion 0.01\nMay 03, 2010\n\nBy REGEKATSU"); sbp = Sbp_CreatePanel(PIECE_X, PIECE_Y); Sbp_MoveShuffle(sbp, time(NULL), SHUFFLE_NUM); while(1){ swiWaitForVBlank(); scanKeys(); showPanel(sbp); if(keysDown() & KEY_LEFT){ Sbp_MoveLeft(sbp); }else if(keysDown() & KEY_RIGHT){ Sbp_MoveRight(sbp); }else if(keysDown() & KEY_UP){ Sbp_MoveUp(sbp); }else if(keysDown() & KEY_DOWN){ Sbp_MoveDown(sbp); } if(Sbp_IsClear(sbp)){ showPanel(sbp); printf("\x01b[17;0H...CLEAR!..."); Sbp_DeletePanel(sbp); return 0; } } } //--------------------------------------------------------------------------------- void showPanel(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- int x, y; printf("\x01b[10;0H"); for(y = 0;y < PIECE_Y;y++){ for(x = 0;x < PIECE_X;x++){ if(Sbp_GetPieceValue(sbp_obj, x, y) == Sbp_GetPieceBlank(sbp_obj)){ printf(" "); }else{ printf("%2X", Sbp_GetPieceValue(sbp_obj, x, y)); } } printf("\n"); } } //---------------------------------------------------------------------------------
Sbp.h
/*--------------------------------------------------------------------------------- Sbp (Sliding Block Puzzle) module header version 0.01 May 03, 2010 By REGEKATSU ---------------------------------------------------------------------------------*/ #ifndef _SBP_H_ #define _SBP_H_ typedef void *SbpObject; #ifdef __cplusplus extern "C" { #endif SbpObject Sbp_CreatePanel(int piece_x, int piece_y); void Sbp_DeletePanel(SbpObject sbp_obj); bool Sbp_IsClear(SbpObject sbp_obj); int Sbp_GetPieceValue(SbpObject sbp_obj, int piece_x, int piece_y); int Sbp_GetPieceBlank(SbpObject sbp_obj); void Sbp_SetPieceBlank(SbpObject sbp_obj, int piece_blank); void Sbp_MoveShuffle(SbpObject sbp_obj, int seed, int shuffle_num); int Sbp_MoveLeft(SbpObject sbp_obj); int Sbp_MoveRight(SbpObject sbp_obj); int Sbp_MoveUp(SbpObject sbp_obj); int Sbp_MoveDown(SbpObject sbp_obj); int Sbp_GetMoveA(SbpObject sbp_obj); int Sbp_GetMoveB(SbpObject sbp_obj); #ifdef __cplusplus } #endif #endif // _SBP_H_
Sbp.c
/*--------------------------------------------------------------------------------- Sbp (Sliding Block Puzzle) module routine version 0.01 May 03, 2010 By REGEKATSU ---------------------------------------------------------------------------------*/ #include <stdlib.h> #include <nds/ndstypes.h> #include "Sbp.h" typedef struct{ int *panel; int piece_x; int piece_y; int piece_max; int piece_blank; int piece_a; int piece_b; }Sbp, *ISbp; void sbp_SwapPiece(int *a, int *b); //--------------------------------------------------------------------------------- SbpObject Sbp_CreatePanel(int piece_x, int piece_y) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = malloc(sizeof(Sbp)); sbp->piece_x = (piece_x <= 0) ? 1 : piece_x; sbp->piece_y = (piece_x <= 0) ? 1 : piece_y; sbp->piece_max = sbp->piece_x * sbp->piece_y; sbp->piece_blank = sbp->piece_max - 1; sbp->panel = malloc(sizeof(int) * sbp->piece_max); if(sbp->panel == NULL) exit(0); int i; for(i = 0;i < sbp->piece_max;i++){ sbp->panel[i] = i; } return (SbpObject)sbp; } //--------------------------------------------------------------------------------- void Sbp_DeletePanel(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; free(sbp->panel); free(sbp_obj); } //--------------------------------------------------------------------------------- bool Sbp_IsClear(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; int i; for(i = 0;i < sbp->piece_max;i++){ if(sbp->panel[i] != i) return false; } return true; } //--------------------------------------------------------------------------------- int Sbp_GetPieceValue(SbpObject sbp_obj, int piece_x, int piece_y) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; if( (piece_x < 0 || piece_x > sbp->piece_x) || (piece_y < 0 || piece_y > sbp->piece_y) ) return -1; return sbp->panel[ piece_x + (sbp->piece_x * piece_y) ]; } //--------------------------------------------------------------------------------- int Sbp_GetPieceBlank(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; return sbp->piece_blank; } //--------------------------------------------------------------------------------- void Sbp_SetPieceBlank(SbpObject sbp_obj, int piece_blank) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; if(piece_blank < 0 || piece_blank >= sbp->piece_max) return; sbp->piece_blank = piece_blank; } //--------------------------------------------------------------------------------- void Sbp_MoveShuffle(SbpObject sbp_obj, int seed, int shuffle_num) { //--------------------------------------------------------------------------------- int i, rnd; srand(seed); for(i = 0;i < shuffle_num;i++){ rnd = rand() % 4; switch(rnd){ case 0: Sbp_MoveLeft(sbp_obj); break; case 1: Sbp_MoveRight(sbp_obj); break; case 2: Sbp_MoveUp(sbp_obj); break; case 3: Sbp_MoveDown(sbp_obj); break; } } } //--------------------------------------------------------------------------------- int Sbp_MoveLeft(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; int y; for(y = 0;y < sbp->piece_y;y++){ if( sbp->panel[ sbp->piece_x * y + sbp->piece_x - 1 ] == sbp->piece_blank){ return sbp->piece_a = sbp->piece_b = 0; } } int i; for(i = 0;i < sbp->piece_max;i++){ if(sbp->panel[i] == sbp->piece_blank) break; } sbp->piece_a = i; sbp->piece_b = i + 1; sbp_SwapPiece(&sbp->panel[sbp->piece_a], &sbp->panel[sbp->piece_b]); return 1; } //--------------------------------------------------------------------------------- int Sbp_MoveRight(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; int y; for(y = 0;y < sbp->piece_y;y++){ if( sbp->panel[ sbp->piece_x * y ] == sbp->piece_blank){ return sbp->piece_a = sbp->piece_b = 0; } } int i; for(i = 0;i < sbp->piece_max;i++){ if(sbp->panel[i] == sbp->piece_blank) break; } sbp->piece_a = i - 1; sbp->piece_b = i; sbp_SwapPiece(&sbp->panel[sbp->piece_a], &sbp->panel[sbp->piece_b]); return 1; } //--------------------------------------------------------------------------------- int Sbp_MoveUp(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; int x; for(x = 0;x < sbp->piece_x;x++){ if( sbp->panel[ sbp->piece_x * (sbp->piece_y - 1) + x ] == sbp->piece_blank){ return sbp->piece_a = sbp->piece_b = 0; } } int i; for(i = 0;i < sbp->piece_max;i++){ if(sbp->panel[i] == sbp->piece_blank) break; } sbp->piece_a = i; sbp->piece_b = i + sbp->piece_x; sbp_SwapPiece(&sbp->panel[sbp->piece_a], &sbp->panel[sbp->piece_b]); return 1; } //--------------------------------------------------------------------------------- int Sbp_MoveDown(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; int x; for(x = 0;x < sbp->piece_x;x++){ if( sbp->panel[x] == sbp->piece_blank){ return sbp->piece_a = sbp->piece_b = 0; } } int i; for(i = 0;i < sbp->piece_max;i++){ if(sbp->panel[i] == sbp->piece_blank) break; } sbp->piece_a = i - sbp->piece_x; sbp->piece_b = i; sbp_SwapPiece(&sbp->panel[sbp->piece_a], &sbp->panel[sbp->piece_b]); return 1; } //--------------------------------------------------------------------------------- int Sbp_GetMoveA(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; return sbp->piece_a; } //--------------------------------------------------------------------------------- int Sbp_GetMoveB(SbpObject sbp_obj) { //--------------------------------------------------------------------------------- ISbp sbp; sbp = (ISbp)sbp_obj; return sbp->piece_b; } //--------------------------------------------------------------------------------- void sbp_SwapPiece(int *a, int *b) { //--------------------------------------------------------------------------------- int temp; temp = *a; *a = *b; *b = temp; } //---------------------------------------------------------------------------------