オセロのプログラム制作過程
オセロのプログラム制作過程
引き続き・・・。
ステップインを繰り返す事で誤った式は全て直したと思うのですが、何故かまだエラーが。。
マウス入力待ちの関数を無限ループにしている事が原因なのかと思っていたのですが、ループを解いてもエラーは変わらずorz
正直何が間違っているのかよく分からない状態になってしまいました\(;o;)/
ステップインを繰り返す事で誤った式は全て直したと思うのですが、何故かまだエラーが。。
マウス入力待ちの関数を無限ループにしている事が原因なのかと思っていたのですが、ループを解いてもエラーは変わらずorz
正直何が間違っているのかよく分からない状態になってしまいました\(;o;)/
- 添付ファイル
-
- オセロ.zip
- (5.05 MiB) ダウンロード数: 177 回
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
Game_mainにwhileループがある事自体が間違いです。
なぜ必要なのでしょうか?
それと、このwhileはループ条件的に絶対に抜けません。
switchのbreakはswitchを抜けるもので、その外側のループには関与しません。
なぜ必要なのでしょうか?
それと、このwhileはループ条件的に絶対に抜けません。
switchのbreakはswitchを抜けるもので、その外側のループには関与しません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
whileにしておかないと幾度となく先手、後手の選択画面が出てきてしまって鬱陶しかったのですよね・・・。
選択自体を別の関数にすると、今度はUturnの値をGame_mainに渡す事が難しくなりそうで困ってました。
ループは終了関数作成の際に抜け出せるようにする予定でした。
取り敢えず先に互いにコマを置いていける環境を作りたかったので。
選択自体を別の関数にすると、今度はUturnの値をGame_mainに渡す事が難しくなりそうで困ってました。
ループは終了関数作成の際に抜け出せるようにする予定でした。
取り敢えず先に互いにコマを置いていける環境を作りたかったので。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
ゲームの状態を変化させる状態遷移と言う考えを使います。
参考として、
「C言語~ゲームプログラミングの館~ 34. メイン関数の書き方。」
http://dixq.net/g/37.html
ですね。
これはメインでの条件での分岐ですが同じことでGameMainでやっても構いません。これでTurnの処理は出来ると思います。
それと初期化時だけやる処理はフラグで管理しましょう。
で、状態やフラグ類はstaticな変数にしてください。関数を抜けても値は保持されます。
[追記]
既にタイトル表示で使ってますね。それと同じことです。
ただのローカル変数では関数を抜けると消えますが、staticな変数は関数を抜けても保持されます。
ただしstaticな変数の初期値はプログラム起動時に一回だけ初期化されるだけですので一度変更するとその値が保持されます。
最後にインデントが一部間違っていますので、全選択→詳細→選択範囲のフォーマットで整形しておいてください(整形しきれない場合は手直しを)。
参考として、
「C言語~ゲームプログラミングの館~ 34. メイン関数の書き方。」
http://dixq.net/g/37.html
ですね。
これはメインでの条件での分岐ですが同じことでGameMainでやっても構いません。これでTurnの処理は出来ると思います。
それと初期化時だけやる処理はフラグで管理しましょう。
で、状態やフラグ類はstaticな変数にしてください。関数を抜けても値は保持されます。
[追記]
既にタイトル表示で使ってますね。それと同じことです。
ただのローカル変数では関数を抜けると消えますが、staticな変数は関数を抜けても保持されます。
ただしstaticな変数の初期値はプログラム起動時に一回だけ初期化されるだけですので一度変更するとその値が保持されます。
最後にインデントが一部間違っていますので、全選択→詳細→選択範囲のフォーマットで整形しておいてください(整形しきれない場合は手直しを)。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
本当に何から何まですみません;
以下は雑談的なもので、お暇な時にでもお答え頂ければ有難いです。
ローグライク系のゲーム(チョコボの不思議なダンジョンや風来のシレンなど)は製作難易度としてはどの程度なのでしょう?
勿論ダンジョンの深さ等で難易度は変わっていくと思いますが、ゲームの骨格作成などを目安に意見を下さると有難いです。
もし簡単であれば、はさみ将棋とSLGの間にワンクッション入れる形にしようかなと。
今はオセロすらまともに作れない状態だからかもしれませんが、はさみ将棋を作り終わった段階でスムーズにSLG製作に行ける技術が備わっている自信がない・・・。
意外と大丈夫そうならそのままSLGに入るつもりではあります。
遠い先の話なのですが、気になってしまって。。
はさみ将棋は、コマをクリックした際に移動可能座標を画面上に表示等 SLGに必要な技術が詰まっていそうなので是が非でも作りたいと思っております!
以下は雑談的なもので、お暇な時にでもお答え頂ければ有難いです。
ローグライク系のゲーム(チョコボの不思議なダンジョンや風来のシレンなど)は製作難易度としてはどの程度なのでしょう?
勿論ダンジョンの深さ等で難易度は変わっていくと思いますが、ゲームの骨格作成などを目安に意見を下さると有難いです。
もし簡単であれば、はさみ将棋とSLGの間にワンクッション入れる形にしようかなと。
今はオセロすらまともに作れない状態だからかもしれませんが、はさみ将棋を作り終わった段階でスムーズにSLG製作に行ける技術が備わっている自信がない・・・。
意外と大丈夫そうならそのままSLGに入るつもりではあります。
遠い先の話なのですが、気になってしまって。。
はさみ将棋は、コマをクリックした際に移動可能座標を画面上に表示等 SLGに必要な技術が詰まっていそうなので是が非でも作りたいと思っております!
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
ローグライク系のゲームは結構難易度は高いです。
迷路生成だけでもこんな感じです。
「Racanhack コード解説」
http://racanhack.sourceforge.jp/rhdoc/index.html
この本がローグライクをテーマに書かれているみたいです。趣旨はデバッグですけどね。
「Amazon.co.jp: デバッグではじめるCプログラミング: 山本 貴光: 本」
http://www.amazon.co.jp/exec/obidos/ASIN/4798114197/
「ローグ型RPGを作る『デバッグではじめるCプログラミング』 | こどものもうそうblog」
http://blog.lv99.com/?eid=799310
ちなみにテキストタイプのローグだと思います。
それとこちらにUNIXオリジナルのローグの最終版を元にした「Rogue 5.4」を改良したソースコードがあります。
「Rogue」
http://yozvox.web.infoseek.co.jp/526F677565.html
テキストだけのものですが、このぐらいの規模があります。
もしグラフィックや不思議のダンジョン風のアクションや演出を入れれば何倍にも膨れ上がります。
RTSを目指して関連知識を身に付けたいなら敵AIに凝ったアクションゲームも良いかも知れませんね。
SLG,RPG,RTSはゲームの総合技術的な部分があるので、これらを作れる人はアクション、シューティング、アドベンチャーは一通り作れる技術力を持っていると私は思いますが、全部作ったほうが良いという意味ではなくSLG,RPG,RTSを作りながら学んでいくのも一つの方法です。
弱点を感じたら、そのとき簡単なアクション、シューティング、アドベンチャーに手を出してみるって感じで良いのでは?
迷路生成だけでもこんな感じです。
「Racanhack コード解説」
http://racanhack.sourceforge.jp/rhdoc/index.html
この本がローグライクをテーマに書かれているみたいです。趣旨はデバッグですけどね。
「Amazon.co.jp: デバッグではじめるCプログラミング: 山本 貴光: 本」
http://www.amazon.co.jp/exec/obidos/ASIN/4798114197/
「ローグ型RPGを作る『デバッグではじめるCプログラミング』 | こどものもうそうblog」
http://blog.lv99.com/?eid=799310
ちなみにテキストタイプのローグだと思います。
それとこちらにUNIXオリジナルのローグの最終版を元にした「Rogue 5.4」を改良したソースコードがあります。
「Rogue」
http://yozvox.web.infoseek.co.jp/526F677565.html
テキストだけのものですが、このぐらいの規模があります。
もしグラフィックや不思議のダンジョン風のアクションや演出を入れれば何倍にも膨れ上がります。
RTSを目指して関連知識を身に付けたいなら敵AIに凝ったアクションゲームも良いかも知れませんね。
SLG,RPG,RTSはゲームの総合技術的な部分があるので、これらを作れる人はアクション、シューティング、アドベンチャーは一通り作れる技術力を持っていると私は思いますが、全部作ったほうが良いという意味ではなくSLG,RPG,RTSを作りながら学んでいくのも一つの方法です。
弱点を感じたら、そのとき簡単なアクション、シューティング、アドベンチャーに手を出してみるって感じで良いのでは?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
この本かなり良さそうですね。
ローグを作りたいというより、普通に勉強になりそうなので購入を検討したいと思います。
ご紹介して下さったサイトを見た限り、全然簡単じゃないですね(笑
テキストタイプでこれだものなぁ・・・。
おっしゃる通りSLG,RPG,RTSは全ての集大成みたいなものでした。。
以前言われた通り、簡単なSLGから入って、徐々にゲームとしての質を高めて行く方が良さそうですね~。
さてご指摘のあった場所は全て訂正し、遂にエラーを吐く事が無くなりました!!
だがコマが置けない!!!
もう、意味がわからなすぎて・・・。
static で定義してある BanData はグローバル変数ですから Flip.cpp からでも値は変更可能ですよね?
それなら Board_Draw 関数をあちらこちらに設けなくても良いはず・・・。
そもそも Ban_Data の値自体初期化されないはずですし。
ステップインで追っていったら Ban_Data の値がしっかり変化していたのですが、ゲームになると微動だにせず・・。
何が怪しいのかさえ分からない状況に陥ったのは初めてです・・・。
ローグを作りたいというより、普通に勉強になりそうなので購入を検討したいと思います。
ご紹介して下さったサイトを見た限り、全然簡単じゃないですね(笑
テキストタイプでこれだものなぁ・・・。
おっしゃる通りSLG,RPG,RTSは全ての集大成みたいなものでした。。
以前言われた通り、簡単なSLGから入って、徐々にゲームとしての質を高めて行く方が良さそうですね~。
さてご指摘のあった場所は全て訂正し、遂にエラーを吐く事が無くなりました!!
だがコマが置けない!!!
もう、意味がわからなすぎて・・・。
static で定義してある BanData はグローバル変数ですから Flip.cpp からでも値は変更可能ですよね?
それなら Board_Draw 関数をあちらこちらに設けなくても良いはず・・・。
そもそも Ban_Data の値自体初期化されないはずですし。
ステップインで追っていったら Ban_Data の値がしっかり変化していたのですが、ゲームになると微動だにせず・・。
何が怪しいのかさえ分からない状況に陥ったのは初めてです・・・。
- 添付ファイル
-
- オセロ.zip
- (7.31 KiB) ダウンロード数: 135 回
Re: オセロのプログラム制作過程
Board.hの
は、変数宣言と実体の定義を同時に行っているため、
Board.hをincludeする度に、実体が作られます。
したがって、Board.cppがincludeして作られたBanDataと、
Flip.cppが(Flip.hを介して)includeして作られたBanDataは、別の変数になります。
なので、Flip()でいくらBanDataの値を変更しても、
Board_Draw()が参照しているBanDataとは別物ですから、描画には反映されません。
これを解決するには、
Board.hでは、externを使った変数宣言が必要になります。
externは外部にある変数を使用する事を宣言するためのものです。
【Board.h】
そして、BanDataの実体をどこかのソースファイルに1つだけ定義する必要があります。
例えば、
【Board.cpp】
とします。
※このとき、実体の定義にはstaticをつけてはいけません。
staticをつけると、その変数は、変数を定義したファイル内でしか参照できなくなるからです。
Board.hをincludeする度に、実体が作られます。
したがって、Board.cppがincludeして作られたBanDataと、
Flip.cppが(Flip.hを介して)includeして作られたBanDataは、別の変数になります。
なので、Flip()でいくらBanDataの値を変更しても、
Board_Draw()が参照しているBanDataとは別物ですから、描画には反映されません。
これを解決するには、
Board.hでは、externを使った変数宣言が必要になります。
externは外部にある変数を使用する事を宣言するためのものです。
【Board.h】
// 盤のデータ
extern int BanData[ BAN_HEIGHT ][ BAN_WIDTH ]; // 宣言のみ
/*
static int BanData[ BAN_HEIGHT ][ BAN_WIDTH ] =
{
(略)
} ;
*/
例えば、
【Board.cpp】
static int GHandle1;
static int GHandle2;
static int GHandle3;
static int GHandle4;
// BanDataの実体定義
int BanData[ BAN_HEIGHT ][ BAN_WIDTH ] =
{
{ -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, 2, 1, 0, 0, 0, -1 } ,
{ -1, 0, 0, 0, 1, 2, 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 }
} ;
※このとき、実体の定義にはstaticをつけてはいけません。
staticをつけると、その変数は、変数を定義したファイル内でしか参照できなくなるからです。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
staticは前回書いた話しですね。
http://dixq.net/forum/viewtopic.php?f=3&t=8520#p70041
この問題#includeの働きについて説明しておきましょう。
#includeはソースファイルにヘッダファイルの内容を組み込みます。この組み込みってのが何かと言うとコピペと同じです。
なのでヘッダを組み込んだソースファイルに全てコピペされてコンパイルされると思ってください。
実行ファイルは次のような過程を踏んで作成されます。
ソースファイル、ヘッダファイル
↓
[プリコンパイル] ヘッダを#includeして#defineマクロを展開、#ifなどのマクロ処理を行う。
↓
中間ソースファイル ← cppの数だけ出来る。つまりヘッダにstatic変数があるとincludeしたcppの数だけ同じstatic変数が宣言される。
↓
[コンパイル]
↓
オブジェクトファイル ← cppの数だけ出来る。includeしたcppの数だけ同じstatic変数が宣言されたまま。
↓
[リンク] オブジェクトとライブラリを結合する。
↓
実行ファイル← 1つにまとまるが、includeしたcppの数だけ同じstatic変数が宣言されたまま。
http://dixq.net/forum/viewtopic.php?f=3&t=8520#p70041
この問題#includeの働きについて説明しておきましょう。
#includeはソースファイルにヘッダファイルの内容を組み込みます。この組み込みってのが何かと言うとコピペと同じです。
なのでヘッダを組み込んだソースファイルに全てコピペされてコンパイルされると思ってください。
実行ファイルは次のような過程を踏んで作成されます。
ソースファイル、ヘッダファイル
↓
[プリコンパイル] ヘッダを#includeして#defineマクロを展開、#ifなどのマクロ処理を行う。
↓
中間ソースファイル ← cppの数だけ出来る。つまりヘッダにstatic変数があるとincludeしたcppの数だけ同じstatic変数が宣言される。
↓
[コンパイル]
↓
オブジェクトファイル ← cppの数だけ出来る。includeしたcppの数だけ同じstatic変数が宣言されたまま。
↓
[リンク] オブジェクトとライブラリを結合する。
↓
実行ファイル← 1つにまとまるが、includeしたcppの数だけ同じstatic変数が宣言されたまま。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
ファイル分割や大規模ゲームの作るにおいて、他にも気になるところを書いておきます。
[title.cpp]
・変数名が雑。GHandle5とかはghTitleとか意味のある名前にしましょう。プログラムが長くなると自分で苦しむことになります。
・インデントが適当。後々バグを追いかけるときに苦労しますよ。
・ローカル変数でのoldinputに意味があるのか?なんのためのoldinputなのかを考えてみてください。
・描画と制御は分けましょう。d.3章 ゲームの設計と分割コンパイル(1) に書いてある通りに作ると大きなゲームになった時にバグの問題を減らせます。
ただし、いつでもこれに従わないといけないわけではありませんが、こう書けるところはこう描くべきです。
[Search.cpp]
・ボード(BanData)の情報は引数で貰いましょう。
・(3 - turn)を関数化することをお勧めします(他の人に分かりづらい=自分でも後で見ると分かりづらい)
・turnと石の色と自分がどちらの色なのかとか本来意味的に別のものを同一に扱っていませんか?
・本来ボード処理内にあって良い処理じゃないでしょうか?別ファイルに分けり意味がありません(ファイル分割のしすぎ)。
意味のある単位でファイルを分けるのが良いとされています。この処理のボード処理の一環では?
[Mouse.cpp]
・これも本来ボード処理内にあって良い処理じゃないでしょうか?
[Game.h]
・無意味にincludeしすぎです。全部のヘッダを見直しましょう。
#include "Mouse.h"
#include "CPU_AI.h"
#include "Board.h"
はcpp側でincludeしてください。必要なものは必要なcppでかでincludeすべきです。
・int Game_first();はなんでしょうか?
[Game.cpp]
・Game_main()だったり、title()だったり、Board_Draw()だったり統一性がありません。
・Uturnをポインタで渡すのはやめたほうが良いのでは、戻り値でUturの変更を処理しましょう。
・Uturnがstatic変数じゃないので関数が呼ばれるたびに毎回0に戻ります。
[Flip.cpp]
・これも本来ボード処理内にあって良い処理じゃないでしょうか?
・コメントを書いてもらっても良いですか?
(dx - x) * 5 + ((dy - y) + 10)
とかコメントなしには理解できません。
[Board.h]
・static int BanData[ BAN_HEIGHT ][ BAN_WIDTH ] はcppに移動。
・同じようなのをあちこちで定義しないこと。
#define BLACK 1 // 黒コマ
#define WHITE 2 // 白コマ
[Board.cpp]
・GHandle1~4も名前をちゃんと付けましょう。
以上長々と書きましたが修正するときに修正が終わったか確認リストを作ってチェックするようにしてくださいね。
[title.cpp]
・変数名が雑。GHandle5とかはghTitleとか意味のある名前にしましょう。プログラムが長くなると自分で苦しむことになります。
・インデントが適当。後々バグを追いかけるときに苦労しますよ。
・ローカル変数でのoldinputに意味があるのか?なんのためのoldinputなのかを考えてみてください。
・描画と制御は分けましょう。d.3章 ゲームの設計と分割コンパイル(1) に書いてある通りに作ると大きなゲームになった時にバグの問題を減らせます。
ただし、いつでもこれに従わないといけないわけではありませんが、こう書けるところはこう描くべきです。
[Search.cpp]
・ボード(BanData)の情報は引数で貰いましょう。
・(3 - turn)を関数化することをお勧めします(他の人に分かりづらい=自分でも後で見ると分かりづらい)
・turnと石の色と自分がどちらの色なのかとか本来意味的に別のものを同一に扱っていませんか?
・本来ボード処理内にあって良い処理じゃないでしょうか?別ファイルに分けり意味がありません(ファイル分割のしすぎ)。
意味のある単位でファイルを分けるのが良いとされています。この処理のボード処理の一環では?
[Mouse.cpp]
・これも本来ボード処理内にあって良い処理じゃないでしょうか?
[Game.h]
・無意味にincludeしすぎです。全部のヘッダを見直しましょう。
#include "Mouse.h"
#include "CPU_AI.h"
#include "Board.h"
はcpp側でincludeしてください。必要なものは必要なcppでかでincludeすべきです。
・int Game_first();はなんでしょうか?
[Game.cpp]
・Game_main()だったり、title()だったり、Board_Draw()だったり統一性がありません。
・Uturnをポインタで渡すのはやめたほうが良いのでは、戻り値でUturの変更を処理しましょう。
・Uturnがstatic変数じゃないので関数が呼ばれるたびに毎回0に戻ります。
前に書いた、これらの事が何も反映されていません。これはメインでの条件での分岐ですが同じことでGameMainでやっても構いません。これでTurnの処理は出来ると思います。
それと初期化時だけやる処理はフラグで管理しましょう。
で、状態やフラグ類はstaticな変数にしてください。関数を抜けても値は保持されます。
[追記]
既にタイトル表示で使ってますね。それと同じことです。
ただのローカル変数では関数を抜けると消えますが、staticな変数は関数を抜けても保持されます。
ただしstaticな変数の初期値はプログラム起動時に一回だけ初期化されるだけですので一度変更するとその値が保持されます。
[Flip.cpp]
・これも本来ボード処理内にあって良い処理じゃないでしょうか?
・コメントを書いてもらっても良いですか?
(dx - x) * 5 + ((dy - y) + 10)
とかコメントなしには理解できません。
[Board.h]
・static int BanData[ BAN_HEIGHT ][ BAN_WIDTH ] はcppに移動。
・同じようなのをあちこちで定義しないこと。
#define BLACK 1 // 黒コマ
#define WHITE 2 // 白コマ
[Board.cpp]
・GHandle1~4も名前をちゃんと付けましょう。
以上長々と書きましたが修正するときに修正が終わったか確認リストを作ってチェックするようにしてくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
>a5uaさん
externにする事で無事ひっくり返す事が出来ました!
分かり易い解説までして下さって本当に有難う御座いますm(_ _)m
>ソフト屋さん
[title.cpp]
・変数名修正しました。
・インデントは以前におっしゃって頂いた方法を使って整形したのですが、独学故いまいち綺麗なソースコード
というものが分かりません。
それでも一応思いつく所は手直ししましたが、まだ駄目な部分は多々あるかと思います。
出来ればご指摘をして頂けると助かります。
・Mouse.cppから単純にコピペしたのが間違いでした。Title.cppは一回限りの起動ですから今の所全く必要
ありませんでした。
・修正しました。分ける大切さは分かりますし、実践しているつもりだったのですが・・・見落としてました。
[Search.cpp]
・引数で貰うという事は呼び出し側がボードの情報を渡すという事ですよね。
Search(BanData[][])という感じで渡せれば大丈夫でしょうか?
・変更してみました。
・turnと石の色など同一に扱ってました・・・。これだと駄目でしたでしょうか・・・。。
・意味のある分け方がまだ分からず、取り敢えず分けてしまっていました。
一緒に致しました。
[Mouse.cpp]
・直しました。 ここでは書かれていなかったため手を付けませんでしたが、ユーザー側の入力関数もボード
に入れるとなるとCPU側の関数もボード内に入れた方が宜しいでしょうか?
[Game.h]
・修正しました。
・以前ゲーム初期化関数を作ろうとして失敗した残骸ですorz 削除しました。
[Game.cpp]
・どの様なネーミングにすれば統一感を出せますでしょうか・・・?
・ちょっと背伸びしてポインタにも手を出しておこうかなと思ったのですが、駄目でしたか。大人しく戻り値
で調整します。
・Uturnはstatic変数にしてありますが・・・。何か書き方がおかしかったでしょうか?
以下もソフト屋さんの指示通りに変更したつもりで、その結果バグも起きなくなったと感謝していたのですが
やはり書き方がおかしかったのでしょうか・・・。
[Flip.cpp]
・確かにボードに関連する処理でした。修正しました。
・一応コメントはあったのですが・・・追記しておきました。
この式の掛けている値などは特に意味はないです。(*10とかでも同じ)
ただ単に置きたい座標から周囲にあった相手コマの座標の差分をX,Yそれぞれ求め、各々に別の値を加え合計する事で
ひっくり返したい方向をswitch文で一方向に定める感じの式です。
[Board.h]
・変更しました。
・削除しました。
[Board.cpp]
・名前変更しました。
ただ今ユーザー側がずっと俺のターン状態なため、ちょっとFlipとCPU_AIを見直してきます・・・orz
externにする事で無事ひっくり返す事が出来ました!
分かり易い解説までして下さって本当に有難う御座いますm(_ _)m
>ソフト屋さん
[title.cpp]
・変数名修正しました。
・インデントは以前におっしゃって頂いた方法を使って整形したのですが、独学故いまいち綺麗なソースコード
というものが分かりません。
それでも一応思いつく所は手直ししましたが、まだ駄目な部分は多々あるかと思います。
出来ればご指摘をして頂けると助かります。
・Mouse.cppから単純にコピペしたのが間違いでした。Title.cppは一回限りの起動ですから今の所全く必要
ありませんでした。
・修正しました。分ける大切さは分かりますし、実践しているつもりだったのですが・・・見落としてました。
[Search.cpp]
・引数で貰うという事は呼び出し側がボードの情報を渡すという事ですよね。
Search(BanData[][])という感じで渡せれば大丈夫でしょうか?
・変更してみました。
・turnと石の色など同一に扱ってました・・・。これだと駄目でしたでしょうか・・・。。
・意味のある分け方がまだ分からず、取り敢えず分けてしまっていました。
一緒に致しました。
[Mouse.cpp]
・直しました。 ここでは書かれていなかったため手を付けませんでしたが、ユーザー側の入力関数もボード
に入れるとなるとCPU側の関数もボード内に入れた方が宜しいでしょうか?
[Game.h]
・修正しました。
・以前ゲーム初期化関数を作ろうとして失敗した残骸ですorz 削除しました。
[Game.cpp]
・どの様なネーミングにすれば統一感を出せますでしょうか・・・?
・ちょっと背伸びしてポインタにも手を出しておこうかなと思ったのですが、駄目でしたか。大人しく戻り値
で調整します。
・Uturnはstatic変数にしてありますが・・・。何か書き方がおかしかったでしょうか?
以下もソフト屋さんの指示通りに変更したつもりで、その結果バグも起きなくなったと感謝していたのですが
やはり書き方がおかしかったのでしょうか・・・。
[Flip.cpp]
・確かにボードに関連する処理でした。修正しました。
・一応コメントはあったのですが・・・追記しておきました。
この式の掛けている値などは特に意味はないです。(*10とかでも同じ)
ただ単に置きたい座標から周囲にあった相手コマの座標の差分をX,Yそれぞれ求め、各々に別の値を加え合計する事で
ひっくり返したい方向をswitch文で一方向に定める感じの式です。
[Board.h]
・変更しました。
・削除しました。
[Board.cpp]
・名前変更しました。
ただ今ユーザー側がずっと俺のターン状態なため、ちょっとFlipとCPU_AIを見直してきます・・・orz
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
混乱させて、ごめんなさい古いソースコードを見ていたみたいです。
[title.cpp]
・インデントは以前におっしゃって頂いた方法を使って整形したのですが、独学故いまいち綺麗なソースコードというものが分かりません。
それでも一応思いつく所は手直ししましたが、まだ駄目な部分は多々あるかと思います。出来ればご指摘をして頂けると助かります。
少なくともGame.cppのswtichのcaseは字下げ(インデントしすぎ)だと思います。
1つのifやforやswitchで1つ下げるぐらいが適度です。
[Search.cpp]
・引数で貰うという事は呼び出し側がボードの情報を渡すという事ですよね。
Search(BanData[][])という感じで渡せれば大丈夫でしょうか?
int Search(int [][BAN_WIDTH],int,int,int);と定義する必要があります。
で呼び出しは、Search(BanData, x, y, T)と言った感じになります。
・turnと石の色など同一に扱ってました・・・。これだと駄目でしたでしょうか・・・。。
そうですね。ターンは自分かAIかの区分だと思いますし、石の色はWHITEかBLACKですよね。
本来別のものですよね。コードを短くする意味はあるかも知れませんが、可読性は下げていると思います。
短いコードで書くことを追求せずに分りやすいコードを書く練習をしてみませんか?
[Mouse.cpp]
・直しました。 ここでは書かれていなかったため手を付けませんでしたが、ユーザー側の入力関数もボード
に入れるとなるとCPU側の関数もボード内に入れた方が宜しいでしょうか?
AIは大きくなるかも知れないので分離したほうが良いと思います。
[Game.cpp]
・Game_main()だったり、title()だったり、Board_Draw()だったり統一性がありません。
初期化 Init,Initialize
計算(処理) Main,Calc
描画 Draw,Graph
終了 End,Finalize
など各ソールファイルで似た役目のものは同じ名前を持つべきです。
Game_Main()でいくなら、Title_Main()、Borad_Main()でしょう。
それとGame_Draw()、Title_Draw()、Borad_Draw()もお忘れなく。
・Uturnはstatic変数にしてありますが・・・。何か書き方がおかしかったでしょうか?
失礼しました。これは違うバージョンのソースの見間違いです。
[title.cpp]
・インデントは以前におっしゃって頂いた方法を使って整形したのですが、独学故いまいち綺麗なソースコードというものが分かりません。
それでも一応思いつく所は手直ししましたが、まだ駄目な部分は多々あるかと思います。出来ればご指摘をして頂けると助かります。
少なくともGame.cppのswtichのcaseは字下げ(インデントしすぎ)だと思います。
1つのifやforやswitchで1つ下げるぐらいが適度です。
[Search.cpp]
・引数で貰うという事は呼び出し側がボードの情報を渡すという事ですよね。
Search(BanData[][])という感じで渡せれば大丈夫でしょうか?
int Search(int [][BAN_WIDTH],int,int,int);と定義する必要があります。
で呼び出しは、Search(BanData, x, y, T)と言った感じになります。
・turnと石の色など同一に扱ってました・・・。これだと駄目でしたでしょうか・・・。。
そうですね。ターンは自分かAIかの区分だと思いますし、石の色はWHITEかBLACKですよね。
本来別のものですよね。コードを短くする意味はあるかも知れませんが、可読性は下げていると思います。
短いコードで書くことを追求せずに分りやすいコードを書く練習をしてみませんか?
[Mouse.cpp]
・直しました。 ここでは書かれていなかったため手を付けませんでしたが、ユーザー側の入力関数もボード
に入れるとなるとCPU側の関数もボード内に入れた方が宜しいでしょうか?
AIは大きくなるかも知れないので分離したほうが良いと思います。
[Game.cpp]
・Game_main()だったり、title()だったり、Board_Draw()だったり統一性がありません。
初期化 Init,Initialize
計算(処理) Main,Calc
描画 Draw,Graph
終了 End,Finalize
など各ソールファイルで似た役目のものは同じ名前を持つべきです。
Game_Main()でいくなら、Title_Main()、Borad_Main()でしょう。
それとGame_Draw()、Title_Draw()、Borad_Draw()もお忘れなく。
・Uturnはstatic変数にしてありますが・・・。何か書き方がおかしかったでしょうか?
失礼しました。これは違うバージョンのソースの見間違いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
[Search.cpp]
・BanDataをBoard.cppに移動して定義していたため、その方法だとCPU_AIからBanDataを覗けないとエラーが
出てしまいました。
BanDataをBoard.hに移すべきでしょうか・・・?
・TurnをMykomaに変更してみました。こういう意味ですよね・・・?見当違いな事してましたらご指摘下さい
m(_ _)m
[Game.cpp]
・名前については色々と変更してみましたが、まだしっくり来てない感じがあります・・・。
Game_で統一してみたりとか試行錯誤はしているのですがorz
取り敢えず修正した物を添付しておきます。
現在確認済みの問題点
・まだ置ける箇所があるにも関わらず置けなくなる。(エラーで固まっている訳ではない)
・パス表示が出ない。
・試合終了しているのに終了画面に飛ばない。
課題点
・CPUのAIがあまりにもお馬鹿過ぎるので修正必須。
・Check_Endからの「置ける場所確認関数」達が鬱陶しいので、どうにかSaerch,Flipと合体させたい。
(挫折気味)
・BanDataをBoard.cppに移動して定義していたため、その方法だとCPU_AIからBanDataを覗けないとエラーが
出てしまいました。
BanDataをBoard.hに移すべきでしょうか・・・?
・TurnをMykomaに変更してみました。こういう意味ですよね・・・?見当違いな事してましたらご指摘下さい
m(_ _)m
[Game.cpp]
・名前については色々と変更してみましたが、まだしっくり来てない感じがあります・・・。
Game_で統一してみたりとか試行錯誤はしているのですがorz
取り敢えず修正した物を添付しておきます。
現在確認済みの問題点
・まだ置ける箇所があるにも関わらず置けなくなる。(エラーで固まっている訳ではない)
・パス表示が出ない。
・試合終了しているのに終了画面に飛ばない。
課題点
・CPUのAIがあまりにもお馬鹿過ぎるので修正必須。
・Check_Endからの「置ける場所確認関数」達が鬱陶しいので、どうにかSaerch,Flipと合体させたい。
(挫折気味)
- 添付ファイル
-
- オセロ.zip
- (5.92 MiB) ダウンロード数: 163 回
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
関数名の迷走が見て取れますね。
とりあえず関数名ですが、ファイル名+機能名を提案します。
ファイル名+機能名にして違和感があるならファイル名の命名に問題があるか関数を格納しているファイルが違うかです。
Screen.hを例に書いてみましょう。
分けわかりませんね。
特にScreen_Finishが名前と役割がくちがっています。
そこで、こんなのはどうでしょう?
Screenと言う名前が良いかは私も悩みどころですが、Title自体をファイル名にした方が良いのかも知れません。
そうするとこうなります。
EndTitleはわざと名前をEndから始めています。
今気づいた事も書いてありますので、よろしくお願いします。
あとバグ取りよりもコードの見やすさを優先して行っています。
[Screen.h/cpp]
・cppファイルで関数ごとに機能説明のコメントが欲しいですね。他のcppファイルも同様に。一部はあるみたいですが。
・MenuElement1つで兼ねるべきではないですね。必要に応じてファイルを分けるべきでしょう。
・外部公開の必要のない変数はstaticを付けましょう。MenuElementとか。
・MenuElementって名前も内容を表してないですね。再考を望みます。
・EndTitle_MainとTitle_Mainは処理がほとんど同じなので内部関数として共通化を検討してください。MenuElementを引数に使うと何とかなりませんか?
[Board.h/cpp]
>・BanDataをBoard.cppに移動して定義していたため、その方法だとCPU_AIからBanDataを覗けないとエラーが出てしまいました。
BanDataをBoard.hに移すべきでしょうか・・・?
そういう場合にこそ引数で渡してください。
Board.cppからBanDataのポインタを貰ってAIに受渡しましょう(要専用関数)。
・Flip()とか外部から呼ばれない関数もヘッダで公開してします。内部関数(static)にしてください。
・関数名にBoard_を付けてくださいね(内部関数を除く)。
>・TurnをMykomaに変更してみました。こういう意味ですよね・・・?見当違いな事してましたらご指摘下さい
> m(_ _)m
MyKomaと言うかCPUも使うのでKomaが正しいのでは?
そうですね。こうしたらどうでしょうか?
Turn ← MY_TURNかCPU_TURNかの区別の変数。
Board_SetMyKoma(koma)で自分のコマの色を設定。
Board_GetKoma(Turn)でコマの色が返る関数。今自分のターンなら自分のコマの色。
Board_GetEnemyKoma(Turn)で対戦相手のコマの色が返る関数。今自分のターンならCPUのコマの色。
あとこれらの関数の中で、3 - Mykoma;とかはなるべくやめてif文で記述しましょう。
・やはりcaseの値をenumしましょう。
・Search()の中のendと言う変数名が意味的に変では?見てみると全部の関数で戻り値がendになっています。ちゃんと名前に意味を持たせ抹消。
・Flip()のインデントが問題。
case 4 : while (1){
は行を分けてください。
・Flip()の(dx - x) * 5 + ((dy - y) + 10) の計算はややこしくしているだけだと思います。
int x,int yの引数が-1,0,1と変化するのに合わせて処理するだけですよね?
こんなテーブルを書いてやると簡単になりませんか?
これを使えば、すごくFlipがシンプルになると思います。考えてみてください。
int Flip(int dx,int dy,int KomaVectorIndex,int MyKoma)
・Search_End()やFlip_End()はSearch()やFlip()と引数だけで動作を変えれませんか?ループ回数の制限とかすればできそうな気が。
・Check_Winner()でBLACKならu(User?)って事になっているけど違うのでは?u,cもちゃんと名前をつけましょう。
と言うよりユーザーは黒固定?それも問題かと。
オセロの公式ルール:黒が先手です。つまり一手目を打つのは黒です。
[Main.cpp]
・func_stateの数値はenum定義しましょう。
・各関数の戻り値もenum定義しましょう。
・Check_Winner()はfunc_state=98;にするときに呼び出してその時点で98,99,100を決めるべきでしょう。
・Game_Finishを何度も呼び出すのは止めましょう。Game_Finishの戻り値を変数に保存すれば呼び出すのは毎フレーム1回で良いはずです。
とりあえずインデントしすぎなので、
このぐらいにしてください。
ながくなりましが、直せるところを直してからバグ取りにしましょう(プログラムがシンプルに成れば、それだけバグは取りやすくなります)。
とりあえず関数名ですが、ファイル名+機能名を提案します。
ファイル名+機能名にして違和感があるならファイル名の命名に問題があるか関数を格納しているファイルが違うかです。
Screen.hを例に書いてみましょう。
//関数のプロトタイプ宣言
void Screen_init(); //Game_Screen_init
void Screen_TitleDraw(); //Game_title_Draw
int Screen_TitleMain(); //Game_title_main
void Screen_GameVictoryDraw(); //Game_Victory_Draw
void Screen_GameOverDraw(); //Game_Over_Draw
void Screen_GameDrawDraw(); //Game_Draw_Draw
int Screen_Finish(); //Game_Finish
特にScreen_Finishが名前と役割がくちがっています。
そこで、こんなのはどうでしょう?
//関数のプロトタイプ宣言
void Screen_init(); //Game_Screen_init
void Screen_TitleDraw(); //Game_title_Draw
int Screen_TitleMain(); //Game_title_main
void Screen_EndTitleWinDraw(); //Game_Victory_Draw
void Screen_EndTitleLoseDraw(); //Game_Over_Draw
void Screen_EndTitleDrawDraw(); //Game_Draw_Draw
int Screen_EndTitleMain(); //Game_Finish
そうするとこうなります。
//関数のプロトタイプ宣言
void Title_init(); //Game_Screen_init
void Title_Draw(); //Game_title_Draw
int Title_Main(); //Game_title_main
void EndTitle_WinDraw(); //Game_Victory_Draw
void EndTitle_LoseDraw(); //Game_Over_Draw
void EndTitle_DrawDraw(); //Game_Draw_Draw
int EndTitle_Main(); //Game_Finish
今気づいた事も書いてありますので、よろしくお願いします。
あとバグ取りよりもコードの見やすさを優先して行っています。
[Screen.h/cpp]
・cppファイルで関数ごとに機能説明のコメントが欲しいですね。他のcppファイルも同様に。一部はあるみたいですが。
・MenuElement1つで兼ねるべきではないですね。必要に応じてファイルを分けるべきでしょう。
・外部公開の必要のない変数はstaticを付けましょう。MenuElementとか。
・MenuElementって名前も内容を表してないですね。再考を望みます。
・EndTitle_MainとTitle_Mainは処理がほとんど同じなので内部関数として共通化を検討してください。MenuElementを引数に使うと何とかなりませんか?
[Board.h/cpp]
>・BanDataをBoard.cppに移動して定義していたため、その方法だとCPU_AIからBanDataを覗けないとエラーが出てしまいました。
BanDataをBoard.hに移すべきでしょうか・・・?
そういう場合にこそ引数で渡してください。
Board.cppからBanDataのポインタを貰ってAIに受渡しましょう(要専用関数)。
・Flip()とか外部から呼ばれない関数もヘッダで公開してします。内部関数(static)にしてください。
・関数名にBoard_を付けてくださいね(内部関数を除く)。
>・TurnをMykomaに変更してみました。こういう意味ですよね・・・?見当違いな事してましたらご指摘下さい
> m(_ _)m
MyKomaと言うかCPUも使うのでKomaが正しいのでは?
そうですね。こうしたらどうでしょうか?
Turn ← MY_TURNかCPU_TURNかの区別の変数。
Board_SetMyKoma(koma)で自分のコマの色を設定。
Board_GetKoma(Turn)でコマの色が返る関数。今自分のターンなら自分のコマの色。
Board_GetEnemyKoma(Turn)で対戦相手のコマの色が返る関数。今自分のターンならCPUのコマの色。
あとこれらの関数の中で、3 - Mykoma;とかはなるべくやめてif文で記述しましょう。
・やはりcaseの値をenumしましょう。
・Search()の中のendと言う変数名が意味的に変では?見てみると全部の関数で戻り値がendになっています。ちゃんと名前に意味を持たせ抹消。
・Flip()のインデントが問題。
case 4 : while (1){
は行を分けてください。
・Flip()の(dx - x) * 5 + ((dy - y) + 10) の計算はややこしくしているだけだと思います。
int x,int yの引数が-1,0,1と変化するのに合わせて処理するだけですよね?
こんなテーブルを書いてやると簡単になりませんか?
typedef struct {
int vx;
int vy;
} BoardVec_t;
static BoardVec_t KomaVector[8] = {
{ -1,-1 },
{ 0,-1 },
{ 1,-1 },
{ -1,0 },
{ 1,0 },
{ -1,1 },
{ 0,1 },
{ 1,1 }
};
int Flip(int dx,int dy,int KomaVectorIndex,int MyKoma)
・Search_End()やFlip_End()はSearch()やFlip()と引数だけで動作を変えれませんか?ループ回数の制限とかすればできそうな気が。
・Check_Winner()でBLACKならu(User?)って事になっているけど違うのでは?u,cもちゃんと名前をつけましょう。
と言うよりユーザーは黒固定?それも問題かと。
オセロの公式ルール:黒が先手です。つまり一手目を打つのは黒です。
[Main.cpp]
・func_stateの数値はenum定義しましょう。
・各関数の戻り値もenum定義しましょう。
・Check_Winner()はfunc_state=98;にするときに呼び出してその時点で98,99,100を決めるべきでしょう。
・Game_Finishを何度も呼び出すのは止めましょう。Game_Finishの戻り値を変数に保存すれば呼び出すのは毎フレーム1回で良いはずです。
とりあえずインデントしすぎなので、
while(ProcessLoop()==0){ //メインループ
switch(func_state){
case 0:
Board_init(); //ボードに関する初期化
Game_Screen_init(); //タイトルに関する初期化
func_state=1;
break;
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
あと、現状だとあまりにも味気ないので置く時とか置いた後のひっくり返し、CPUの置くアクションとか演出にも気を使ってみましょう。
とりあえず、ちゃんと動いてからからですけどね。AIを賢くする前にやりませんか?
フラッシュやらjavascriptやらjavaやらの世間に出回っているオセロ(リバーシ)を参考にしてみてください。世間には迎合しない!と言うオリジナルの演出でも、もちろんOK!
とりあえず、ちゃんと動いてからからですけどね。AIを賢くする前にやりませんか?
フラッシュやらjavascriptやらjavaやらの世間に出回っているオセロ(リバーシ)を参考にしてみてください。世間には迎合しない!と言うオリジナルの演出でも、もちろんOK!
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
あぁ効果音やBGMについては実は地味に自作しておりました。
取り敢えずエラー無くしてからにしようと思ってます。
効果音やBGMなど今勉強出来るものはしときたいですよね。
多分SLG作る時には他の事を沢山学ばないといけないでしょうし・・・orz
取り敢えずエラー無くしてからにしようと思ってます。
効果音やBGMなど今勉強出来るものはしときたいですよね。
多分SLG作る時には他の事を沢山学ばないといけないでしょうし・・・orz
Re: オセロのプログラム制作過程
[Screen.h/cpp]
名前変えるだけなのに地味に大変な作業ですよね・・・。
何かこう、一つ変えれば他の同名のものも変更後の名前になってくれる機能とかあれば良いのですが。。
・MenuElementを引数に使うと何とかなりませんか?
・まだ引数を上手く活用出来てないため、全くビジョンが浮かびませんでしたorz
一応自分なりに統一化は果たしましたが、こんな感じでどうなのでしょう・・・。
[Board.h/cpp]
・上手く引数で引き渡す様にしたはずなのに実行後にエラーが・・・。
引数で引き渡す場合、大雑把でも構いませんがメリットは一体どういったものなのでしょうか?
取り敢えず改善出来た部分もあるので添付します。
[追記]
FlipやSearch関連以外の所は修正しました。
Flipの所はだいぶ時間が掛かりそうなので・・・・・。
名前変えるだけなのに地味に大変な作業ですよね・・・。
何かこう、一つ変えれば他の同名のものも変更後の名前になってくれる機能とかあれば良いのですが。。
・MenuElementを引数に使うと何とかなりませんか?
・まだ引数を上手く活用出来てないため、全くビジョンが浮かびませんでしたorz
一応自分なりに統一化は果たしましたが、こんな感じでどうなのでしょう・・・。
[Board.h/cpp]
・上手く引数で引き渡す様にしたはずなのに実行後にエラーが・・・。
引数で引き渡す場合、大雑把でも構いませんがメリットは一体どういったものなのでしょうか?
取り敢えず改善出来た部分もあるので添付します。
[追記]
FlipやSearch関連以外の所は修正しました。
Flipの所はだいぶ時間が掛かりそうなので・・・・・。
- 添付ファイル
-
- オセロ.zip
- (7.59 KiB) ダウンロード数: 173 回
Re: オセロのプログラム制作過程
Board_CPU関数でBanDataのコピーを受け取っているのですね。これは良いと思います。
しかし、 これは、右辺に要素が1つしかないので、
と解釈されます。
とするべきでしょう。
実行時エラーは、上記が原因で、配列の範囲外にアクセスしているからです。
CPU_inputで受け取ったコピーCPU_BanDataをBoard_Searchに渡していますが、
これだと、Board.cppが保持しているBanDataに対して処理が行われません。
(Board_SearchにCPU_BanDataが渡されているのに、Board_Searchが呼び出すFlipでは、BanDataに対して処理を行っているのはバグとなります)
CPUが盤面をシミュレートして、次の手を決定するような処理をしないのなら、
Board_Searchはもとに戻したほうがいいと思います。
盤面のシミュレートを行うなら、それ用の関数を用意すべきだと思います。
しかし、 これは、右辺に要素が1つしかないので、
と解釈されます。
とするべきでしょう。
実行時エラーは、上記が原因で、配列の範囲外にアクセスしているからです。
CPU_inputで受け取ったコピーCPU_BanDataをBoard_Searchに渡していますが、
これだと、Board.cppが保持しているBanDataに対して処理が行われません。
(Board_SearchにCPU_BanDataが渡されているのに、Board_Searchが呼び出すFlipでは、BanDataに対して処理を行っているのはバグとなります)
CPUが盤面をシミュレートして、次の手を決定するような処理をしないのなら、
Board_Searchはもとに戻したほうがいいと思います。
盤面のシミュレートを行うなら、それ用の関数を用意すべきだと思います。
最後に編集したユーザー a5ua on 2011年6月08日(水) 15:43 [ 編集 1 回目 ]
Re: オセロのプログラム制作過程
今更ですが、ローグライクゲームの参考書を・・・
ダンジョンゲームプログラミング
開発言語はC++で、内容も分かりやすくて読みやすいと思います。
ダンジョンゲームプログラミング
開発言語はC++で、内容も分かりやすくて読みやすいと思います。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
[Screen.h/cpp]
・cppファイルで関数ごとに機能説明のコメントが欲しいですね。
ごめんなさい。更に関数のコメントを1行目に移動してもらって良いですか?
これを こんな感じで。 ・今日気づきましたが、TitleElement_tの定義は下記のように書いたほうがメモリのムダが少ないです。
あと、Title_mainとEndTitle_mainとして呼び出す入り口は分けたほうが良いと思います。
こんな風に出来ると思います。文字列の幅もGetDrawStringWidthで自動的に得ます。
それと、ここで表示するのは無作法なのでDrawで色変更するようにしてみましょう。
ちなみに穴埋めとさせていただきます。
[main.cpp]
・enumの定数定義は変数との区別のために大文字をお勧めします。
init→INIT
・戻り値のenum定義は各関数があるヘッダに記述しないとバグの原因となります。
enum Title_Select { zokkou = 1, shuuryou }; → title.hへ
enum Winner { user = 1, cpu, draw }; → board.hへ
・もうひとつは、こう書くと変な代入はエラーになるのでバグを事前に減らせます。
enum func_state_enum { INIT, TITLE, GAME, TITLE_WIN, TITLE_LOSE, TITLE_DRAW };
func_state_enum func_state = INIT ;
・間違いですね。case title:時も同じようにしてください。
誤 正 上のを反映すると。 ・Drawとmainの順番が逆です。
必ずmain→drawの順で呼んでください。
こうした方が処理の都合上良いことがあるからです(こうしないと処理反映が1フレーム遅れます)。
長くなったので分けます。1/2
編集メニューにある置換機能を使えば一括の文字列の置き換えは可能ですよ。名前変えるだけなのに地味に大変な作業ですよね・・・。
何かこう、一つ変えれば他の同名のものも変更後の名前になってくれる機能とかあれば良いのですが。。
・cppファイルで関数ごとに機能説明のコメントが欲しいですね。
ごめんなさい。更に関数のコメントを1行目に移動してもらって良いですか?
これを こんな感じで。 ・今日気づきましたが、TitleElement_tの定義は下記のように書いたほうがメモリのムダが少ないです。
これだと効率的な処理では無いですね。ほとんど同じロジックですので共通化できると思うのですが。>・EndTitle_MainとTitle_Mainは処理がほとんど同じなので内部関数として共通化を検討してください。MenuElementを引数に使うと何とかなりませんか?
・まだ引数を上手く活用出来てないため、全くビジョンが浮かびませんでしたorz
一応自分なりに統一化は果たしましたが、こんな感じでどうなのでしょう・・・。
あと、Title_mainとEndTitle_mainとして呼び出す入り口は分けたほうが良いと思います。
こんな風に出来ると思います。文字列の幅もGetDrawStringWidthで自動的に得ます。
それと、ここで表示するのは無作法なのでDrawで色変更するようにしてみましょう。
ちなみに穴埋めとさせていただきます。
// 画面専用メニューバー
typedef struct{
int x, y; //座標格納用変数
char *name; //項目名格納用変数
int cmode; //カラーモード
}TitleElement_t;
// カラーモード
enum {
CMODE_NORMAL, //通常
CMODE_ONMOUSE, //ON MOUSE
};
static TitleElement_t TitleElement[2]={ //タイトル画面構造体の変数初期化
{ 500, 500, "ゲームスタート", CMODE_NORMAL }, // タグの中身の順番で格納される。
{ 500, 570, "ゲーム終了", CMODE_NORMAL },
};
EndTitleElementも同様。
// プロトタイプ
static int title_common( TitleElement_t titleElement[], int num);//共通タイトル内部関数
// タイトル画面の関数
int Title_main() {
return title_common(TitleElement,2);//共通タイトル内部関数
}
// エンドタイトル画面の関数
int EndTitle_main() {
return (1);//共通タイトル内部関数
}
//共通タイトル内部関数
static int title_common( TitleElement_t titleElement[], int num){
int nowinput ;
int mx, my ;
// マウスの入力情報を初期化する
nowinput = 0 ;
mx = 0 ;
my = 0 ;
// マウスの入力情報(座標)
nowinput = GetMouseInput() ;
GetMousePoint( &mx, &my ) ;
// メニューの数だけ処理
for( int m=0 ; m<num ; m++ ) {
// 文字列の幅を得る。
int w = GetDrawStringWidth(titleElement[m].name,(int)strlen(titleElement[m].name));
int h = 20;//高さは決め打ち。
// 座標
int x = titleElement[i].x;
int y = titleElement[i].y - 5;
// マウスの座標と比較。
titleElement[i].cmode=CMODE_NORMAL; //通常カラー
if( (x <= mx) && ・・・省略(2)
titleElement[i].cmode=CMODE_ONMOUSE; //on mouseカーソル色
// マウスの左クリック
if( ( nowinput & MOUSE_INPUT_LEFT ) != 0 ){
// 押された文字列に対応する番号を持ち帰る。
return (3);
}
}
}
// マウスの座標を表示する
DrawFormatString( 0, 0, GetColor( 255,255,255 ), "X:%d Y:%d", mx, my ) ;
return 0;
}
で実はTitle_Drawとかも共通化出来ます。cmodeを付ける都合からも共通化は必要です。考えてみてください。
[main.cpp]
・enumの定数定義は変数との区別のために大文字をお勧めします。
init→INIT
・戻り値のenum定義は各関数があるヘッダに記述しないとバグの原因となります。
enum Title_Select { zokkou = 1, shuuryou }; → title.hへ
enum Winner { user = 1, cpu, draw }; → board.hへ
・もうひとつは、こう書くと変な代入はエラーになるのでバグを事前に減らせます。
enum func_state_enum { INIT, TITLE, GAME, TITLE_WIN, TITLE_LOSE, TITLE_DRAW };
func_state_enum func_state = INIT ;
・間違いですね。case title:時も同じようにしてください。
誤 正 上のを反映すると。 ・Drawとmainの順番が逆です。
必ずmain→drawの順で呼んでください。
こうした方が処理の都合上良いことがあるからです(こうしないと処理反映が1フレーム遅れます)。
長くなったので分けます。1/2
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
続きです。2/2
[game.cpp]
・Uturnの値もenum宣言してください。
・Uturnが内部の状態を表したり、引数になってみたり一貫性が無い気がします。
特にこのあたり。 Uturnの値の持つ意味、あと白黒先行の問題を整理してみてください。
[cpu_AI.cpp]
・Board_CPUの仕組みは、a5uaさんの書かれた問題を直せばOKです。
ただしコピーに対して処理していることは理解してください。たまたま今はFlipが盤面を直接触っているのでバグになりませんが本来はFlipも引渡された引数の盤面に対してひっくり返しを行うべきです。そうした場合は、CPU_input内のローカル配列CPU_BanData自体を変更しますが複製ですので本来の盤面は変化しません。
[Board.h/cpp]
2.盤面の複製などがある場合は、引数で渡して複製だけを変更できる(ちゃんとしたAIの処理としては必要)
3.逆説的ですがグローバル変数を避けるためには引数渡ししかありません。
「グローバル変数 - Wikipedia」
http://ja.wikipedia.org/wiki/%E3%82%B0% ... 9%E6%95%B0
[追記]
これも参考になるので今分かるところだけ読んでみても損はありません。
「プログラミングの禁じ手Web版 C言語編(InternetArchiveよりサルベージ) - Akio’s Log」
http://d.hatena.ne.jp/elwoodblues/20090206/1233878763
[Board.h/cpp]
>・Flip()とか外部から呼ばれない関数もヘッダで公開してします。内部関数(static)にしてください。
これですがヘッダではなく、cpp側に置いてくださいね。
・関数名にBoard_を付けてくださいね(内部関数を除く)。 ← まだ未完ですね。
・未完項目
[game.cpp]
・Uturnの値もenum宣言してください。
・Uturnが内部の状態を表したり、引数になってみたり一貫性が無い気がします。
特にこのあたり。 Uturnの値の持つ意味、あと白黒先行の問題を整理してみてください。
[cpu_AI.cpp]
・Board_CPUの仕組みは、a5uaさんの書かれた問題を直せばOKです。
ただしコピーに対して処理していることは理解してください。たまたま今はFlipが盤面を直接触っているのでバグになりませんが本来はFlipも引渡された引数の盤面に対してひっくり返しを行うべきです。そうした場合は、CPU_input内のローカル配列CPU_BanData自体を変更しますが複製ですので本来の盤面は変化しません。
[Board.h/cpp]
1.どの関数が何を参照して何を変更するか明確に記述できる。関数が多くなったときの関数の機能の明確化や適当な記述の引数で引き渡す場合、大雑把でも構いませんがメリットは一体どういったものなのでしょうか?
2.盤面の複製などがある場合は、引数で渡して複製だけを変更できる(ちゃんとしたAIの処理としては必要)
3.逆説的ですがグローバル変数を避けるためには引数渡ししかありません。
「グローバル変数 - Wikipedia」
http://ja.wikipedia.org/wiki/%E3%82%B0% ... 9%E6%95%B0
[追記]
これも参考になるので今分かるところだけ読んでみても損はありません。
「プログラミングの禁じ手Web版 C言語編(InternetArchiveよりサルベージ) - Akio’s Log」
http://d.hatena.ne.jp/elwoodblues/20090206/1233878763
[Board.h/cpp]
>・Flip()とか外部から呼ばれない関数もヘッダで公開してします。内部関数(static)にしてください。
これですがヘッダではなく、cpp側に置いてくださいね。
static int Flip(int,int,int,int,int); //コマを返す関数
static int Flip_End(int,int,int,int,int);//コマを置けるか調べる関数その2
・未完項目
以上です。
>・TurnをMykomaに変更してみました。こういう意味ですよね・・・?見当違いな事してましたらご指摘下さい
> m(_ _)m
MyKomaと言うかCPUも使うのでKomaが正しいのでは?
そうですね。こうしたらどうでしょうか?
Turn ← MY_TURNかCPU_TURNかの区別の変数。
Board_SetMyKoma(koma)で自分のコマの色を設定。
Board_GetKoma(Turn)でコマの色が返る関数。今自分のターンなら自分のコマの色。
Board_GetEnemyKoma(Turn)で対戦相手のコマの色が返る関数。今自分のターンならCPUのコマの色。
あとこれらの関数の中で、3 - Mykoma;とかはなるべくやめてif文で記述しましょう。
・やはりcaseの値をenumしましょう。
・Search()の中のendと言う変数名が意味的に変では?見てみると全部の関数で戻り値がendになっています。ちゃんと名前に意味を持たせましょう。
・Flip()のインデントが問題。
case 4 : while (1){
は行を分けてください。
・Flip()の(dx - x) * 5 + ((dy - y) + 10) の計算はややこしくしているだけだと思います。
int x,int yの引数が-1,0,1と変化するのに合わせて処理するだけですよね?
こんなテーブルを書いてやると簡単になりませんか?
・Search_End()やFlip_End()はSearch()やFlip()と引数だけで動作を変えれませんか?ループ回数の制限とかすればできそうな気が。typedef struct { int vx; int vy; } BoardVec_t; static BoardVec_t KomaVector[8] = { { -1,-1 }, { 0,-1 }, { 1,-1 }, { -1,0 }, { 1,0 }, { -1,1 }, { 0,1 }, { 1,1 } };
・Check_Winner()でBLACKならu(User?)って事になっているけど違うのでは?u,cもちゃんと名前をつけましょう。
と言うよりユーザーは黒固定?それも問題かと。
オセロの公式ルール:黒が先手です。つまり一手目を打つのは黒です。
[補足]
→ 黒固定から黒白可変にと言う変更ですね。この手の変更に弱いプログラムはプログラム構造的にデータの抽象化やデータの持ち方が整理されていない変更に弱い(メンテナンス性の低い)バグを作り出しやすいプログラムです。この手の悪癖を直さないと大規模なプログラムでは未完成になる恐れが高くなります。
※ 作っている間にややこしくて手直し出来なくなる&どうして良いか自分でもプログラム構造が把握できなくなるって事です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
>a5uaさん
あぁ・・・そうでしたorz
それにこれではCPU側で変更したBanDataの情報が共有されないですね。。
ポインタを使ってやり取りすればちゃんとユーザー側で入力した盤の情報とCPU側で入力した情報はリンクするはずですよね。
取り敢えず元に戻しましたが、AI強化を考える段階に入ったらa5uaさんのおっしゃる通りにしないと駄目な気がとてもしますorz
アドバイス有難う御座いますm(_ _)m
>バグさん
とても面白そうな本の紹介感謝です!
自分はまだC++には手を出してないので早いですが、いずれ読んでみたいと思いますm(_ _)m
あぁ・・・そうでしたorz
それにこれではCPU側で変更したBanDataの情報が共有されないですね。。
ポインタを使ってやり取りすればちゃんとユーザー側で入力した盤の情報とCPU側で入力した情報はリンクするはずですよね。
取り敢えず元に戻しましたが、AI強化を考える段階に入ったらa5uaさんのおっしゃる通りにしないと駄目な気がとてもしますorz
アドバイス有難う御座いますm(_ _)m
>バグさん
とても面白そうな本の紹介感謝です!
自分はまだC++には手を出してないので早いですが、いずれ読んでみたいと思いますm(_ _)m
Re: オセロのプログラム制作過程
>ソフト屋さん
main→drawの流れはBoard_draw とGame_mainの所もその他の場所も全てでしょうか?
初心者ながらに、盤を描いてからゲームが始まる などと考えていたのですが、勘違いだったとしたら変な癖が付く前にしっかり把握しておこうと思いまして・・・m(_ _)m
main→drawの流れはBoard_draw とGame_mainの所もその他の場所も全てでしょうか?
初心者ながらに、盤を描いてからゲームが始まる などと考えていたのですが、勘違いだったとしたら変な癖が付く前にしっかり把握しておこうと思いまして・・・m(_ _)m
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
draw→mainだとキーを押した反応の描画は次のフレームですよね。つまり1フレーム送れることになります。小人 さんが書きました:>ソフト屋さん
main→drawの流れはBoard_draw とGame_mainの所もその他の場所も全てでしょうか?
初心者ながらに、盤を描いてからゲームが始まる などと考えていたのですが、勘違いだったとしたら変な癖が付く前にしっかり把握しておこうと思いまして・・・m(_ _)m
ただし、実際には次のように遅れて画面に表示されます。
1フレーム目(見えている画面は-1フレーム目のdraw状態)
draw 0フレーム目の操作を反映した状態を表示
main 1フレームの状態を制御 ・・・ ここの状態は何フレーム後に画面に出るか注目です。(1)
screenflip 0フレーム目のdrawを表画面に出す。
2フレーム目(見えている画面は0フレーム目のdraw状態)
draw 1フレーム目の操作を反映した状態を表示
main 2フレームの状態を制御
screenflip 1フレーム目のdrawを表画面に出す。
3フレーム目(見えている画面は1フレーム目のdraw状態)
draw 2フレーム目の操作を反映した状態を表示
main 3フレームの状態を制御
screenflip 2フレーム目のdrawを表画面に出す。 (1)の状態はここで始めて表示されます。つまり4フレーム目のところで実際に1フレーム目の操作が眼に見えるわけです。
4フレーム目(見えている画面は2フレーム目のdraw状態)
この遅延をできるだけ減らしたいとすれば、main→drawの順番がベストです。
こういう遅れは、アクションやシューティングの場合は致命的です。
[追記]
それとmain処理はmain処理で固めて、drawはdrawでまとめて行うべきです。
ここら辺は、龍神録や私のRPG講座のコードもそうなっています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
なにか行き詰っておられますか?書き込みがないので心配になってしまいました。
無理に我々の言うことを実践せずに、今の自分で出来る範囲の事をしてもらえば良いと思います。
小人 さんにやる気があるので、ついつい欲張って書いてしまいましたから。
あと全部いっぺんに直さずに少しずつ直して、こちらに報告してもらったほうが進んでいることが実感できて良いかも知れません。
Flipの共通化も必要ならサンプルを書きますよ。
無理に我々の言うことを実践せずに、今の自分で出来る範囲の事をしてもらえば良いと思います。
小人 さんにやる気があるので、ついつい欲張って書いてしまいましたから。
あと全部いっぺんに直さずに少しずつ直して、こちらに報告してもらったほうが進んでいることが実感できて良いかも知れません。
Flipの共通化も必要ならサンプルを書きますよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
お恥ずかしい事に全く進展がない状態で・・・。
mainとdrawでそれぞれファイルを作り、boardやtitleではファイル名に関する処理しか行わない様に作り変えたいという気持ちはあるのですが、ポインタを使ってのboard情報のやり取りがどうもエラー続きなため後回しにしましたorz
FlipとSearchに関しても後回し。
Flipを作り直す時にEnd_Flipなどと共通化出来る様な形にしたいです。
ずっと悩んでいた原因は主にTitle.cppでの共通化です。
今添付してるファイルは試行錯誤段階で、この状態ではTitle関数が呼び出され文字色変更がされても、すぐにTitle_Drawによって文字色が戻ってしまう状態?(この認識で正しいのか自信はないですが・・・)です。
Title_Draw_commonを使って各Title_DrawからDrawFormatStringを消してみましたが、背景にタイトル文字が塗りつぶされる結果に。。
Title_DrawからDraw_commonを呼び出す事も考えましたが、titleElement[].cmodeはグローバル関数ではないため、Draw_commonへ渡すにはTitle_common内でTitle_Draw関数を呼び出さないと駄目。
しかしそれだとMain関数とDraw関数は分けられないし、折角共通化した意味も無くなってしまい・・・。
とこんな感じですorz
mainとdrawでそれぞれファイルを作り、boardやtitleではファイル名に関する処理しか行わない様に作り変えたいという気持ちはあるのですが、ポインタを使ってのboard情報のやり取りがどうもエラー続きなため後回しにしましたorz
FlipとSearchに関しても後回し。
Flipを作り直す時にEnd_Flipなどと共通化出来る様な形にしたいです。
ずっと悩んでいた原因は主にTitle.cppでの共通化です。
今添付してるファイルは試行錯誤段階で、この状態ではTitle関数が呼び出され文字色変更がされても、すぐにTitle_Drawによって文字色が戻ってしまう状態?(この認識で正しいのか自信はないですが・・・)です。
Title_Draw_commonを使って各Title_DrawからDrawFormatStringを消してみましたが、背景にタイトル文字が塗りつぶされる結果に。。
Title_DrawからDraw_commonを呼び出す事も考えましたが、titleElement[].cmodeはグローバル関数ではないため、Draw_commonへ渡すにはTitle_common内でTitle_Draw関数を呼び出さないと駄目。
しかしそれだとMain関数とDraw関数は分けられないし、折角共通化した意味も無くなってしまい・・・。
とこんな感じですorz
- 添付ファイル
-
- オセロ.zip
- (7.87 KiB) ダウンロード数: 154 回
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
参考になるようにTitle.cppを共通化してみました。
問題点はやはり、title_common_main()からtitle_common_draw()を呼び出していることでした。
title_common_main()とtitle_common_draw()の情報のやりとりはcmodeのみを使って行います。
staticな変数は、たとえ関数を抜けても変更された値は保持しますのでcmodeの値を受け渡すことが可能となります。
ご自分のものと比べてみてください。
[追記]
内部関数と外部関数の区別が付きやすいように内部関数は全部小文字の名前にしておきました。
問題点はやはり、title_common_main()からtitle_common_draw()を呼び出していることでした。
title_common_main()とtitle_common_draw()の情報のやりとりはcmodeのみを使って行います。
staticな変数は、たとえ関数を抜けても変更された値は保持しますのでcmodeの値を受け渡すことが可能となります。
ご自分のものと比べてみてください。
[追記]
内部関数と外部関数の区別が付きやすいように内部関数は全部小文字の名前にしておきました。
#include "Title.h"
//画面専用メニューバー
typedef struct{
int x, y; // 座標格納用変数
char* name; // 項目名格納用変数
int cmode; //カラーモード
}TitleElement_t;
// カラーモード
enum {
CMODE_NORMAL, //通常
CMODE_ONMOUSE, //ON MOUSE
};
//タイトル画面構造体の変数初期化
static TitleElement_t TitleElement[2]={
{ 500, 500, "ゲームスタート", CMODE_NORMAL }, // タグの中身の順番で格納される。
{ 500, 570, "ゲーム終了", CMODE_NORMAL },
};
//エンドタイトル画面構造体変数の初期化
static TitleElement_t EndTitleElement[2]={
{ 300, 500, "タイトル画面へ",CMODE_NORMAL },
{ 300, 570, "ゲーム終了", CMODE_NORMAL },
};
static int GHtitle;
static int GHvictory;
static int GHgameover;
static int GHdraw;
// プロトタイプ
static int title_common_main( TitleElement_t titleElement[], int num);//共通タイトル内部関数
static void title_common_draw( TitleElement_t titleElement[], int num, int gh);//共通描画の内部関数
//ゲーム画面を初期化するための関数
void Title_init(){
GHtitle = LoadGraph(TEXT("画像/title.png"));
GHvictory = LoadGraph(TEXT("画像/勝利画面.png"));
GHgameover = LoadGraph(TEXT("画像/敗北画面.png"));
GHdraw = LoadGraph(TEXT("画像/引き分け画面.png"));
}
// タイトル画面の関数
int Title_main() {
return title_common_main(TitleElement,2);//共通タイトル内部関数
}
// エンドタイトル画面の関数
int EndTitle_main() {
return title_common_main(EndTitleElement,2);//共通タイトル内部関数
}
//タイトル画面描画関数
void Title_Draw(){
title_common_draw(TitleElement,2,GHtitle);//共通描画の内部関数
}
//勝利画面描画関数
void EndTitle_WinDraw(){
title_common_draw(EndTitleElement,2,GHvictory);//共通描画の内部関数
}
//敗北画面描画関数
void EndTitle_LoseDraw(){
title_common_draw(EndTitleElement,2,GHgameover);//共通描画の内部関数
}
//引き分け画面描画関数
void EndTitle_DrawDraw(){
title_common_draw(EndTitleElement,2,GHdraw);//共通描画の内部関数
}
//共通タイトル内部関数
static int title_common_main( TitleElement_t titleElement[], int num){
int nowinput ;
int mx, my ;
// マウスの入力情報を初期化する
nowinput = 0 ;
mx = 0 ;
my = 0 ;
// マウスの入力情報(座標)
nowinput = GetMouseInput() ;
GetMousePoint( &mx, &my ) ;
// メニューの数だけ処理
for( int m=0 ; m<num ; m++ ) {
// 文字列の幅を得る。
int w = GetDrawStringWidth(titleElement[m].name,(int)strlen(titleElement[m].name));
int h = 20;//高さは決め打ち。
// 座標
int x = titleElement[m].x;
int y = titleElement[m].y - 5;
// マウスの座標と比較。
titleElement[m].cmode=CMODE_NORMAL; //通常カラー
if( (x <= mx) && (mx <= (x+w)) && (y <= my) && (my <= (y+h) )){
titleElement[m].cmode=CMODE_ONMOUSE; //on mouseカーソル色
// マウスの左クリック
if( ( nowinput & MOUSE_INPUT_LEFT ) != 0 ){
// 押された文字列に対応する番号を持ち帰る。
if(m==0)return 1;
else if(m==1)return 2;
}
}
}
// マウスの座標を表示する
DrawFormatString( 0, 0, GetColor( 255,255,255 ), "X:%d Y:%d", mx, my ) ;
return 0;
}
// 共通描画の内部関数
static void title_common_draw( TitleElement_t titleElement[], int num, int gh ){
int i;
// 背景画像
DrawGraph(0,0,gh,FALSE);
// モードでtitleElement[m].
for( i=0; i<num; i++){ //メニュー項目描画
switch(titleElement[i].cmode){
case CMODE_NORMAL:
DrawFormatString( titleElement[i].x, titleElement[i].y, GetColor(255,255,255), TitleElement[i].name );
break;
case CMODE_ONMOUSE:
DrawFormatString( titleElement[i].x, titleElement[i].y, GetColor(0,255,255), TitleElement[i].name );
break;
}
}
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
あぁ・・・そうでした。staticは関数が終了しても値を保持するのに・・・、何故気付かなかったのやら。。
今見ててふと疑問に思ったのですが、int型って数字しか扱えないのでは無かったでしょうか?
本当に今更なのですが、そういえばGHandle系は全部int型にも関わらずLoadGraphという値?を持っていたので。
これは見えない所でLoadGraphに数字が与えられていたりとかそういう事なのでしょうか・・・?
何だか途方も無い見当違いをしている気もしますが・・・。
それとmain関数を呼び出してからdraw関数 という正しい形に変更してからマウスの座標が表示されなくなったのですが、これはつまり
マウスの座標描画→しかしDraw関数によって塗りつぶされる
という事態が発生しているのですか・・・ね?
最終的には座標消す予定だったので、まぁ良いかなとも思ったのですが座標あるとバグ起きた時にバグ起きた座標を特定出来るのでちょっと便利だったり。
ただマウスの座標情報をDraw関数に引き渡すのはちょっと難しそうで、どうしたもんかなぁと。
どうせ最終的には要らない要素ですから、表示させるために結構手間が掛かる(新しい関数作ったりなど)なら もうバッサリ切ろうと思うのですが、どうなのでしょう?
今見ててふと疑問に思ったのですが、int型って数字しか扱えないのでは無かったでしょうか?
本当に今更なのですが、そういえばGHandle系は全部int型にも関わらずLoadGraphという値?を持っていたので。
これは見えない所でLoadGraphに数字が与えられていたりとかそういう事なのでしょうか・・・?
何だか途方も無い見当違いをしている気もしますが・・・。
それとmain関数を呼び出してからdraw関数 という正しい形に変更してからマウスの座標が表示されなくなったのですが、これはつまり
マウスの座標描画→しかしDraw関数によって塗りつぶされる
という事態が発生しているのですか・・・ね?
最終的には座標消す予定だったので、まぁ良いかなとも思ったのですが座標あるとバグ起きた時にバグ起きた座標を特定出来るのでちょっと便利だったり。
ただマウスの座標情報をDraw関数に引き渡すのはちょっと難しそうで、どうしたもんかなぁと。
どうせ最終的には要らない要素ですから、表示させるために結構手間が掛かる(新しい関数作ったりなど)なら もうバッサリ切ろうと思うのですが、どうなのでしょう?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
int値はDXライブラリの中の画像情報を保持する構造体の番号を指していると思ってもらって良いです。小人 さんが書きました:あぁ・・・そうでした。staticは関数が終了しても値を保持するのに・・・、何故気付かなかったのやら。。
今見ててふと疑問に思ったのですが、int型って数字しか扱えないのでは無かったでしょうか?
本当に今更なのですが、そういえばGHandle系は全部int型にも関わらずLoadGraphという値?を持っていたので。
これは見えない所でLoadGraphに数字が与えられていたりとかそういう事なのでしょうか・・・?
何だか途方も無い見当違いをしている気もしますが・・・。
アルゴリズムとしてテーブル構造なのかリスト構造なのかソースコードの中を追いかけたことは有りませんが。
Drawで背景を塗りつぶしてますね。なので、Mainで情報は表示できません。小人 さんが書きました: それとmain関数を呼び出してからdraw関数 という正しい形に変更してからマウスの座標が表示されなくなったのですが、これはつまり
マウスの座標描画→しかしDraw関数によって塗りつぶされる
という事態が発生しているのですか・・・ね?
最終的には座標消す予定だったので、まぁ良いかなとも思ったのですが座標あるとバグ起きた時にバグ起きた座標を特定出来るのでちょっと便利だったり。
ただマウスの座標情報をDraw関数に引き渡すのはちょっと難しそうで、どうしたもんかなぁと。
どうせ最終的には要らない要素ですから、表示させるために結構手間が掛かる(新しい関数作ったりなど)なら もうバッサリ切ろうと思うのですが、どうなのでしょう?
表示するとしたらマウスの座標をstaticにして表示をDrawでするしかないでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
おぉなるほど。
御回答有難う御座いますm(_ _)m
やっぱりマウスの座標は諦める事にします。
これで残す大仕事はFlipの作り直しかぁ・・・頑張らないと。
そう言えば最近 優しいCと明解C言語入門編(こちらは辞書代わりとして購入済)を読破し、次に何を読もうかなと考えているのですが
候補は
①ポインタ完全攻略系・・・ポインタ自体そこまで難しいとは思わず、苦手意識は無いのですが咄嗟に これポインタ使って書き直して と言われた時少し困ってしまう気がして、しっかり勉強すべきかなと。
②アルゴリズム系・・・以前紹介されたサイトを拝読した感じ、これは必要だなと思う事がかなり書かれていたので一冊購入しておくべきかなと考えてます。
ただどの本にしようかな・・・と。
アルゴリズムの絵本から入れば読み易いでしょうが、買うとなると今後その本と付き合っていく事になりますから、なるべく詳しく書かれたアルゴリズムとデータ構造の方が良いのかな など。
③C++系・・・正直C言語で充分だと思うのですが、もし就職でこちらの道を進む場合は必須でしょうし(DirectXの理解、特に3D、も必要ですから自分には敷居が高過ぎる気もしますが) 何よりC++で簡単かつ綺麗に書ける様になれば添削なさってくれている方々も助かるかなと。
C++で綺麗なソースコードを書くのにも経験が必要でしょうし、こちらも早めに勉強しておくべきかなとも思ってます。
購入予定の本は迷い中です。
C++の絵本で良いのかなぁ・・・。
取り敢えず次のステップで考えているものは以上です。
お勧めの順番や購入推奨の書籍が御座いましたら宜しくお願いしますm(_ _)m
御回答有難う御座いますm(_ _)m
やっぱりマウスの座標は諦める事にします。
これで残す大仕事はFlipの作り直しかぁ・・・頑張らないと。
そう言えば最近 優しいCと明解C言語入門編(こちらは辞書代わりとして購入済)を読破し、次に何を読もうかなと考えているのですが
候補は
①ポインタ完全攻略系・・・ポインタ自体そこまで難しいとは思わず、苦手意識は無いのですが咄嗟に これポインタ使って書き直して と言われた時少し困ってしまう気がして、しっかり勉強すべきかなと。
②アルゴリズム系・・・以前紹介されたサイトを拝読した感じ、これは必要だなと思う事がかなり書かれていたので一冊購入しておくべきかなと考えてます。
ただどの本にしようかな・・・と。
アルゴリズムの絵本から入れば読み易いでしょうが、買うとなると今後その本と付き合っていく事になりますから、なるべく詳しく書かれたアルゴリズムとデータ構造の方が良いのかな など。
③C++系・・・正直C言語で充分だと思うのですが、もし就職でこちらの道を進む場合は必須でしょうし(DirectXの理解、特に3D、も必要ですから自分には敷居が高過ぎる気もしますが) 何よりC++で簡単かつ綺麗に書ける様になれば添削なさってくれている方々も助かるかなと。
C++で綺麗なソースコードを書くのにも経験が必要でしょうし、こちらも早めに勉強しておくべきかなとも思ってます。
購入予定の本は迷い中です。
C++の絵本で良いのかなぁ・・・。
取り敢えず次のステップで考えているものは以上です。
お勧めの順番や購入推奨の書籍が御座いましたら宜しくお願いしますm(_ _)m
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
柴田氏の本中心でご紹介します。
①ポインタ完全攻略系
「BohYoh.com【著書】詳解C言語ポインタ完全攻略」
http://www.bohyoh.com/Books/ShoukaiCptr/index.htm
半分アルゴリズム系のサイトですが、
「ポインタを使ったデータ構造」
http://wwws.kobe-c.ac.jp/deguchi/c/list/frame.html
②アルゴリズム系
「BohYoh.com【著書】明解 C言語によるアルゴリズムとデータ構造」
http://www.bohyoh.com/Books/MeikaiCAlgo/index.html
紹介したのもあるかも。サイトの数々。
「アルゴリズム入門」
http://www5c.biglobe.ne.jp/~ecb/algorit ... thm00.html
「アルゴリズムとデータ構造」
http://www.codereading.com/algo_and_ds/
「アルゴリズムとデータ構造編 トップページ」
http://www.geocities.jp/ky_webid/algorithm/index.html
「コーディングに役立つ! アルゴリズムの基本 - @IT」
http://www.atmarkit.co.jp/fcoding/index/algorithm.html
「C言語講座>アルゴリズム研究室(トップ)」
http://www1.cts.ne.jp/~clab/algorithm/algorithm.html
③C++系
「BohYoh.com【著書】新版明解C++入門編」
http://www.bohyoh.com/Books/MeikaiCPP01/index.html
「マイコミ ブックス - ロベールのC++入門講座-」
http://book.mycom.co.jp/book/978-4-8399 ... 05-2.shtml
こっちはサイトもあります。
「ロベールの部屋」
http://www7b.biglobe.ne.jp/~robe/
C++の絵本は端的で分りやすいですが、端折り過ぎなのであくまで補助の本だと思います。
>何よりC++で簡単かつ綺麗に書ける様になれば添削なさってくれている方々も助かるかなと。
まぁ、C++で書いたところで簡単になることはなく逆に長くなることが多いですが。
綺麗に書けば分かりやすくはなります。ただ汚くなるとC言語より分かり辛いです。
>C++で綺麗なソースコードを書くのにも経験が必要でしょうし、こちらも早めに勉強しておくべきかなとも思ってます。
それは間違いないですね。
ゲーム界のアルゴリズムも紹介しておきます。
「地球にやさしいアルゴリズム---目次 - 地球にやさしいアルゴリズム:ITpro」
http://itpro.nikkeibp.co.jp/article/COL ... ST=develop
「パズル問題解法のアルゴリズム」
http://www.ic-net.or.jp/home/takaken/pz/index.html
「ジャンル別ゲームの作り方とアルゴリズムまとめ - ネットサービス研究室」
http://d.hatena.ne.jp/seikenn/20090627/1246028707
「ゲームプログラム」
http://www5f.biglobe.ne.jp/~kenmo/progr ... am_ind.htm
「White Paper - MOHA's Web Page」
http://homepage3.nifty.com/moha/
「シミュレーションゲーム作成工房 より強力な思考ルーチンを求めて」
http://www.jyouhoukaiseki.com/
んで、本と。
「Amazon.co.jp: ゲームのアルゴリズム 改訂版 思考ルーチンと物理シミュレーション: 橋口 ゆうすけ: 本」
「Amazon.co.jp: コンピュータゲームのアルゴリズム&ネットワーキング: Jouni Smed/Harri Hakonen, 加藤 諒, 中本 浩: 本」
「Amazon.co.jp: ゲーム開発者のためのAI入門: David M. Bourg, Glenn Seemann, 株式会社クイープ: 本」
「Amazon.co.jp: 実例で学ぶゲームAIプログラミング: Mat Buckland, 松田 晃一: 本」
①ポインタ完全攻略系
「BohYoh.com【著書】詳解C言語ポインタ完全攻略」
http://www.bohyoh.com/Books/ShoukaiCptr/index.htm
半分アルゴリズム系のサイトですが、
「ポインタを使ったデータ構造」
http://wwws.kobe-c.ac.jp/deguchi/c/list/frame.html
②アルゴリズム系
「BohYoh.com【著書】明解 C言語によるアルゴリズムとデータ構造」
http://www.bohyoh.com/Books/MeikaiCAlgo/index.html
紹介したのもあるかも。サイトの数々。
「アルゴリズム入門」
http://www5c.biglobe.ne.jp/~ecb/algorit ... thm00.html
「アルゴリズムとデータ構造」
http://www.codereading.com/algo_and_ds/
「アルゴリズムとデータ構造編 トップページ」
http://www.geocities.jp/ky_webid/algorithm/index.html
「コーディングに役立つ! アルゴリズムの基本 - @IT」
http://www.atmarkit.co.jp/fcoding/index/algorithm.html
「C言語講座>アルゴリズム研究室(トップ)」
http://www1.cts.ne.jp/~clab/algorithm/algorithm.html
③C++系
「BohYoh.com【著書】新版明解C++入門編」
http://www.bohyoh.com/Books/MeikaiCPP01/index.html
「マイコミ ブックス - ロベールのC++入門講座-」
http://book.mycom.co.jp/book/978-4-8399 ... 05-2.shtml
こっちはサイトもあります。
「ロベールの部屋」
http://www7b.biglobe.ne.jp/~robe/
C++の絵本は端的で分りやすいですが、端折り過ぎなのであくまで補助の本だと思います。
>何よりC++で簡単かつ綺麗に書ける様になれば添削なさってくれている方々も助かるかなと。
まぁ、C++で書いたところで簡単になることはなく逆に長くなることが多いですが。
綺麗に書けば分かりやすくはなります。ただ汚くなるとC言語より分かり辛いです。
>C++で綺麗なソースコードを書くのにも経験が必要でしょうし、こちらも早めに勉強しておくべきかなとも思ってます。
それは間違いないですね。
ゲーム界のアルゴリズムも紹介しておきます。
「地球にやさしいアルゴリズム---目次 - 地球にやさしいアルゴリズム:ITpro」
http://itpro.nikkeibp.co.jp/article/COL ... ST=develop
「パズル問題解法のアルゴリズム」
http://www.ic-net.or.jp/home/takaken/pz/index.html
「ジャンル別ゲームの作り方とアルゴリズムまとめ - ネットサービス研究室」
http://d.hatena.ne.jp/seikenn/20090627/1246028707
「ゲームプログラム」
http://www5f.biglobe.ne.jp/~kenmo/progr ... am_ind.htm
「White Paper - MOHA's Web Page」
http://homepage3.nifty.com/moha/
「シミュレーションゲーム作成工房 より強力な思考ルーチンを求めて」
http://www.jyouhoukaiseki.com/
んで、本と。
「Amazon.co.jp: ゲームのアルゴリズム 改訂版 思考ルーチンと物理シミュレーション: 橋口 ゆうすけ: 本」
「Amazon.co.jp: コンピュータゲームのアルゴリズム&ネットワーキング: Jouni Smed/Harri Hakonen, 加藤 諒, 中本 浩: 本」
「Amazon.co.jp: ゲーム開発者のためのAI入門: David M. Bourg, Glenn Seemann, 株式会社クイープ: 本」
「Amazon.co.jp: 実例で学ぶゲームAIプログラミング: Mat Buckland, 松田 晃一: 本」
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
ついでに役立ちそうなものを山盛りでご紹介。
「Cプログラミング診断室」 ネタが少し古いですが、今にも通じる普遍的な問題点が沢山あります。
http://www.pro.or.jp/~fuji/mybooks/cdia ... ml#mokuji3
「C言語のよくある間違い」
http://www.ncos.co.jp/products/cgi-bin/errorcall.cgi
「Language C FAQ (Japanese)」
http://www.kouno.jp/home/c_faq/c0.html
「C言語再入門 | 株式会社きじねこ」
http://www.kijineko.co.jp/tech/creintro
あとはポインタ関係。
「Part4 誰もがつまずくポインタを完璧理解 - C/C++は永久に不滅です!:ITpro」
http://itpro.nikkeibp.co.jp/article/COL ... ST=develop
「「配列とポインタの完全制覇」」
http://kmaebashi.com/programmer/pointer.html
「ポインタ虎の巻」
http://www.nurs.or.jp/~sug/soft/tora/index.htm
「データ型のアラインメントとは何か,なぜ必要なのか?」
http://www5d.biglobe.ne.jp/~noocyte/Pro ... nment.html
「Cプログラミング診断室」 ネタが少し古いですが、今にも通じる普遍的な問題点が沢山あります。
http://www.pro.or.jp/~fuji/mybooks/cdia ... ml#mokuji3
「C言語のよくある間違い」
http://www.ncos.co.jp/products/cgi-bin/errorcall.cgi
「Language C FAQ (Japanese)」
http://www.kouno.jp/home/c_faq/c0.html
「C言語再入門 | 株式会社きじねこ」
http://www.kijineko.co.jp/tech/creintro
あとはポインタ関係。
「Part4 誰もがつまずくポインタを完璧理解 - C/C++は永久に不滅です!:ITpro」
http://itpro.nikkeibp.co.jp/article/COL ... ST=develop
「「配列とポインタの完全制覇」」
http://kmaebashi.com/programmer/pointer.html
「ポインタ虎の巻」
http://www.nurs.or.jp/~sug/soft/tora/index.htm
「データ型のアラインメントとは何か,なぜ必要なのか?」
http://www5d.biglobe.ne.jp/~noocyte/Pro ... nment.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
ご紹介有難う御座います。
取り敢えず外れの無さそうな明解C++を購入して他はサイトをじっくり読んでから決めてみます。
さて本題ですが、やっとFlip辺りを大改築してみました。
ソフト屋さんに教えてもらった
の使い方をずっと考えていたのですが・・・分からず、自己流のプログラムとなってしまった事を先に謝罪しておきます。
プログラム自体は正常に起動はしてます。
発見出来た問題点は
・コマを置けない状態でパス画面が出ない・・・原因不明です。。Gameファイル内のPass_stateに到達していない事はメッセージボックスを使って確認したので、Check_end関数が正常に働いていない可能性が高いですが。
・ゲームが終了しても終了画面に移らない・・・これも原因は上と同じだと思います。
改善した点
Flipを整理したら置ける場所があるのに何故かエラーで固まる現象は無くなりました。
[追記]
無くなったと思ったら、ありました・・・。FlipやSearchは大幅に改善したはずなのですが、原因が全く分からない・・・。
つまるところ以前から存在していた問題点は何一つ解決していない事になりますorz
[/追記]
先手が黒になる様に調整。
関数名整理。
色々共通化。
Board_Check_WinnerはGameファイルからTekikomaとMykomaを引数で貰い、それをそのままSwitch文のcaseとして使った所「定数を使って下さい」エラーが出たため、仕方なく無理矢理動かしています。
取り敢えず外れの無さそうな明解C++を購入して他はサイトをじっくり読んでから決めてみます。
さて本題ですが、やっとFlip辺りを大改築してみました。
ソフト屋さんに教えてもらった
typedef struct {
int vx;
int vy;
} BoardVec_t;
static BoardVec_t KomaVector[8] = {
{ -1,-1 },
{ 0,-1 },
{ 1,-1 },
{ -1,0 },
{ 1,0 },
{ -1,1 },
{ 0,1 },
{ 1,1 }
};
プログラム自体は正常に起動はしてます。
発見出来た問題点は
・コマを置けない状態でパス画面が出ない・・・原因不明です。。Gameファイル内のPass_stateに到達していない事はメッセージボックスを使って確認したので、Check_end関数が正常に働いていない可能性が高いですが。
・ゲームが終了しても終了画面に移らない・・・これも原因は上と同じだと思います。
改善した点
Flipを整理したら置ける場所があるのに何故かエラーで固まる現象は無くなりました。
[追記]
無くなったと思ったら、ありました・・・。FlipやSearchは大幅に改善したはずなのですが、原因が全く分からない・・・。
つまるところ以前から存在していた問題点は何一つ解決していない事になりますorz
[/追記]
先手が黒になる様に調整。
関数名整理。
色々共通化。
Board_Check_WinnerはGameファイルからTekikomaとMykomaを引数で貰い、それをそのままSwitch文のcaseとして使った所「定数を使って下さい」エラーが出たため、仕方なく無理矢理動かしています。
- 添付ファイル
-
- オセロ.zip
- (7.88 KiB) ダウンロード数: 124 回
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
・まだ何かMykomaとTekikomaとkomaの命名規則の扱いが曖昧なような。
Mykomaと命名するときはプレーヤーコマに限定してください。
それ以外の扱いの所が散見されます。
MykomaなのにCPUコマの番号が入っている場合がありませんか?
それなのにMykomaにプレーヤーコマの番号しか許さない関数があったります。
それと何度も書きましたが、3 - Mykoma;は止めましょう。
ごめんなさいバグ取りの前に、これが気になってコードを追いかけられません。
・Board_Searchのflagってひっくり返し数のカウント?
flagじゃなくてflip_countとかにしてもらえませんか?
ここだけじゃないのですが変数の命名が色々と問題です。
flagならON/OFFやenum値にしましょう。
カウント値ならcountなどを名前に付けましょう。
・Board_Check_Winnerですが、++userじゃなくてblack++とかにした方が分りやすいです。
変数の名前通りの使い方をしないとバグの原因(たぶん最も多いミスの原因)となります。
そして判断前にこうするだけです。
・同じenumを2つ定義するのはやめてヘッダに移してください。あとenum名は重ならないように工夫を。
Board.cpp(184): enum winner { INIT, USER, CPU, DRAW };
Game.cpp(24): enum winner { NOONE , USER, CPU, DRAW };
・ここも直してくださいね。Title_main()を2回呼び出しています。
・初心者にお薦めできなことシリーズ。
if文で{}を使わない事。if文の範囲を間違って制御することが多い。
Game_main()の次の部分です。
これだとBoard_Check_End()で0が戻ってきてUSER_PASSになっても、プレーヤー側の入力ターンを行うのですが意図と違いませんか?
これは、デバッガで追いかけると分かる問題ですね。
・エラーになったコードを見ないと何とも・・・
>Board_Check_WinnerはGameファイルからTekikomaとMykomaを引数で貰い、それをそのままSwitch文のcaseとして使った所「定数を使って下さい」エラーが出たため、仕方なく無理矢理動かしています
他にも問題がありますが、今回は以上!
Mykomaと命名するときはプレーヤーコマに限定してください。
それ以外の扱いの所が散見されます。
MykomaなのにCPUコマの番号が入っている場合がありませんか?
それなのにMykomaにプレーヤーコマの番号しか許さない関数があったります。
それと何度も書きましたが、3 - Mykoma;は止めましょう。
ごめんなさいバグ取りの前に、これが気になってコードを追いかけられません。
・Board_Searchのflagってひっくり返し数のカウント?
flagじゃなくてflip_countとかにしてもらえませんか?
ここだけじゃないのですが変数の命名が色々と問題です。
flagならON/OFFやenum値にしましょう。
カウント値ならcountなどを名前に付けましょう。
・Board_Check_Winnerですが、++userじゃなくてblack++とかにした方が分りやすいです。
変数の名前通りの使い方をしないとバグの原因(たぶん最も多いミスの原因)となります。
そして判断前にこうするだけです。
if(Mykoma == BLACK){ //プレーヤーのコマが黒だった場合
user = black;
cpu = white;
} else {
user = white;
cpu = black;
}
Board.cpp(184): enum winner { INIT, USER, CPU, DRAW };
Game.cpp(24): enum winner { NOONE , USER, CPU, DRAW };
・ここも直してくださいね。Title_main()を2回呼び出しています。
if(Title_main()==zokkou) //タイトル画面表示&スタート押されたらGame関数へ
func_state=GAME;
if(Title_main()==shuuryou) //ゲーム終了が入力されたらブレイク
end = 1;
Title_Draw();
break;
if文で{}を使わない事。if文の範囲を間違って制御することが多い。
Game_main()の次の部分です。
case USER_TURN:
if(Board_Check_End(Mykoma) == 0) //置ける場所があるかチェック
game_state = USER_PASS;
if(Board_Check_Mouse(Mykoma) == 1){ //プレーヤー側の入力ターン
Board_Flip(Mykoma);
game_state = CPU_TURN;
}else{
game_state = USER_TURN;
}
break;
これは、デバッガで追いかけると分かる問題ですね。
・エラーになったコードを見ないと何とも・・・
>Board_Check_WinnerはGameファイルからTekikomaとMykomaを引数で貰い、それをそのままSwitch文のcaseとして使った所「定数を使って下さい」エラーが出たため、仕方なく無理矢理動かしています
他にも問題がありますが、今回は以上!
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
if文の{}について
全て無くそうとし、愚直に消していくとエラー多発するため慎重に置き換えていったのですが
TitleとBoard_searchだけはどうも{}を取るとおかしな事になってしまったため残してあります。
他の項目については一応手直ししてみました。
これによって終了画面まで行く事が出来ましたが
・試合結果に関わらず勝利画面になる?
・勝利画面からタイトル画面へ移行する際に不明なfunc_stateの表示が多発する。(←Mainファイルが原因だと思いますが調査中)
などの問題点を現在調査してます。
そういえば全く別の話ですが、よくSLGなどでマウスカーソルを動かすとその座標のマス枠が光ったりし、マウスが何処をさしているか分かり易くする工夫があります。
これはマウスの座標を表示する要領で、マウス座標をstaticにしてDraw関数で マス目の枠を光らせる画像 を上書きする形で描画する感じでしょうか?
多分はさみ将棋を製作する過程で学ぶ事になるとは思いますが。
[追記]
勝利画面からタイトル画面へ そこからまた勝利画面のループの原因について
Boardの情報が初期化されていない事に気付きました(多分これが原因?)
Board_init内でBanDataと同じ配列を宣言しておき、BanDataにコピーするプログラムを組み込めば大丈夫でしょうか。
というより試してみます。
成功したら添付ファイルを置き換えておきます。
[追記2]
駄目でした。
全て無くそうとし、愚直に消していくとエラー多発するため慎重に置き換えていったのですが
TitleとBoard_searchだけはどうも{}を取るとおかしな事になってしまったため残してあります。
他の項目については一応手直ししてみました。
これによって終了画面まで行く事が出来ましたが
・試合結果に関わらず勝利画面になる?
・勝利画面からタイトル画面へ移行する際に不明なfunc_stateの表示が多発する。(←Mainファイルが原因だと思いますが調査中)
などの問題点を現在調査してます。
そういえば全く別の話ですが、よくSLGなどでマウスカーソルを動かすとその座標のマス枠が光ったりし、マウスが何処をさしているか分かり易くする工夫があります。
これはマウスの座標を表示する要領で、マウス座標をstaticにしてDraw関数で マス目の枠を光らせる画像 を上書きする形で描画する感じでしょうか?
多分はさみ将棋を製作する過程で学ぶ事になるとは思いますが。
[追記]
勝利画面からタイトル画面へ そこからまた勝利画面のループの原因について
Boardの情報が初期化されていない事に気付きました(多分これが原因?)
Board_init内でBanDataと同じ配列を宣言しておき、BanDataにコピーするプログラムを組み込めば大丈夫でしょうか。
というより試してみます。
成功したら添付ファイルを置き換えておきます。
[追記2]
駄目でした。
- 添付ファイル
-
- オセロ.zip
- (7.87 KiB) ダウンロード数: 124 回
最後に編集したユーザー 小人 on 2011年6月15日(水) 15:23 [ 編集 2 回目 ]
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
あれ?逆に取られてしまいました?小人 さんが書きました:if文の{}について
全て無くそうとし、愚直に消していくとエラー多発するため慎重に置き換えていったのですが
TitleとBoard_searchだけはどうも{}を取るとおかしな事になってしまったため残してあります。
if文に{}は必須と言う意味で書きました。
すいません。
{}を書かないと手痛いミスが頻発するので書いたほうがいいよって事です。
この表現がまずかったか。・初心者にお薦めできなことシリーズ。
if文で{}を使わない事。
出来れば今のオセロでも採用して欲しいですね。小人 さんが書きました: そういえば全く別の話ですが、よくSLGなどでマウスカーソルを動かすとその座標のマス枠が光ったりし、マウスが何処をさしているか分かり易くする工夫があります。
これはマウスの座標を表示する要領で、マウス座標をstaticにしてDraw関数で マス目の枠を光らせる画像 を上書きする形で描画する感じでしょうか?
多分はさみ将棋を製作する過程で学ぶ事になるとは思いますが。
それとマウスの座標を残すのではなく、ボード上の光る位置をstaticで残してDrawで描画するってのが良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
いえいえこちらこそ早とちりしてしまって申し訳御座いません。
直してきます。
[追記]
アドバイスを頂いてから明解C言語のif文を見直したら、サンプルプログラムがことごとく{}を使っていなかったので完全に勘違いしてしまいました(笑
{}使って表記してくれていても良いのに・・・。
>それとマウスの座標を残すのではなく、ボード上の光る位置をstaticで残してDrawで描画するってのが良いと思います。
という事はマウスの座標を一旦(Mouse関数外で宣言してある)staticな変数に収納し、それをDrawにて描画するという認識で大丈夫でしょうか?
直してきます。
[追記]
アドバイスを頂いてから明解C言語のif文を見直したら、サンプルプログラムがことごとく{}を使っていなかったので完全に勘違いしてしまいました(笑
{}使って表記してくれていても良いのに・・・。
>それとマウスの座標を残すのではなく、ボード上の光る位置をstaticで残してDrawで描画するってのが良いと思います。
という事はマウスの座標を一旦(Mouse関数外で宣言してある)staticな変数に収納し、それをDrawにて描画するという認識で大丈夫でしょうか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
いえマウス座標ではなく、光るマスの縦横番号とか抽象的なものが良いでしょう。小人 さんが書きました: という事はマウスの座標を一旦(Mouse関数外で宣言してある)staticな変数に収納し、それをDrawにて描画するという認識で大丈夫でしょうか?
出来るだけマウスの処理の所で処理は済ましてしまうべきです。後々改造しづらいですよ。
それにこうするとCPUがコマを置く時にも容易に光らせることが出来ますよね。
前にも提案しましたが演出はゲームの大事な要素ですので、オセロでまずできるだけの演出を施してみましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
ごめんなさい、おっしゃってくださっている内容が把握しきれず・・・
自分がぼんやり考えていた形は
Board.cpp
static int x,y; //変数名は仮。光るマスの座標の役割
Board_Draw関数内の Switch文 各caseの中で
普通のマップ(コマの画像など)描画の次の行に
if( (h == y) && ( w == x){
DrawGraph(光ってるマス目の画像)
}
を加えて
x、yにそれぞれマウスがさしている座標を代入しようかと思っていたのですが、これでは融通が利かなくなり良くないという事ですよね。
どの様な形にしたら宜しいでしょうか?
自分がぼんやり考えていた形は
Board.cpp
static int x,y; //変数名は仮。光るマスの座標の役割
Board_Draw関数内の Switch文 各caseの中で
普通のマップ(コマの画像など)描画の次の行に
if( (h == y) && ( w == x){
DrawGraph(光ってるマス目の画像)
}
を加えて
x、yにそれぞれマウスがさしている座標を代入しようかと思っていたのですが、これでは融通が利かなくなり良くないという事ですよね。
どの様な形にしたら宜しいでしょうか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
ここで
if( (h == y) && ( w == x){
マウスの座標系はドット単位で、マスの単位はブロックなのでは無いでしょうか?
つまりhとyは座標単位が違いませんかって事ですね。
でよりハード的な単位である画面座標ではなくオセロボード上のマスの縦横単位1~8のにしたほうが良くないですかって事です。
if( (h == y) && ( w == x){
マウスの座標系はドット単位で、マスの単位はブロックなのでは無いでしょうか?
つまりhとyは座標単位が違いませんかって事ですね。
でよりハード的な単位である画面座標ではなくオセロボード上のマスの縦横単位1~8のにしたほうが良くないですかって事です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
あぁぁぁおっしゃる通りです。そのつもりでした。
この場合Mouse関数内の w、hを使おうかと思ってました。
しかしCPU側の入力を光らせる(多分置いたコマの場所のみになる・・・のでしょうか)にはこの方法だとあんまり良くないのかなぁと思ってますが、どうなのでしょうか。
CPUの入力関数において、入力関数が終了する前に
Search関数によってひっくり返せる事が判明した座標を、Boardの中にある関数(まだ作ってないですが)に引数として引渡し それを描画すればいけるような気もしますが、こんな感じで良いのでしょうか・・・?
この場合Mouse関数内の w、hを使おうかと思ってました。
しかしCPU側の入力を光らせる(多分置いたコマの場所のみになる・・・のでしょうか)にはこの方法だとあんまり良くないのかなぁと思ってますが、どうなのでしょうか。
CPUの入力関数において、入力関数が終了する前に
Search関数によってひっくり返せる事が判明した座標を、Boardの中にある関数(まだ作ってないですが)に引数として引渡し それを描画すればいけるような気もしますが、こんな感じで良いのでしょうか・・・?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
まぁ、こちらが教えすぎても勉強のチャンスを減らすことになるので、自分で思いつく方法でやってみてください。
その上で問題があれば質問してもらえば良いです。試行錯誤してる時が勉強になるんですよね。
あとソース見たときに問題を感じたら突っ込みますから。
ちなみに光ると言っても単に光ると面白く無いので明滅とかエフェクトも考えてくださいね~。
光るマスを絵で描くよりも半透明とか加算合成とか使ってもらったほうが勉強になりますから。
そう言えばw、hって幅と高さを示す名前なんですよね。widthとheight。
位置を表す名前じゃないから変えてもらったほうが良いかな。
その上で問題があれば質問してもらえば良いです。試行錯誤してる時が勉強になるんですよね。
あとソース見たときに問題を感じたら突っ込みますから。
ちなみに光ると言っても単に光ると面白く無いので明滅とかエフェクトも考えてくださいね~。
光るマスを絵で描くよりも半透明とか加算合成とか使ってもらったほうが勉強になりますから。
そう言えばw、hって幅と高さを示す名前なんですよね。widthとheight。
位置を表す名前じゃないから変えてもらったほうが良いかな。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
既にこんなの作ってしまってましたorz
明暗ですか~・・。
加算合成や半透明なんかも全然知りませんでした。
一応透過処理だけは勉強しましたが。
座標という事で取り敢えずXとYに置き換えてみました。
あとよく将棋などで、前のターンに相手がコマを置いた場所が光り続ける演出は この仕組みとは全く別物ですね、多分。
相手のターンになっても光っていないといけないのでどんなプログラムなのか皆目検討も付きませんが。
他に出来る事から進めていこうかなと思います。
明暗ですか~・・。
加算合成や半透明なんかも全然知りませんでした。
一応透過処理だけは勉強しましたが。
座標という事で取り敢えずXとYに置き換えてみました。
あとよく将棋などで、前のターンに相手がコマを置いた場所が光り続ける演出は この仕組みとは全く別物ですね、多分。
相手のターンになっても光っていないといけないのでどんなプログラムなのか皆目検討も付きませんが。
他に出来る事から進めていこうかなと思います。
- 添付ファイル
-
- オセロ.zip
- (8.39 KiB) ダウンロード数: 124 回
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: オセロのプログラム制作過程
コードは、また後で見させてもらいますね。
>あとよく将棋などで、前のターンに相手がコマを置いた場所が光り続ける演出は この仕組みとは全く別物ですね、多分。
>相手のターンになっても光っていないといけないのでどんなプログラムなのか皆目検討も付きませんが。
ここら辺はいろんなモノが同時に動くアクションやシューティングなどにヒントがあります。
でも一言で書くと、ひっくり返した場所を配列などに記録しておいて相手のターンの時に表示しているだけですよ。
要望としてはコマのひっくり返りや、AI思考中の演出(実際には一瞬ですが、考えてる風にもったいぶって)もほしいですね。
で、演出アイデア。手間を考えずに色々書いときます。全部やらなくて良いですし、それ以上のことをやっても構いません。
置いたところとひっくり返るところが予告としてピカっと光るとか、置くときに石が上から降ってくるとか、置いたときに「ババーン」書き文字がジョジョ風に出るとか、敵にキャラ性を持たせてしゃべるとか、大量にコマをひっくり返すと演出が違うとか、いや書くだけは楽だな。
今の敵や味方の石数のとかの表示もあれば見栄えが上がります。パス回数も表示したほうが良いかな?
>あとよく将棋などで、前のターンに相手がコマを置いた場所が光り続ける演出は この仕組みとは全く別物ですね、多分。
>相手のターンになっても光っていないといけないのでどんなプログラムなのか皆目検討も付きませんが。
ここら辺はいろんなモノが同時に動くアクションやシューティングなどにヒントがあります。
でも一言で書くと、ひっくり返した場所を配列などに記録しておいて相手のターンの時に表示しているだけですよ。
要望としてはコマのひっくり返りや、AI思考中の演出(実際には一瞬ですが、考えてる風にもったいぶって)もほしいですね。
で、演出アイデア。手間を考えずに色々書いときます。全部やらなくて良いですし、それ以上のことをやっても構いません。
置いたところとひっくり返るところが予告としてピカっと光るとか、置くときに石が上から降ってくるとか、置いたときに「ババーン」書き文字がジョジョ風に出るとか、敵にキャラ性を持たせてしゃべるとか、大量にコマをひっくり返すと演出が違うとか、いや書くだけは楽だな。
今の敵や味方の石数のとかの表示もあれば見栄えが上がります。パス回数も表示したほうが良いかな?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: オセロのプログラム制作過程
色々修正したので新しく添付しておきます。
修正点
バグが確認出来る限り一切無いと思います。
やっと完成しました。
効果音の実装
(問題点)
・タイトルにカーソルを合わせた時に鳴る筈の音がならない。
別の音に差し替えたら鳴ったのですが、カーソルが合っている間中鳴り続けていたため修正した結果が上。
・タイトル画面立ち上がりと共にBGMもどきの効果音を鳴らそうと思っていたのに、鳴らない。
ただゲーム開始を押した段階で鳴るため、これはこれでアリな気も・・・。
CPUのAIを改善しなくては・・・。
修正点
バグが確認出来る限り一切無いと思います。
やっと完成しました。
効果音の実装
(問題点)
・タイトルにカーソルを合わせた時に鳴る筈の音がならない。
別の音に差し替えたら鳴ったのですが、カーソルが合っている間中鳴り続けていたため修正した結果が上。
・タイトル画面立ち上がりと共にBGMもどきの効果音を鳴らそうと思っていたのに、鳴らない。
ただゲーム開始を押した段階で鳴るため、これはこれでアリな気も・・・。
CPUのAIを改善しなくては・・・。
- 添付ファイル
-
- オセロ.zip
- (113.85 KiB) ダウンロード数: 140 回