0

Okay, so I know you shouldn't /really/ make variables global - they're meant to be local. However I am programming a blackjack game and I need to reset the cards every time the user wants to play again - so I have made a function called 'reset' and it calls that if the it is going to repeat. My main question is, should I do this or is there a better method of solving my problem, or is there a better way of doing this than just typing out global _____ every time? Here's my code if anyone wants to see;

import random
playagain = True
def reset():
    global cards
    global gameCards
    global playerCards
    global cpuCards
    global pgameCards
    global cpugameCards
    global start
    cards = ["A♠", "2♠", "3♠", "4♠", "5♠", "6♠", "7♠", "8♠", "9♠", "10♠", "J♠", "Q♠", "K♠",
             "A♥", "2♥", "3♥", "4♥", "5♥", "6♥", "7♥", "8♥", "9♥", "10♥", "J♥", "Q♥", "K♥",
             "A♣", "2♣", "3♣", "4♣", "5♣", "6♣", "7♣", "8♣", "9♣", "10♣", "J♣", "Q♣", "K♣",
             "A♦", "2♦", "3♦", "4♦", "5♦", "6♦", "7♦", "8♦", "9♦", "10♦", "J♦", "Q♦", "K♦"]
    gameCards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
    playerCards = []
    cpuCards = []
    pgameCards = []
    cpugameCards = []
    start = 0

[...]

while playagain == True:
    reset()
    winner = game()
    print("Your cards: ", playerCards)
    print("CPU's cards: ", cpuCards)
    print(winner)
    askUser = input("Play again? Y/N ")
    if askUser.upper() == "Y":
        playagain = True
    else:
        playagain = False
hannah
  • 3
  • 3
  • 4
    The best way to do this is to not use global variables at all. Python makes it annoying to do this, among a few reasons, precisely to discourage you from using them. – juanpa.arrivillaga Apr 27 '18 at 21:12
  • 2
    Create a class, make these member values, and then provide a `new_game()` method that sets all of the values to their initial states. – g.d.d.c Apr 27 '18 at 21:13
  • 1
    There is most likely always a better solution not using globals. – What Apr 27 '18 at 21:14
  • @juanpa.arrivillaga is there any other way that would make it possible to do what I need? – hannah Apr 27 '18 at 21:15
  • @g.d.d.c I'm not too sure how to do that - I am still fairly new to python, any help? – hannah Apr 27 '18 at 21:17
  • This question belongs on https://codereview.stackexchange.com – jaco0646 Apr 28 '18 at 00:28
  • 1
    @jaco0646 sorry! kind of new to this, came via Google to find a solution and didn't find it so just asked here. thanks for letting me know for the future – hannah Apr 28 '18 at 01:02
  • @hannah, no problem. Your question is valid; there just happens to be a more appropriate venue where you'd potentially get better answers in this case. – jaco0646 May 06 '18 at 02:02

3 Answers3

0

Just to give a notch in the right direction:

import random

playagain = True

class Game:
    def __init__(self):
        # init all members
        pass

    def Reset(self):
        self.cards = ["A?", "2?", "3?", "4?", "5?", "6?", "7?", "8?", "9?", "10?", "J?", "Q?", "K?",
                 "A?", "2?", "3?", "4?", "5?", "6?", "7?", "8?", "9?", "10?", "J?", "Q?", "K?",
                 "A?", "2?", "3?", "4?", "5?", "6?", "7?", "8?", "9?", "10?", "J?", "Q?", "K?",
                 "A?", "2?", "3?", "4?", "5?", "6?", "7?", "8?", "9?", "10?", "J?", "Q?", "K?"]
        self.gameCards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
        self.playerCards = []
        self.cpuCards = []
        self.pgameCards = []
        self.cpugameCards = []
        self.start = 0

Here you have an Object that holds all methods the object can do. You have to read a bit about object oriented programming and learn about the way it is implemented in python.

