「マインスイーパ」ver0.10


遊べるとこまで書けたのでソース公開です。
時間計測が無い以外は大体実現できるようになってます。
周辺地雷 0 なら 1 以上が見つかるまでセルを開いてく動作とか、初回に開いた時の地雷補正とか。



MineSweeper.h

/*---------------------------------------------------------------------------------
	
	MineSweeper class header
	
	version 0.10
	Apr 08, 2013
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _MINE_SWEEPER_H_
#define _MINE_SWEEPER_H_


//NULL 値、bool 型の定義。
#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

#ifndef bool
#define bool unsigned char
#endif

#ifndef true
#define true 1
#endif

#ifndef false
#define false 0
#endif


//セルマーカの状態定数。
typedef enum {
	MARKER_NON = 0, 
	MARKER_FLAG, 
	MARKER_QUESTION, 
	MARKER_MAX
} MARKER;

//オブジェクト(構造体ポインタ)の定義。
typedef struct _MineSweeper* MineSweeper;


#ifdef __cplusplus
extern "C" {
#endif


//マインスイーパオブジェクトを生成します。
MineSweeper MineSweeperCreate(int width, int height, int mines, int seed);
//マインスイーパオブジェクトを破棄します。
MineSweeper MineSweeperDestroy(MineSweeper mineSweeper);

//適当なセルに指定した数だけ地雷を設置します。
void MineSweeperSetMinesRandom(MineSweeper mineSweeper, int mines);
//適当なセルに地雷を設置します。成功したら 1 を、そうでなければ 0 を返します。
int MineSweeperSetMineRandom(MineSweeper mineSweeper);
//指定したセルに地雷を設置します。成功したら 1 を、そうでなければ 0 を返します。
int MineSweeperSetMine(MineSweeper mineSweeper, int x, int y);
//指定したセルの地雷を除去します。成功したら 1 を、そうでなければ 0 を返します。
int MineSweeperRemoveMine(MineSweeper mineSweeper, int x, int y);

//指定されたセル周辺の地雷数を取得します。
int MineSweeperGetAroundMines(MineSweeper mineSweeper, int x, int y);
//全てのセル周辺の地雷数を設定します。
void MineSweeperSetAroundMinesAll(MineSweeper mineSweeper);
//指定されたセル周辺の地雷数を設定します。
void MineSweeperSetAroundMines(MineSweeper mineSweeper, int x, int y);

//地雷原の幅を取得します。
int MineSweeperGetWidth(MineSweeper mineSweeper);
//地雷原の高さを取得します。
int MineSweeperGetHeight(MineSweeper mineSweeper);

//現存する地雷数を取得します。
int MineSweeperGetMines(MineSweeper mineSweeper);
//現在の旗数を取得します。
int MineSweeperGetFlags(MineSweeper mineSweeper);

//地雷除去に成功したかどうか調べます。成功したら true を、そうでなければ false を返します。
bool MineSweeperIsSuccess(MineSweeper mineSweeper);
//地雷除去に失敗したかどうか調べます。失敗したら true を、そうでなければ false を返します。
bool MineSweeperIsFailure(MineSweeper mineSweeper);

//開いてるセルの数を取得します。
int MineSweeperGetOpenCount(MineSweeper mineSweeper);
//指定したセルが開いてるか調べます。開いていれば true を、閉じていれば false を返します。
bool MineSweeperIsOpen(MineSweeper mineSweeper, int x, int y);
//指定されたセルを中心に、周囲に地雷が見つかるまで開きます。まだ開かれてなかったなら 1 を、既に開かれてたら 0 を返します。
int MineSweeperSetOpenAround(MineSweeper mineSweeper, int x, int y);
//指定されたセルを開きます。成功したら 1 を、そうでなければ 0 を返します。
int MineSweeperSetOpen(MineSweeper mineSeeper, int x, int y);

//地雷が設置されたセルが開いてるか調べます。開いていれば true を、閉じていれば false を返します。
bool MineSweeperIsOpenMine(MineSweeper mineSweeper);
//指定したセルに地雷が設置されてるか調べます。設置されてたら true を、そうでなければ false を返します。
bool MineSweeperIsMine(MineSweeper mineSweeper, int x, int y);

//指定されたセルのマーカを取得します。
int MineSweeperGetMarker(MineSweeper mineSweeper, int x, int y);
//指定されたセルにマーカを付けます。但し既に開かれてたら何もしません。
void MineSweeperSetMarker(MineSweeper mineSweeper, int x, int y, int marker);


#ifdef __cplusplus
}
#endif

#endif	// _MINE_SWEEPER_H_


MineSweeper.c

/*---------------------------------------------------------------------------------
	
	MineSweeper class routine
	
	version 0.10
	Apr 08, 2013
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "MineSweeper.h"


//値が指定した下限値より小さければ、指定下限値に丸めます。
#define FIX_MIN(SET_VAL,SET_DEF) (((SET_VAL)>(SET_DEF))?(SET_VAL):(SET_DEF))
//値が指定した上限値より大きければ、指定上限値に丸めます。
#define FIX_MAX(SET_VAL,SET_DEF) (((SET_VAL)>(SET_DEF))?(SET_DEF):(SET_VAL))


//地雷原の定義。
typedef struct {
	//セル開閉の状態
	bool isOpen;
	//セルマーカーの状態(なし、旗、?マーク)。
	int marker;
	//セル直下の地雷有無。
	bool isMine;
	//セル周辺の地雷数。
	int aroundMines;
} Field;

//オブジェクト(構造体実態)の定義。
typedef struct _MineSweeper {
	
	//地雷原領域。
	Field* field;
	//地雷原の幅。
	int width;
	//地雷原の高さ。
	int height;
	
	//地雷数。
	int mines;
	//旗数。
	int flags;
	
} _MineSweeper;


//---------------------------------------------------------------------------------
//マインスイーパオブジェクトを生成します。
//---------------------------------------------------------------------------------
MineSweeper MineSweeperCreate(int width, int height, int mines, int seed) {
//---------------------------------------------------------------------------------
	
	MineSweeper mineSweeper;
	
	assert(width > 0 && height > 0 && mines >= 0);
	
	//オブジェクト領域(構造体ポインタ)を確保、初期化する。
	mineSweeper = (MineSweeper)malloc(sizeof(_MineSweeper));
	memset(mineSweeper, 0, sizeof(_MineSweeper));
	
	//幅、高さ、を設定する。
	mineSweeper->width = width;
	mineSweeper->height = height;
	
	//地雷原領域を確保、初期化する。
	mineSweeper->field = malloc(sizeof(Field) * (mineSweeper->width * mineSweeper->height));
	memset(mineSweeper->field, 0, sizeof(Field) * (mineSweeper->width * mineSweeper->height));
	
	//指定されたシード値で乱数を初期化して、地雷を設置する。
	srand(seed);
	MineSweeperSetMinesRandom(mineSweeper, mines);
	
	//オブジェクト領域を返す。
	return mineSweeper;
	
}

//---------------------------------------------------------------------------------
//マインスイーパオブジェクトを破棄します。
//---------------------------------------------------------------------------------
MineSweeper MineSweeperDestroy(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	
	//地雷原領域、オブジェクト領域(構造体ポインタ)を開放する。
	free(mineSweeper->field);
	free(mineSweeper);
	
	//NULL ポインタを返す。
	return NULL;
	
}

//---------------------------------------------------------------------------------
//適当なセルに指定した数だけ地雷を設置します。
//---------------------------------------------------------------------------------
void MineSweeperSetMinesRandom(MineSweeper mineSweeper, int mines) {
//---------------------------------------------------------------------------------
	
	int count;
	
	assert(mineSweeper != NULL);
	assert(mines >= 0);
	
	//指定された数だけ地雷を設置し終えるまで繰り返す。
	count = 0;
	while(count < mines) {
		count += MineSweeperSetMineRandom(mineSweeper);
	}
	
}

//---------------------------------------------------------------------------------
//適当なセルに地雷を設置します。成功したら 1 を、そうでなければ 0 を返します。
//---------------------------------------------------------------------------------
int MineSweeperSetMineRandom(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	
	return MineSweeperSetMine(mineSweeper, rand() % mineSweeper->width, rand() % mineSweeper->height);
	
}

//---------------------------------------------------------------------------------
//指定したセルに地雷を設置します。成功したら 1 を、そうでなければ 0 を返します。
//---------------------------------------------------------------------------------
int MineSweeperSetMine(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	//セルが既に開かれてたら何もしない。
	if(mineSweeper->field[x + mineSweeper->width * y].isOpen == true) {
		return 0;
	}
	
	//指定先に地雷が未設置なら、設置して 1 を返す。
	if(mineSweeper->field[x + mineSweeper->width * y].isMine == false) {
		mineSweeper->field[x + mineSweeper->width * y].isMine = true;
		//地雷数、旗数を 1 増やして、地雷原全域の周辺地雷数も設定する。
		mineSweeper->mines++;
		mineSweeper->flags++;
		MineSweeperSetAroundMinesAll(mineSweeper);
		return 1;
	}
	//指定先に地雷が設置済みなら 0 を返す。
	return 0;
	
}

//---------------------------------------------------------------------------------
//指定したセルの地雷を除去します。成功したら 1 を、そうでなければ 0 を返します。
//---------------------------------------------------------------------------------
int MineSweeperRemoveMine(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	//セルが既に開かれてたら何もしない。
	if(mineSweeper->field[x + mineSweeper->width * y].isOpen == true) {
		return 0;
	}
	
	//指定先に地雷が設置されてれば、除去して 1 を返す。
	if(mineSweeper->field[x + mineSweeper->width * y].isMine == true) {
		mineSweeper->field[x + mineSweeper->width * y].isMine = false;
		//地雷数、旗数を 1 減らして、地雷原全域の周辺地雷数も設定する。
		mineSweeper->mines--;
		mineSweeper->flags--;
		MineSweeperSetAroundMinesAll(mineSweeper);
		return 1;
	}
	//指定先に地雷が無ければ 0 を返す。
	return 0;
	
}

//---------------------------------------------------------------------------------
//指定されたセル周辺の地雷数を取得します。
//---------------------------------------------------------------------------------
int MineSweeperGetAroundMines(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	return mineSweeper->field[x + mineSweeper->width * y].aroundMines;
	
}

//---------------------------------------------------------------------------------
//全てのセル周辺の地雷数を設定します。
//---------------------------------------------------------------------------------
void MineSweeperSetAroundMinesAll(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	int x;
	int y;
	
	assert(mineSweeper != NULL);
	
	for(y = 0;y < mineSweeper->height;y++) {
		for(x = 0;x < mineSweeper->width;x++) {
			MineSweeperSetAroundMines(mineSweeper, x, y);
		}
	}
	
}

//---------------------------------------------------------------------------------
//指定されたセル周辺の地雷数を設定します。
//---------------------------------------------------------------------------------
void MineSweeperSetAroundMines(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	int thisX;
	int thisY;
	int aroundMines;
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	aroundMines = 0;
	
	for(thisY = FIX_MIN(y - 1, 0);thisY <= FIX_MAX(y + 1, mineSweeper->height - 1);thisY++) {
		for(thisX = FIX_MIN(x - 1, 0);thisX <= FIX_MAX(x + 1, mineSweeper->width - 1);thisX++) {
			aroundMines += (MineSweeperIsMine(mineSweeper, thisX, thisY) == true) ? 1:0;
		}
	}
	
	mineSweeper->field[x + mineSweeper->width * y].aroundMines = aroundMines;
	
}

//---------------------------------------------------------------------------------
//地雷原の幅を取得します。
//---------------------------------------------------------------------------------
int MineSweeperGetWidth(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	
	return mineSweeper->width;
	
}

//---------------------------------------------------------------------------------
//地雷原の高さを取得します。
//---------------------------------------------------------------------------------
int MineSweeperGetHeight(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	
	return mineSweeper->height;
	
}

//---------------------------------------------------------------------------------
//現在の地雷数を取得します。
//---------------------------------------------------------------------------------
int MineSweeperGetMines(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	
	return mineSweeper->mines;
	
}

//---------------------------------------------------------------------------------
//現在の旗数を取得します。
//---------------------------------------------------------------------------------
int MineSweeperGetFlags(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	
	return mineSweeper->flags;
	
}

//---------------------------------------------------------------------------------
//地雷除去に成功したかどうか調べます。成功したら true を、そうでなければ false を返します。
//---------------------------------------------------------------------------------
bool MineSweeperIsSuccess(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	
	return (MineSweeperGetOpenCount(mineSweeper) >= (mineSweeper->width * mineSweeper->height - mineSweeper->mines)) ? true:false;
	
}

//---------------------------------------------------------------------------------
//地雷除去に失敗したかどうか調べます。失敗したら true を、そうでなければ false を返します。
//---------------------------------------------------------------------------------
bool MineSweeperIsFailure(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	
	return MineSweeperIsOpenMine(mineSweeper);
	
}

//---------------------------------------------------------------------------------
//開いてるセルの数を取得します。
//---------------------------------------------------------------------------------
int MineSweeperGetOpenCount(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	int openCount;
	int x;
	int y;
	
	assert(mineSweeper != NULL);
	
	//開いてるセルの数を集計する。
	openCount = 0;
	for(y = 0;y < mineSweeper->height;y++) {
		for(x = 0;x < mineSweeper->width;x++) {
			openCount += (MineSweeperIsOpen(mineSweeper, x, y) == true) ? 1:0;
		}
	}
	
	return openCount;
	
}

//---------------------------------------------------------------------------------
//指定したセルが開いてるか調べます。開いていれば true を、閉じていれば false を返します。
//---------------------------------------------------------------------------------
bool MineSweeperIsOpen(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	return mineSweeper->field[x + mineSweeper->width * y].isOpen;
	
}

//---------------------------------------------------------------------------------
//指定されたセルを中心に、周囲に地雷が見つかるまで開きます。まだ開かれてなかったなら 1 を、既に開かれてたら 0 を返します。
//---------------------------------------------------------------------------------
int MineSweeperSetOpenAround(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	int openAnswer;
	int thisX;
	int thisY;
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	//指定されたセルを開く。
	if((openAnswer = MineSweeperSetOpen(mineSweeper, x, y)) == 0) {
		//既に開かれてたら何もしない。
		return openAnswer;
	}
	
	//開いたセル周辺の地雷数が 0 なら隣接セルも開いて、周辺地雷 0 でなくなるまで繰り返し処理する。
	if(mineSweeper->field[x + mineSweeper->width * y].aroundMines == 0) {
		for(thisY = FIX_MIN(y - 1, 0);thisY <= FIX_MAX(y + 1, mineSweeper->height - 1);thisY++) {
			for(thisX = FIX_MIN(x - 1, 0);thisX <= FIX_MAX(x + 1, mineSweeper->width - 1);thisX++) {
				MineSweeperSetOpenAround(mineSweeper, thisX, thisY);
			}
		}
	}
	return openAnswer;
	
}

//---------------------------------------------------------------------------------
//指定されたセルを開きます。成功したら 1 を、そうでなければ 0 を返します。
//---------------------------------------------------------------------------------
int MineSweeperSetOpen(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	//セルが既に開かれてたら何もしない。
	if(mineSweeper->field[x + mineSweeper->width * y].isOpen == true) {
		return 0;
	}
	
	//旗が立てられてたら何もしない。
	if(mineSweeper->field[x + mineSweeper->width * y].marker == MARKER_FLAG) {
		return 0;
	}
	
	//旗以外のマーカなら、マーク無しに設定する。
	if(mineSweeper->field[x + mineSweeper->width * y].marker != MARKER_FLAG) {
		mineSweeper->field[x + mineSweeper->width * y].marker = MARKER_NON;
	}
	
	//セルを開いた状態に設定する。
	mineSweeper->field[x + mineSweeper->width * y].isOpen = true;
	return 1;
	
}

//---------------------------------------------------------------------------------
//地雷が設置されたセルが開いてるか調べます。開いていれば true を、閉じていれば false を返します。
//---------------------------------------------------------------------------------
bool MineSweeperIsOpenMine(MineSweeper mineSweeper) {
//---------------------------------------------------------------------------------
	
	int x;
	int y;
	
	assert(mineSweeper != NULL);
	
	//地雷が設置されたセルが開かれてたら true を返す。
	for(y = 0;y < mineSweeper->height;y++) {
		for(x = 0;x < mineSweeper->width;x++) {
			if((MineSweeperIsOpen(mineSweeper, x, y) == true) && 
				(MineSweeperIsMine(mineSweeper, x, y) == true)) {
				return true;
			}
		}
	}
	
	//地雷が設置されたセルが開かれてなければ false を返す。
	return false;
	
}

//---------------------------------------------------------------------------------
//指定したセルに地雷が設置されてるか調べます。設置されてたら true を、そうでなければ false を返します。
//---------------------------------------------------------------------------------
bool MineSweeperIsMine(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	return mineSweeper->field[x + mineSweeper->width * y].isMine;
	
}

//---------------------------------------------------------------------------------
//指定されたセルのマーカを取得します。
//---------------------------------------------------------------------------------
int MineSweeperGetMarker(MineSweeper mineSweeper, int x, int y) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	
	return mineSweeper->field[x + mineSweeper->width * y].marker;
	
}

//---------------------------------------------------------------------------------
//指定されたセルにマーカを付けます。但し既に開かれてたら何もしません。
//---------------------------------------------------------------------------------
void MineSweeperSetMarker(MineSweeper mineSweeper, int x, int y, int marker) {
//---------------------------------------------------------------------------------
	
	assert(mineSweeper != NULL);
	assert(x >= 0 && x < mineSweeper->width && y >= 0 && y < mineSweeper->height);
	assert(marker >= MARKER_NON && marker < MARKER_MAX);
	
	//既に開かれてるセルなら何もしない。
	if(mineSweeper->field[x + mineSweeper->width * y].isOpen == true) {
		return;
	}
	
	switch(marker) {
		
	//旗指定だった場合。
	case MARKER_FLAG:
		
		//旗以外の状態で、旗数が 0 でなかった場合。
		if(mineSweeper->field[x + mineSweeper->width * y].marker != MARKER_FLAG && 
			mineSweeper->flags > 0) {
			//旗数を 1 減らして、旗マークを設定する。
			mineSweeper->flags--;
			mineSweeper->field[x + mineSweeper->width * y].marker = MARKER_FLAG;
		}
		break;
		
	//旗以外だった場合。
	default:
		
		//現在旗状態だったら、旗数を 1 戻す。
		if(mineSweeper->field[x + mineSweeper->width * y].marker == MARKER_FLAG) {
			mineSweeper->flags++;
		}
		
		//?指定だったら、?マークを設定する。
		if(marker == MARKER_QUESTION) {
			mineSweeper->field[x + mineSweeper->width * y].marker = MARKER_QUESTION;
			
		//無し指定だったら、マーク無しに設定する。
		} else {
			mineSweeper->field[x + mineSweeper->width * y].marker = MARKER_NON;
			
		}
		break;
		
	}
	
}

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


main.c

/*---------------------------------------------------------------------------------
	
	MineSweeper class sample
	
	version 0.10
	Apr 08, 2013
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

//#define NDEBUG

#include <stdio.h>
#include <time.h>
#include <nds.h>
//マインスイーパクラスのヘッダをインクルードする。
#include "MineSweeper.h"


//地雷原の幅。
#define WIDTH 9
//地雷原の高さ。
#define HEIGHT 9
//地雷数。
#define MINES 10


//マインスイーパオブジェクト変数を宣言する。
MineSweeper mineSweeper;

//カーソル横座標変数。
int cursorX;
//カーソル縦座標変数。
int cursorY;


//ゲーム画面を表示します。
void draw(void);
//地雷を全て表示します。
void drawMines(void);


//---------------------------------------------------------------------------------
//メインプログラム。
//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
	
	//キーリピート入力用変数。
	u32 keys;
	
	//コンソールを初期化する。
	consoleDemoInit();
	
	//タイトル、バージョン、公開日、コピーライトを表示する。
	printf("MineSweeper class sample\n\nversion 0.10\nApr 08, 2013\n\nBy REGEKATSU\n");
	
	//地雷原の幅、高さ、現在時間を乱数初期化値としてオブジェクトを生成する。
	mineSweeper = MineSweeperCreate(WIDTH, HEIGHT, MINES, (int)time(NULL));
	
	//カーソル座標変数を初期化する。
	cursorX = 0;
	cursorY = 0;
	
	//ゲームループ。
	while(1) {
		
		//ゲームを一定間隔(1 / 60 秒)で更新する。
		swiWaitForVBlank();
		
		//キー入力を取得する。
		scanKeys();
		keys = keysDownRepeat();
		
		//カーソルを左に移動する。
		if(keys & KEY_LEFT) {
			if(--cursorX < 0) {
				cursorX = WIDTH - 1;
			}
			
		//カーソルを右に移動する。
		} else if(keys & KEY_RIGHT) {
			if(++cursorX >= WIDTH) {
				cursorX = 0;
			}
			
		//カーソルを上に移動する。
		} else if(keys & KEY_UP) {
			if(--cursorY < 0) {
				cursorY = HEIGHT - 1;
			}
			
		//カーソルを下に移動する。
		} else if(keys & KEY_DOWN) {
			if(++cursorY >= HEIGHT) {
				cursorY = 0;
			}
			
		}
		
		//カーソルにあるセルを開く。
		if(keys & KEY_A) {
			
			//初回のみ開いたセルが地雷なら、地雷を別セルに移す。
			if(MineSweeperGetOpenCount(mineSweeper) == 0) {
				while(MineSweeperIsMine(mineSweeper, cursorX, cursorY) == true) {
					MineSweeperRemoveMine(mineSweeper, cursorX, cursorY);
					while(!MineSweeperSetMineRandom(mineSweeper)) {}
				}
			}
			
			MineSweeperSetOpenAround(mineSweeper, cursorX, cursorY);
			
		//カーソルにある、閉じたセルにマーカを点ける。
		} else if(keys & KEY_B) {
			
			//マーカが?マークなら、マーカ無しを設定する。
			if(MineSweeperGetMarker(mineSweeper, cursorX, cursorY) == MARKER_QUESTION) {
				MineSweeperSetMarker(mineSweeper, cursorX, cursorY, MARKER_NON);
				
			//マーカ無しで、且つ旗数 0 じゃなければ、旗マークを設定する。
			} else if(MineSweeperGetMarker(mineSweeper, cursorX, cursorY) == MARKER_NON && 
				MineSweeperGetFlags(mineSweeper) > 0) {
				MineSweeperSetMarker(mineSweeper, cursorX, cursorY, MARKER_FLAG);
				
			//マーカが旗マーク、または旗数 0 なら、?マークを設定する。
			} else if(MineSweeperGetMarker(mineSweeper, cursorX, cursorY) == MARKER_FLAG || 
				MineSweeperGetFlags(mineSweeper) == 0) {
				MineSweeperSetMarker(mineSweeper, cursorX, cursorY, MARKER_QUESTION);
				
			} 
			
		}
		
		//ゲーム画面を表示する。
		draw();
		
		//クリア判定。
		
		//ゲームオーバの場合。
		if(MineSweeperIsFailure(mineSweeper) == true) {
			//埋まってる全ての地雷と、ゲームオーバのメッセージを表示する。
			drawMines();
			printf("\x01b[20;0H...GAME OVER...");
			break;
		}
		//ゲームクリアの場合。
		if(MineSweeperIsSuccess(mineSweeper) == true) {
			//ゲームクリアを表示する。
			printf("\x01b[20;0H...GAME CLEAR!...");
			break;
		}
		
	}
	
	//マインスイーパオブジェクトを破棄して、ゲームを終了する。
	mineSweeper = MineSweeperDestroy(mineSweeper);
	while(1) {}
	return 0;
	
}

//---------------------------------------------------------------------------------
//ゲーム画面を表示します。
//---------------------------------------------------------------------------------
void draw(void) {
//---------------------------------------------------------------------------------
	
	int x;
	int y;
	
	//旗数、地雷数を表示する。
	printf("\x01b[8;0HFLAGS:%03d, MINES:%03d", 
		MineSweeperGetFlags(mineSweeper), 
		MineSweeperGetMines(mineSweeper));	
	
	//表示行を指定して、地雷原の幅、高さに合わせて表示する。
	printf("\x01b[10;0H");
	for(y = 0;y < HEIGHT;y++) {
		for(x = 0;x < WIDTH;x++) {
			
			//カーソルの描画。
			
			if(cursorX == x && cursorY == y) {
				//カーソルを表示する。
				printf(">");
			} else {
				//なければ空白を表示する。
				printf(" ");
			}
			
			//セルの描画。
			
			//セルが開いてる場合。
			if(MineSweeperIsOpen(mineSweeper, x, y) == true) {
				
				if(MineSweeperIsMine(mineSweeper, x, y) == true) {
					//地雷を表示する。
					printf("B");
				} else {
					//周辺地雷数を表示する。
					printf("%d", MineSweeperGetAroundMines(mineSweeper, x, y));
				}
				
			//セルが閉じてる場合。
			} else {
				
				switch(MineSweeperGetMarker(mineSweeper, x, y)) {
					
				//閉じた状態を表示する。
				case MARKER_NON:
					printf("-");
					break;
					
				//旗マークを表示する。
				case MARKER_FLAG:
					printf("F");
					break;
					
				//?マークを表示する。
				case MARKER_QUESTION:
					printf("?");
					break;
				}
			}
			
		}
		printf("\n");
	}
	
}

//---------------------------------------------------------------------------------
//地雷を全て表示します。
//---------------------------------------------------------------------------------
void drawMines(void) {
//---------------------------------------------------------------------------------
	
	int x;
	int y;
	
	//地雷原の幅、高さに合わせて表示する。
	for(y = 0;y < HEIGHT;y++) {
		for(x = 0;x < WIDTH;x++) {
			//地雷があれば表示する。
			if(MineSweeperIsMine(mineSweeper, x, y) == true) {
				printf("\x01b[%d;%dHB", 10 + y, x * 2 + 1);
			}
		}
	}
	
}

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