オセロで、石を反転する範囲の捜索の仕方がわかりません
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
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
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
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
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
ごめんなさい。
話の間が開いたので、どこからの続きの話になるか探せてませんので、このママ強引に続けさせてもらうとして、この関数を呼び出す形で指定した場所から8方向に置く処理を作ってみてください。その時、置ける数のトータルもカウントしてください。
8つの方向は構造体配列を使うと簡単に作れます。
話の間が開いたので、どこからの続きの話になるか探せてませんので、このママ強引に続けさせてもらうとして、この関数を呼び出す形で指定した場所から8方向に置く処理を作ってみてください。その時、置ける数のトータルもカウントしてください。
8つの方向は構造体配列を使うと簡単に作れます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
回答が遅くなってしまったので今更感満載ですが、左上はおけそうだけど、どちらもおけない場所です。sadora3 さんが書きました: asdさんのテスト用の盤面の左上からどちらも裏返せますか?
白も黒も両方置けるのは右下ですよー(*´ヮ`)
Advanced Supporting Developer
無理やりこじつけ(ぉ
無理やりこじつけ(ぉ
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
理解力が乏しくてすみません。
「この関数を呼び出す形で指定した場所から8方向に置く処理」とありますが、PutLine関数の中は書き換わりますか?また、「置く処理」とは、色を反転させるのですよね?
「この関数を呼び出す形で指定した場所から8方向に置く処理」とありますが、PutLine関数の中は書き換わりますか?また、「置く処理」とは、色を反転させるのですよね?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
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
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
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
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
インデントが間違っていますが、プログラムとしてはOKだと思います。
ただ、上にも書いた通りテストコード込みでお願いしたいです。
あと取り消す処理がないので、次のバージョンでは置けないときは取り消す処理と、ひっくり返した総数をAllWayPutの戻り値で返すようにしてください。
ただ、上にも書いた通りテストコード込みでお願いしたいです。
あと取り消す処理がないので、次のバージョンでは置けないときは取り消す処理と、ひっくり返した総数をAllWayPutの戻り値で返すようにしてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
すみません、インデントはどこがおかしいのでしょうか?
あとテストコードとはなんでしょうか?
あとテストコードとはなんでしょうか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
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
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
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
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
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
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
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
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
>出来ました。マウス操作で置けるようにして、置けなければメッセージを出すようにしました。
>ところで、なぜ置けませんとメッセージを出すようにしたのでしょうか?
はい。テストOKだと思います。
なぜか?ですがメッセージを出さないと、なぜ置かれなかったのか明示されない事になります。
つまりテスト出来ないのです。
まぁ、ゲームとしても問題ありますよね。
>また、「それでバグがなければ終了ということでよろしいですか?」と、ありますが、終了とはなんでしょうか?
>何を終了するのですか?
このトピックのタイトルからして質問としては、これで終わりだと思っていたのですが、どうなんでしょうか?
今後、sadora3さんが、このオセロにどういう機能を追加するにしてもこのトピックとしては長くなったので一旦終了したほうが良いかなと思った次第です。
まだ、聞きたいことがあれば整理してもらって別トピックを立ちあげてもらった方が良いでしょう。
>ところで、なぜ置けませんとメッセージを出すようにしたのでしょうか?
はい。テストOKだと思います。
なぜか?ですがメッセージを出さないと、なぜ置かれなかったのか明示されない事になります。
つまりテスト出来ないのです。
まぁ、ゲームとしても問題ありますよね。
>また、「それでバグがなければ終了ということでよろしいですか?」と、ありますが、終了とはなんでしょうか?
>何を終了するのですか?
このトピックのタイトルからして質問としては、これで終わりだと思っていたのですが、どうなんでしょうか?
今後、sadora3さんが、このオセロにどういう機能を追加するにしてもこのトピックとしては長くなったので一旦終了したほうが良いかなと思った次第です。
まだ、聞きたいことがあれば整理してもらって別トピックを立ちあげてもらった方が良いでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロで、石を反転する範囲の捜索の仕方がわかりません
そうですね。分かりました。
長い間本当にありがとうございました。
また、なにかあればよろしくお願いします。
長い間本当にありがとうございました。
また、なにかあればよろしくお願いします。