こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

マインスイーパーもどき(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)) = " "
の部分でコンパイル時に
「コンパイルエラー:修正候補 識別子」
とでます。ヘルプを見てもよくわかりませんでした。
テキストが長すぎるので途中は省きました。
よろしくお願いします。

投稿日時 - 2006-11-19 11:08:06

QNo.2548700

困ってます

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

補足拝見しました。他のプロシージャで特におかしいところはないのですが、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
とした方がよいでしょう。

投稿日時 - 2006-11-20 09:37:14

お礼

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

投稿日時 - 2006-11-20 19:52:24

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.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

投稿日時 - 2006-11-19 19:56:21

補足

ご回答ありがとうございます。
ご指摘の通りバリアント型に変えてみましたが、エラーは起きませんでしたが、置き換わりませんでした。
実は文字数の関係で途中のプロシージャを省いて書きましたが、そっちに原因があるかもしれないので書いておきます。
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

投稿日時 - 2006-11-19 23:53:20

ANo.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とやってもエラーにはならないのですが)既に宣言された変数の型を変換してくれるわけではありません。

投稿日時 - 2006-11-19 17:45:42

補足

ご返答ありがとうございます。
今度は↓のように直しましたが、
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

投稿日時 - 2006-11-19 19:11:47

ANo.2

そもそも、
> 9が地雷で0が何もないと言うことです。
なのに、

> CStr(f(a, b)) = "*"
> CStr(f(a, b)) = " "
ってどういうことなんでしょう?

> Dim minefield(11, 13) As Integer
と、変数のデータ型がIntegerなので、数値以外のもの、つまり文字列("*"や" ")は設定できません。
別途文字列型の配列を用意す必要がありそうですが・・・
#またはVariant型にしてしまうか・・・

・・・関数名が「show」ということは、ひょっとして表示をしたい(表示用の文字列を作りたい)のでしょうか?

投稿日時 - 2006-11-19 12:19:15

補足

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

投稿日時 - 2006-11-19 16:57:37

ANo.1

「識別子」というのは変数とか、値を代入できるプロパティなどを指します。

CStr()というのは、引数に指定されたオブジェクトを文字列に変換する関数で、それ自体に何かの値を代入するということはできません。

投稿日時 - 2006-11-19 11:25:21

補足

ご回答ありがとうございます。とりあえず以下のように直しましたが、まだエラーが出ます。
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
エラー内容は同じです。

投稿日時 - 2006-11-19 17:02:24

あなたにオススメの質問