• ベストアンサー

マインスイーパーもどき(VBA)

ExcelのVBAでマインスイーパーもどきを作っていますが、どうも上手くいきません。9が地雷で0が何もないと言うことです。以下、ソースです。 Sub mine() Dim minefield(11, 13) As Integer Dim i As Integer, a As Integer, b As Integer, x As Integer x = 0 Randomize For i = 1 To 20 a = Int(Rnd * 10) + 1 b = Int(Rnd * 12) + 1 If minefield(a, b) = 9 Then x = x + 1 i = i - 1 End If minefield(a, b) = 9 Next i MsgBox "地雷が" & x & "回重複" countMine minefield, 10, 12 showInt minefield, 10, 12 show minefield, 10, 12 End Sub Sub show(f() As Integer, h As Integer, w As Integer)  Dim a As Integer, b As Integer For a = 1 To 10 For b = 1 To 12 If (f(a, b) = 9) Then CStr(f(a, b)) = "*" If (f(a, b) = 0) Then CStr(f(a, b)) = " " Next b Next a End Sub If (f(a, b) = 9) Then CStr(f(a, b)) = "*" If (f(a, b) = 0) Then CStr(f(a, b)) = " " の部分でコンパイル時に 「コンパイルエラー:修正候補 識別子」 とでます。ヘルプを見てもよくわかりませんでした。 テキストが長すぎるので途中は省きました。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.5

補足拝見しました。他のプロシージャで特におかしいところはないのですが、mine()の中で、 countMine minefield, 10, 12 showInt minefield, 10, 12 show minefield, 10, 12 と記述していますね。 countMine で各マスの周囲の地雷の数を調べてf()に代入 showIntでf()の内容をセルに表示 してから、 showの中で、f()の中の9と0をそれぞれ"*"と" "に置換 しているのですが、置換したf()の内容をセルに表示させる部分がありません。 このソースのままだと、"*"が表示されないのは当然なのですが、これは、単にまだVBAの一部を省略していて、他の部分でセルに転記しているのですか? 単純に、 show minefield, 10, 12 showInt minefield, 10, 12 と順番を入れ替えると、それっぽい画面になるのですが。 (ただ、これではまだゲームではないですよね) 蛇足ながら、countMine()の中で、 For a = 1 To 10 For b = 1 To 12 は For a = 1 To h For b = 1 To w とした方がよいでしょう。

cermet
質問者

お礼

置換したあとにセルに入れるの忘れてました・・・ 何とか完成させることができました。 ありがとうございました。

その他の回答 (4)

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.4

f(a, b) = CStr(f(a, b)) は意味がありません。 これは、左辺のf(a, b)の型を変換する、という意味ではありません。 f(a, b)に整数の9が入っている状態では、CStr(f(a, b))は文字列の"9"に変換されます。したがってこの式は、 f(a, b) = "9" という意味になります。しかし、 「そもそもf(a, b)はIntegerとして宣言されている」 ので、f(a, b)には"9"が自動的に整数の9に変換されて代入されます。つまり、f(a, b)の値は変わりません。一度宣言されたf()の型を変えることはできないのです。 だから、次の行の f(a, b) = "*" で、「型が一致しません」とエラーが出るのです。 Integer型の変数に、整数に変換できない文字列を代入しているからです。 No.2の方も書いておられますが、いっそ、Sub mine()の中の Dim minefield(11, 13) As Integer を Dim minefield(11, 13) As Variant にして、show()を以下のようにしてしまえば、エラーにはならず、CStr()も必要なくなるでしょう。(個人的にはあまりお勧めできるやり方ではありませんが) Sub show(f() As Variant, h As Integer, w As Integer)   Dim a As Integer, b As Integer   For a = 1 To 10     For b = 1 To 12       If (f(a, b) = 9) Then         f(a, b) = "*"       ElseIf (f(a, b) = 0) Then         f(a, b) = " "       End If     Next b   Next a End Sub

cermet
質問者

補足

