初學Python,編了一個手工挖雷,歡迎各位程式高手提供改進意見。
import numpy as np
import random
random.seed()
ISMINEFLAG=0X10
OPENEDFLAG=0X20
MARKEDFLAG=0X40
MINESFLAG=0XF0
AROUNDFLAG=0X0F
def makemine(dim=(10,10,50)):
"""Make a mine ndarray,default size is 10*10,default mines is 50
Mine's item value type is np.byte in 8 digits, details as follows:
7------0
XXXXXXXX
0-3: surround mines(0-8 is valid)
4: mine flag. 1 if has mine, otherwise 0
5: opened flag.
6: marked flag
7: reserved
"""
if dim[2]>=dim[0]*dim[1]:
print("Provided mines is more than mine array items!")
return None
try:
a=np.ndarray((dim[0],dim[1]),dtype=np.byte)
except :
print("nparray construct failed!")
return None
a.fill(0)
for mm in random.sample(range(dim[0]*dim[1]),dim[2]):
x,y=divmod(mm,dim[1])
a[x,y]|=ISMINEFLAG
for x in range(dim[0]):
for y in range(dim[1]):
v=0
for i in range(x-1,x+2):
for j in range(y-1,y+2):
if 0<=i<dim[0] and 0<=j<dim[1] and not(all([i==x,j==y])):
v+=int(bool(a[i,j]&ISMINEFLAG))
a[x,y]=(a[x,y]&MINESFLAG)+v
return a
def testbit(bit:np.byte,n:int):
if n>=8 or n<0:
return None
return bool(bit&(1<<n))
def action(arr,act=(0,0,1)): #x,y,action 1 is mine, 2 is marked
x,y,a=act
if (a not in range(1,3)) or (x not in range(arr.shape[0])) or (y not in range(arr.shape[1])):
print("\nAct prarmetier is wrong!\n",x,y,a)
return
if a==2: #mark or unmark
if not testbit(arr[x,y],5):
arr[x,y]^=MARKEDFLAG
elif a==1:
if testbit(arr[x,y],5): # Has Opened
return
if testbit(arr[x,y],4):
print("\n({},{}) has a mine!\n".format(x,y))
else:
openmine(arr,x,y)
else:
pass
def openmine(arr,x,y): #Has not opened
if (arr[x,y]&AROUNDFLAG)==0:
for i in range(x-1,x+2):
for j in range(y-1,y+2):
if 0<=i<arr.shape[0] and 0<=j<arr.shape[1] :
if not testbit(arr[i,j],5):
arr[i,j]|=OPENEDFLAG
openmine(arr,i,j)
else:
arr[x,y]|=OPENEDFLAG
return
def show(arr):
for x in range(arr.shape[0]):
for y in range(arr.shape[1]):
if testbit(arr[x,y],5): #has opened
print(arr[x,y]&AROUNDFLAG,end=" ")
else:
if testbit(arr[x,y],6): #has marked
print(r"?",end=" ")
else:
print(r"*",end=" ")
print("\n")
return
if __name__=="__main__":
while True:
try:
xs,ys,mines=map(int,input(r"Input xs,ys,mines,SPACE seperates Nums. Ctrl+C exit):").split())
if xs<0 or ys<0 or mines>xs*ys:
raise ValueError
except ValueError:
print("\nInput xs,ys,mines error!\n")
else:
break
a=makemine((xs,ys,mines))
## print(a)
show(a)
while True:
try:
x,y,act=map(int,input(r"Input x,y,act=1 or 2,SPACE seperates Nums. Ctrl+C exit):").split())
action(a,(x,y,act))
## print("\n",a)
show(a)
except ValueError:
print("\nInput error!\n")
uj5u.com熱心網友回復:
運行不了
uj5u.com熱心網友回復:
什么提示?我的可以正常運行uj5u.com熱心網友回復:
改進版,增加了雙擊和雙擊后連續挖雷操作,增加了索引提示,完善其他細節.有其他需要改進的歡迎各位高手指出.import numpy as np
import random
random.seed()
ISMINEFLAG=0X10
OPENEDFLAG=0X20
MARKEDFLAG=0X40
AROUNDFLAG=0X0F
def makemine(dim=(10,10,50)):
"""Make a mine ndarray,default size is 10*10,default mines is 50
Mine-array item value type is np.byte in 8 digits, details as follows:
7------0
XXXXXXXX
0-3: surround mines(0-8 is valid)
4: mine flag. 1 if mine, otherwise 0
5: opened flag. 1 means opened.
6: marked flag. 1 means marked
7: reserved
"""
if dim[2]>=dim[0]*dim[1]:
print("Provided mines are more than mine-array items!")
return None
try:
a=np.zeros((dim[0],dim[1]),dtype=np.byte)
except :
print("Mine-array construct failed!")
return None
for mm in random.sample(range(dim[0]*dim[1]),dim[2]): #mark all rand mines
x,y=divmod(mm,dim[1])
a[x,y]|=ISMINEFLAG
for x in range(dim[0]):
for y in range(dim[1]):
v=0
for i in range(x-1,x+2):
for j in range(y-1,y+2):
if 0<=i<dim[0] and 0<=j<dim[1] and not(all([i==x,j==y])):
v+=(a[i,j]&ISMINEFLAG)>>4
a[x,y]+=v
return a
def testbit(bit:np.byte,n:int):
if n>=8 or n<0:
return None
return bool(bit&(1<<n))
def action(arr,act=(0,0,1)): #x,y,action 1 is mine, 2 is marked,3 is double click
x,y,a=act
if (a not in range(1,4)) or (x not in range(arr.shape[0])) or (y not in range(arr.shape[1])):
print("\nAct prarmetier is wrong!\n",x,y,a)
return
if a==2: #mark or unmark
if not testbit(arr[x,y],5):
arr[x,y]^=MARKEDFLAG
elif a==1:
if testbit(arr[x,y],5): # Has Opened
return
if testbit(arr[x,y],4):
print("\n({},{}) has a mine!".format(x,y))
else:
openmine(arr,x,y)
elif a==3:
if testbit(arr[x,y],5): #opened item can be doubl-clicked
for i in range(x-1,x+2):
for j in range(y-1,y+2):
if 0<=i<arr.shape[0] and 0<=j<arr.shape[1] and not(all([i==x,j==y])):
if not testbit(arr[i,j],6) and not testbit(arr[i,j],5) and not testbit(arr[i,j],4):
arr[i,j]|=OPENEDFLAG
if (arr[i,j]&AROUNDFLAG)==0: #continue mine after doubleclick and found surround mines is 0
openmine(arr,i,j)
def openmine(arr,x,y):
if (arr[x,y]&AROUNDFLAG)==0:
for i in range(x-1,x+2):
for j in range(y-1,y+2):
if 0<=i<arr.shape[0] and 0<=j<arr.shape[1] :
if not testbit(arr[i,j],5): # has not opened
arr[i,j]|=OPENEDFLAG
openmine(arr,i,j)
else:
arr[x,y]|=OPENEDFLAG
return
def show(arr):
print("\n ",end="")
for i in range(0,arr.shape[1],2):
dd=3 if i<10 else 2
print(i,end=" "*dd)
print("\n")
print("-"*2*(arr.shape[1]+1))
for x in range(arr.shape[0]):
print(str(x).rjust(2),end="|")
for y in range(arr.shape[1]):
if testbit(arr[x,y],5): #has opened
print(arr[x,y]&AROUNDFLAG,end=" ")
else:
if testbit(arr[x,y],6): #has marked
print(r"?",end=" ")
else:
print(r"*",end=" ")
print("\n")
return
if __name__=="__main__":
while True:
try:
xs,ys,mines=map(int,input(r"Input xs,ys,mines.SPACE seperates nums. Ctrl+C exit):").split())
if xs<0 or ys<0 or mines>xs*ys:
raise ValueError
except ValueError:
print("\nInput xs,ys,mines error! Use default(10,10,50)\n")
a=makemine()
break
else:
a=makemine((xs,ys,mines))
break
show(a)
while True:
try:
x,y,act=map(int,input(r"Input x,y,act(act=1 or 2 or 3,means mine,mark,doubleclick.SPACE seperates three nums. Ctrl+C exit):").split())
action(a,(x,y,act))
show(a)
except ValueError:
print("\nInput x,y,act error!\n")
uj5u.com熱心網友回復:
效果圖如下
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/21470.html
上一篇:知識圖譜
