こんにちは
前回の記事の続きをしていきます
前回は画面作成と、ボタンを押したらそこに●が表示される仕組みを作りました
今回は挟んだ石をひっくり返す処理を実装します
書いてるコードはみやすさの問題で実際とは違う部分もいくつかあります。
全体の流れ
おしたボタンの座標によってひっくり返すかチェックする方向の決定
↓
おいた石と隣接する石の色と比べ返すかどうかの判断
↓
ひっくり返すべきと判断したらひっくり返す
↓
また違う方向で同じことを行う
ボタンを押したときの処理の命令の前回からの変更点
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click…Button64.Click 'テキストが入ってないときのみ動かす If sender.Text = "" Then stnPlace(sender) 'ボタンの番号をbtnNmbへ抜き出す処理 Dim btnName As String = sender.Name btnName = btnName.Replace("Button", "") Dim btnNmb As Integer = Integer.Parse(btnName) revChk(btnNmb) '石をひっくり返す処理 trnChange() End If End Sub
新しく関数revChkを追加した。この関数でひっくり返す処理を行う。
また、その関数に使う数字としてボタンの座標が必要なのでボタンのデフォルト名「Button○」から数字を抜き取る作業を行っている
座標によってひっくり返す方向の決定
'場所に応じて処理をする方向を決める。 Private Function revChk(ByVal btnNumber As Integer) Dim chkDir() As Integer = {-8, -1, 1, 8, -9, -7, 7, 9} '確認する方向の関数 -8=上 -1=左 1=右 8=下 -9=左上 -7=右上 7=左下 9=右下 Dim i As Integer '座標ごとにチェックする方向を除外 If btnNumber >= 1 And btnNumber <= 16 Then Array.Clear(chkDir, 0, 1) '上のチェックを除外 Array.Clear(chkDir, 4, 1) '左上のチェックを除外 Array.Clear(chkDir, 5, 1) '右上のチェックを除外 End If If {1, 2, 9, 10, 17, 18, 25, 26, 33, 34, 41, 42, 49, 50, 57, 58}.Contains(btnNumber) Then Array.Clear(chkDir, 1, 1) '左のチェックを除外 Array.Clear(chkDir, 4, 1) '左上のチェックを除外 Array.Clear(chkDir, 6, 1) '左下のチェックを除外 End If If {7, 8, 15, 16, 23, 24, 31, 32, 39, 40, 47, 48, 55, 56, 63, 64}.Contains(btnNumber) Then Array.Clear(chkDir, 2, 1) '右のチェックを除外 Array.Clear(chkDir, 5, 1) '右上のチェックを除外 Array.Clear(chkDir, 7, 1) '右下のチェックを除外 End If If btnNumber >= 49 And btnNumber <= 64 Then Array.Clear(chkDir, 3, 1) '下のチェックを除外 Array.Clear(chkDir, 7, 1) '右下のチェックを除外 Array.Clear(chkDir, 6, 1) '左下のチェックを除外 End If 'それぞれの方向で盤面チェック For Each i In chkDir Select Case i Case -8 upChk(btnNumber) Case -1 lChk(btnNumber) Case 1 rChk(btnNumber) Case 8 unChk(btnNumber) Case -9 lupChk(btnNumber) Case -7 rupChk(btnNumber) Case 7 lunChk(btnNumber) Case 9 runChk(btnNumber) End Select 'Console.WriteLine(i) Next End Function
流れとしては
ひっくり返すかどうかのチェックする方向の配列を決定(上下左右斜めの8方向)
↓
座標によってチェックする必要のない方向を除外
↓
方向chk関数を使いひっくり返すか判断&ひっくり返す
↓
それぞれの方向で繰り返す
チェックする方向を進める方法
基準とする座標から方向と対応した数字を減らしていくようにした
青が座標で赤が方向の数字を表している
例えば座標10の場所から左上が黒かどうかをチェックしたいなら10-9=1の座標の色ともとの座標の色の比較をする、そこで同じ色ならさらに左上をチェックして違う色のところまで同じことを繰り返す…という感じ
なんか伝われ!!
チェックする必要のない方向の除外
'座標ごとにチェックする方向を除外 If btnNumber >= 1 And btnNumber <= 16 Then Array.Clear(chkDir, 0, 1) '上のチェックを除外 Array.Clear(chkDir, 4, 1) '左上のチェックを除外 Array.Clear(chkDir, 5, 1) '右上のチェックを除外
上端二行なら上の石をひっくり返すことはないのでその方向は除外
同じように8方向で座標によって除外する方向を設定。
盤面チェックをすると決めた方向でチェックを繰り返す
'それぞれの方向で盤面チェック For Each i In chkDir Select Case i Case -8 upChk(btnNumber) Case -1 lChk(btnNumber) Case 1 rChk(btnNumber) Case 8 unChk(btnNumber) Case -9 lupChk(btnNumber) Case -7 rupChk(btnNumber) Case 7 lunChk(btnNumber) Case 9 runChk(btnNumber) End Select 'Console.WriteLine(i) Next
for文を使い、chkDirに格納された方向の配列を繰り返し、場合によってupChk(上をひっくり返すかどうか判断し実際にひっくり返す関数)などを実行する
伝わってる気がしない、もうダメだ
ひっくり返すべきか判断して実際にひっくり返す処理
'上をひっくり返す処理 Private Function upChk(ByVal btnNmb0 As Integer) Dim btn000 As Button 'チェック対象のボタンの変数 Dim n As Integer = 0 'ボタンチェック回数 Dim i As Integer 'ループ変数 '① Do n += 1 btnNmb0 += -8 btn000 = chgNmbtoBtn(btnNmb0) 'ボタンに●が入っていないなら中止 If btn000.Text <> "●" Then Exit Function End If '同じ色の端の石来たら終了 If btnNmb0 >= 1 And btnNmb0 <= 8 And btn000.ForeColor <> turnColor() Then Exit Function End If Loop While btn000.ForeColor <> turnColor() 'n-1回盤面をひっくり返す② For i = 2 To n btnNmb0 += 8 btn000 = chgNmbtoBtn(btnNmb0) btn000.ForeColor = turnColor() Next i
ここの流れについては
①
↓
繰り返した回数(nとする)の記録
↓
元の座標の取得(例:座標25)
↓
上方向の座標(座標Yとする)の取得(例:25-8=17)
↓
chgNmbtoBtn関数(自前の関数)を使い数字を対応するButtonオブジェクトに変換し、btn000変数に格納
(例:chgNmbtoBto(17)=Button17 btn000はButton17を表している)
↓
座標Yに異常がないかの確認、同色かつ端の石ならその場で終了、石がおいてなくても終了
↓
座標Yの石の色とそのターンの色(先行なら黒など)が違うかの確認 →同じなら→ ①(もう一回同じ操作)
↓
違うなら
↓
②
↓
座標Yの下の石をひっくり返す、これをn-1回繰り返す
↓
終了
こんな感じです、伝わってる気も誰かが読んでるような気もしない
実際の動作
こんな感じになった!!案外なんとか動きました