ページ 11

テーブルゲームを作っております

Posted: 2010年9月20日(月) 09:08
by ニット
陣取りゲームを作っております。
6×6マスの盤上でOption.PlayerNumで設定した人数で陣地を取り合います。
相手の駒の周囲8マスには駒が置けません。
自分のターンに盤上に1マスずつ置いていき置けなくなったほうが負けです。

そこで使う判定用の関数が上手く作れません。
bool MapJudge( int cx, int cy, int num );
でその処理を行っております。

盤は6×6ですが判定するときに変な場所を見ないように左右上下1マス余分に取ってあります。
その為、一番上の1マス目はMapTbl[1][1]の座標に値が入ります。

添付したソースは一部なので不具合があるかも知れません。
これが出来ればほぼ出来るのですがどのように修正すればよいかアドバイスを頂けないでしょうか

Re:テーブルゲームを作っております

Posted: 2010年9月20日(月) 10:52
by やっくん
上手く作れないとは具体的にどのように上手く作れないのでしょうか?
添付ソースのコメントアウトしている部分からの推測ですが、「チェック関数が任意の人数に対応してなく、1:1の場合にしか対応していない」ということでしょうか?

もしそうであれば、
>相手の駒の周囲8マスには駒が置けません。
これを逆に考えて、置く予定の場所の周囲8マスが"全て"【0】または【自分のNo】ならば置けるとしてはどうでしょう?

Re:テーブルゲームを作っております

Posted: 2010年9月20日(月) 11:25
by box
> そこで使う判定用の関数が上手く作れません。
> bool MapJudge( int cx, int cy, int num );

とりあえず、引数と戻り値の説明だけでもしてほしいです。

Re:テーブルゲームを作っております

Posted: 2010年9月21日(火) 01:07
by ニット
皆さんご回答ありがとうございます。
お陰さまで置けるか置けないかの判定は出来ました。

> bool MapJudge( int cx, int cy, int num );
失礼しました。
この関数は指定した座標の周囲8マスを検査し置けるか置けないかを判定します。

戻り値・・・置けるか置けないか
int cx, int cy・・・セルの座標
int num・・・どのプレイヤーのターンか

この関数を利用すれば置けるか置けないかを
判定し置けない方を負けにすることができると思います。
もし置けない場合はOption.ModeをM_RESULT;にしたいのですが上手く判定されていないようです。
間違ってそうな部分をご指摘いただけないでしょうか?

// 勝ち判定
                int WinF = false;            
                for(int i=1; i<MAP_H-1; i++){
                    for(int j=1; j<MAP_W-1; j++){
                        if ( MapJudge( j, i, Option.Num ) ) WinF = true;
                    }
                }
                if( !WinF ) Option.Mode = M_RESULT;

Re:テーブルゲームを作っております

