How do I remove a variable with just its value - python

I'm trying to make a game similar to this one, https://gyazo.com/8d8dff02a09d27ba28ed303979f64894 its called Farkle! How it works is, you roll a dice, if you roll a 1 and get 100 points (or another die gives you points) That die is taken away until you Farkle, change turns or you win the game. But I'm not sure how to temporarily take the dice away based on its value after rolling it. Can someone please tell me the method for removing a variable based on its value?
from random import randint
score1 = 0
def dices():
score1 = 0
a = 0
dice1 = randint(1, 6)
dice2 = randint(1, 6)
dice3 = randint(1, 6)
dice4 = randint(1, 6)
dice5 = randint(1, 6)
dice6 = randint(1, 6)
rolled_dice = [dice1, dice2, dice3, dice4, dice5, dice6]
one_count = rolled_dice.count(1)
a = [0, 100, 200, 300, 1000, 2000, 300][one_count]
two_count = rolled_dice.count(2)
score1 += a
a = [0, 0, 0, 200, 1000, 2000, 3000][two_count]
score1 += a
three_count = rolled_dice.count(3)
a = [0, 0, 0, 300, 1000, 2000, 3000][three_count]
score1 += a
four_count = rolled_dice.count(4)
a = [0, 0, 0, 400, 1000, 2000, 3000][four_count]
score1 += a
five_count = rolled_dice.count(5)
a = [0, 50, 100, 500, 1000, 2000, 3000][five_count]
score1 += a
six_count = rolled_dice.count(6)
a = [0, 0, 0, 600, 1000, 2000, 3000][six_count]
score1 += a
print(score1)
if score1 == 0:
print("Farkle!")
print(rolled_dice)
dices()

Let's think of it as we would in real life. If you roll dices and want to keep some results, you can mark them down or put them aside until you rolled the others. You do not throw them away since the result is still of importance.
The same happens when coding, you do not want to throw away values that you might later need. Instead you write them down somewhere safe until you need them.
You could achieve that by keeping the results of your dices in a list and writing a reroll function that only rerolls some dices, but not all.
import random
def reroll(dices, *pos):
for x in pos:
dices[x] = random.randint(1, 6)
# This creates a list with 6 dices result in it
dices = [random.randint(1, 6) for _ in range(6)]
print(dices) # [1, 5, 3, 6, 6, 5]
# We now only want to reroll the first and third dices
reroll(dices, 0, 2)
print(dices) # [4, 5, 1, 6, 6, 5]
An even better solution that does not mutate your data, i.e. that allows you to keep the previous result when you reroll, would be to make reroll return a new list of values where it rerolled only some dices.
import random, copy
def reroll(dices, *pos):
dices = copy.copy(dices)
for x in pos:
dices[x] = random.randint(1, 6)
return dices
dices = [random.randint(1, 6) for _ in range(6)]
# reroll returns a new list of values
new_dices = reroll(dices, 0, 2)
print(dices) # [6, 3, 4, 2, 4, 3]
print(new_dices) # [1, 3, 2, 2, 4, 3]

Related

Move all elements to right/left/let user choose (python)

I want to let the user choose either to move elements in an rng list either to the left, right or let them choose. I saw a similar post, but after reading it I did not see a way to choose which direction and do multiple repeats of the process.
import random
randlist = []
for i in range(10):
randlist.append(random.randint(0,10))
x = input("Right? Left? Choose?")
if x == "Right":
#Move all elements to the right once
elif x == "Left":
#Move all elements to the left once
else:
#Let User input both direction and amount of moves to the specified side
Slicing the array helps here. Only when rotating more than the
length of array needs to be taken care. if lenght of array is
10 then rotaing 13 times is same as rotaing 3 times.
Code:
import random
def rotate_right(arr, n):
m = n % len(arr)
m = len(arr) - m
return arr[m:] + arr[0:m]
def rotate_left(arr, n):
n = n % len(arr)
return arr[n:] + arr[0:n]
randlist = []
for i in range(10):
randlist.append(random.randint(0, 10))
print(randlist)
print(rotate_right(randlist,13))
print(rotate_left(randlist,14))
x = input("Right? Left? Choose?")
if x == "Right":
print(rotate_right(randlist,1))
elif x == "Left":
print(rotate_left(randlist,1))
Output:
[0, 7, 3, 3, 0, 4, 0, 6, 6, 3]
[6, 6, 3, 0, 7, 3, 3, 0, 4, 0]
[0, 4, 0, 6, 6, 3, 0, 7, 3, 3]
Right? Left? Choose?

