Python+Cursesで、にゃんこスイーパーを書いてみました。
Ubuntuのターミナルで動きます。
ファイルに、chmod +x nyankosweeper.pyとして、実行権を付けて動かして下さい。
$./nyankosweeper.py [number of cats]として、動かします。
[number of cats]は、省略できます。省略すると、猫の数は56個となります。
スペースキーで、開き、’z’キーで、マークを付けます。カーソルは矢印キーで動かします。
’q’キーで抜け出せられます。
pyinstallerで、コンパイルできます。コンパイルしなくとも、そもそも速度はあんまり問題ないですが。
nyankosweeper.py
#!/usr/bin/python3
import curses
import random
import locale
import select
import sys
xsize = 40
ysize = 23
vvram = [[0 for i in range(ysize)] for j in range(xsize)]
mask = [["#" for i in range(ysize)] for j in range(xsize)]
itod = " 123456789"
ac = "#😺?"
def getkey():
c = stdscr.getkey()
return c
def putchar(x, y, a):
stdscr.addstr(y, x*2, a, curses.A_REVERSE)
def putcharr(x, y, a):
stdscr.addstr(y, x*2, a)
def putmines(n):
for i in range(n):
while(True):
(x, y) = (random.randint(0, xsize-1), random.randint(0, ysize-1))
if (vvram[x][y] == 0):
vvram[x][y] = '*'
break
#
def calccell(x, y):
if (vvram[x][y] == 0):
cnt = 0
for dx in range(-1, 2):
for dy in range(-1, 2):
if x+dx >= 0 and y+dy >= 0 and x+dx < xsize and y+dy < ysize:
cnt += 1 if vvram[x+dx][y+dy] == '*' else 0
vvram[x][y] = cnt
return(cnt)
def reveal(x, y):
if mask[x][y] != ' ':
mask[x][y] = ' '
if vvram[x][y] == 0:
for dx in range(-1, 2):
for dy in range(-1, 2):
if x+dx >= 0 and y+dy >= 0 and x+dx < xsize and y+dy < ysize:
reveal(x+dx, y+dy)
def cursor(x, y):
putcharr(x, y, retchar(x, y))
def printmines():
for x in range(xsize):
for y in range(ysize):
c = vvram[x][y]
if c == '*':
putchar(x, y, "😻")
elif (c >= 0 and c <= 9):
putchar(x, y, itod[c])
def retchar(x, y):
m = mask[x][y]
if m in ac:
return(m)
else:
c = vvram[x][y]
if c >= 0 and c <= 9:
return(itod[c])
def drawchar(x, y):
putchar(x, y, retchar(x, y))
def drawscreen():
for x in range(xsize):
for y in range(ysize):
drawchar(x, y)
def calcfield():
for x in range(xsize):
for y in range(ysize):
calccell(x, y)
def endcheck():
c = 0
for x in range(xsize):
for y in range(ysize):
c += 1 if mask[x][y] in ac else 0
return(c == mines)
def mainloop():
(x, y) = (xsize//2, ysize//2)
while True:
drawscreen()
if endcheck():
printmines()
putchar(0, 23, "You win. hit key")
getkey()
return(0)
cursor(x, y)
stdscr.refresh()
c = getkey()
if c in ('4','h',"KEY_LEFT"):
x = x-(1 if x != 0 else 0)
elif c in ( '6',"l","KEY_RIGHT"):
x = x+(1 if x != xsize-1 else 0)
elif c in ('8',"k","KEY_UP"):
y = y-(1 if y != 0 else 0)
elif c in ('2',"j","KEY_DOWN"):
y = y+(1 if y != ysize-1 else 0)
elif (c == 'z' or c=='m') and mask[x][y] != ' ':
mask[x][y] = ac[(ac.index(mask[x][y])+1) % 3]
elif c == ' ':
if vvram[x][y] == '*':
printmines()
putchar(x, y, "X")
putchar(0, 23, "You lose. hit key")
getkey()
return(-1)
reveal(x, y)
elif c == 'q':
return(1)
def game():
putmines(mines)
calcfield()
mainloop()
return
def main():
try:
game()
except KeyboardInterrupt:
pass
else:
return
def getv():
argvs = sys.argv
argc = len(argvs)
m = 56
if argc == 2:
try:
m = int(sys.argv[1])
if m > 300:
print('too many nyankos')
exit(0)
except ValueError:
print('not a number')
exit(0)
return(m)
mines = getv()
locale.setlocale(locale.LC_ALL, '')
stdscr = curses.initscr()
stdscr.keypad(True)
curses.curs_set(0)
main()
curses.endwin()
del stdscr