ご回答ありがとうございます。 ご指摘の通りバリアント型に変えてみましたが、エラーは起きませんでしたが、置き換わりませんでした。 実は文字数の関係で途中のプロシージャを省いて書きましたが、そっちに原因があるかもしれないので書いておきます。 Sub countMine(f() As Variant, h As Integer, w As Integer) Dim i As Integer, j As Integer Dim a As Integer, b As Integer Dim x As Integer, y As Integer, z As Integer For a = 1 To 10 For b = 1 To 12 If f(a, b) < 9 Then x = 0 For y = -1 To 1 For z = -1 To 1 If f(a + z, b + y) = 9 Then x = x + 1 Next z Next y f(a, b) = x End If Next b Next a End Sub Sub showInt(f() As Variant, h As Integer, w As Integer) Dim i As Integer Const a As Integer = 7 Const b As Integer = 3 Do While h > 0 For i = 1 To w Cells(a + h, b + i) = f(h, i) Next i h = h - 1 Loop End Sub

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.3

No.1です。補足拝見しました。 CStr (f(a, b)) だけでは同じエラーが出るのは当然です。これをどうしたいのか、コンパイラにはわかりません。たとえば、 S = CStr(f(a, b)) などと他の変数に代入するのであればエラーがなくなります。 それで、やりたいことがわかるようでわからないのです。なぜ文字列に変換したいのでしょうか?最終的にセルに"*"と表示させたいのなら、そのタイミングで変換してセルの値をセットすればいいはずです。 If (f(a, b) = 9) Then f(a, b) = "*" If (f(a, b) = 0) Then f(a, b) = " " この2行では、9と0であったらそれぞれ"*"と" "に配列の内容を置きかえようとしているようですが、そもそもf()は f() As Integer と宣言されているので、整数しか代入できません。 もしかして、CStr (f(a, b))と書くとf()の型を文字列に変換されると思っていらっしゃるのなら、ちょっとCStr()や変数の型について誤解されています。 たとえば、 Dim S as String Dim i as Integer とStringで宣言された変数Sに、Integerで宣言された変数iを「文字列として」代入したいようなときに、 S = CStr(i) というような使い方をします。(VBAの場合は型の扱いが割とルーズなので、別にS = iとやってもエラーにはならないのですが)既に宣言された変数の型を変換してくれるわけではありません。

cermet
質問者

補足

ご返答ありがとうございます。 今度は↓のように直しましたが、 f(a, b) = "*" の部分で「型が一致しません」のエラーが起こります。 もしかして f(a, b) = CStr(f(a, b)) は、できないのでしょうか? Sub show(f() As Integer, h As Integer, w As Integer) Dim a As Integer, b As Integer For a = 1 To 10 For b = 1 To 12 If (f(a, b) = 9) Then f(a, b) = CStr(f(a, b)) f(a, b) = "*" ElseIf (f(a, b) = 0) Then f(a, b) = CStr(f(a, b)) f(a, b) = " " End If Next b Next a End Sub

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.2

そもそも、 > 9が地雷で0が何もないと言うことです。 なのに、 > CStr(f(a, b)) = "*" > CStr(f(a, b)) = " " ってどういうことなんでしょう? > Dim minefield(11, 13) As Integer と、変数のデータ型がIntegerなので、数値以外のもの、つまり文字列("*"や" ")は設定できません。 別途文字列型の配列を用意す必要がありそうですが・・・ #またはVariant型にしてしまうか・・・ ・・・関数名が「show」ということは、ひょっとして表示をしたい(表示用の文字列を作りたい)のでしょうか?

cermet
質問者

補足

説明不足で申し訳ないです。 地雷である9を*におきかえ、何もないことを示す0を に置き換えたいのです。

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.1

「識別子」というのは変数とか、値を代入できるプロパティなどを指します。 CStr()というのは、引数に指定されたオブジェクトを文字列に変換する関数で、それ自体に何かの値を代入するということはできません。

cermet
質問者

補足

ご回答ありがとうございます。とりあえず以下のように直しましたが、まだエラーが出ます。 Sub show(f() As Integer, h As Integer, w As Integer) Dim a As Integer, b As Integer For a = 1 To 10 For b = 1 To 12 CStr (f(a, b)) If (f(a, b) = 9) Then f(a, b) = "*" If (f(a, b) = 0) Then f(a, b) = " " Next b Next a End Sub エラー内容は同じです。