2D List not calculating properly

I'm trying to do a game of life. There's this weird bug I can't really fix because I don't really know where the problem is? I'm guessing it's in the loop? I don't really know. I tried to debug it using the if total > 0 print(total), and the total is only 2 when it should've been 3. I'm sorry if i'm explaining it confusing because i'm also confused.
def test():
board = [[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0]]
#Tracking the neighbor, it shows that there is 3 alive neighbors in
#here.
print(board[2][1])
print(board[2-1][1+1])
print(board[2][1+1])
print(board[2+1][1+1])
return board
def update(grid, N):
newGrid = grid.copy()
for i in range(N):
if i == 0 or i == 4:
continue
for j in range(N):
if j == 0 or j == 4:
continue
total = 0
total = total + grid[i][j-1] #
total = total + grid[i][j+1] #
total = total + grid[i-1][j] #
total = total + grid[i+1][j] #
total = total + grid[i-1][j-1] #
total = total + grid[i-1][j+1] #
total = total + grid[i+1][j-1] #
total = total + grid[i+1][j+1] #
# In here it only states that there's only 2 alive neighbors
# when there should've been 3
if total > 0:
print(total)
# apply Conway's rules
if grid[i][j] == 1:
if (total < 2) or (total > 3):
newGrid[i][j] = 0
elif total == 3:
newGrid[i][j] = 1
else:
if total == 3:
newGrid[i][j] = 1
grid[:] = newGrid[:]
return(grid)
f = 0
zboard = test()
while f <= 3:
print("Generation: " + str(f))
gen = update(zboard, 5)
for i in gen:
print(i)
f += 1
You need to use deepcopy.
When you do newGrid = grid.copy(), since you have a 2D-list, the sublists in newGrid will not be independent from the sublists from grid. Your problem was that grid was updated each time you updated newGrid.
You need to replace this:
newGrid = grid.copy()
by this :
import copy
newGrid = copy.deepcopy(grid)
Here is an example to show you what was happening. cop_1 is a dependent copy whereas cop_2 is an independent one :
board = [[0, 0],
[0, 0]]
cop_1 = board.copy()
import copy
cop_2 = copy.deepcopy(board)
board[0][0] = 3 # change a value of board
print("cop_1[0][0] =", cop_1[0][0])
# cop_1[0][0] = 3
print("cop_2[0][0] =", cop_2[0][0])
# cop_2[0][0] = 0
If you run the code like you posted, you get a mistake because you didn't indent the lines after your function def test(): until return board

How to store random integers generated from multiple lists

I am trying to write a script that simulates a dice game with unconventional dice. The objective of the game is to determine which dice is better based on repeated experiments where the larger number/roll wins. Here is working example I have so far:
from random import randint, seed
from datetime import datetime
import itertools as it
seed(datetime.now())
def find_the_best_dice(dices):
assert all(len(dice) == 6 for dice in dices)
for dice1, dice2 in it.combinations(dices, 2):
num_rounds = 100
num_dice1_wins = 0
num_dice2_wins = 0
for _ in range(num_rounds):
dice1_result = dice1[randint(0, 5)]
dice2_result = dice2[randint(0, 5)]
if dice1_result > dice2_result:
num_dice1_wins += 1
elif dice2_result > dice1_result:
num_dice2_wins += 1
return ("index of winning dice or -1 if tie")
find_the_best_dice(dices=[[1, 1, 6, 6, 8, 8], [2, 2,
4, 4, 9, 9], [3, 3, 5, 5, 7, 7]])
The issue I am facing is not knowing how to store the number of wins for more than 2 dice.
Usually, I would use a dictionary for something like this but since your representation of a dice is a list (unhashable) you can convert them into a frozenset or a tuple. I prefer a tuple since it preserves order and repetition (if any).
num_rounds = 100
dice_wins = {tuple(x):0 for x in dices}
for dice1, dice2 in it.combinations(dices, 2):
for _ in range(num_rounds):
dice1_result = dice1[randint(0, 5)]
dice2_result = dice2[randint(0, 5)]
if dice1_result > dice2_result:
dice_wins[tuple(dice1)] += 1
elif dice2_result > dice1_result:
dice_wins[tuple(dice2)] += 1
max_win = max(list(dice_wins.values()))
die_with_max_win = [dice for dice in dices if dice_wins[tuple(dice)] == max_win]
if len(die_with_max_win) == 1:
return die_with_max_win[0] # only dice with that many wins
else:
return -1 # more than one dice with max wins
Hope this helps!
If you’re talking about dice with the same amount of dots, a ‘best’ dice doesn’t exist. For example, if on average dice A wins from dice B and dice B from dice C, it’s still possible that on average dice C wins from dice A.

