マルチプルインスタンス。


部品として再利用し易いゲームアルゴリズムを書いてみるテスト。
ただの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;
	
}

//---------------------------------------------------------------------------------