Cパズルプログラミング-再帰編 > 8クイーン > 対象移動の実装 > queen17.c


[Prev] [Next] [Up] [Contents][フレーム表示] [フレーム解除

queen17.c 応援する 

/************************************************************************/
/*      8クイーン   その17                                    */
/*                                                                      */
/*      対称性のチェックの準備                                             */
/*                                                                      */
/*      盤面のクイーンの並び方で大小比較のための関数を用意               */
/*                                                                      */
/*      usage:  queen                                                   */
/*                                                                      */
/************************************************************************/
#include <stdio.h>

int     answercount;
char    board[8][8];            /* チェス盤 */

#define QUEEN   'Q'
#define BLANK   '.'

#define TRUE    1
#define FALSE   0

void    initboard( void );
void    copyboard( char dest[8][8], char src[8][8] );
void    rotate( char dest[8][8], char src[8][8] );
void    lrmirror( char dest[8][8], char src[8][8] );
int     isunique( void );
void    setqueen( int x, int y );
void    setblank( int x, int y );
int     ison( int x, int y );
int     isokleft( int x, int y );
int     isokleftup( int x, int y );
int     isokleftdown( int x, int y );
int     isok( int x, int y );
void    tryqueen( int x, int y );
void    foundanswer( void );
void    printboard( char b[8][8] );
int     main( int argc, char **argv );

/*----------------------------------------------------------------------*/
/*      チェス盤の初期化                                                */
/*----------------------------------------------------------------------*/
void    initboard( void )
{
        int     x, y;

        for( x=0; x<8; ++x ) {
                for( y=0; y<8; ++y ) {
                        board[x][y] = BLANK;
                }
        }
}


/*----------------------------------------------------------------------*/
/*      チェス盤のコピー                                                */
/*----------------------------------------------------------------------*/
void    copyboard( char dest[8][8], char src[8][8] )
{
        int     x, y;

        for( x=0; x<8; ++x )
                for( y=0; y<8; ++y )
                        dest[x][y] = src[x][y];
}

/*----------------------------------------------------------------------*/
/*      盤面上のコマを90度回転する                                  */
/*----------------------------------------------------------------------*/
void    rotate( char dest[8][8], char src[8][8] )
{
        char    work[8][8];             /* to, from が同じ配列でもOK   */
        int     x, y;

        for( x=0; x<8; ++x )
                for( y=0; y<8; ++y )
                        work[y][7-x] = src[x][y];

        copyboard( dest, work );
}

/*----------------------------------------------------------------------*/
/*      盤面上のコマを左右反転する                                   */
/*----------------------------------------------------------------------*/
void    lrmirror( char dest[8][8], char src[8][8] )
{
        char    work[8][8];             /* to, from が同じ配列でもOK   */
        int     x, y;

        for( x=0; x<8; ++x )
                for( y=0; y<8; ++y )
                        work[7-x][y] = src[x][y];

        copyboard( dest, work );
}

/*----------------------------------------------------------------------*/
/*      回転・反転などによるユニーク性のチェック                    */
/*----------------------------------------------------------------------*/
int     isunique( void )
{
        char    work[8][8];             /* 作業用盤面        */              

        printboard( board );                            /*  候補  */

        rotate( work, board );  printboard( work );     /*  90度回転       */
        rotate( work, work );   printboard( work );     /* 180度回転       */
        rotate( work, work );   printboard( work );     /* 270度回転       */
        lrmirror( work, board ); printboard( work );    /* 左右裏返し        */
        rotate( work, work );   printboard( work );     /*  90度回転       */
        rotate( work, work );   printboard( work );     /* 180度回転       */
        rotate( work, work );   printboard( work );     /* 270度回転       */
}

/*----------------------------------------------------------------------*/
/*      チェス盤の指定場所にクイーンをセット                              */
/*----------------------------------------------------------------------*/
void    setqueen( int x, int y )
{
        board[x][y] = QUEEN;
}

/*----------------------------------------------------------------------*/
/*      チェス盤の指定場所をブランクにする                               */
/*----------------------------------------------------------------------*/
void    setblank( int x, int y )
{
        board[x][y] = BLANK;
}

/*----------------------------------------------------------------------*/
/*      指定位置(x,y)が盤上かどうかの判定                             */
/*----------------------------------------------------------------------*/
int     ison( int x, int y )
{
        if( x<0 || x>=8 )
                return  FALSE;
        if( y<0 || y>=8 )
                return  FALSE;

        return  TRUE;
}

/*----------------------------------------------------------------------*/
/*      同じy座標 (←) のところに他のクイーンがないことを確認           */
/*----------------------------------------------------------------------*/
int     isokleft( int x, int y )
{
        int     i;
        int     stat = TRUE;

        for(;;) {
                --x;
                if( ! ison( x, y ) )
                        break;

                if( board[x][y] == QUEEN ) {
                        stat = FALSE;
                        break;
                }
        }

        return stat;
}

/*----------------------------------------------------------------------*/
/*      左上対角線上 (\) のところに他のクイーンがないことを確認  */
/*----------------------------------------------------------------------*/
int     isokleftup( int x, int y )
{
        int     i;
        int     stat = TRUE;

        for(;;) {
                --x;
                --y;
                if( ! ison( x, y ) )
                        break;

                if( board[x][y] == QUEEN ) {
                        stat = FALSE;
                        break;
                }
        }

        return stat;
}

/*----------------------------------------------------------------------*/
/*      左下対角線上 (/) のところに他のクイーンがないことを確認  */
/*----------------------------------------------------------------------*/
int     isokleftdown( int x, int y )
{
        int     i;
        int     stat = TRUE;

        for(;;) {
                --x;
                ++y;
                if( ! ison( x, y ) )
                        break;

                if( board[x][y] == QUEEN ) {
                        stat = FALSE;
                        break;
                }
        }

        return stat;
}

/*----------------------------------------------------------------------*/
/*      左上対角線上 (\) のところに他のクイーンがないことを確認  */
/*----------------------------------------------------------------------*/
int     isok( int x, int y )
{
        if( ! isokleft( x, y ) ) {      /* 効き筋(←)にあるので置けない      */
                return  FALSE;
        }

        if( ! isokleftup( x, y ) ) {    /* 効き筋(\)にあるので置けない      */
                return  FALSE;
        }

        if( ! isokleftdown( x, y ) ) {  /* 効き筋(/)にあるので置けない      */
                return  FALSE;
        }

        return  TRUE;
}

/*----------------------------------------------------------------------*/
/*      チェス盤の指定場所をにクイーンを置けるか調べる                 */
/*----------------------------------------------------------------------*/
void    tryqueen( int x, int y )
{
        int     z;

        if( ! isok( x, y ) )
                return;

        setqueen( x, y );               /* 置いた */

        if( x == 7 ) {                  /* 8個置き終えた */
                foundanswer();
        } else {                        /* 一つ右側について調べる */       
                for( z=0; z<8; ++z ) {
                        tryqueen( x+1, z );
                }
        }

        setblank( x, y );               /* 外した */
}

/*----------------------------------------------------------------------*/
/*      解が見つかった                                                 */
/*----------------------------------------------------------------------*/
void    foundanswer( void )
{
        isunique();             /* ユニークかどうかの検査を行う予定     */

        ++answercount;
        printf( "Answer %d\n", answercount );

        printboard( board );
}

/*----------------------------------------------------------------------*/
/*      チェス盤のプリント                                               */
/*----------------------------------------------------------------------*/
void    printboard( char b[8][8] )
{
        int     x, y;

        for( y=0; y<8; ++y ) {
                for( x=0; x<8; ++x ) {
                        printf( " %c", b[x][y] );
                }
                printf( "\n" );
        }
        printf( "\n" );
}

/*----------------------------------------------------------------------*/
/*      メイン                                                             */
/*----------------------------------------------------------------------*/
int     main( int argc, char **argv )
{
        int     y;

        answercount = 0;
        initboard();

        for( y=0; y<8; ++y ) {
                tryqueen( 0, y );
        }
}

/************************************************************************/
/*                              End                                     */
/************************************************************************/

[Prev] [Next] [Up] [Contents][フレーム表示] [フレーム解除

このサイトについて|ヘルプ|Q&A|個人情報保護|プライバシーポリシー|利用規約|コメント・トラックバック規約|削除規程|広告掲載
Copyright (c) 2005-2007 Time Intermedia Corporation