How do I make this Loop?

So here are the directions for this step in my program:
Create a loop that traverses through the dice list.
Inside the loop add one to the appropriate index value in the counts list for each value in the dice list. When the loop is done, the counts list should have the number of times each value occurs in the dice list. Heres what I have:
# Step 1
from random import randint
class Dice(object):
def __init__(self):
self.dice = []
x = 0
while x < 5:
self.dice.append(str(randint(1,6)))
x += 1
hand = Dice() # Creates a Dice object
print hand.dice # Prints the instance variable dice (5 random numbers)
# Step 2
class Dice(object):
def __init__(self):
self.dice = []
def roll(self,how_many):
for i in range(how_many):
self.Dice.append(randint(1,6))
hand.roll = ([0,2,3]) # Change the numbers in index positions 0, 2, and 3.
print hand.dice # Prints the instance variable dice (5 random numbers)
#Step 3
def score(self):
self.counts = [0, 0, 0, 0, 0, 0, 0]
for i in range(counts):
index + 1
print i
Use enumerate:
>>> lst = [4, 4, 5, 2, 6]
>>> counts = [0] * 7
>>> for i, e in enumerate(lst):
... counts[e] += 1
...
>>> print counts
[0, 0, 1, 0, 2, 1, 1]

Using a variable from one function in another function (parameter 'dice' unfilled)

Hi im trying to create a game where the computer generates 5 random numbers between 1 and 6. but my issue is i have created a list which will gain '1' in its respective section depending on what number comes up. e.g. if the computer generates 31534 the list needs to show [1,0,2,1,1,0] (because there was two 3's it fills 2 in the 3 slot) it only displays the 5 random numbers and nothing else
from random import randint
def rollDice():
dice = [str(randint(1, 6)) for _ in range(5)]
print(dice)
return dice
#-----------------------------------------------------------------
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
if x == 1:
totals = totals[1] + 1
elif x == 2:
totals = totals[2] + 1
elif x == 3:
totals = totals[3] + 1
elif x == 4:
totals = totals[4] + 1
elif x == 5:
totals = totals[5] + 1
print(totals)
return totals
#------------------------------------------------------------------
rollDice()
countVals()
I believe your error lies when you increment the count of each number,
totals = totals[1] + 1
should be,
totals[1] = totals[1] + 1
Also depending on your application you may be able to simplify your code
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
totals[x - 1] += 1
print (totals)
return totals
I think the problem is that the result returned by your rollDice function is a list of strings. The if - else statement in countVals then falls through cause for example '5' == 5 -> False. You could modify rollDice to return a list of int's instead (don't convert your ints to strings):
def rollDice():
dice = [randint(1, 6) for _ in range(5)]
print(dice)
return dice
If you absolutely want rollDice to return a list of strings you could convert the strings to ints using the int method in your countVals method. Example: int('5') -> 5, or just compare strings and not ints. x == '5'
Also make sure that you are saving your totals back to the right index in you totals list (in rollDice). You could do this a little more succinctly as follows: totals[1] += 1, for example:
def countVals(dice):
totals = [0, 0, 0, 0, 0, 0] #alternatively could be 'totals = [0]*6' :)
for value in dice:
totals[value - 1] += 1
print(totals)
return totals
(assuming rollDice has been modified to return a list of integers)
You should be able to call the methods as follows totals = countVals(rollDice()) to get your list of totals.
You could try the following:
dice = rollDice()
countVals(dice)
Also you want to fix the indentation of the print and return statements in countVals(). Currently, they only trigger if x==5. And as Salvador Dali mentions, either remove str from rollDice() or change the comparisons in countVals() to x == '1', etc.
Edit:
Here is how you may want to write your script:
def rollDice():
dice = [randint(1, 6) for _ in range(5)]
print(dice)
return dice
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
# x can be, 1-5. Index of totals can be 0-4.
totals[x-1] += 1
print(totals)
return totals
dice = rollDice()
countVals(dice)

Categories

Resources