マインスイーパーのとある処理について(文章まとまってなくてすみません)

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ゆうとぴあ

マインスイーパーのとある処理について(文章まとまってなくてすみません)

#1

投稿記事 by ゆうとぴあ » 3年前

[0]はじめに

この掲示板を使うのは初めてで、色々と不器用ですがよろしくお願いします。かなり長い文面となっています。不明点はどんどん質問し返してください。どうしても解決したい内容なので、ご協力お願いします。

[1] 質問というかお願い(?)

現在C言語でマインスイーパー を作成しています。

<何を回答して欲しいのか>

この後長々と仕様やらなんやらについて説明しますが、最終的に以下のことを回答していただければ良いので、回答に必要ないと思った箇所はさらっと目を通すだけで良いかと思います。

↓回答して欲しいこと↓
一括オープンのコードを書いて欲しい!

*一括オープンとは?
マインスイーパーをプレイしたことがある方ならわかると思いますが、周囲に何もないマスを開くとその周囲のマスもどんどん開いていく(数字マスが現れるまで開く)という仕様のことです。なお、一括オープンは私が名付けた仮の名前です。

↓回答の際に注意して欲しい事↓
・変数は基本的に自由に設定して使ってください。
・外部ライブラリの使用はなるべく避けてください。
・ポインタや構造体はまだ理解が浅いので、なるべく使用は避けていただきたいですが、仕方ない場合は使用してください。

以下、さらっと見てください。

<現在の自作マインスイーパー の仕様>

*コマンドプロンプトで動くだけ(ウィンドウが開くなどの凝ったものではない)。

*マインスイーパー のゲーム自体の仕様(例えば、旗を立てたところは開かないなど)はGoogleで無料で遊べるマインスイーパー(+α)を目指している。←スマホでGoogleを開き、マインスイーパー と検索したら一番上に出てくる緑を基調としたやつのことです。

*プレイヤーは盤面の行数と列数や地雷数を自由に設定できる(上限下限あり)。

*プレイヤーは基本的にキーボードのテンキーで数値を入力して行や列を選択したり、行動を選択する。

*マインスイーパーの3つの状態は2次元配列(行×列)で管理している。←3つの状態とは開いているか否か、地雷があるか否か、旗があるか否か(基本的に否の場合は0、そうで無いときは1)。それぞれの配列はopen、bomb、flagとしている。

*マスの描写は■や△などを使用しており、for文を二重にすることによって行×列の盤面を描写している(その際先ほどの3つの状態を使用する)。

>他にもいろいろと仕様がありますが質問に関係無さそうな仕様は省略してあります。(知りたい仕様などがあれば質問し返してください)

<今作りたい仕様(仮に一括オープンと名付ける)>

簡単に言うと、開いたマスの周辺に何もなければ、数字マスが現れるまで開き続けるという仕様。数字マスという状態は配列で管理しておらず、周りの地雷の数を盤面の描写時に数えて地雷が1つ以上隣接していれば数字描写している。

少し詳しく言うと、マスを開いたとき、周囲8マスに地雷がなければ旗以外のマスのopenに1を代入する。また、周囲8マスそれぞれに対しても周囲8マスを調べ、地雷がなければ…というように開く仕様。

<一括オープンを実現するためにどんなコードを書いているか>

本当はソースコードを見せるのが良いと思うのですが、これが初のコーディングなのでハッキリ言って見づらく、混乱を招くようなコメントも多々あるため、回答者さんからの依頼がある場合のみ載せますが、なかなか読みづらいということだけ把握をお願いします。

ところで、今書いているコードの全体的な構造を大まかにお伝えします(実行される順に書いてます)。

注)一部の変数を除いてグローバル変数を使っています(ポインタに抵抗があったので)。なお、関数の引数はローカル変数です。

・再帰関数とカウント関数は自作関数です。

メイン関数{
・マインスイーパーのカスタムを行う
・3つの状態の初期化

・プレイヤーの行動(行と列、行動を選択)
・とりあえず、プレイヤーが選択したマスのopenに1を代入したり、flagに1を代入したりする。
・その他のマスの状態の変更。再帰関数を呼び出すが、引数にはプレイヤーが選択した行と列を使用する(→再帰関数へ)
・各マスの状態に基づいてマスを描写する
*繰り返し(*へ戻る)
}

再帰関数{
・プレイヤーが開いたマスの周りの地雷を数える。カウント関数を呼び出すが、引数には再帰関数の引数を使う(→カウント関数へ)
・カウント関数の結果に基づいて処理を決定する(周囲の地雷が0個の場合は一括オープンのコードを実行する。そうで無いときは何もしない)。
・周囲8マスのそれぞれの行と列を用いて再帰関数を呼び出す。引数にはもちろんその行と列を使う(→再帰関数へ)
}

カウント関数{
・隣接する周囲8マスの地雷を数える
}

<何故悩んでいるのか>

一言で言うと一括オープンの部分がうまくいきません。どううまくいかないのかというと、開いて欲しいところが開かない(現在のプログラムでは周囲8マスのうち左上しか調べてくれない←全部調べてくれるコードを書いたつもりだったが…)、処理が無限ループするなどです。もうかれこれ2週間くらい悩んでます。

<結局何を回答して欲しいのか>
一括オープンのコードを書いて欲しい!というのが願いです。もうかなり時間を費やしてしまったので、答えというか解決例のようなものを見たいです。もちろん、書いていただいたコードは何がどうなっているのか理解した上で使う予定です。

[2]環境など

<環境>
・Windows10
・gccもしくは学習用C言語開発環境(苦しんで覚えるC言語というサイトのものです)
・コーディングにはVScodeを使っています。

<C言語の理解度等>
・C言語の入門の内容のうち、ポインタと構造体以外は一応使った事があります。
・ライブラリは標準ライブラリしか使っていません。

ゆうとぴあ

Re: マインスイーパーのとある処理について(文章まとまってなくてすみません)

#2

投稿記事 by ゆうとぴあ » 3年前

すみません、二回送信をタップしてしまったようで、同じ書き込みが2つ掲載されてしまいました。削除の方法を今探していますが、知っている方がいたら返信してください。また、削除法が分かり次第消します。質問の答えはもう一つの書き込みにお願いします。

ゆうとぴあ

Re: マインスイーパーのとある処理について(文章まとまってなくてすみません)

#3

投稿記事 by ゆうとぴあ » 3年前

消せないみないなのでこのままにします。

返信

“C言語何でも質問掲示板” へ戻る