最近パズドラにはまってます。そこで、花火を打った時の落ちコンの分布をグラフ化しようと思いました。
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で管理してます。縦軸が回数で横軸がコンボ数です。
これだけです。
終
制作・著作
━━━━━
ⓃⒽⓀ