Edited at

ぷよぷよ in python

More than 3 years have passed since last update.


ぷよぷよ in python

haskellの記事眺めてたらこんなの見付けた。

http://qiita.com/tanakh/items/c2e157f0a48667370b0e

問題はこっち。

http://okajima.air-nifty.com/b/2011/01/2011-ffac.html

まだ全然haskell力(はすけるちから)が足りないからさっぱり理解できないので、

とりあえずhaskellは置いといて、

せっかくなのでpythonで書いてみる事にした。

なんか


  • pythonの文字列がindex指定で書き換えられないからbytearrayにしたり

  • 探索で隣同士で再帰しちゃって無限再帰しちゃったり

予想外に手間取ったけど、2時間ちょうどくらい…かな。

いや、ちょっと超えちゃったかな。まぁいいや。

c++で書けば良かった。

for(int i=0; i<10; ++i) 形式のループが使えないのがものすごい不便。

ぷよの箱の横幅/縦幅はベタ書きしてないので、縦横広がってもそのまま動くと思う。

まぁ縦横広がる事があるのかわからんけど。

動かしたのはpython2.7.6


puyo.py

#!/usr/bin/env python

# -*- coding:utf-8 -*-

puyo_array = [
" GYRR",
"RYYGYG",
"GYGYRR",
"RYGYRG",
"YGYRYG",
"GYRYRG",
"YGYRYR",
"YGYRYR",
"YRRGRG",
"RYGYGG",
"GRYGYR",
"GRYGYR",
"GRYGYR",
]

# pythonの文字列はindex指定で書き換えられないのでbytearrayに変換
puyo = [ bytearray(line) for line in puyo_array ]

def show():
print "-" * 8
for x in puyo:
print "|{}|".format(x)
print "-" * 8
print

def erase():
u'''4つ以上繋がってるの消す'''
class Way:
u'''どっちから探索来たか'''
UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4

def mark(dx, dy, p, dst = None):
u'''隣接してる同色を辿る'''
if dx < 0 or dy < 0:
return

try:
if puyo[dy][dx] == p:
points.append((dx, dy))
# 入ってきた方向に探索すると無限再帰するので
if dst != Way.RIGHT:
mark(dx+1, dy, p, Way.LEFT)
if dst != Way.UP:
mark(dx, dy+1, p, Way.DOWN)
if dst != Way.LEFT:
mark(dx-1, dy, p, Way.RIGHT)
if dst != Way.DOWN:
mark(dx, dy-1, p, Way.UP)
except IndexError as e:
pass

for y, line in enumerate(puyo):
for x, p in enumerate(line):
if chr(p) != " ":
points = []
mark(x, y, puyo[y][x])

if len(points) >= 4: # 4連結以上
for x, y in points:
puyo[y][x] = " " # 消す

def drop():
u'''浮いてるの落とす'''
height = len(puyo)
assert(height > 0)
width = len(puyo[0])
is_zenkeshi = True
for x in range(width):
for y in range(0, height)[::-1]: # 下から嘗める
if chr(puyo[y][x]) == " ":
for y2 in range(0, y+1)[::-1]:
if chr(puyo[y2][x]) != " ":
puyo[y][x] = puyo[y2][x]
puyo[y2][x] = " "
break
else:
is_zenkeshi = False
# 全部消えてたらTrue
return is_zenkeshi

if __name__ == '__main__':
import itertools
for i in itertools.count():
print i
show()

erase()
if drop():
break

print "finish!!"
show()