LoginSignup
1
2

More than 3 years have passed since last update.

パズドラの落ちコンの分布を探る

Last updated at Posted at 2019-09-28

最近パズドラにはまってます。そこで、花火を打った時の落ちコンの分布をグラフ化しようと思いました。

import random
from matplotlib import pyplot as plt

tate = 5
yoko = 6
iro = 6

class UnionFind():
    #nは頂点数
    def __init__(self, n):
        self.parent = [-1]*n

    #aの属する集合の根を取得
    def root(self,a):
        if self.parent[a] < 0:return a
        self.parent[a] = self.root(self.parent[a])
        return self.parent[a]

    #aの属する集合の要素数を取得
    def size(self,a):
        return -self.parent[self.root(a)]

    #aとbをくっつける
    def connect(self,a,b):
        if self.root(a) == self.root(b):return False
        a = self.root(a);b = self.root(b)
        if self.size(a) < self.size(b):a,b = b,a
        self.parent[a] += self.parent[b]
        self.parent[b] = a
        return True

#コンボ数を数える関数
def count(ls : list) -> (int,list):
    check = [[0 for i in ls[j]] for j in range(len(ls))]
    #同じ色で消えるところを色塗り
    for i in range(len(ls)):
        for j in range(len(ls[0])):
            try:
                #横
                if ls[i][j] == ls[i][j+1] == ls[i][j+2]:
                    if check[i][j] != 0 or check[i][j+1] != 0 or check[i][j+2] != 0:
                        check[i][j],check[i][j+1],check[i][j+2] = ls[i][j],ls[i][j],ls[i][j]
                    else:
                        check[i][j],check[i][j+1],check[i][j+2] = ls[i][j],ls[i][j],ls[i][j]
            except:
                pass
            try:
                #縦
                if ls[i][j] == ls[i+1][j] == ls[i+2][j]:
                    if check[i][j] != 0 or check[i+1][j] != 0 or check[i+2][j] != 0:
                        check[i][j],check[i+1][j],check[i+2][j] = ls[i][j],ls[i][j],ls[i][j]
                    else:
                        check[i][j],check[i+1][j],check[i+2][j] = ls[i][j],ls[i][j],ls[i][j]
            except:
                pass
    #UnionFind
    uni = UnionFind(len(ls)*len(ls[0]))
    #graph = [[] for i in range(len(ls)*len(ls[0]))]
    for i in range(len(ls)):
        for j in range(len(ls[0])):
            if check[i][j] == 0:continue
            for x,y in [[1,0],[-1,0],[0,1],[0,-1]]:
                try:
                    if check[i][j] == check[i+x][j+y]:
                        uni.connect(len(ls[0])*i+j,len(ls[0])*(i+x)+j+y)
                        #graph[len(ls[0])*i+j].append(len(ls[0])*(i+x)+j+y)
                except:
                    pass
    #コンボ数を集計
    conbo = 0
    for i in uni.parent:
        if i < -2:conbo+=1
    return conbo,check

#乱数を使ってパズルを更新する関数
def update(ls : list,n : int) -> (int,list):
    conbo,check = count(ls)
    for i in range(len(ls)):
        for j in range(len(ls[0])):
            if check[i][j] > 0:
                check[i][j] = random.randint(1,n)
            else:
                check[i][j] = ls[i][j]
    return conbo,check

#n回数花火を打ってコンボ数の分布をみる
def analytics(n : int) -> list:
    buf = [0]*n
    for i in range(n):
        ls = [[1]*yoko for i in range(tate)]
        conbo = -1
        while True:
            c,ls = update(ls,iro)
            if c == 0:
                break
            else:
                conbo += c
        buf[i] = conbo
    dis = [0]*(max(buf)+1)
    for i in buf:
        dis[i] += 1
    return dis
ls = analytics(10000)
lef = [i for i in range(len(ls))]
plt.bar(lef,ls)
plt.show()

コードは上のやつで全部です。tateは縦の個数、yokoは横の個数、iroは色の種類です。乱数に補正がかかってないとしてパズルを更新しています。色のつながりはUnionFindで管理してます。縦軸が回数で横軸がコンボ数です。

6×7盤面 6色
6_7_6.png

5×6盤面 6色
5_6_6.png

4×5盤面 6色
4_5_6.png

これだけです。
  終
制作・著作
━━━━━
 ⓃⒽⓀ

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2