What
  • 304
  • 1
  • 12
  • thank you! I'm studying A-Level computer science so OOP is coming later in the course (hardly anything was covered in the old GCSE) - but I will look into it and do some reading on it, will be helpful to get a little ahead and within my current code :) – hannah Apr 27 '18 at 21:25
  • 1
    @What what are those class variables for? – Paul Panzer Apr 27 '18 at 21:26
  • @confused just to create some anticipation: all datatypes in python are objects so learning how to use methods and access variables will come handy. – What Apr 27 '18 at 21:28
  • [I think you probably wanted to create instance variables instead of class variables.](https://stackoverflow.com/questions/1680528/how-to-avoid-having-class-data-shared-among-instances) – user2357112 Apr 27 '18 at 21:29
  • If you just want anticipation, this seems like a good use of type hints: `cards: list; gameCards: list`, etc. – zondo Apr 27 '18 at 21:32
0

Using Global variables is a feature of python but if you want to code elegantly I believe global variables shouldn't be used at all.

I like to pass variables from function to function instead. My solution may not look very elegant but it actually is in my opinion.

Note: I have also included the 3 print statements into the game() function to make it simpler since they are called no matter what the output of game is.

Here is my solution:

import random
playagain = True
def reset():
    cards = ["A♠", "2♠", "3♠", "4♠", "5♠", "6♠", "7♠", "8♠", "9♠", "10♠", "J♠", "Q♠", "K♠",
             "A♥", "2♥", "3♥", "4♥", "5♥", "6♥", "7♥", "8♥", "9♥", "10♥", "J♥", "Q♥", "K♥",
             "A♣", "2♣", "3♣", "4♣", "5♣", "6♣", "7♣", "8♣", "9♣", "10♣", "J♣", "Q♣", "K♣",
             "A♦", "2♦", "3♦", "4♦", "5♦", "6♦", "7♦", "8♦", "9♦", "10♦", "J♦", "Q♦", "K♦"]
    gameCards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
    playerCards = []
    cpuCards = []
    pgameCards = []
    cpugameCards = []
    start = 0
    return cards, gameCards, playerCards, cpuCards, pgameCards, cpugameCards, start



def game(cards, gameCards, playerCards, cpuCards, pgameCards, cpugameCards, start):

    # [Main Code]

    winner = 'abcd' # put whatever you return from your original game() function as the value of winner 
    print("Your cards: ", playerCards)
    print("CPU's cards: ", cpuCards)
    print(winner)

while playagain == True:
    cards, gameCards, playerCards, cpuCards, pgameCards, cpugameCards, start = reset()
    game(cards, gameCards, playerCards, cpuCards, pgameCards, cpugameCards, start)
    askUser = input("Play again? Y/N ")
    if askUser.upper() == "Y":
        playagain = True
    else:
        playagain = False
Flaming_Dorito
  • 486
  • 3
  • 11
  • 1
    I have used that for my main game's program - didn't know I could implement that here. – hannah Apr 27 '18 at 21:34
  • @confused yeah its a pretty nice way to have the program flow and the advantage of this is that since functions are taking input values and giving output values and each function is a system, you can reuse functions with a few modifications in other programs as well. I'm not the greatest at explaining it lol, lemme know if you have any questions. – Flaming_Dorito Apr 27 '18 at 21:39
  • 1
    thanks for the help! seems to be running well now – hannah Apr 27 '18 at 21:54
0

Extending on What's answer, instead of resting all the cards in the game you could delete the current Game object and create new object. And then set all your initial states within a init function. Below is a example

import random

class Game:
    cards = []
    gameCards = []
    playerCards = []
    pgameCards = []
    cpugameCards = []
    start = 0
    '''+all your class attributes'''

    def __init__(self):
        '''insert your initial states here'''
        pass

Then to start a new game you would do something like the following:

'''To start a new game'''
game = Game()

Then to finish the current game you could do something like the following:

'''To end the current game'''
del game

If your resetting a game aren't you technically creating a new game? That's why I recommend creating and deleting game objects

Reason why you do not want to deal with global variables can be found here

All the best with your game!

Tyler N
  • 44
  • 5
  • thanks! I will bear this in mind as I look into OOP and go back to my program and modify it – hannah Apr 27 '18 at 21:52