6ボールパズルをpythonで実装

#はじめに
6ボールパズルをpython上で実装しようと思ってやってたら，くそコードが出来上がりました．
飽きたのでネットの海に放流して終了しよう・・・

操作方法
a:右60deg回転
b:左60deg回転
j:左移動
l:右移動
k:落下開始


参考動画
https://www.youtube.com/watch?v=Q6As1gRT6fE&t=660s

運動シミュレーションを行っている感じがしますが，ちょっと難しいので，まったく同じものは作れそうにないです．

#アルゴリズム
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/af987852-5bd2-2f72-6a64-3e93fd87772d.png)
ボールに4方向a,b,c,dを定義します．

条件

1. ボールは$b,c$にしか動かない
2. $b$に動くには，$a,b$にボールがない
3. $c$に動くには，$c,d$にボールがない
4. $b,c$どちらにも動ける場合，$a,d$にあっても問題ない，動く方向は$b,c$ランダム


![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/91b6798d-8af4-bfae-5669-a17ab1e0d811.png)
このような状態がちょっと難しいです．

探索方向
下の層から動けるかを確認し，動けなくなるまで動かしていく
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/1e532e94-41cb-6c85-1c15-dade9a0006d0.png)

#データ構造
列の場所が，行の場所で0.5個分ずれるので，少々扱いにくい
いろいろ悩まないように次のように，番号をつける

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/32b933c7-0ab0-de88-5485-a1001941303c.png)

赤，青，黄，紫，緑，空
の6種
空を0とする

19列,12行にする

#落下-テストプログラム
![fall1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/1f6bda01-d91a-c2e4-f96b-571b08c9b81c.gif)
（この結果は，下のプログラムでは，opencvで描画していないので，ちょっと違いますが，落下処理は同じです．ネクストの表示が2個分しかないですが，単純なミスでした）

別パターン1
![fall2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/b5f53d65-aa31-1a29-bbc1-e0394a96c0ae.gif)

別パターン2
![fall3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/c52dc37f-c061-74be-bc2b-3fe54a0a797e.gif)

結構いい感じの結果が得られて満足です．

ちょっと問題かもしれないパターン1
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/103c2043-2e5f-0be0-c376-7b04c9f62587.jpeg)

これは固定されて動かない．左端の青を落としてやるか悩む．
現状，壁は左右，右下，左下に球があるという認識でやっているため，こうなる．

![fall4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/bb6b4f78-50d4-8706-a8d5-05de1d97986b.gif)

![fall5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/ae8bbcc6-994e-ffd4-1412-7290e8fcc4f4.gif)
これは，ランダムでどちらかのパターンが選ばれる

プログラムはgithubに上げました．


#入力系
ボールセット（3個）をキーボード等で動かし，落下させた際
ボールセットがどこに落下されるか計算したいです．
キーボードで入力した左右移動量でボールセットを動かし，ボールセット落下ボタンが入ったら，直線的に落下させ，3個のボールの内どれかが，すでにあるボールに衝突し，直線的に動けなくなるとボールセットが崩れて，そこからは先ほどの落下方式で処理させようと思います．

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/cf473a8d-0368-236d-6bb8-a2221bbdd8c9.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/83dac0bf-e357-5103-9546-e551a1e8dee7.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/4b4bb92d-d801-fb37-e571-5db77e69b829.png)

###直線的落下時の判定ー逆三角
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/1d0b2c1e-243c-6366-a34e-3c887ed03076.png)
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/2f98a53b-f623-393f-7409-d8083bf4fc8a.png)



###直線的落下時の判定ー三角
ちょっと，調べるべき場所が多いためめんどくさいが頑張ろう
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/77a5a9c9-a056-4588-cd68-b2d3f5fec1cb.png)

###結果1-床への衝突
![fall6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/f80f62d8-0400-fb21-cebc-1c4c586a7054.gif)


![fall7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/5c22a25f-7f37-411c-1652-fcc03c4f5be3.gif)

悪くはない，しかし，スタート地点が悪いと
![fall8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/be43d30e-de8c-0db6-628f-749380e4b395.gif)
こんな感じで，0.5ずらす必要が出てくる．
ずらす方向は，右寄りなら左へ，左寄りなら右へとした

###結果2-逆三角-真下にある
![fall9.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/58458018-f52e-471d-5f63-150c25697bc7.gif)

ちゃんと，ずらして，落下させています．

###結果2-逆三角-左下にある
![fall10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/c18207d8-5af0-e58b-9950-1df3d8a1fc9e.gif)

ちょっと不自然，黄色の横の水色は黄色の下ではなく，できれば，右下に落ちてほしい．．．
ただし，ランダムで
![fall11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/ef148b90-99a7-54c7-1430-58e277469466.gif)

この場合もある
現状の処理では，右下・左下どちらにも行ける場合はランダムで選択にしているためである．

追記：
>条件

>1. ボールは$b,c$にしか動かない
>2. $b$に動くには，$a,b$にボールがない
>3. $c$に動くには，$c,d$にボールがない
>4. $b,c$どちらにも動ける場合，$a,d$にあっても問題ない，動く方向は$b,c$ランダム

条件4を書き換える
4. $b,c$どちらにも動ける場合，$a$に球があるときは$c$,$d$に球があるときは$b$，どちらにもないときは$b,c$ランダム

に変更する．
ランダムではなくなり，自然になった・・・

#ヘキサゴン・ピラミッドの検出
最後に検出方法を考える
原始的な方法しか思いつかなかったが

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/a7e5d5fb-c1f7-21cb-7d8f-495afbd8658f.png)

こんな感じで，開始点を走査して検出してみる
ピラミッドも同様にする．

#7個以上つながると削除
これをするための検出方法
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/39e699d7-d6d2-8cd3-b969-d44d0ea7e346.png)

#最終結果
コードがすごい長くなってしまったので，ちょっとここには載せられない．
[github](https://github.com/hirona222/6-ball-puzzle/tree/master/6-ball-puzzle)とかいうやつに初めて載せてみます．
ball6_puzzle_exe.pyがゲーム実行プログラムです．

操作方法
a:右60deg回転
b:左60deg回転
j:左移動
l:右移動
k:落下開始

q:ゲーム終了