在扫雷游戏中,将雷均匀地分布在局面中依靠一种布雷算法。
将布雷的位置视为一维数组,其长度为高×宽。
数字 -1 表示 有雷;数字 0 表示非雷。
算法一:朴素的想法
- 随机寻找一个位置;
- 如果该位置是空的,则布雷;
- 如果该位置是雷,那么返回 步骤1;
- 直到布雷数到达总雷数。
经测试,当雷数为99时,算法的运行时间为1.2754秒。但是这种算法在雷数较大时性能急剧下降,因为随机选择的位置大概率是雷。当雷数为479时,算法的运行时间长达33.0841秒。y = [0] * Row * Column
num_i = 0
while num_i < num:
while True:
idd = random.randint(0, Row * Column - 1) # 产生a, b的一个整数型随机数
if y[idd] != -1:
y[idd] = -1
num_i += 1
break
算法二:算法一改进
算法一的问题在于如果布雷数量很大,可能多次随机出的布雷位置相同,布满特定数量的雷需要的时间增加。
那么只要在每次选择出 布雷 的位置后,将这个位置从下次挑选范围内除去即可。
维护两个列表,no_bomb,is_bomb。前者是没有雷的方格索引,后者是有雷的方格索引。
y = [0]*(Row*Column)
no_bomb = list(range(0,Row*Column))
is_bomb = []
count_bomb = 0
while count_bomb < Num:
Id = random.randint(0,Row*Column - count_bomb - 1)
is_bomb.append(no_bomb[Id])
no_bomb.pop(Id)
count_bomb += 1
for i in is_bomb:
y[i]=-1
算法三:洗牌算法
洗牌算法的步骤为:
Step1:初始化一维局面数组,使得前RowColumn-Num个位置均为0,后Num个位置均为-1
Step2:遍历数组从id= RowColumn-Num到id=RowColumn-1的位置
_*Step3_:交换当前访问位置与在当前访问位置之前随机选取的位置的值
y = [0]*(Row*Column-Num)
y = y+[-1]*Num
for i in range(Row*Column-Num,Row*Column):
idd = random.randint(0,i-1)
y[idd],y[i] = y[i],y[idd]
算法四:洗牌算法改进
当雷数少于一半时,算法不变;但当雷数多于一半时,我们把非雷看作雷,而把雷看作非雷。这样仅仅添加一个选择语句后,就兼顾了算法在雷数较多与较少时的性能。
if Num<Row*Column/2:
y=[0]*(Row*Column-Num)
y=y+[-1]*Num
for i in range(Row*Column-Num,Row*Column):
idd=random.randint(0,i-1)
y[idd],y[i]=y[i],y[idd]
else:
y=[-1]*Num
y=y+[0]*(Row*Column-Num)
for i in range(Num,Row*Column):
idd=random.randint(0,i-1)
y[idd],y[i]=y[i],y[idd]