DOBON.NET DOBON.NETプログラミング掲示板過去ログ

VBでクロスワード

  • 題名: VBでクロスワード
  • 著者: JING
  • 日時: 2010/02/02 21:35:57
  • ID: 26369
  • この記事の返信元:
    • (なし)
  • この記事への返信:
  • ツリーを表示
環境/言語:[Vista VB.NET 2005]
分類:[.NET]

初めまして。JINGと申します。
Vista VB.NET 2005で http://www.gamedesign.jp/flash/kanafla/kanafla.html
こちらのようなクロスワードを作ろうと考えているのですが、

Private btnMoji(71) As Button 'ア〜ンのボタン
Private btnMasu(25) As Button '5*5のマス目
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

btnMoji(0) = btnA
btnMoji(1) = btnI
btnMoji(2) = btnU
btnMoji(3) = btnE
        ・
        ・
        ・
btnMoji(70) = btnN

btnMasu(0) = btn1
btnMasu(1) = btn2
btnMasu(2) = btn3
btnMasu(3) = btn4
        ・
        ・
        ・
btnMasu(24) = btn25
End Sub

For〜Nextで複数のボタンに一度に命令を与えようと上記のように71個と25個の配列を作っているのですが、
ブログラムとしてあまりに不恰好な気がします。他に簡単な配列の記述はありますでしょうか?
それと、マスで使用中の文字を使用不可(Enabled = False)にする記述が、対象が配列同士になるとうまく書けません。
プログラムというよりもIf文、アルゴリズムの領域の問題かと思いますが、進展がなくなって久しいので、こちらに投稿した次第です。
よろしくお願いします。
■No26369に返信(JINGさんの記事)
> Private btnMoji(71) As Button 'ア〜ンのボタン
> Private btnMasu(25) As Button '5*5のマス目
> 71個と25個の配列を作っているのですが

違います。上記は btnMoji(0)〜btnMoji(71)までの72個と、
btnMasu(0)〜btnMasu(25)までの26個の宣言を意味します。

> 他に簡単な配列の記述はありますでしょうか?
デザイナでボタンを生成するのではなく、
プログラムコードで生成してみては如何でしょう。

Private Buttons As List(Of Button)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    Buttons = New List(Of Button)()

    Me.SuspendLayout()
    For c As Integer = Asc("ア") To Asc("ン")
        Dim btn As New Button()
        btn.Text = Chr(c)
        AddHandler btn.Click, AddressOf Buttons_Click
        Buttons.Add(btn)
        FlowLayoutPanel1.Controls.Add(btn)
    Next
    Me.ResumeLayout()
End Sub

Private Sub Buttons_Click(ByVal sender As Object, ByVal e As EventArgs)
    MsgBox(DirectCast(sender, Button).Text)
End Sub


ただ、これだと 83 個のボタンになってしまうので、
「ヰ」や「ッ」などを除いた 71 個とするならば、
このような方法もあります。

Const KATAKANA As String = "アイウエオ〜略〜ワヲン"
For Each c As Char In KATAKANA
    Dim btn As New Button()
    btn.Text = c
    AddHandler btn.Click, AddressOf Buttons_Click
    Buttons.Add(btn)
    FlowLayoutPanel1.Controls.Add(btn)
Next
■No26371に返信(魔界の仮面弁士さんの記事)
魔界の仮面弁士さん、返信ありがとうございます。
>
> Const KATAKANA As String = "アイウエオ〜略〜ワヲン"
> For Each c As Char In KATAKANA
> Dim btn As New Button()
> btn.Text = c
> AddHandler btn.Click, AddressOf Buttons_Click
> Buttons.Add(btn)
> FlowLayoutPanel1.Controls.Add(btn)
> Next

こちらの方で開発を進めようと思います。
配列に対するプロパティの変更とイベントの宣言が簡単にできるので、
開発が随分楽になりました。
それと、後述の

>マスで使用中の文字を使用不可(Enabled = False)にする記述が、対象が配列同士になるとうまく書けません。

こちらの質問なのですが、

Private Sub Buttons_Click(ByVal sender As Object, ByVal e As EventArgs)

  Dim i As Integer, j As Integer
  For i = 0 To Me.Buttons.Count - 1
    For j = 0 To Me.Masu.Count - 1 'Masuの概要はButtonsと同じです

      If sender Is Buttons(i) Then
        If Masu(j).BackColor = Color.Yellow Then
          Masu(j).Text = CType(sender, Button).Text
            If Masu(j).Text = Buttons(i).Text Then
              Buttons(i).Enabled = False
            Else
              Buttons(i).Enabled = True
            End If
        End If
      End If

    Next
  Next

End Sub

と、このようにLoopさせるだけでよいと思ったのですが、一度 False になったボタンが True になりません。どう記述すればよいのでしょうか?
  • 題名: Re[3]: VBでクロスワード
  • 著者: こど。
  • 日時: 2010/02/07 19:41:30
  • ID: 26395
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
こんばんは。

そのコードの意味をそのまま文章にして書いてみると何がおかしいか分かると思いますが、
押したボタンがボタンリストのあるボタンと一致した際にのみ、
 黄色いマス(カレントマス)にその際のテキストをセットした後、
 そのマスとボタンのテキストが一致すればボタンを無効化、
 一致しなければボタンを有効化
していますよ。
代入後なのでもちろん必ず一致しFalseをセットする方にしか行きませんし、対象が常にsenderのボタンになってしまいます。

Trueを設定する方の処理は「黄色いマスとテキストが一致しているために無効状態にある【あるボタン】を復帰させる」ことで、senderとは別のボタンです。
また、Falseをセットするのはsenderそのものなのでそもそもループの中にある必要はありません。
やりたいことをコード云々無関係にまず整理してみるとよいですよ。

※なお、無理にひとかたまりの複合ループで頑張るコードは(本質的には無用な、コード制御のためのIfをつけることで)実際に記述できますが、こういった処理は目的別にループを書いた方が見通しのよいコードになりますよ。

DOBON.NET | プログラミング道 | プログラミング掲示板