我正在创建一个python应用程序来玩游戏Perudo(或骗子的骰子)。
我正在尝试创建一个函数来计算允许玩家(或AI)进行的所有可能移动并返回它们的列表,以便它可以拒绝非法移动。
转动被存储为2个数字的列表,例如[10,6]代表十六。
如果起始变量currentbid
是[19,3]
(十九个三分球)并且有20个骰子在玩,那么唯一可能的动作是19个四分球,19个五分球,19个六分球,20个二分球,20个三分球,20个四分球,20五和二十六。不允许召唤一个。
该程序应输出以上内容:
[[19,4],[19,5],[19,6],[20,2],[20,3],[20,4],[20,5],[20,6]]
但输出为:
[[20,6],[20,6],[20,6],[20,6],[20,6],[20,6],[20,6],[20,6]]
我做错了什么?
def calcpossiblemoves(self, currentbid, totalnoofdice):
self.possiblemoves = [] # Create a list of possible moves that will be added too
self.bid = currentbid
while self.bid[0] <= totalnoofdice:
while self.bid[1] < 6:
self.bid[1] += 1
self.possiblemoves.append(self.bid) # <- I think the problem is something to do with this line
print(self.possiblemoves) #For tracking the process
# Increase 1st number, reset 2nd number to 1
self.bid[0] += 1
self.bid[1] = 1 # Which will get increased to 2
#print("Reached 6")
return self.possiblemoves
答案 0 :(得分:1)
你最好考虑一个基数为6的数字,你可以有效地获得20个骰子的数字范围,包括0到126个。
current_bid = [19, 3]
offset = current_bid[0] * 6 + current_bid[1]
# 117 - and divmod(117, 6) == (19, 3)
因此,要获得剩余的有效出价,您可以在117 - 126的范围内进行数学计算,并获得有效的骰子数和余数。
valid_bids_with1s = ([n // 6, n % 6 + 1] for n in range(offset, 126))
valid_bids = [[a, b] for a, b in valid_bids_with1s if b != 1]
这给了你:
[[19, 4],
[19, 5],
[19, 6],
[20, 2],
[20, 3],
[20, 4],
[20, 5],
[20, 6]]
答案 1 :(得分:1)
问题在于您使用的是list
s,它们是可变对象,而您正在创建引用,而不是副本。您可以通过每次复制self.bid
列表来解决此问题,但最“pythonic”解决方案不是使用list
,而是使用tuple
,而是:
def calcpossiblemoves(self, currentbid, totalnoofdice):
possiblemoves = []
numberof, value = currentbid
while numberOf <= totalnoofdice:
while value < 6:
value += 1
possiblemoves.append((numberOf, value))
# Increase 1st number, reset 2nd number to 1
numberof += 1
value = 1 # Which will get increased to 2
#print("Reached 6")
return self.possiblemoves
请注意,这不会更新self.bid
(但您可以轻松添加),并且您会获得list
个不可变的tuple
。
编辑:因为tuple
是不可变的,所以我使用元组解包来创建两个变量。这是为了防止出现以下问题:
>>> bid = (1, 2)
>>> bid[0] += 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
我可以写bid = (bid[0]+1, bid[1])
,但使用两个变量,imho,更容易理解。
一般来说,确保list
的所有成员的意思相同,而tuple
或dict
中的值含义不同,这是一个很好的经验法则,或自定义容器,例如NamedTuple
或自定义类。
在此示例中,外部list
包含多个出价,但每个内部list
都有个骰子和值< / em>,表示list
可能是错误的类型。
答案 2 :(得分:0)
您在列表中附加相同的对象,这说明您获得了最后一次值的6倍。
替换
self.possiblemoves.append(self.bid) # <- I think the problem is something to do with this line
通过
self.possiblemoves.append(list(self.bid)) # make a copy of the list to make it independent from next modifications on self.bid
答案 3 :(得分:0)
问题是对self.bid的引用。它在列表中反复出现相同的变量,这意味着当您在循环中更新它时,您将更新每个实例(在这种情况下,列表中的所有变量)。我已经改写了你想要做的工作,以便你想要保持相同的格式,但正如其他人所说,你可以从编码的角度清理它。
def calcpossiblemoves(currentbid, totalnoofdice):
possiblemoves = []# in range(totalnoofdice) #Create a list of possible moves that will be added too
bid = currentbid
available_bid = None
while bid[0] <= totalnoofdice:
while bid[1] < 6:
bid[1] += 1
available_bid = [bid[0],bid[1]]
possiblemoves.append(available_bid) # <- I think the problem is something to do with this line
print(possiblemoves) #For tracking the process
# Increase 1st number, reset 2nd number to 1
bid[0] += 1
bid[1] = 1 # Which will get increased to 2
#print("Reached 6")
return possiblemoves
calcpossiblemoves([19,3],20)