/*=============================================*
*
* マインスイーパ―簡易版
* provided by C
*
*=============================================*/
#include "DxLib.h"
// プロトタイプ宣言
int Search( int Field[ 10 ][ 10 ] , int Clicks[ 10 ][ 10 ] , int px , int py ) ;
// グローバル変数宣言
// はじめ、消さなくてはならないマスは全部で90コある
int Block_n = 90 ;
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
char Key[ 256 ] ;
// ウインドウモードに変更
if( ChangeWindowMode( TRUE ) != DX_CHANGESCREEN_OK ) return -1 ;
// 画面モードの変更
// サイズはぎりぎりいっぱいでいいと思うよ
if( SetGraphMode( 22 * 10 , 22 * 10 , 32 ) != DX_CHANGESCREEN_OK ) return -1 ;
// タイトルを変更
SetMainWindowText( "MineSweeper" ) ;
// DXライブラリ初期化処理
if( DxLib_Init() == -1 ) return -1;
// この配列に地雷情報を突っ込む
int Field[ 10 ][ 10 ] = { 0 } ;
// この配列にはクリックしたか(値が公開されているかどうか)どうかのフラグを突っ込む
int Clicks[ 10 ][ 10 ] = { 0 } ;
// 地雷セット
int mine_n = 0 ;
while( mine_n < 10 )
{
int px , py ;
// 地雷の場所がかぶらないように注意してマスを選ぶ
do
{
px = GetRand( 10 - 1 ) ;
py = GetRand( 10 - 1 ) ;
} while( Field[ px ][ py ] == -1 ) ;
// Fieldのどこかにランダムで地雷を埋める
Field[ px ][ py ] = -1 ;
// 地雷の情報からその周囲のマスに地雷情報を付け足す
if( px != 0 )
{
if( Field[ px - 1 ][ py ] != -1 ) Field[ px - 1 ][ py ] ++ ;
if( py != 0 && Field[ px - 1 ][ py - 1 ] != -1 ) Field[ px - 1 ][ py - 1 ] ++ ;
}
if( py != 0 )
{
if( Field[ px ][ py - 1 ] != -1 ) Field[ px ][ py - 1 ] ++ ;
if( px != 10 - 1 && Field[ px + 1 ][ py - 1 ] != -1 ) Field[ px + 1 ][ py - 1 ] ++ ;
}
if( px != 10 - 1 )
{
if( Field[ px + 1 ][ py ] != -1 ) Field[ px + 1 ][ py ] ++ ;
if( py != 10 - 1 && Field[ px + 1 ][ py + 1 ] != -1 ) Field[ px + 1 ][ py + 1 ] ++ ;
}
if( py != 10 - 1 )
{
if( Field[ px ][ py + 1 ] != -1 ) Field[ px ][ py + 1 ] ++ ;
if( px != 0 && Field[ px - 1 ][ py + 1 ] != -1 ) Field[ px - 1 ][ py + 1 ] ++ ;
}
mine_n ++ ;
}
// マウスカーソルを見えるようにセット
SetMouseDispFlag( TRUE );
// マウスの位置を格納する変数
int MouseX , MouseY ;
// グラフィックの描画先を裏画面にセット
SetDrawScreen( DX_SCREEN_BACK ) ;
int g_over = 0 ;
int g_clear = 0 ;
// ESCキーが押されるまでループ
while( !ProcessMessage() && !GetHitKeyStateAll( Key ) && !Key[ KEY_INPUT_ESCAPE ] )
{
// 画面をクリア
ClearDrawScreen() ;
// 描画
for( int i = 0 ; i < 10 ; i ++ )
{
for( int j = 0 ; j < 10 ; j ++ )
{
int C_Block ;
if( Clicks[ i ][ j ] == 0 ) C_Block = TRUE ;
else C_Block = FALSE ;
DrawBox( 0 + i * 22 , 0 + j * 22 , i * 22 + 20 , j * 22 + 20 , GetColor( 0 , 128 , 255 ) , C_Block ) ;
if( Clicks[ i ][ j ] == 1 && Field[ i ][ j ] != 0 ) DrawFormatString( 8 + i * 22 , 2 + j * 22 , GetColor( 255 , 255 , 255 ) , "%d" , Field[ i ][ j ] ) ;
}
}
// 全部マスを開けるとクリアー
if( Block_n == 0 ) g_clear = 1 ;
// マウスのクリックを検知
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 )
{
// マウスの位置を取得、フラグを立てる
GetMousePoint( &MouseX , &MouseY ) ;
int px = MouseX / 22 ;
int py = MouseY / 22 ;
// 探知開始
Search( Field , Clicks , px , py ) ;
// 地雷を踏んでしまったら
if( Field[ px ][ py ] == -1 ) g_over = 1 ;
}
// ゲームクリアー
if( g_clear == 1 )
DrawString( 0 , 0 , "GAME CLEAR!" , GetColor( 255 , 0 , 0 ) ) ;
// ゲームオーバー
if( g_over == 1 )
DrawString( 0 , 0 , "GAME OVER!" , GetColor( 255 , 120 , 0 ) ) ;
// 画面を表示
ScreenFlip() ;
}
// DXライブラリ使用の終了処理
DxLib_End() ;
// ソフトの終了
return 0 ;
}
// マスを開ける探知再帰関数
int Search( int Field[ 10 ][ 10 ] , int Clicks[ 10 ][ 10 ] , int px , int py )
{
if( Clicks[ px ][ py ] != 1 )
{
Clicks[ px ][ py ] = 1 ;
Block_n -- ;
}
if( Field[ px ][ py ] == 0 )
{
// 左側の処理
if( px != 0 )
{
if( Clicks[ px - 1 ][ py ] != 1 ) Search( Field , Clicks , px - 1 , py ) ;
if( py != 0 && Clicks[ px - 1 ][ py - 1 ] != 1 ) Search( Field , Clicks , px - 1 , py - 1 ) ;
}
// 上側の処理
if( py != 0 )
{
if( Clicks[ px ][ py - 1 ] != 1 ) Search( Field , Clicks , px , py - 1 ) ;
if( px != 10 - 1 && Clicks[ px + 1 ][ py - 1 ] != 1 ) Search( Field , Clicks , px + 1 , py - 1 ) ;
}
// 右側の処理
if( px != 10 - 1 )
{
if( Clicks[ px + 1 ][ py ] != 1 ) Search( Field , Clicks , px + 1 , py ) ;
if( py != 10 - 1 && Clicks[ px + 1 ][ py + 1 ] != 1 ) Search( Field , Clicks , px + 1 , py + 1 ) ;
}
// 下側の処理
if( py != 10 - 1 )
{
if( Clicks[ px ][ py + 1 ] != 1 ) Search( Field , Clicks , px , py + 1 ) ;
if( px != 0 && Clicks[ px - 1 ][ py + 1 ] != 1 ) Search( Field , Clicks , px - 1 , py + 1 ) ;
}
}
return 1 ;
}
再帰関数の練習としては便利だと思ったのでUP
ゲームオーバーまたはクリアの後にリセットでもう一度遊べるようにするべきですが、再帰の練習のためにしていません。