オセロで、石を反転する範囲の捜索の仕方がわかりません
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
何処ら辺がわからないか書いてもらわないと返答しようがないのですが、再帰処理自体の仕組みは調べられましたか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
仕組み・・・は多分わからないと思います。
スタックという単語を見た覚えがあります。
10の階乗をやってみようと思ったのですが、何をどうすればいいのかさっぱり分かりませんでした。
スタックという単語を見た覚えがあります。
10の階乗をやってみようと思ったのですが、何をどうすればいいのかさっぱり分かりませんでした。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
C言語のアルゴリズムの勉強をされたことはありますか?sadora3 さんが書きました:仕組み・・・は多分わからないと思います。
スタックという単語を見た覚えがあります。
10の階乗をやってみようと思ったのですが、何をどうすればいいのかさっぱり分かりませんでした。
結局ゲームは、C言語の様々なアルゴリズムや再帰処理などテクニックを使わないと組めない難易度が高くなりがちな分野です。
特にパズルやオセロなどは再帰処理を始めとして簡易なAIなど様々な知識を必要とします。
そこを勉強する気がなかったり、勉強する方法を見つけられないと前に進めないと思ってもらうしか無いのです。厳しい言い方かも知れませんが現実的にそうなのです。
階乗の答えでもありますが、参考サイトです。
「パズル問題解法のアルゴリズム」
http://www.ic-net.or.jp/home/takaken/pz/index.html
読んだ上で、見ずに階乗のプログラムを自分で組んでみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
それじゃ練習として再帰で、オセロの(1,1)から(8,8)までのポイントに白を置く関数を書いてみて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
分からないにしても出来る限りのコードを書いてもらえないでしょうか。
ヒントは、今までの内容を見なおして下さい。
ヒントは、今までの内容を見なおして下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
>>sadora3 さん
softya(ソフト屋) さんの書いた
再帰で、オセロの(1,1)から(8,8)までのポイントに白を置く関数について
どこまで考えられたでしょうか?
(1)この関数を呼び出したとき、どのポイントが白になればよいのでしょうか
(2)この関数の引数はどうなると思いますか
(3)あるポイントに白を置く処理はどう書きますか
(4)あるポイントに白を置いた次のポイントはどう表現しますか
(5)この関数の定義の中でこの関数を呼び出すかどうかをどう判定しますか
softya(ソフト屋) さんの書いた
再帰で、オセロの(1,1)から(8,8)までのポイントに白を置く関数について
どこまで考えられたでしょうか?
(1)この関数を呼び出したとき、どのポイントが白になればよいのでしょうか
(2)この関数の引数はどうなると思いますか
(3)あるポイントに白を置く処理はどう書きますか
(4)あるポイントに白を置いた次のポイントはどう表現しますか
(5)この関数の定義の中でこの関数を呼び出すかどうかをどう判定しますか
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
再帰の初歩的な使い方については、自分で考えろというのは酷ではないでしょうか。
階乗やフィボナッチ数列の例しか初心者には見つけられず、
それ以上の使い方を考えだせる人は少数派なのでは?
せめてアルゴリズムを日本語で説明するとかしないと、
知らない人には雲をつかむような話ではないかと思います。
このように私は考えますので、再帰で白を置く関数を書いてみました。
見るかどうかはsadora3さんが判断してください。
階乗やフィボナッチ数列の例しか初心者には見つけられず、
それ以上の使い方を考えだせる人は少数派なのでは?
せめてアルゴリズムを日本語で説明するとかしないと、
知らない人には雲をつかむような話ではないかと思います。
このように私は考えますので、再帰で白を置く関数を書いてみました。
見るかどうかはsadora3さんが判断してください。
► スポイラーを表示
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
tatuさん。たいちうさん。ありがとうございます。
tatuさんのヒントを頼りに、たいちうさんのは見ずに頑張ってみようかと思います。
tatuさんのヒントを頼りに、たいちうさんのは見ずに頑張ってみようかと思います。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
>>sadora3 さん
私の書いたことを頼りにするつもりでしたら
(1)この関数を呼び出したとき、どのポイントが白になればよいのでしょうか
についてどう考えているかを書いてください。
私の書いたことを頼りにするつもりでしたら
(1)この関数を呼び出したとき、どのポイントが白になればよいのでしょうか
についてどう考えているかを書いてください。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
そういう誤解の余地があるんですね。言葉が足りませんでした。sadora3 さんが書きました:全てのマスが白になればいいかと・・・。
それでは、ルールを書き加えて(1,1)から(8,8)まで直線で白を置いて下さい。
(1,1),(2,2)・・・・(8,8)と白を置きます。
その他の盤面は何も置いていない状態とします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
それでOKですよ。
じゃあ、今後のためにx,yは別引数にして、かつ盤面の外側が-1で埋まっていたはずですので、それを判断して止まるように変えてもらえますか?
じゃあ、今後のためにx,yは別引数にして、かつ盤面の外側が-1で埋まっていたはずですので、それを判断して止まるように変えてもらえますか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
プログラミングのできるひとというのは、日本語でも抽象的な説明ができるひとだと思うんですよね。
経験としての話ですが…
プログラミングに慣れていないひとは、「どこ」と問われたら、具体的にマスの位置を答えようとします。
ひとつのマスに絞れないので結果から求めてしまう。
結果だけを求めているように見える。
プログラミングに慣れているひとは、この程度だと、引数x,yが示すマスを現在注目しているマスとする、とか、現在注目しているマスを引数x,yで示す、とかの設計や実装にあたる作業を無意識に一瞬で済ませてしまいます。
プログラミングに慣れていないひとは、「現在注目しているマス」という考え方からしてできない。
関数原型すら作れず手も足も出ない。
#書いてるうちに進んでた。
経験としての話ですが…
プログラミングに慣れていないひとは、「どこ」と問われたら、具体的にマスの位置を答えようとします。
ひとつのマスに絞れないので結果から求めてしまう。
結果だけを求めているように見える。
プログラミングに慣れているひとは、この程度だと、引数x,yが示すマスを現在注目しているマスとする、とか、現在注目しているマスを引数x,yで示す、とかの設計や実装にあたる作業を無意識に一瞬で済ませてしまいます。
プログラミングに慣れていないひとは、「現在注目しているマス」という考え方からしてできない。
関数原型すら作れず手も足も出ない。
#書いてるうちに進んでた。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
つづいて、これを改造していきます。
置く色を引数に追加しましょう。SIROの部分をWhiteLineの引数とするわけです。
ISLeさん、ありがとうございます。
やはり、抽象化がネックなんでしょうか?
置く色を引数に追加しましょう。SIROの部分をWhiteLineの引数とするわけです。
ISLeさん、ありがとうございます。
やはり、抽象化がネックなんでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
変数で何かを示すという基本的なところですけどね。softya(ソフト屋) さんが書きました:ISLeさん、ありがとうございます。
やはり、抽象化がネックなんでしょうか?
そういう意味では、動作が変わらなくても変数名にこだわることが重要かもしれません。
文章のように読める、読み易いコードにも繋がると思います。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
せっかく引数にしたのに、WhiteLineの再帰呼び出し時に使っていませんね。これを直しましょう。
それとSの引数変数名はSIRO/KUROどちらでも使えるような変数名を考えてみて下さい。
最初の呼び出しもWhiteLine( 1 , 1 , SIRO );とすべきです。
あと今更ですが、WhiteLine( int y , int x ,よりはWhiteLine( int x , int y ,の方が後々混乱しないと思うので今のうちに直しましょう。
それとSの引数変数名はSIRO/KUROどちらでも使えるような変数名を考えてみて下さい。
最初の呼び出しもWhiteLine( 1 , 1 , SIRO );とすべきです。
あと今更ですが、WhiteLine( int y , int x ,よりはWhiteLine( int x , int y ,の方が後々混乱しないと思うので今のうちに直しましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
コードとしてはOKだと思います。
ただ、Cは何かの略だと思いますが変数名として意味がわからないほど短い気がしますね。もっと良い名前を考えてみましょう。
次の改造は斜め以外に対応するために方向を追加しますが、前回苦しんでいるのでx,yの増加分を引数とする形にしようと思います。
y+1 , x+1 の+1をx,yで分けて引数にします。そうすれば、引数を変えるだけで好きな方向に白い線を引くことができますよね。
引数を追加した場合の最初の呼び出し。
WhiteLine( 1 , 1 , 1 , 1 , SIRO ); //右下へ
// いろんなパターン
WhiteLine( 1 , 1 , 1 , 0 , SIRO ); //右へ
WhiteLine( 1 , 1 , 0 , 1 , SIRO ); //下へ
WhiteLine( 4 , 4 , -1 , -1 , SIRO );//左上へ
ただ、Cは何かの略だと思いますが変数名として意味がわからないほど短い気がしますね。もっと良い名前を考えてみましょう。
次の改造は斜め以外に対応するために方向を追加しますが、前回苦しんでいるのでx,yの増加分を引数とする形にしようと思います。
y+1 , x+1 の+1をx,yで分けて引数にします。そうすれば、引数を変えるだけで好きな方向に白い線を引くことができますよね。
引数を追加した場合の最初の呼び出し。
WhiteLine( 1 , 1 , 1 , 1 , SIRO ); //右下へ
// いろんなパターン
WhiteLine( 1 , 1 , 1 , 0 , SIRO ); //右へ
WhiteLine( 1 , 1 , 0 , 1 , SIRO ); //下へ
WhiteLine( 4 , 4 , -1 , -1 , SIRO );//左上へ
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
それじゃ、またまた機能追加で何個置けたか戻り値で返すようにしましょうか。※ 今後のための機能です。
int WhiteLine( int x , int y , int Way_x , int Way_y , int Color, int count )
にしてcountで置けた数を再帰的にカウントアップして、returnで最終的に置けた個数を返しますが、再帰でうまくカウントされるようにしないと行けません。
それを考えてみて下さい。
最初の呼び出しは
int IshiCount = WhiteLine( 1 , 1 , 1 , 1 , SIRO, 0 );//初期のカウントは0個
となります。
int WhiteLine( int x , int y , int Way_x , int Way_y , int Color, int count )
にしてcountで置けた数を再帰的にカウントアップして、returnで最終的に置けた個数を返しますが、再帰でうまくカウントされるようにしないと行けません。
それを考えてみて下さい。
最初の呼び出しは
int IshiCount = WhiteLine( 1 , 1 , 1 , 1 , SIRO, 0 );//初期のカウントは0個
となります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
おしいですね。エラーになりませんかこれ?
再起した時の戻り値の処理がありませんよ。
再起した時の戻り値の処理がありませんよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
再帰におけるWhiteLineの戻り値が処理されていないって事です。
あとプログラムの流れ次第でreturn 値;が無い流れがあるのも問題です。
コンパイラで警句が出るはずなんですが。
あとプログラムの流れ次第でreturn 値;が無い流れがあるのも問題です。
コンパイラで警句が出るはずなんですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
うーん・・・コンパイル時、一瞬「値を返さない~」みたいなメッセージが出てきますが、その後ちゃんと実行されてました。戻り値は4行目のreturn count;があると思うのですが・・・。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
処理を追ってみましょう。sadora3 さんが書きました: こうでしょうか?
WhiteLine( 1 , 1 , 1 , 1 , SIRO, 0 ); BanData[1][1]に白が置かれます
再帰→ WhiteLine( 2 , 2 , 1 , 1 , SIRO, 1 ); BanData[2][2]に白が置かれます
再帰→ WhiteLine( 3 , 3 , 1 , 1 , SIRO, 2 ); BanData[3][3]に白が置かれます
……
再帰→ WhiteLine( 8 , 8 , 1 , 1 , SIRO, 7 ); BanData[8][8]に白が置かれます
再帰→ WhiteLine( 9 , 9 , 1 , 1 , SIRO, 8 ); BanData[9][9]に白を置こうとしますが、BanData[9][9]は壁なので8を返します。
WhiteLine( 8 , 8 , 1 , 1 , SIRO, 7 )の6行目に返ってきました。この返り値をWhiteLine( 7 , 7 , 1 , 1 , SIRO, 6 )に渡してあげたいですが、返り値を返せません。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
実行はされると思います。警告ですから。
>戻り値は4行目のreturn count;があると思うのですが・・・。
4行目のreturnは、1つ前の関数に戻るだけです。
それ以前には戻りません。
じゃあ、勉強になると思うのでデバッガで4行目でブレークしてF10トステップトレースしてみて下さい。
流れがわかると思います。
「デバッガの使い方」
http://ext-web.edu.sgu.ac.jp/koike/semi/VC2005/c17.html
>戻り値は4行目のreturn count;があると思うのですが・・・。
4行目のreturnは、1つ前の関数に戻るだけです。
それ以前には戻りません。
じゃあ、勉強になると思うのでデバッガで4行目でブレークしてF10トステップトレースしてみて下さい。
流れがわかると思います。
「デバッガの使い方」
http://ext-web.edu.sgu.ac.jp/koike/semi/VC2005/c17.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
遅れてすみません。
これであってますか?
デバッガ使うとプログラムの流れが凄くわかりやすくなりますね。
Priestさん回答ありがとうございました。
Priestさんの言っていることが少し理解できませんでしたが、デバッガを使って良く理解出来ました。
int WhiteLine( int x , int y , int Way_x , int Way_y , int Color , int count){
int a;
if( BanData[ y ][ x ] == WALL ){ return count; }
BanData[ y ][ x ] = Color;
a = WhiteLine( x + Way_x , y + Way_y , Way_x , Way_y , Color , count + 1 );
return a;
}
デバッガ使うとプログラムの流れが凄くわかりやすくなりますね。
Priestさん回答ありがとうございました。
Priestさんの言っていることが少し理解できませんでしたが、デバッガを使って良く理解出来ました。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
okですが、インデントが変です。
それと安易にaなどと名前をつけるのは止めましょう。
それとこう書く方法もあります。※ 弱点:戻り値をデバッグしにくい。
int WhiteLine( int x , int y , int Way_x , int Way_y , int Color , int count){
int a;
if( BanData[ y ][ x ] == WALL ){ return count; }
BanData[ y ][ x ] = Color;
a = WhiteLine( x + Way_x , y + Way_y , Way_x , Way_y , Color , count + 1 );
return a;
}
それとこう書く方法もあります。※ 弱点:戻り値をデバッグしにくい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
分かりました。変数の名前は何か考えて変えておきます。
次は何をすればよろしいのでしょうか?
次は何をすればよろしいのでしょうか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
ちょっと思い出すのに時間がかかりました。
これで、任意の方向に石を置くだけの処理は出来ましたね。
既に白だけじゃないのでWhiteLine()でなくPutLine()が正しいかもしれませんが名前も考えておいて下さい。
関数名は動詞+名詞を基本とすることがお勧めです。
さて、次は置く場所の盤の状態を見て置くかどうか決める処理を追加します。
本物のオセロなら石をひっくり返すのですが、この場合は上書きしてしまいましょう。
基本的はWALLと同じですが、同じ色なら、違う色なら、空きならの条件を追加しましょう。
これで、任意の方向に石を置くだけの処理は出来ましたね。
既に白だけじゃないのでWhiteLine()でなくPutLine()が正しいかもしれませんが名前も考えておいて下さい。
関数名は動詞+名詞を基本とすることがお勧めです。
さて、次は置く場所の盤の状態を見て置くかどうか決める処理を追加します。
本物のオセロなら石をひっくり返すのですが、この場合は上書きしてしまいましょう。
基本的はWALLと同じですが、同じ色なら、違う色なら、空きならの条件を追加しましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
int PutLine( int x , int y , int Way_x , int Way_y , int Color , int count){
int BackValue;
if( BanData[ y ][ x ] == WALL ){ return count; }
else if( BanData[ y ][ x ] != Color ){ BanData[ y ][ x ] =Color; }
else if( BanData[ y ][ x ] ==Color ){ return count; }
else if( BanData[ y ][ x ] == BAN ){ return count; }
BackValue = PutLine( x + Way_x , y + Way_y , Way_x , Way_y , Color , count + 1 );
return BackValue;
}
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
その順番だとうまく行かないと思います。
テストプログラムを組んで試してみて下さい。
テストプログラムは、今後の動作確認のためにも必要です。
それとBackValueよりBackCountの方が良いですかね。
あるいはRetrunCountとかTotalCountとか。countであると言う意味は残っていたほうが良いと思います。
テストプログラムを組んで試してみて下さい。
テストプログラムは、今後の動作確認のためにも必要です。
それとBackValueよりBackCountの方が良いですかね。
あるいはRetrunCountとかTotalCountとか。countであると言う意味は残っていたほうが良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
目の前にプログラムを実行し、デバッグする環境があるのですから、
作ってみたものに対してテストデータ(テスト用の盤面データ)を用意し、適当な引数を与えて関数を呼び出せば
自分が想定している動作をしているかどうかすぐに確認できると思います。
softyaさんも指摘していますが、自分で作ったものはまず自分でテストして確認してみましょう。
そのうえで動作がおかしい場合には、
1.想定している動作(こうなってほしい動作)
2.実際の動作(与えたパラメータ、結果)
を添えて質問するようにしないと、回答者のみなさんに公開デバッグをお願いするような形になってしまい
自分の身にならないですよ。
ちなみに、盤面データBanDataの初期化・宣言部分を#ifdefなどで
切り分けてテスト用盤面を用意しておくと、今後デバッグ、テストをするうえで
楽になりますよ^^
こうしておくとプロプロセッサ(ビルドオプション)でDEBUGというシンボルが定義(#define DEBUGでも可)されているときは、初期盤面がテスト用の盤面に置き換わります。
本当の初期盤面からテストすると望んだ状況を作るのは難しいので、こういう方法で考えられる石の配置を自分で用意して
それにたいして関数を呼び出して望んだ動作をしてくれるか確認するといいですよ。
ちなみに上のテスト盤面では左上は白も黒も1個も取れない場所、右下は白も黒も裏返すことができる場所になっています。
作ってみたものに対してテストデータ(テスト用の盤面データ)を用意し、適当な引数を与えて関数を呼び出せば
自分が想定している動作をしているかどうかすぐに確認できると思います。
softyaさんも指摘していますが、自分で作ったものはまず自分でテストして確認してみましょう。
そのうえで動作がおかしい場合には、
1.想定している動作(こうなってほしい動作)
2.実際の動作(与えたパラメータ、結果)
を添えて質問するようにしないと、回答者のみなさんに公開デバッグをお願いするような形になってしまい
自分の身にならないですよ。
ちなみに、盤面データBanDataの初期化・宣言部分を#ifdefなどで
切り分けてテスト用盤面を用意しておくと、今後デバッグ、テストをするうえで
楽になりますよ^^
#ifdef DEBUG
//テスト用初期盤面
static int BanDate[10][10]={
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,0,1,1,1,1,1,1,1,-1},
{-1,2,1,0,0,0,0,0,2,-1},
{-1,2,0,1,0,0,0,0,2,-1},
{-1,2,0,0,1,2,0,0,2,-1},
{-1,2,0,0,2,1,0,0,2,-1},
{-1,2,0,0,0,0,1,0,2,-1},
{-1,2,0,0,0,0,0,1,2,-1},
{-1,2,1,1,1,1,1,1,0,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
};
#else
//初期盤面
static int BanDate[10][10]={
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,0,0,0,0,0,0,0,0,-1},
{-1,0,0,0,0,0,0,0,0,-1},
{-1,0,0,0,0,0,0,0,0,-1},
{-1,0,0,0,1,2,0,0,0,-1},
{-1,0,0,0,2,1,0,0,0,-1},
{-1,0,0,0,0,0,0,0,0,-1},
{-1,0,0,0,0,0,0,0,0,-1},
{-1,0,0,0,0,0,0,0,0,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
};
#endif
本当の初期盤面からテストすると望んだ状況を作るのは難しいので、こういう方法で考えられる石の配置を自分で用意して
それにたいして関数を呼び出して望んだ動作をしてくれるか確認するといいですよ。
ちなみに上のテスト盤面では左上は白も黒も1個も取れない場所、右下は白も黒も裏返すことができる場所になっています。
Advanced Supporting Developer
無理やりこじつけ(ぉ
無理やりこじつけ(ぉ
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
うーん・・・。何をすればいいのか分からなくなってきました。
「置く場所の盤の状態を見て置くかどうか決める処理」とはなんでしょうか?
この処理は何が出来るようになるのでしょうか?
asdさんのテスト用の盤面の左上からどちらも裏返せますか?
それと公開デバッグみたいになっていてすみませんでした。
「置く場所の盤の状態を見て置くかどうか決める処理」とはなんでしょうか?
この処理は何が出来るようになるのでしょうか?
asdさんのテスト用の盤面の左上からどちらも裏返せますか?
それと公開デバッグみたいになっていてすみませんでした。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
> 「置く場所の盤の状態を見て置くかどうか決める処理」とはなんでしょうか?
別の色の石なら石をひっくり返します。それ以外なら処理を止めてひっくり返せた数を返します。つまりオセロの処理の根幹です。
これは無意識にオセロで人間がやっていることを明文化し、コンピュータに分かるようにすることそのものです。
こういう事がプログラミングをすると言うことで、人の無意識な部分を含めて明文化しないといけません。
それと今更かもしれませんが、オセロをプログラミングするのが苦手な人がいます。
アクションとか動くものを創るほうが楽しい人ですね。
なので、オセロを絶対にやる必然はありません。
将棋やチェスなどAI系が好きな人には凄く好まれる題材ではありますけどね。
【補足】
「全く知らない人にも分かるオセロ入門」と言うマニュアルを文章だけで書くのに等しいので、オセロの説明文が文章でスラスラ出てくるぐらい頭の中で整理されている必要があります。
別の色の石なら石をひっくり返します。それ以外なら処理を止めてひっくり返せた数を返します。つまりオセロの処理の根幹です。
これは無意識にオセロで人間がやっていることを明文化し、コンピュータに分かるようにすることそのものです。
こういう事がプログラミングをすると言うことで、人の無意識な部分を含めて明文化しないといけません。
それと今更かもしれませんが、オセロをプログラミングするのが苦手な人がいます。
アクションとか動くものを創るほうが楽しい人ですね。
なので、オセロを絶対にやる必然はありません。
将棋やチェスなどAI系が好きな人には凄く好まれる題材ではありますけどね。
【補足】
「全く知らない人にも分かるオセロ入門」と言うマニュアルを文章だけで書くのに等しいので、オセロの説明文が文章でスラスラ出てくるぐらい頭の中で整理されている必要があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
ゲーム作りはなかなか楽しいよね・・・
初心者の自分からすると、盤面が二次元配列である以上。
二次元配列(盤面)、白1、黒2、空0、壁-1、自分のスコア(int)、相手のスコア(int)、終了条件(int)
置く判定
1.0である。
2.置いた場合、スコアが伸びる
反転の判定
1.隣に他の色がある、自分の色にぶつかったら間にある色をかえる、壁にぶつかったらなにもしない
2.8方向調べて、スコアの伸び数を返す
パス:置かずにターンを終了させる
終了判定:互いがパスを選んだらゲーム終了。(*空のマスがあっても終了させる)
これなら、構造体やら再帰やらめんどうなことしなくてすむと思う。
初心者の自分からすると、盤面が二次元配列である以上。
二次元配列(盤面)、白1、黒2、空0、壁-1、自分のスコア(int)、相手のスコア(int)、終了条件(int)
置く判定
1.0である。
2.置いた場合、スコアが伸びる
反転の判定
1.隣に他の色がある、自分の色にぶつかったら間にある色をかえる、壁にぶつかったらなにもしない
2.8方向調べて、スコアの伸び数を返す
パス:置かずにターンを終了させる
終了判定:互いがパスを選んだらゲーム終了。(*空のマスがあっても終了させる)
これなら、構造体やら再帰やらめんどうなことしなくてすむと思う。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
if( BanData[ y ][ x ] != Color ){
これですと、もしcolorが1なら1以外という意味になってしまいますよね。
1ならば2、2ならば1という風にしなければなりませんよね。
この処理はどうすればいいのでしょうか?
ただの屍のようださんのやり方ですが、私一人だとそれでも書けない気がします・・・。
ソフト屋さんが一から教えて下さっているので、その方法でやろうと思います。
これですと、もしcolorが1なら1以外という意味になってしまいますよね。
1ならば2、2ならば1という風にしなければなりませんよね。
この処理はどうすればいいのでしょうか?
ただの屍のようださんのやり方ですが、私一人だとそれでも書けない気がします・・・。
ソフト屋さんが一から教えて下さっているので、その方法でやろうと思います。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
そこを上手く行かせるために処理の順番が重要なんですね。sadora3 さんが書きました:if( BanData[ y ][ x ] != Color ){
これですと、もしcolorが1なら1以外という意味になってしまいますよね。
1ならば2、2ならば1という風にしなければなりませんよね。
この処理はどうすればいいのでしょうか?
単一の答えしか無い==で処理できるものを先に処理して、複数の値が該当してしまう!=は一番最後です。
そうすれば、変な条件分岐は起きないはずですよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
int PutLine( int x , int y , int Way_x , int Way_y , int Color , int count){
if( BanData[ y ][ x ] == BAN ){ return count; }
else if( BanData[ y ][ x ] == Color ){ return count; }
else if( BanData[ y ][ x ] == WALL ){ return count; }
else if( BanData[ y ][ x ] != Color ){ BanData[ y ][ x ] = Color; }
return PutLine( x + Way_x , y + Way_y , Way_x , Way_y , Color , count + 1 );
}
戻り値はPutLine関数をそのまま書くことにしました。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
ごめんなさい。
話の間が開いたので、どこからの続きの話になるか探せてませんので、このママ強引に続けさせてもらうとして、この関数を呼び出す形で指定した場所から8方向に置く処理を作ってみてください。その時、置ける数のトータルもカウントしてください。
8つの方向は構造体配列を使うと簡単に作れます。
話の間が開いたので、どこからの続きの話になるか探せてませんので、このママ強引に続けさせてもらうとして、この関数を呼び出す形で指定した場所から8方向に置く処理を作ってみてください。その時、置ける数のトータルもカウントしてください。
8つの方向は構造体配列を使うと簡単に作れます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
回答が遅くなってしまったので今更感満載ですが、左上はおけそうだけど、どちらもおけない場所です。sadora3 さんが書きました: asdさんのテスト用の盤面の左上からどちらも裏返せますか?
白も黒も両方置けるのは右下ですよー(*´ヮ`)
Advanced Supporting Developer
無理やりこじつけ(ぉ
無理やりこじつけ(ぉ
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
理解力が乏しくてすみません。
「この関数を呼び出す形で指定した場所から8方向に置く処理」とありますが、PutLine関数の中は書き換わりますか?また、「置く処理」とは、色を反転させるのですよね?
「この関数を呼び出す形で指定した場所から8方向に置く処理」とありますが、PutLine関数の中は書き換わりますか?また、「置く処理」とは、色を反転させるのですよね?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
置く処理は自分の色を置いて、その時に自分の色に挟まれた逆の色を自分の色にひっくり返すことです。オセロの基本的なルールですよね?[追記・補正]
反転がない=置けない場合は置いたことを取り消する処理も出来れば入れてください。
PutLine関数の中は書き換わりますか? → 書き換える必要はないはずです。
度々質問されますが、オセロのルールを逸脱した機能を作ろうとした事はありません。
全てオセロのルールですので再確認をお願いします。
反転がない=置けない場合は置いたことを取り消する処理も出来れば入れてください。
PutLine関数の中は書き換わりますか? → 書き換える必要はないはずです。
度々質問されますが、オセロのルールを逸脱した機能を作ろうとした事はありません。
全てオセロのルールですので再確認をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
void AllWayPut(){
int StoneCount = 0;
struct AllWay{
int X;
int Y;
} Cheak[] = {
{ 0 , -1 }, { 1 , -1 }, { 1 , 0 }, { 1 , 1 },
{ 0 , 1 }, {-1 , 1 }, { -1 , 0 }, { -1 , - 1 },
};
if( BanData[ masuY ][ masuX ] == BAN ){
BanData[ masuY ][ masuX ] = KURO;
for(int i = 0; i < 8; i++ ){
StoneCount += PutLine( masuX + Cheak[i].X , masuY + Cheak[i].Y , Cheak[i].X , Cheak[i].Y , SIRO , 0 );
}
}
}
「置けない場合は置いたことを取り消する処理」はPutLine関数の中を書き換えますか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
置けない場合というのはどういう場合でしょうか?
「置けない場合は置いたことを取り消する処理」はPutLine関数の中を書き換えますか? → ほんとうに必要になりますか?
オセロの基本的なルールですが、「置けない場合は置いたことを取り消す場合」とはどういう場合にどの石に発生するのでしょうか?
【補足】
asdさんも書いてくれていますが、動作確認を自分でしてください。
私がOKだしたらOKだと思っているなら間違いです。
自分で動作確認して自信があったら「出来ました」であり、上手く行かなかったら「こういう問題があります」と書いてください。
テスト方法も考えて、テストルーチンも添えて掲載してもらったほうが良いでしょう。
私に任せすぎて思考停止していなか心配になって来ました。
「置けない場合は置いたことを取り消する処理」はPutLine関数の中を書き換えますか? → ほんとうに必要になりますか?
オセロの基本的なルールですが、「置けない場合は置いたことを取り消す場合」とはどういう場合にどの石に発生するのでしょうか?
【補足】
asdさんも書いてくれていますが、動作確認を自分でしてください。
私がOKだしたらOKだと思っているなら間違いです。
自分で動作確認して自信があったら「出来ました」であり、上手く行かなかったら「こういう問題があります」と書いてください。
テスト方法も考えて、テストルーチンも添えて掲載してもらったほうが良いでしょう。
私に任せすぎて思考停止していなか心配になって来ました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
void AllWayPut(){
int StoneCount = 0;
struct AllWay{
int X;
int Y;
}Cheak[] = {
{ 0 , -1 }, { 1 , -1 }, { 1 , 0 }, { 1 , 1 },
{ 0 , 1 }, {-1 , 1 }, { -1 , 0 }, { -1 , - 1 },
};
if( BanData[ masuY ][ masuX ] == BAN ){
BanData[ masuY ][ masuX ] = SIRO;
for( int i = 0 ; i < 8 ; i++ ){
StoneCount += PutLine( masuX + Cheak[i].X , masuY + Cheak[i].Y , Cheak[i].X , Cheak[i].Y , SIRO , 0 );
}
}
}
>反転がない=置けない場合は置いたことを取り消する処理も出来れば入れてください。
まず八方向に反転した後に、白石で挟まれていなかった場合の反転された石を黒石に戻すと思っていましたが、そもそも反転出来ない場合はその方向には反転しないのですね。
取り消す石は、白石で挟むために最初に置く白石一個だけですね。
これで八方向に石を置き、その置いた石の総数をカウントします。
反転出来ない方向の模索の仕方はどうすればいいのでしょうか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
インデントが間違っていますが、プログラムとしてはOKだと思います。
ただ、上にも書いた通りテストコード込みでお願いしたいです。
あと取り消す処理がないので、次のバージョンでは置けないときは取り消す処理と、ひっくり返した総数をAllWayPutの戻り値で返すようにしてください。
ただ、上にも書いた通りテストコード込みでお願いしたいです。
あと取り消す処理がないので、次のバージョンでは置けないときは取り消す処理と、ひっくり返した総数をAllWayPutの戻り値で返すようにしてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
すみません、インデントはどこがおかしいのでしょうか?
あとテストコードとはなんでしょうか?
あとテストコードとはなんでしょうか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
beatleさん作成の「投稿前チェックリスト チェック3 : インデントを揃えよう」を御覧ください。
「mixcpp/投稿前チェックリスト - PukiWiki」
http://uchan.net/w/index.php?mixcpp%2F% ... 5%B9%A5%C8
空白4個の字下げはタブ1個でも構いません。
>あとテストコードとはなんでしょうか?
asdさんが書いてくれたコードでメインを含めて動作確認するためのコードです。
動作確認のためには余分なコードもなく良いと思うのですが。
「mixcpp/投稿前チェックリスト - PukiWiki」
http://uchan.net/w/index.php?mixcpp%2F% ... 5%B9%A5%C8
空白4個の字下げはタブ1個でも構いません。
>あとテストコードとはなんでしょうか?
asdさんが書いてくれたコードでメインを含めて動作確認するためのコードです。
動作確認のためには余分なコードもなく良いと思うのですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
static int BanData[ BAN_TATE ][ BAN_YOKO ] =
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,0,1,1,1,1,1,1,1,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,1,1,1,1,1,1,0,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
};
while(ProcessLoop() == 0){
DrawBoard();
MouseRelate();
ScreenFlip();
}
int MouseRelate(){
int mouseX = 0;
int mouseY = 0;
GetMousePoint(&mouseX, &mouseY);
masuX = mouseX / BAN_SIZE;
masuY = mouseY / BAN_SIZE;
if((GetMouseInput() & MOUSE_INPUT_LEFT) != 0){ AllWayPut(); }
return 0;
}
int PutLine(int x, int y, int Way_x, int Way_y, int Color, int count){
if(BanData[ y ][ x ] == BAN){ return count; }
else if(BanData[ y ][ x ] == Color){ return count; }
else if(BanData[ y ][ x ] == WALL){ return count; }
else if(BanData[ y ][ x ] != Color){BanData[ y ][ x ] = Color;}
return PutLine(x + Way_x, y + Way_y, Way_x, Way_y, Color, count + 1);
}
int AllWayPut(){
int StoneCount = 0;
struct AllWay{
int X;
int Y;
}Cheak[] = {
{0, -1}, {1, -1}, {1, 0}, {1, 1 },
{0, 1}, {-1, 1}, {-1, 0}, {-1, - 1},
};
if(BanData[ masuY ][ masuX ] == BAN){
BanData[ masuY ][ masuX ] = SIRO;
for(int i = 0; i < 8; i++){
StoneCount += PutLine(masuX + Cheak[i].X, masuY + Cheak[i].Y, Cheak[i].X, Cheak[i].Y, SIRO, 0);
}
if(StoneCount == 0){BanData[ masuY ][ masuX ] = BAN;}
}
return StoneCount;
}
こういうことですか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
起動するだけで、動作確認が出来るソースコードと言う意味でテストコードと呼んでます。
asdさんもテスト用の盤面データを用意すると書いていますよね。
凝ったものなら、指定したパターンで置いてひっくり返した結果と事前に手作業で用意した結果データを付きあわせて異常がないかまでテストできると完璧です。
インデントに関しては、何故か全角空白文字になっていますがわざわざ変換していませんか?
ここの投稿は、そのまま受け付けてくれるはずです。
あとインデントのミスですが。 {}では1つ下げるが行われないといけません。
asdさんもテスト用の盤面データを用意すると書いていますよね。
凝ったものなら、指定したパターンで置いてひっくり返した結果と事前に手作業で用意した結果データを付きあわせて異常がないかまでテストできると完璧です。
インデントに関しては、何故か全角空白文字になっていますがわざわざ変換していませんか?
ここの投稿は、そのまま受け付けてくれるはずです。
あとインデントのミスですが。 {}では1つ下げるが行われないといけません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
なんどもすみません。まだテストコードというものが理解できません。具体的な例を見せてくれませんか?
>asdさんが書いてくれたコードでメインを含めて動作確認するためのコード
メインとはメインループのことですよね?
>asdさんが書いてくれたコードでメインを含めて動作確認するためのコード
メインとはメインループのことですよね?
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
テストコードってのは要するに「それをコピーペーストしてコンパイルすればすぐさま実行できるもの」ということだと思うよ
例えば上でsadora3さんが書いた
っていうのが本当に正しいか確かめようと思っても↑だけでは動作しないからいちいち他の部分まで作らないとダメだよねってことだと思うよ
例えば上でsadora3さんが書いた
void AllWayPut(){
int StoneCount = 0;
struct AllWay{
int X;
int Y;
}Cheak[] = {
{ 0 , -1 }, { 1 , -1 }, { 1 , 0 }, { 1 , 1 },
{ 0 , 1 }, {-1 , 1 }, { -1 , 0 }, { -1 , - 1 },
};
if( BanData[ masuY ][ masuX ] == BAN ){
BanData[ masuY ][ masuX ] = SIRO;
for( int i = 0 ; i < 8 ; i++ ){
StoneCount += PutLine( masuX + Cheak[i].X , masuY + Cheak[i].Y , Cheak[i].X , Cheak[i].Y , SIRO , 0 );
}
}
}
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
なるほど。ありがとうございます。
これが置けないときは取り消す処理と、戻り値にひっくり返した総数をAllWayPutの戻り値で返すようにしたプログラムです。
テストコードとはこういうことですね。
int AllWayPut(){
int StoneCount = 0;
struct AllWay{
int X;
int Y;
}Cheak[] = {
{0, -1}, {1, -1}, {1, 0}, {1, 1 },
{0, 1}, {-1, 1}, {-1, 0}, {-1, - 1},
};
if(BanData[ masuY ][ masuX ] == BAN){
BanData[ masuY ][ masuX ] = SIRO;
for(int i = 0; i < 8; i++){
StoneCount += PutLine(masuX + Cheak[i].X, masuY + Cheak[i].Y, Cheak[i].X, Cheak[i].Y, SIRO, 0);
}
if(StoneCount == 0){BanData[ masuY ][ masuX ] = BAN;}
}
return StoneCount;
}
#include "DxLib.h"
#define BAN_SIZE 64
#define WALL -1
#define BAN 0
#define SIRO 1
#define KURO 2
#define BAN_YOKO 10
#define BAN_TATE 10
void DrawInit();
void DrawBoard();
int MouseRelate();
int PutLine(int, int, int, int, int, int);
int AllWayPut();
static int GH_HAIKEI;
static int GH_SIRO;
static int GH_KURO;
static int GH_BAN;
static int masuX;
static int masuY;
static int BanData[ BAN_TATE ][ BAN_YOKO ] =
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,0,1,1,1,1,1,1,1,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,1,1,1,1,1,1,0,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
};
int ProcessLoop(){
if(ProcessMessage() != 0){ return -1; }
if(ClearDrawScreen() != 0){ return -1; }
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
ChangeWindowMode(TRUE);
SetGraphMode(640, 640, 32);
if(DxLib_Init() == -1 || SetDrawScreen(DX_SCREEN_BACK) != 0){ return -1; }
DrawInit();
while(ProcessLoop() == 0){
DrawBoard();
MouseRelate();
ScreenFlip();
}
DxLib_End();
return 0;
}
void DrawInit(){
GH_HAIKEI = LoadGraph( "画像/背景.png" );
GH_SIRO = LoadGraph( "画像/白.png" );
GH_KURO = LoadGraph( "画像/黒.png" );
GH_BAN = LoadGraph( "画像/将棋板.png" );
}
void DrawBoard(){
int x,y;
DrawGraph(0, 0, GH_HAIKEI, FALSE);
for(x = 1; x < BAN_YOKO; x++){
for(y = 1; y < BAN_TATE; y++){
switch(BanData[ y ][ x ]){
case BAN:
DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_BAN, TRUE);
break;
case SIRO:
DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_BAN, TRUE);
DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_SIRO, TRUE);
break;
case KURO:
DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_BAN, TRUE);
DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_KURO, TRUE);
break;
}
}
}
}
int MouseRelate(){
int mouseX = 0;
int mouseY = 0;
GetMousePoint(&mouseX, &mouseY);
masuX = mouseX / BAN_SIZE;
masuY = mouseY / BAN_SIZE;
if((GetMouseInput() & MOUSE_INPUT_LEFT) != 0){ AllWayPut(); }
return 0;
}
int PutLine(int x, int y, int Way_x, int Way_y, int Color, int count){
if(BanData[ y ][ x ] == BAN){ return count; }
else if(BanData[ y ][ x ] == Color){ return count; }
else if(BanData[ y ][ x ] == WALL){ return count; }
else if(BanData[ y ][ x ] != Color){BanData[ y ][ x ] = Color;}
return PutLine(x + Way_x, y + Way_y, Way_x, Way_y, Color, count + 1);
}
int AllWayPut(){
int StoneCount = 0;
struct AllWay{
int X;
int Y;
}Cheak[] = {
{0, -1}, {1, -1}, {1, 0}, {1, 1 },
{0, 1}, {-1, 1}, {-1, 0}, {-1, - 1},
};
if(BanData[ masuY ][ masuX ] == BAN){
BanData[ masuY ][ masuX ] = SIRO;
for(int i = 0; i < 8; i++){
StoneCount += PutLine(masuX + Cheak[i].X, masuY + Cheak[i].Y, Cheak[i].X, Cheak[i].Y, SIRO, 0);
}
if(StoneCount == 0){BanData[ masuY ][ masuX ] = BAN;}
}
return StoneCount;
}
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
お疲れ様でした。基本的な所は出来ていると思います。
と思ったらバグっています。ほんとにテストされましたか?
私が悪いところもあるんですが、テストしていなとしたら一番いけません。テストしていて問題が有り報告していないもの良くないです。
テスト結果を教えて欲しいと書いたはずです。
【補足】怒っているんじゃないですよ、テストが大事だということを分かって貰いたいだけです。
今回のように私もミスしますし、誰だってミスはあります。
ただ、プログラミングは仕様分析・設計・コーディング・テスト・デバッグの何れかが抜けても完成しません。
どれも大事なんです。そこを理解して欲しいのです。
PutLine()でひっくり返しの終端に相手石がなかったら、ひっくり返しの取り消しを入れ忘れてましたね。当方のオオボケでした。
途中で、そんな話もあったのに見逃してしまいました。
と言うことで改善案を検討してみてください。
それと画像がなくても実行できるようにお願いします。
※ MouseRelateと言う名前が意味がわかりません。
と思ったらバグっています。ほんとにテストされましたか?
私が悪いところもあるんですが、テストしていなとしたら一番いけません。テストしていて問題が有り報告していないもの良くないです。
テスト結果を教えて欲しいと書いたはずです。
【補足】怒っているんじゃないですよ、テストが大事だということを分かって貰いたいだけです。
今回のように私もミスしますし、誰だってミスはあります。
ただ、プログラミングは仕様分析・設計・コーディング・テスト・デバッグの何れかが抜けても完成しません。
どれも大事なんです。そこを理解して欲しいのです。
PutLine()でひっくり返しの終端に相手石がなかったら、ひっくり返しの取り消しを入れ忘れてましたね。当方のオオボケでした。
途中で、そんな話もあったのに見逃してしまいました。
と言うことで改善案を検討してみてください。
それと画像がなくても実行できるようにお願いします。
void DrawBoard(){
int x,y;
// DrawGraph(0, 0, GH_HAIKEI, FALSE);
for(x = 1; x < BAN_YOKO; x++){
for(y = 1; y < BAN_TATE; y++){
DrawBox(x * BAN_SIZE, y * BAN_SIZE, x * BAN_SIZE+BAN_SIZE-1, y * BAN_SIZE+BAN_SIZE-1, GetColor(128,128,0), TRUE );
switch(BanData[ y ][ x ]){
case BAN:
// DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_BAN, TRUE);
break;
case SIRO:
// DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_BAN, TRUE);
// DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_SIRO, TRUE);
DrawCircle(x*BAN_SIZE+BAN_SIZE/2, y*BAN_SIZE+BAN_SIZE/2, BAN_SIZE/2, GetColor(255,255,255), TRUE );
break;
case KURO:
// DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_BAN, TRUE);
// DrawGraph(x * BAN_SIZE, y * BAN_SIZE, GH_KURO, TRUE);
DrawCircle(x*BAN_SIZE+BAN_SIZE/2, y*BAN_SIZE+BAN_SIZE/2, BAN_SIZE/2, GetColor(0,0,0), TRUE );
break;
}
}
}
}
付記。【テストコードとは】
テストコードは出来れば、自動でテストが行われるのが望ましいんです。
なので、自動で置いて結果を表示して、作っておいた結果と等しいかチェックを繰り返してくれるとコードの正当性が評価しやすくなります。
あとテキストファイルに結果をログとして残す必要もありますし、DXライブラリでの表示も不要だったります。
今回は、そこまでしなくて良いですが、AI搭載など機能アップを測るのならぜひ作って欲しい所です。
※ MouseRelateと言う名前が意味がわかりません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
#include "DxLib.h"
#define WALL -1
#define BAN 0
#define SIRO 1
#define KURO 2
void DrawBoard();
void DrawCount();
int CeackLine(int, int, int, int, int, int);
int PutLine(int, int, int, int, int, int);
int AllWayPut();
static int Count;
static int BanData[ 10 ][ 10 ] =
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,0,1,1,1,1,1,1,1,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,1,1,1,1,1,1,0,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
};
int ProcessLoop(){
if(ProcessMessage() != 0){ return -1; }
if(ClearDrawScreen() != 0){ return -1; }
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
ChangeWindowMode(TRUE);
SetGraphMode(640, 640, 32);
if(DxLib_Init() == -1 || SetDrawScreen(DX_SCREEN_BACK) != 0){ return -1; }
while(ProcessLoop() == 0){
DrawBoard();
DrawCount();
ScreenFlip();
}
DxLib_End();
return 0;
}
void DrawBoard(){
int x,y;
DrawBox( 0, 0, 640, 640, GetColor( 255, 200, 140 ), TRUE ) ;
for(x = 1; x < 9; x++){
for(y = 1; y < 9; y++){
switch(BanData[ y ][ x ]){
case BAN:
DrawBox( x * 64, y * 64, x * 64 + 64, y * 64 + 64, GetColor( 0, 0, 0 ), FALSE );
break;
case SIRO:
DrawBox( x * 64, y * 64, x * 64 + 64, y * 64 + 64, GetColor( 0, 0, 0 ), FALSE );
DrawCircle( x * 64 + 32, y * 64 + 32, 25, GetColor( 255, 255, 255 ), TRUE );
break;
case KURO:
DrawBox( x * 64, y * 64, x * 64 + 64, y * 64 + 64, GetColor( 0, 0, 0 ), FALSE );
DrawCircle( x * 64 + 32, y * 64 + 32, 25, GetColor( 0, 0, 0 ), TRUE );
break;
}
}
}
}
void DrawCount(){
Count += AllWayPut();
DrawFormatString( 0, 0, 0, "%d", Count ) ;
}
int CheakLine(int x, int y, int Way_x, int Way_y, int Color, int EnemyColor){
if(BanData[ y ][ x ] == EnemyColor){
if(BanData[ y + Way_y ][ x + Way_x ] == Color){ return 1; }
if(BanData[ y + Way_y ][ x + Way_x ] == EnemyColor){
CheakLine(x + Way_x, y + Way_y, Way_x, Way_y, Color, EnemyColor);
}
else{ return 0; }
}
else{ return 0; }
return CheakLine(x + Way_x, y + Way_y, Way_x, Way_y, Color, EnemyColor);
}
int PutLine(int x, int y, int Way_x, int Way_y, int Color, int count){
if(BanData[ y ][ x ] == BAN){ return count; }
else if(BanData[ y ][ x ] == Color){ return count; }
else if(BanData[ y ][ x ] == WALL){ return count; }
else if(BanData[ y ][ x ] != Color){BanData[ y ][ x ] = Color;}
return PutLine(x + Way_x, y + Way_y, Way_x, Way_y, Color, count + 1);
}
int AllWayPut(){
int StoneCount = 0;
struct AllWay{
int X;
int Y;
}Cheak[] = {
{0, -1}, {1, -1}, {1, 0}, {1, 1 },
{0, 1}, {-1, 1}, {-1, 0}, {-1, - 1},
};
if(BanData[ 1 ][ 1 ] == BAN){
BanData[ 1 ][ 1 ] = SIRO;
for(int i = 0; i < 8; i++){
if(CheakLine(8 + Cheak[i].X, 8 + Cheak[i].Y, Cheak[i].X, Cheak[i].Y, SIRO, KURO) == 1){
StoneCount += PutLine(8 + Cheak[i].X, 8 + Cheak[i].Y, Cheak[i].X, Cheak[i].Y, SIRO, 0);
}
}
if(StoneCount == 0){BanData[ 1 ][ 1 ] = BAN;}
}
return StoneCount;
}
自動でテストが行われるというのはこういうことでしょうか?
これで石をひっくり返している途中に相手の石がなければひっくり返らなくなりました。
バグとはマウス関係のものでしたか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
前回は石を挟んでいないのにひっくり返す場合がありました。これはバグですね。
説明がありませんが、CheakLine()でガードしたという事でしょうか?
それでOKだと思います。
※ PutLine()だけで済ます方法もありますが、今回はこのままいきましょう。
で、テストに関しては何処をテストしたのか分かりづらいのでなんとかして欲しい所ですがsadora3さんには高難度になりそうなので今回は止めておきます。
テストを自動するということのイメージがどうにも伝わっていない様です。
なので、このプログラムをマウス操作で普通に置けるようにしてみてください。あと石を置けなかったらMessageBox()で置けませんとメッセージを出すことにしましょう。
それでバグがなければ終了ということでよろしいですか?
説明がありませんが、CheakLine()でガードしたという事でしょうか?
それでOKだと思います。
※ PutLine()だけで済ます方法もありますが、今回はこのままいきましょう。
で、テストに関しては何処をテストしたのか分かりづらいのでなんとかして欲しい所ですがsadora3さんには高難度になりそうなので今回は止めておきます。
テストを自動するということのイメージがどうにも伝わっていない様です。
なので、このプログラムをマウス操作で普通に置けるようにしてみてください。あと石を置けなかったらMessageBox()で置けませんとメッセージを出すことにしましょう。
それでバグがなければ終了ということでよろしいですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
#include "DxLib.h"
#define WALL -1
#define BAN 0
#define SIRO 1
#define KURO 2
void DrawBoard();
void MouseOperation();
int CeackLine(int, int, int, int, int, int);
int PutLine(int, int, int, int, int, int);
int AllWayPut();
static int Count;
static int masuX;
static int masuY;
static int BanData[ 10 ][ 10 ] =
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,0,1,1,1,1,1,1,1,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,0,0,0,0,0,0,2,-1},
{-1,2,1,1,1,1,1,1,0,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
};
int ProcessLoop(){
if(ProcessMessage() != 0){ return -1; }
if(ClearDrawScreen() != 0){ return -1; }
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
ChangeWindowMode(TRUE);
SetGraphMode(640, 640, 32);
if(DxLib_Init() == -1 || SetDrawScreen(DX_SCREEN_BACK) != 0){ return -1; }
while(ProcessLoop() == 0){
DrawBoard();
MouseOperation();
ScreenFlip();
}
DxLib_End();
return 0;
}
void DrawBoard(){
int x,y;
DrawBox( 0, 0, 640, 640, GetColor( 255, 200, 140 ), TRUE ) ;
for(x = 1; x < 9; x++){
for(y = 1; y < 9; y++){
switch(BanData[ y ][ x ]){
case BAN:
DrawBox( x * 64, y * 64, x * 64 + 64, y * 64 + 64, GetColor( 0, 0, 0 ), FALSE );
break;
case SIRO:
DrawBox( x * 64, y * 64, x * 64 + 64, y * 64 + 64, GetColor( 0, 0, 0 ), FALSE );
DrawCircle( x * 64 + 32, y * 64 + 32, 25, GetColor( 255, 255, 255 ), TRUE );
break;
case KURO:
DrawBox( x * 64, y * 64, x * 64 + 64, y * 64 + 64, GetColor( 0, 0, 0 ), FALSE );
DrawCircle( x * 64 + 32, y * 64 + 32, 25, GetColor( 0, 0, 0 ), TRUE );
break;
}
}
}
}
int CheakLine(int x, int y, int Way_x, int Way_y, int Color, int EnemyColor){
if(BanData[ y ][ x ] == EnemyColor){
if(BanData[ y + Way_y ][ x + Way_x ] == Color){ return 1; }
if(BanData[ y + Way_y ][ x + Way_x ] == EnemyColor){
CheakLine(x + Way_x, y + Way_y, Way_x, Way_y, Color, EnemyColor);
}
else{ return 0; }
}
else{ return 0; }
return CheakLine(x + Way_x, y + Way_y, Way_x, Way_y, Color, EnemyColor);
}
int PutLine(int x, int y, int Way_x, int Way_y, int Color, int count){
if(BanData[ y ][ x ] == BAN){ return count; }
else if(BanData[ y ][ x ] == Color){ return count; }
else if(BanData[ y ][ x ] == WALL){ return count; }
else if(BanData[ y ][ x ] != Color){BanData[ y ][ x ] = Color;}
return PutLine(x + Way_x, y + Way_y, Way_x, Way_y, Color, count + 1);
}
int AllWayPut(){
int StoneCount = 0;
struct AllWay{
int X;
int Y;
}Cheak[] = {
{0, -1}, {1, -1}, {1, 0}, {1, 1 },
{0, 1}, {-1, 1}, {-1, 0}, {-1, - 1},
};
if(BanData[ masuY ][ masuX ] == BAN){
BanData[ masuY ][ masuX ] = SIRO;
for(int i = 0; i < 8; i++){
if(CheakLine(masuX + Cheak[i].X, masuY + Cheak[i].Y, Cheak[i].X, Cheak[i].Y, SIRO, KURO) == 1){
StoneCount += PutLine(masuX + Cheak[i].X, masuY + Cheak[i].Y, Cheak[i].X, Cheak[i].Y, SIRO, 0);
}
}
if(StoneCount == 0){
BanData[ masuY ][ masuX ] = BAN;
MessageBox(GetMainWindowHandle(), "ここには石は置けません", "警告", MB_OK);
}
}
return StoneCount;
}
void MouseOperation(){
int mouseX = 0;
int mouseY = 0;
GetMousePoint(&mouseX, &mouseY);
masuX = mouseX / 64;
masuY = mouseY / 64;
if((GetMouseInput() & MOUSE_INPUT_LEFT) != 0){ Count += AllWayPut(); }
DrawFormatString( 0, 0, 0, "%d", Count );
}
ところで、なぜ置けませんとメッセージを出すようにしたのでしょうか?
また、「それでバグがなければ終了ということでよろしいですか?」と、ありますが、終了とはなんでしょうか?
何を終了するのですか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
>出来ました。マウス操作で置けるようにして、置けなければメッセージを出すようにしました。
>ところで、なぜ置けませんとメッセージを出すようにしたのでしょうか?
はい。テストOKだと思います。
なぜか?ですがメッセージを出さないと、なぜ置かれなかったのか明示されない事になります。
つまりテスト出来ないのです。
まぁ、ゲームとしても問題ありますよね。
>また、「それでバグがなければ終了ということでよろしいですか?」と、ありますが、終了とはなんでしょうか?
>何を終了するのですか?
このトピックのタイトルからして質問としては、これで終わりだと思っていたのですが、どうなんでしょうか?
今後、sadora3さんが、このオセロにどういう機能を追加するにしてもこのトピックとしては長くなったので一旦終了したほうが良いかなと思った次第です。
まだ、聞きたいことがあれば整理してもらって別トピックを立ちあげてもらった方が良いでしょう。
>ところで、なぜ置けませんとメッセージを出すようにしたのでしょうか?
はい。テストOKだと思います。
なぜか?ですがメッセージを出さないと、なぜ置かれなかったのか明示されない事になります。
つまりテスト出来ないのです。
まぁ、ゲームとしても問題ありますよね。
>また、「それでバグがなければ終了ということでよろしいですか?」と、ありますが、終了とはなんでしょうか?
>何を終了するのですか?
このトピックのタイトルからして質問としては、これで終わりだと思っていたのですが、どうなんでしょうか?
今後、sadora3さんが、このオセロにどういう機能を追加するにしてもこのトピックとしては長くなったので一旦終了したほうが良いかなと思った次第です。
まだ、聞きたいことがあれば整理してもらって別トピックを立ちあげてもらった方が良いでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
そうですね。分かりました。
長い間本当にありがとうございました。
また、なにかあればよろしくお願いします。
長い間本当にありがとうございました。
また、なにかあればよろしくお願いします。