Posted: 2010年9月21日(火) 05:05
by やっくん
WinFは「勝ちでは無い」、つまり置けるところが存在するっていうことで良いですか?
どこで上手く行ってないかよくわかりませんが、とりあえず以下のようにbreak文を挟んだ方が良いかも知れません。どこか1箇所でもおける場所があればそれ以上、式を評価する必要は無いように思えす。
ただし、これだけでは望む動作にはならないと思います(^^;

for(int i=1; i<MAP_H-1; i++){
for(int j=1; j<MAP_W-1; j++){
if ( MapJudge( j, i, Option.Num ) ){
WinF = true;
break;
}
}
if(WinF) break;
}

具体的にどのように上手くいかないのでしょうか? 画像

Re:テーブルゲームを作っております

Posted: 2010年9月21日(火) 10:01
by ニット
確かに無駄ですよね。
ありがとうございます。
サンプル用のソースを作ってみたのですが置けない状態になっても
Option.Mode = M_RESULT;になってくれません。
不具合があったらすみません。

Re:テーブルゲームを作っております

Posted: 2010年9月21日(火) 11:08
by asd
実際に動かして確認したわけではないのですが、
6x6の盤面で緩衝領域1マスということで以下のような理解をしていますが正しいですか?
□・・・プレーヤーが駒を置けるマス
X・・・緩衝領域(範囲外アクセス防止マス)のため駒は置けないマス

 ABCDEFGH
0XXXXXXXX
1X□□□□□□X
2X□□□□□□X
3X□□□□□□X
4X□□□□□□X
5X□□□□□□X
6X□□□□□□X
7XXXXXXXX
上記の理解が正しいとすると、現在のMapJudge関数は緩衝領域に駒が置けると
判断しているのではないでしょうか?
そのためMapJudge関数内でcx-1,cy-1,cx+1,cy+1のいずれかが緩衝領域にかかる場合は
そこに駒が置けるかどうかは判定してはいけないことになります。
その前提で少し書き換えてみました(動作未確認です、ゴメンナサイ)
bool MapJudge( int cx, int cy, int num ){
    //調査座標用変数
    int dx=cx-1;
    int dy=cy-1;
    bool ret = true;//最終的な戻り値
    if( cx==0 || cx==MAP_H-1 || cy==0 || cy==MAP_W-1 ){
        return false;
    }else{
        for(dy = cy - 1;dy <= cy + 1;dy++){
            for(dx = cx - 1;dx <= cx + 1;dx++){
            //緩衝領域はチェックをスキップする
            if(dy <= 0 || dy >= MAP_W - 1 || dx <= 0 || dx >= MAP_H - 1){ continue; }
            //1箇所でも相手の駒が見つかったら置いちゃダメ
            if(MapTbl[dy][dx] != num){ return false; }
        }
        }
        return true;
    }
}
上記の通りdy、dxが0やMAP_H+1(MAP_W+1)になった箇所は判定せず、に無視することで解決するのではないでしょうか?

Re:テーブルゲームを作っております

Posted: 2010年9月21日(火) 11:12
by asd
先ほどのソースで判定条件が間違っていました。
//緩衝領域はチェックをスキップする
            if(dy <= 0 || dy >= MAP_W - 1 || dx <= 0 || dx >= MAP_H - 1){ continue; }
            //1箇所でも相手の駒が見つかったら置いちゃダメ
            if(MapTbl[dy][dx] != num){ return false; }
この部分が正しくは、
//緩衝領域はチェックをスキップする
            if(dy <= 0 || dy >= MAP_H - 1 || dx <= 0 || dx >= MAP_W - 1){ continue; }
            //1箇所でも相手の駒が見つかったら置いちゃダメ
            if(MapTbl[dy][dx] != 0 && MapTbl[dy][dx] != num){ return false; }
ですね。
何もないマスがある場合も置けないと判定していました。
ご迷惑をおかけしました。

(追記)
あぁ、編集で追記すればよかったですね。レス数を増やしてしまってゴメンナサイorz
(追記2)
緩衝領域チェックでの変数も若干直しました。
(dyは縦方向なのでMAP_Hと比較する、dxは横方向なのでMAP_Wと比較するのが正しい)
何度もすみません。 画像

Re:テーブルゲームを作っております

Posted: 2010年9月21日(火) 11:23
by やっくん
動かして確認してみました。
for(int i=1; i<MAP_H-1; i++){ 
  for(int j=1; j<MAP_W-1; j++){ 
    if ( MapJudge( j, i, Option.Num ) ){ 
      WinF = true; 
   DrawFormatString(0, 0, GetColor(255,255,255), "x:%d y:%d", j, i);      
      break; 
    } 
  } 
  if(WinF) break; 
}
上記のように1命令追加してみてください。
これで何故おかしいかわかるかと思います。
mainループで

Loop();
ClearDrawScreen();
Draw();
ScreenFlip();



ClearDrawScreen();
Loop();
Draw();
ScreenFlip();

と順番を変えることもお忘れなく。

応えは↓↓(一応、作る楽しみを壊したくないので反転で伏せます^^;

すでに石が置かれているマスもチェックしている。
すでに石が置かれているとそこは置けないという判定が無い。
画像

Re:テーブルゲームを作っております

Posted: 2010年9月21日(火) 11:35
by やっくん
プレイして見ての感想ですが、どちらの順番であるか赤のターンなどとどこかに表示するとわかりやすいと思います。これから付ける予定でしたらすみません(^^;