search
LoginSignup
1
Help us understand the problem. What are the problem?

posted at

updated at

にゃんこスイーパー

Python+Cursesで、にゃんこスイーパーを書いてみました。
Ubuntuのターミナルで動きます。
ファイルに、chmod +x nyankosweeper.pyとして、実行権を付けて動かして下さい。

$./nyankosweeper.py [number of cats]として、動かします。
[number of cats]は、省略できます。省略すると、猫の数は58個となります。

スペースキーで、開き、’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 = 58

    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

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
1
Help us understand the problem. What are the problem?