このディレクトリの索引
#  出典: プログラミングのお題スレ Part3 #729
#  
#  お題:○×ゲームで○が勝つ局面までの手順を深さ優先探索ですべて探し出して出力。手順の重複は認めない。
#  
#  列者臨
#  在皆兵
#  前陣闘
#  


勝ち(列者臨).
勝ち(在皆兵).
勝ち(前陣闘).
勝ち(列在前).
勝ち(者皆陣).
勝ち(臨兵闘).
勝ち(列皆闘).
勝ち(臨皆前).


'○×ゲームで○が勝つ局面までの手順を深さ優先探索ですべて探し出して出力。手順の重複は認めない。' :-
        すべて('○×ゲームで○が勝つ局面までの手順を深さ優先探索で探し出して'(_手順),出力(_手順)).

'○×ゲームで○が勝つ局面までの手順を深さ優先探索で探し出して'(_手順) :-
        交互着手(臨兵闘者皆陣列在前,○,×,[],[],_勝ち,_手順).

交互着手(_,_,_手番,_,_手番の着手点ならび,_手番,[]) :-
        勝ち(_手番の着手点ならび),!.
交互着手(_着手可能点文字列,_手番,_次の手番,_手番の着手点ならび,_次の手番の着手点ならび,_勝ち,[_着手|_着手ならび]) :-
        選択(_着手可能点文字列,_着手,_残り着手可能点文字列),
        交互着手(_残り着手可能点文字列,_次の手番,_手番,_次の手番の着手点ならび,[_着手|_手番の着手点ならび],_勝ち,_着手ならび).

選択(_着手可能点文字列,_着手,_残り着手可能点文字列) :-
        副文字列(_着手可能点文字列,_開始位置,1,_残り文字数,_着手),
        着手以外の文字列を残り着手可能点とする(_着手可能点文字列,_開始位置,_残り文字数,_残り着手可能点文字列).

着手以外の文字列を残り着手可能点文字列とする(_着手可能点文字列,_前文字列長,_後文字列長,_残り着手可能点文字列) :-
        副文字列(_着手可能点文字列,0,_前文字列長,_,_前文字列),
        副文字列(_着手可能点文字列,_,_後文字列長,0,_後文字列),
        二つの文字列の結合(_前文字列,_後文字列,_残り着手可能点文字列).

勝ち(_着手ならび) :-
        勝ち(_文字列),
        全ての文字列の構成文字は着手ならびに含まれる(_文字列,_着手ならび).

全ての文字列の構成文字は着手ならびに含まれる(_文字列,_着手ならび) :-
        すべて(副文字列(_文字列,_,1,_,文字),含まれる(_文字,_着手ならび)).

出力(_手順) :-
        文字列ならびを結合して出力し改行する(_手順).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



副文字列(_文字列,_副文字列の開始位置,_文字列長,_残り文字列長,_副文字列) :-
        sub_atom(_文字列,_副文字列の開始位置,_文字列長,_残り文字列長,_副文字列).
文字列ならびを結合する(_文字列ならび,_結合した文字列) :-
        atomic_list_concat(_文字列ならび,_結合した文字列).

二つの文字列の結合(_文字列_1,_文字列_2,_結合した文字列) :-
        atom_concat(_文字列_1,_文字列_2,_結合した文字列).

含まれる(_要素,_ならび) :-
        member(_要素,_ならび).

すべて(P,Q) :-
        forall(P,Q).

文字列ならびを結合して出力し改行する(_文字列ならび) :-
        atomic_list_concat(_文字列ならび,_結合した文字列),
        writef('%t\n',[_結合した文字列]).