Level 7: Help - IncrediCoders/Python1 GitHub Wiki

Syntax Turtle added this page on June 6, 2023


Hello, Posse team! It's us, Grafika and Syntax, to help you make a card game! This page is to help you, in case you get stuck with the instructions that I gave you in the courtyard. First, make sure you read all the texts that I sent you, which are compiled in Level 7 of the book! (You know, the Python Adventures book that chronicles our first week of school and our adventures with Cryptic Creeper? That's the book!)

Next, you'll want to make sure that your Level 7 files are loaded in Replit or in Visual Studio Code. If you have any problems, please read the instructions at Set up the Replit online editor or, for Visual Studio Code, see Load the IncrediCoders Files.

Here are the different sections on this page to help you out with your IncrediCards game:

  1. Play the Game - See the final version of the IncrediCards game (what it looks like after you go through the instructions).

  2. Glossary of Terms - This list goes through the instructions we sent you, and it explains every term and idea in depth, one topic at a time, as we bring it up in the book!

  3. Advice on Writing the Code - Eventually, in the book, we ask you to write your own code. If you get stuck, these hints will help you out!

  4. The Final Code - After you're done, it might not work the way you expected, or it might not work the same as our version (see Play the Game). Check out our final code to see what you missed! IMPORTANT: Please don't cheat yourself! Finish the game first!

1. Play the Game

In this IncrediCards game, you can run the game to see what the finished game looks like before you build it (or while you're building it). You can see the full instructions on how to download and run the game at Try the IncrediCoders Games.

You're going to build this IncrediCards game (if you haven't already).

But first you can run the program to see what the finished program looks like, before you build it (or while you're building it). You can see the full instructions on how to download and run the program at Try the IncrediCoders Games.

Here is the download to run the Level 7 game - IncrediCards:

Here are the instructions on how to play the Level 7 game: Level 7 Instructions

2. Glossary of Terms

Let's start with some definitions so that you know what all the words mean. These map to those text messages that we sent you, which you'll find in Level 7 of the book:

  1. from init import: This code imports the init.py file, which sets up the game and includes the features and functions that you'll use throughout this game.

  2. Card(): This is the function that loads in the card for each of the objects. The variables for these cards will be assigned to this function.

  3. Annie Conda: The first parameter in the Card() function, is the name of that card. On Line 4, Annie Conda is the argument that we pass into the function. We use the name 'Annie Conda' in the game, when we describe who's turn it is.

  4. python: The second parameter is the card's TechType. On Line 4, we assign 'python' as Annie Conda's TechType.

  5. 'java': The third parameter is the card's weakness TechType. On Line 4, we assign 'java' as Annie Conda's weakness. (It's the weakness of all cards that are of the Python TechType.) For example, if a Java card attacks Annie's card, then she loses one additional health (a total of four health, instead of three).

  6. bash: The fourth parameter is the card's resistance TechType. On Line 4, we assign bash as Annie's resistance. For example, if a Bash card attacks Annie, then she loses one less point of health (she loses two health instead of three).

  7. annie_conda_img: The fifth parameter represents the card's image. It's the card that appears on the screen for the current variable/character.

  8. icon_python: The sixth (and final) parameter is the card's icon. The icon shows the card's TechType. For Annie Conda, it's the Python icon.

  9. DECK = []: As I (Grafika) mentioned, this code (on Line 26) creates the DECK list. Other programming languages call it an array. You're going to be adding each card's variable to another spot in the list. Then we can shuffle the order of the cards.

    • In the deck list, we include these 20 cards, which are appended to the list, in Lines 29-48 of the code:

      1. Annie Conda
      2. Bayo Wolf
      3. Captain Javo
      4. Cryptic Creeper
      5. Emily Airheart
      6. Grafika Turtle
      7. Intelli-Scents
      8. Java Lynn
      9. Jitter Bug
      10. Justin Timbersnake
      11. Mrs. Scratcher
      12. Paul Python
      13. Queen Cobra
      14. Ram and Rom
      15. Sidewinder
      16. Syntax Turtle
      17. Viralmuto
      18. Virobotica
      19. Virobots
      20. Woodchuck Norris
  10. .append(): This is the function (or method) that adds something to a list. For example, on Line 29, DECK.append(annie_conda) adds what is in the variable annie_conda into the DECK list. We use this to deal out the cards to the players.

  11. random.shuffle(DECK): On Line 51, this is a function that shuffles the cards that are in the deck. This means that all the variables (the cards) that are in the DECK list are arranged in a random order.

  12. PlayScreen(GameState): On Line 53, the game's play screen is one of a few different game states that are like modes or screens that the player can move between. Other game states are the welcome screen and the game over screen.

  13. class: Also on Line 53, you can organize your program in sections so that you do not have to repeat the code. You can then call the class when you need to. (In Python, the class is called an object.) In other words, a class is a template that creates a new object and might include methods and variables.

  14. self: This is a parameter that we use to set what you see on the screen. For example, Line 55 adds the self variable to initialize (to set up) the play screen.

  15. self.next_state: On Line 57, we set "Victory" to the self.next_state variable. When you finish the play screen state, it moves to the victory screen, where the player can choose to start over or close the window.

  16. self.tech_attack_button: On Line 59, we set this variable to draw the TechType Attack button onto the screen.

  17. self.instructions_box: On Line 60, we set this variable to draw the instructions box onto the screen. The instructions box is in the middle, in between the cards. This box displays the instructions and the descriptions of what happens in the game.

  18. self.coin: On Line 62, we set this variable to draw the coin on the screen. When the player clicks the TechType Attack button, the coin spins to see whether it lands on heads or tails.

  19. self.turn_counter: On Line 63, we set the variable to number 1 for the first turn, in order to begin counting the number of turns.

  20. self.flipping: On Line 64, we set this variable to False, because we don't want the coin to spin (or flip) yet.

  21. self.attacking: On Line 65, we set this variable to False, because one of the players hasn't started yet (hasn't yet attacked).

  22. self.side_up: On Line 66, we set the variable to None, because we haven't spun the coin yet. Note that the game starts with the coin facing heads side up.

  23. start(): On Line 68, this function draws all the other elements on the screen.

  24. self.players: Lines 69-71 set up the self.players, self.player1, and self.player2 variables, so that we can use them later in the game. Based on the text messages we sent you, you should have removed the hash tags from the beginning of Lines 69-85.

  25. self.attacker: On Line 73, we set the active player to be the attacker. This is based on the coin toss that the players see, before they pick their cards.

  26. self.defender: Likewise, on Line 74, the defender is the player who is going to be attacked for that turn.

  27. self.player1_card_display: On Lines 76-77, we display the cards that the players picked. Although we randomly assigned three cards to each player, the player gets to pick which card to start with.

  28. self.player1_healthbar: On Lines 79-80, we display the players' healthbars.

  29. self.player1_ondeck: On Lines 82-83, we display the players' On Deck panels, which show all their cards, except for the two cards being played (one by each player).

  30. self.dialog_box: This is the variable on Line 85. This line of code displays the dialog box in the middle of the screen, between the two players' cards. This is the box where the players will see the instructions and information about the game they're playing.

  31. get_event(): We use this function on Line 87, to check if the currently active player clicks the TechType Attack button or any of the On Deck cards. Because you have to write in Lines 90 and 93-94, we'll explain those lines in the next section (with advice on how to write the code).

  32. button_action(): On Line 96, this next function flips the coin when the active player clicks the TechType Attack button. Because you need to write in Lines 98-100, we cover that in the next section.

  33. update(): On Line 102, this function updates all aspects of the game, including the player information the healthbars, decks, and the cards. You fill in Lines 104-117.

  34. if self.attacking: On Line 119, this code command sets who is attacking and defending during the current turn. You write in Lines 121-122.

  35. message: The message variable is used on Lines 125-127. These lines of code add each turn's messages to the dialog box.

  36. self.side_up: On Line 129, we check if the coin landed with heads facing up (Paul's face is on the coin).

  37. damage: On Lines 130-136, we deal the amount of damage to the defending player's card. We check the different possibilities, if the defender is resistant (Line 132), weak to the attacking player's TechType (Line 134), or neutral to the attacking player's TechType (Line 136). This last one (neutral) means that the defender receives the normal amount of damage (3 points), because the defender isn't weak or resistant to the attacking card's TechType.

  38. turn_msg: This variable can be found on Lines 132, 134, 136, and 139. (We also use it to display the final message on Line 137.) This collects the information to display about the current round of attack. It then adds that text into the message variable (on Line 137), in order to add it to the rest of the text in the dialog box.

  39. message: Just like earlier, we use the message variable (on Line 137) to update the dialog box with the information about what just happened. For example, it tells you who attacked and how much damage was received. The information about the new round gets added at the end.

  40. add_to_message(message, turn_msg): Also on Line 137, we use the add_to_message() function to grab the message for the turn we're on (in the turn_msg variable), and we also take the existing message (that's stored in the message variable). The add_to_message() function combines both of those into one string (one long line of text), and then we assign it back to the message variable (on the left of the = operator). That way we update the message variable to show that message in the dialog box (like we mentioned above).

  41. else:: On Line 138, this else statement runs if the coin didn't land on heads (since Line 129 is checking if self.side_up equals 'Heads'). In other words, the coin landed on tails.

  42. self.dialog_box.set_message(message): On Line 143, this function shows the results (using the newly updated message variable) in the dialog box.

  43. self.player1.refresh_hand(): On Line 146, this function shows the results (using refresh_hand() to update the players' cards). Each player has a hand of cards, which is the group of cards that they are given at the beginning of the game. Line 147 refreshes Player 2's cards.

  44. self.attacking = FALSE: On Line 149, we set self.attacking to FALSE, in order to end that round of the attack. This ends the current player's turn, in order to give the other player a turn to attack.

  45. self.turn_counter: On Line 150, this variable tracks the total number of turns we've had (and which turn we're on). We then use the += operator to add the number on the right (which is 1) to this variable (the total number of turns).

  46. self.switch_active_player(): On Line 153, this method switches the players so that the other player is now active and gets a turn to attack.

  47. winner: On Line 155, we set the winner variable with the self.check_game_end() function. This function checks if there's a winner yet (if one of the players ran out of cards). This line assigns the winner information into the winner variable (who the winner is).

  48. if winner:: If there is a winner (from Line 155), then Line 156 runs the content of this if block (Lines 157-158).

  49. winner.set_as_winner(): On Line 157, this function sets up the winner information for the victory screen.

  50. self.done: On Line 158, we set this variable to True to identify that the game is over!

  51. flip_coin(): On Line 160, this function determines which side is up! We define the function here, in our IncrediCards.py file (and not in our init.py file). This way, we can see the code that runs when we call this function (Lines 161-162).

  52. side: On Line 161, we start with the side variable. We're going to use the = operator to assign whether the coin lands on heads or tails.

  53. random.random(): Also on Line 161, we use this random number generator to pick a number between 0.1 and 1.0. If the number is less than 0.5, we assign "Heads" to the side variable. If the number is greater than 0.5 (the else statement), then we assign the "Tails" state to the side variable.

  54. return side: On Line 162, this sends the contents of the side variable back through the function, in order to update the animation of the coin, for it to land on heads or tails.

  55. switch_active_player(): On Line 164, we define this switch_active_player() function to set which player has the active turn.

  56. self.player1.active_turn: On Line 165, we check if Player 1 is currently active. If so, we want to switch turns so that Player 2 becomes active.

  57. self.attacker: On Line 166, we set Player 2 as the attacker.

  58. self.defender: On Line 167, we set Player 1 as the new defender (in order to switch turns with Player 2).

  59. else: Line 168 runs, if it's not currently Player 1's turn. That means it was Player 2's turn. In this else block, on Line 169, we set Player 1 as the new attacker (using self.attacker). And on Line 170, we set Player 2 as the new defender (using self.defender).

  60. self.attacker.active_turn: On Line 172, we set the new attacker's turn to active, by assigning it the True value. Likewise, on Line 173, we set the defender's active turn to False.

  61. check_game_end(): On Line 175, we define this function to check the status of both players. If one player survives, then we end the game.

  62. exiting = False: On Line 177, we set exiting to False, so that the game will continue. This is our default state.

  63. if not self.player1.active:: On Line 178, we check if Player 1 isn't active, which means that Player 1 has ran out of cards and lost the game.

  64. exiting = self.player2: On Line 179, since Player 1 lost the game, we assign Player 2 to the exiting variable, which means we will exit the game with Player 2 assigned as our winner!

  65. elif: On Line 180, we run this elif statement if Player 2 isn't active, which means that Player 2 ran out of cards and lost the game. In this case, on Line 181, we set Player 1 to the exiting variable, as our winner!

  66. return exiting: On Line 182, we return the exiting variable back through our function, in order to end the game.

  67. draw(): On Line 184, we define our draw() function. This block of code updates all of the graphics on the screen, for each new round.

  68. super().draw(surface): On Line 185, this statement resets the background on the screen.

  69. self.turn_counter: On Line 187, we check if this is the first turn in the game.

  70. self.instructions_box.draw(surface): On Line 188, since this is the first turn, we display the initial instructions, so that the players know how the game works! Line 189 updates the dialog box.

  71. self.player1_card_display.draw(surface): On Line 191, this statement displays Player 1's active card. Similarly, Line 192 displays Player 2's active card.

  72. self.player1_healthbar.draw(surface): On Line 194, this statement displays Player 1's healthbar, so Player 1 knows how much health the currently active card has left. Similarly, Line 195 displays Player 2's healthbar.

  73. self.player1_ondeck.draw(surface): On Line 197, this statement displays Player 1's On Deck box, so players can keep track of the cards in their hand. Similarly, Line 198 displays Player 2's On Deck box.

  74. self.coin.draw(surface): On Line 200, this statement draws the coin on the game screen. In computer science, the term draw means that the computer draws something on the screen. It means the same thing as showing or displaying an image.

  75. self.tech_attack_button.draw(surface): On Line 201, this statement draws the TechType Attack button on the game screen. This is the only button that the player can use to attack (later, you'll create another button, the Coded Attack button, in Challenge 2).

  76. states = {}: This statement on Line 203 declares a collection of states, or different screens needed for the game. This is when the state machine is formed. A state machine provides the overall structure for the game logic. That includes any different modes or screens. It's a logical structure for your game code, where you don't need to put all your code into a loop to run the game.

  77. "Title" : TitleScreen(): On Line 204, the title screen is the first screen you see when you run the game. There are some graphics for the title and cards and a button to start the game.

  78. "GetNames": GetNameScreen(): On Line 205, this screen is shown to get the names from the players, who click in the box and type their name before hitting the Enter key to move forward.

  79. "CoinFlip": CoinFlipScreen(): On Line 206, this screen flips the coin between the two players, to see who gets to go first. This screen includes a coin animation and a button to continue.

  80. "ChooseHand" : ChooseHandScreen(DECK): On Line 207, this screen displays each player's hand of cards, so that they can choose their starting card. We pass the DECK parameter in the ChooseHandScreen() method, because we've shuffled the order of the cards in the deck, and we want the new order of cards to be used for this screen.

  81. "Game" : PlayScreen(): On Line 208, this is the main game playing screen, where the turn action happens. (This is where the players take turns attacking each other.) There are a lot of elements on this screen, like the cards, info box, On Deck boxes, the TechType Attack button, and the coin animation.

  82. "Victory" : VictoryScreen(): On Line 209, this screen displays at the end of the game, when one player is named the winner. There is an option to play again, which starts the state machine back at the GetNameScreen, or exit the game if they are done.

  83. game = GameRunner(SCREEN, states, "Title"): Line 212 is the line that actually starts the game runner. Everything up to this line was all setup, but this is where the action starts. (The code starts running with this line.)

3. Advice on Writing the Code

My instructions get a little trickier as we go through Level 7 in the book. Eventually, I ask you to write your own code. This section gives you some hints on how to write your code!

On Line 1, similar to the other challenges, this will import the code from the init.py file.

On Lines 4-24, all the cards for all of the characters are created with their name, attack strengths and weaknesses, their TechType attack (the programming language that each character is associated with), an image of them, and their TechType icon.

We had you type out Lines 23-24. We had you copy Line 23, to add the Virobots card to the game! Note that 'Virobots' is the name of the card, 'bash' is the TechType for all our evil baddies, 'python' is the weakness of the Bash TechType, and 'small_basic' is the resistance of the Bash TechType (which means that Virobotica is resistant to Small Basic cards, like our cards, Grafika and Syntax). The variable virobots_img brings in the card image, and icon_bash shows the Virobots' TechType icon. This icon is shown by itself (off of the card) in the On Deck box.

For Line 24, we broke it up more, and we had you type in one part of the code at a time. Just like how the code is formatted on Lines 4-21, Line 24 starts with the woodchuck_norris variable. You assign to it the return value of the Card() function. Just like on Line 23, you put in the parameters that we mentioned in the book. These parameters provide the card name, TechType, weakness, strength (or resistance), the card image, and the card's TechType icon. Be sure to end the line of code with the end parenthesis of the Card() function!

On Line 26, we created a new list, with the code **DECK = []**.

On Lines 29-48, the card variables, which were made on Lines 4-24, are put into the DECK list.

On Line 51, the deck of cards is randomly shuffled using the random.shuffle(DECK) function. As we mentioned in our text conversation, the random object includes methods that allow you to randomly select something. We use the shuffle() method to randomly shuffle the order of the cards. DECK is our list, which includes all the variables that represent each card.

Line 53 defines the PlayScreen() class, with the code, class PlayScreen(GameState):

In Lines 55-66, we pass the self variable into our _init_() function, to set up (or initialize) the display with all the graphics on it.

On Lines 68-85, this section is the start of the game, once all of the cards are labeled and in the deck list. In the book, we asked you to remove the hash tags at the beginning of Lines 69-85.

On Lines 87-94, we check if the player clicks the TechType Attack button and if the players click an On Deck card.

On Line 90, you copy the code self.tech_attack_button.get_event(event) (at the same indentation level as the comment on Line 89). As I mentioned, this checks if the player clicks the button, and it stores that information into the get_event() function, to use it later.

On Line 93, add the code self.player1_ondeck.get_event(event) to check if a player clicks a card in the Player 1 On Deck box. If so, this moves that card into the main position (for attacking and defending).

On Line 94, add the code to check if a player clicks a card in the Player 2 On Deck box. This is almost the same line of code as Line 93. It just replaces the number "1" with "2" instead. It should look like self.player2_ondeck.get_event(event) and should be at the same indentation level as Line 93.

On Lines 96-100, we define the button_action() function, which flips the coin when the player clicks the TechType Attack button.

On Line 98, self.side_up is currently showing the static image of the coin (either showing heads or tails). The self.flip_coin() function captured whether the coin will flip to heads or tails, and then it gets saved back into the self.side_up variable to update it to either heads or tails. The full line of code is self.side_up = self.flip_coin() (on Line 98).

Line 99 determines what part of the animation plays. So, if Line 98 sets the self.side.up variable to heads, then Line 99 sets how much of the animation to play, so that it lands on heads. If self.side.up is set to tails, then Line 99 determines how much of the animation to play, to show the coin land on tails.

On Line 99, type self.coin.set_side(self.side_up) to pass the variable self.side_up into the self.coin.set_side() function (which is what determines how much of the animation it's going to show).

On Line 100, you set the variable self.flipping to True, which runs the animation. The full line is self.flipping = True and should be at the same indentation level as Lines 97-99.

On Lines 102-158, we define the update() function. This is the main function of the game (the main turn loop). It updates all the parts of the screen, including the healthbars (Lines 104-105), the On Deck boxes (Lines 107-108), the main cards that are displayed (Lines 110-111), and the updated coin (Lines 114-117). It shows which card you picked to start the game with (Lines 119-122), it updates the messages (Lines 124-127), it deals damage to the cards and updates with those messages (Lines 129-140 and 143), it updates the players' hands (Lines 146-147), it counts the turns (Lines 149-150), it switches players between turns (Line 153), and it sets the winner to end the game (Lines 155-158).

Let's dig into what's inside the update() function! First, let's look at Lines 104-105, updating the healthbars. As we mentioned in our text message, type in self.player1_healthbar.update() on Line 104 (keep the same indentation level as the comment on Line 103). In the attribute self.player1_healthbar, self represents the screen, player1 makes it clear that the attribute is assigned to Player 1, and _healthbar clarifies that we're working with Player 1's healthbar. We're using the update() function to update the healthbar to show the correct HP (health points) for the player's active card.

Line 105 is very similar to Line 104. The only difference is that this is updating the healthbar for Player 2. The full line of code is self.player2_healthbar.update() on Line 105.

Next, Lines 107-108 update the On Deck boxes. Line 107 is similar to Line 104. The only difference is that we use _ondeck instead of _healthbar in the attribute name. This updates our Player 1 On Deck box, in case Player 1 clicked a card in the box to switch to it (or their defending card got eliminated). As we mentioned in the text chat, the full line is self.player1_ondeck.update() on Line 107.

Similarly, the next line just clarifies that it's updating Player 2's On Deck box, and the full code is self.player2_ondeck.update() on Line 108. Both lines should be indented at the same level as Lines 103-105.

Now let's look at how we update the main cards that are displayed, on Lines 110-111. Line 110 is also very similar to Lines 104 and 107. You can just update the end of the attribute to _card_display instead of _healthbar or _ondeck. This line updates Player 1's main card, in case they switched it (through the On Deck box) or it got eliminated. The full line of code is self.player1_card_display.update() on Line 110.

Line 111 is the same (there's a pattern here), but we swap out the player1 part of the attribute with player2 instead. This way we're updating the Player 2 card (in case it got switched or eliminated). The full code is self.player2_card_display.update() on Line 111.

Lines 114-117 update the coin. On Line 114, the code if self.flipping: checks whether a player clicked the TechType Attack button.

On Line 115, we assign the self.coin.update(dt) function to the self.flipping variable. self.coin is our attribute to show that we're referring to the screen (with self) and to the coin. Our update() function updates the animation (and visual state) of the coin flipping. We pass the dt parameter into the function, which is our delta time (the speed that the number of frames are played). In other words, dt determines the speed of the coin flipping animation. The full line of code is self.flipping = self.coin.update(dt) on Line 115.

On Line 116, we check if the coin flipping animation is done yet. The full line of code is if not self.flipping:

On Line 117, if the animation is done (as determined by Line 116), then we set the self.attacking variable to True. This sets the active card to attack for the next round. The full line of code is self.attacking = True on Line 117.

Our final section of code that we need you to write is on Lines 121-122. These lines of code set which card is going to be attacking and which card is defending, at the beginning of each turn.

On Line 121, we set the current attacking card to the offense_card variable. The full line of code is offense_card = self.attacker.current_card on Line 121.

Line 122 is very similar. Instead, we assign the defending card to the defense_card variable. The full line of code is defense_card = self.defender.current_card on Line 122.

That's it for the new code that we hadn't written yet! Next, we'll just summarize the other lines of code in your IncrediCards.py file.

On Lines 125-127, we create each turn's message. We include the turn_counter (Line 125), the name of who's attacking (Line 126), and the result of the last turn's coin flip (Line 127).

Lines 129-140 include the logic when the attacking player gets heads, after clicking the TechType Attack button. Line 130 assigns the damage to the defending card. Lines 131-132 display the message if the defending player loses 2 health. Lines 133-134 display the message if the defending player loses 4 health, and Lines 135-136 display the message if the defending player loses 3 health (which is the normal amount, without a weakness or resistance in place). Lines 138-140 run if the attacking player gets tails and the TechType Attack misses. On Line 140, we save that information into the message variable.

On Line 143, we show the turn's full message in the dialog box in the middle of the screen.

On Lines 146-147, the refresh_hand() method makes sure that each card (the two main cards and the On Deck cards) are still alive (not yet defeated) and are playable.

On Line 149, we end the turn, and then on Line 150, we update the turn counter to the next turn, in order to keep track of which turn we're on.

On Line 153, we switch the active player so that the other player gets a turn to attack.

On Line 155, we check to see if one player lost all their cards, and then we save the information of who won into the winner variable. If there is a winner captured in that variable (Line 156), then we update the player status as the winner (Line 157), and we end the game (Line 158). This brings up the victory screen (which shows you who won). The players can then choose to play again or exit the game.

The next functions (on Lines 160-201) update animations and graphics on the screen.

On Lines 160-162, the flip_coin() function randomly generates whether the coin lands on "Heads" (if the number is below 0.5) or "Tails" (the number is below 0.5). It returns the result of the coin flip.

On Lines 164-173, the switch_active_player() function switches who the active player is (whose turn it is in the game). It sets the attacking player to active (Line 172) and the defending player to inactive (Line 173).

On Lines 175-182, we use the check_game_end() function to see if the game has ended. Line 177 starts by setting the exiting variable to False, so that we don't exit unless there's a winner. Line 178 checks if Player 1 lost, and if so, Line 179 assigns the winner, self.player2, to the exiting variable. On Line 180, the elif statement checks whether Player 2 lost the game. If so, Line 181 assigns the winner, self.player1, to the exiting variable.

Line 182 returns the exiting variable, which is the result of who won the game. If the value of exiting is still set to False, then nobody has won yet, and the game continues.

On Lines 184-201, the draw() function draws (or displays) all the elements of the game screen. Line 189 displays the dialog box, and Lines 191-192 display each player's active card on the screen. (We refer to the screen with the variable surface.) Then, we display the healthbars (Lines 194-195), the On Deck boxes (Lines 197-198), the coin (Line 200), and the TechType Attack button (Line 201).

On Lines 203-210, we define the different states of the game. The states are the different game modes or screens. This is also called the state machine.

Line 204 opens the Title screen, where you click the button to start the game. Line 205 opens the GetNames screen, where the players enter their names at the beginning of the game. Line 206 opens the CoinFlip screen, where you flip the coin to see which player gets to go first. Line 207 opens the ChooseHand screens, where each player picks which card to start with. Line 208 opens the Game screen, where you play the game. (You're on this screen the most.) Finally, Line 209 opens the Victory screen, where you can choose to play again or to exit the game.

Line 212 loads everything into the GameRunner() function (including the different screens, turn game logic, and everything else), and it starts the game!

4. The Final Code

I included a solution file for Level 7: IncrediCards. This file has all the code filled in, so if you run into any issues with your code (for example, if it doesn't compile/run, or if something isn't working correctly in your program), then you can take a look at the final code file to see what you did differently:

IMPORTANT: Please don't cheat yourself! Finish the game first!

Next Steps

Next, you can take on the two extra challenges to build more features for the IncrediCards game, and to learn more!

Take the Challenges!

  1. Challenge 1: In this challenge, you are going to add two more cards to each player's deck, so that you can switch between five cards (instead of three cards).

  2. Challenge 2: In this second challenge, you are going to add a second attack option, the Coded Attack (which has special abilities, like to get an extra turn).

More Level 7 Resources

  • Level 7: Unplugged Activity - I wrote this page with more details than what you saw in the book. In this game,

  • Level 7: Rewards - If you completed the IncrediCards program that we talked about, then I set up this page to act as a reward. You can see some illustrations of me and learn more about who I am! You'll also find the WHAT Award digital download, to show off your accomplishment!

  • Level 7: IncrediCards - All Online Resources - Return back to the main Level 7 page, with all our online resources!

Level 7

After you're completely done with Level 6 (did you do the challenges?), then it's time to move on to Level 7! While you read through Level 7 in your book, you can check out the resources from CHARACTER, as he teaches you how to build the IncrediCards program:

Syntax and I love to make card games like IncrediCards! We hope you had fun learning about it too!

--Grafika and Syntax Turtle

⚠️ **GitHub.com Fallback** ⚠️