[Basic knowledge of python] 7. Practical operation-Using Python to implement the "Text PK" game (1)

Preface

I want to start by talking to you about how a project is generally completed. More specifically, how do programmers think and solve problems?

I think one of the most important abilities is [problem decomposition]. Problem dismantling refers to when doing something or facing a problem, breaking it down into multiple steps or levels, and gradually executing and solving the problem until the final result is achieved.
I will summarize the process of completing a project into the following three steps:
Insert image description here
clarifying the project goals refers to what purpose we want the program to achieve and what functions it can achieve, thereby helping us break the project into different units; and a proper disassembly plan , with moderately increasing difficulty, can help us gradually and smoothly execute the project and finally complete the project. These three steps can be said to be interlocking.

Then, we will officially enter the practical operation of the project. In this process, you need to use your brain and hands more.

Clarify project goals

The requirement we want to realize this time is: human-machine PK mini game. Please refer to the diagram below for specific effects.
Insert image description here
To put it simply, in this game, the attributes of the player and the enemy will be randomly generated, and they will attack each other at the same time until one party's health is less than zero.

In addition, such a battle will last for three rounds, with a best-of-three round system. At the end, the battle result will be output and the winner will be announced.
Insert image description here
After it is clear what effect the project is to achieve, the project can be dismantled.

Analyze the process and dismantle the project

When writing code, we don't need to be strict about getting it right in one step. Especially for learners who are new to programming, better practice results can be achieved by gradually increasing the difficulty level by level.

In order to warm you up and take care of the learning rhythm of most students, I split the mini-game we want to implement into three versions from the perspective of "superposition of functions and increasing difficulty".
Insert image description here
Version 1.0 mainly helps us clarify the combat logic. Versions 2.0 and 3.0 will involve some new knowledge points. I will introduce them to you when you encounter them.

When the project is clearly broken down, all that is left is to execute it step by step, that is, repeat the cycle of "execute → encounter problems → solve problems → continue execution".

Next, let’s start writing the code officially. Let’s conquer it one version at a time!

Step by step execution, code implementation

First, let's take a look at how version 1.0 is implemented.

Version 1.0: Custom attributes, manual PK

Insert image description here
In the first stage of the code, our main task is to clarify the logic of the battle, and then use the print() function to print the battle process to the terminal.

Let’s first think about what are the most basic elements of a human-machine PK game. We can use the most classic King of Fighters game to figure it out.

Insert image description here
According to the settings of this version, there are three main steps we have to do: 1. Specify and display the attributes of the player and the enemy. 2. Both sides attack each other at the same time, and the blood volume will be deducted according to the opponent's attack power. 3. If one party's health volume is less than Equal to 0, the game is over.

In order to keep our thinking clear, the flow chart is drawn like this:
Insert image description here
Don’t say that you don’t usually play games and don’t know how to do it. All the steps in this version are not very "intelligent" and only use the only function Print(). In other words, we only need to print the steps one by one, and it will be considered successful.

Okay, let's start from step 1: set the attributes of [player] and [enemy], namely [blood volume] and [attack].

print('【玩家】血量:100 攻击:50')  # 自定义玩家角色的血量和攻击
print('【敌人】血量:100 攻击:30')  # 自定义敌人角色的血量和攻击

Step 2: Manually calculate the remaining blood volume of both sides after one attack.

print('你发起了攻击,【敌人】剩余血量50')  # 人工计算敌人血量:100-50=50
print('敌人向你发起了攻击,【玩家】剩余血量70')  # 人工计算玩家血量:100-30=70

Step 3: Continue to do manual calculations: If the player attacks the enemy twice, the enemy's blood volume will be equal to 0. At this time, the battle can be ended and the game results can be printed.

print('你发起了攻击,【敌人】剩余血量0')  # 双方同时攻击,若血量出现小于等于0,游戏结束
print('敌人向你发起了攻击,【玩家】剩余血量40')

print('敌人死翘翘了,你赢了!') # 打印结果

It's very simple! What we have to do now is to put these three pieces of code together, and then I will add some visually modified line breaks and dividing lines to make the running results clearer.

print('【玩家】\n血量:100\n攻击:50')  # 自定义玩家角色的血量和攻击,用换行符'\n'来优化视觉
print('------------------------')  # 辅助功能,起到视觉分割的作用,让代码的运行结果更清晰

print('【敌人】\n血量:100\n攻击:30')
print('------------------------')

print('你发起了攻击,【敌人】剩余血量50')  # 人工计算敌人血量:100-50=50
print('敌人向你发起了攻击,【玩家】剩余血量70')  # 人工计算玩家血量:100-30=70
print('------------------------')

print('你发起了攻击,【敌人】剩余血量0')  # 双方同时攻击,若血量出现小于等于0,游戏结束
print('敌人向你发起了攻击,【玩家】剩余血量40')
print('-----------------------')

print('敌人死翘翘了,你赢了!') # 打印结果

Try running it.
operation result:

print('【玩家】\n血量:100\n攻击:50')  # 自定义玩家角色的血量和攻击,用换行符'\n'来优化视觉
print('------------------------')  # 辅助功能,起到视觉分割的作用,让代码的运行结果更清晰

print('【敌人】\n血量:100\n攻击:30')
print('------------------------')

print('你发起了攻击,【敌人】剩余血量50')  # 人工计算敌人血量:100-50=50
print('敌人向你发起了攻击,【玩家】剩余血量70')  # 人工计算玩家血量:100-30=70
print('------------------------')

print('你发起了攻击,【敌人】剩余血量0')  # 双方同时攻击,若血量出现小于等于0,游戏结束
print('敌人向你发起了攻击,【玩家】剩余血量40')
print('-----------------------')

print('敌人死翘翘了,你赢了!') # 打印结果

Hmm... Although it seems a bit interesting, all the information comes out at once, and it doesn't reflect the progress of the game at all.

Therefore, in order to make the printed things appear one after another with time intervals, we need to set up something similar to a "timer". In Python, we need to use two lines of code to implement: (Knock on the blackboard, very simple new knowledge)

import time   #调用time模块
time.sleep(secs)   
#使用time模块下面的sleep()函数,括号里填的是间隔的秒数(seconds,简称secs)
#time.sleep(1.5)就表示停留1.5秒再运行后续代码

There is a new term here - module. It is an important concept in Python. I will introduce it to you in detail in a subsequent article.

You can think of a module as a treasure chest containing many magical functions. However, if you want to use the functions in this treasure chest, you must first open it with a code like import module name.

Then here we want to use the sleep() function in the time module, which means that the code running results will not appear all at once, but in batches. It must be written in the form of time.sleep(secs).

If I want to set the printed information to appear every 1.5 seconds, the code can be written like this:

import time  #通常import语句会写到代码的开头

print('【玩家】\n血量:100\n攻击:50')  
print('------------------------')  
time.sleep(1.5)
#暂停1.5秒,再继续运行后面的代码

print('【敌人】\n血量:100\n攻击:30')
print('------------------------')
time.sleep(1.5)
#同上

print('你发起了攻击,【敌人】剩余血量50')  
print('敌人向你发起了攻击,【玩家】剩余血量70') 
print('------------------------')
time.sleep(1.5)

print('你发起了攻击,【敌人】剩余血量0')  
print('敌人向你发起了攻击,【玩家】剩余血量40')
print('-----------------------')
time.sleep(1.5)

print('敌人死翘翘了,你赢了!') 

Okay, now that we understand the code, let’s run it directly to see the effect.

Huh~ I finally completed version 1.0, but I think you must be complaining silently in your heart that using print() to write every sentence is too stupid and weak.

That's right, but the code has to be implemented step by step. Just think of it as a little warm-up.

Moreover, this version of the code has two obvious flaws: first, the attributes (health volume & attack) of the player and the enemy are decided by me, so there is no suspense about the outcome; second, the change of health volume during the battle. If you have to calculate it manually, what's the use of a computer?

Don't worry, these are all issues we will solve in version 2.0.

Version 2.0: Random attributes, automatic PK

Insert image description here
As mentioned before, at this stage, we mainly add two new functions: [Random Attribute] and [Auto Combat]. The flow chart is drawn like this: Think about it:
Insert image description here
defining the attributes of both characters by yourself is simply a black box. Operation, the outcome has already been determined. Therefore, in order to make the game fair, we must change the attributes from being determined by ourselves to being randomly generated.

Now comes the problem. We need to randomly generate attributes (numbers), which is not taught in this article. what to do?

Check it out yourself, it will be available online.
This is also my most recommended approach. If you can solve the problem independently, you will be super satisfied.
Now that you have mastered a certain amount of code reading ability, if you encounter a stuck point and search online, you can actually solve most of your current problems. "Look it up if you don't understand" is also one of the working habits of programmers.

After searching on the Internet, we found that there is such an effect:
Insert image description here
We can see from this text that to randomly generate integers, we need to use the randint() function in the random module. There are two integers in the brackets, which delineate the random generation of integers. range.
Sample code:

import random 
#调用random模块,与
a = random.randint(1,100)
# 随机生成1-100范围内(含1和100)的一个整数,并赋值给变量a
print(a)

operation result:

73

Now that you have mastered random, let’s do a little exercise to practice:

Please listen to the questions: 1. Define two variables to store the values ​​​​of the player's blood volume and the player's attack power. 2. The blood volume is a random number between 100-150, and the attack power is a random number between 30-50. 3. Print the two variables come out.

Sample code:

import random
player_life = random.randint(100,150)
#表示玩家血量
player_attack = random.randint(30,50)
#表示玩家攻击
print(player_life)
print(player_attack)

operation result:

玩家的血量是:115
玩家的攻击力是:32

Okay, we already know how to generate random attributes. Now we are going to print out the attribute display. Please read the following code to understand the meaning of each line:

import time
import random
#也可合并写成一行:import time,random

# 生成随机属性
player_life = random.randint(100,150) # “player_life” 代表玩家血量
player_attack = random.randint(30,50) # “player_attack” 代表玩家攻击
enemy_life = random.randint(100,150) # “enemy_life” 代表敌人血量
enemy_attack = random.randint(30,50) # “enemy_attack” 代表敌人攻击

# 展示双方角色的属性
print('【玩家】\n'+'血量:'+str(player_life)+'\n攻击:'+str(player_attack))
#player_life和player_attack的数据类型都是整数,所以拼接时需要先用str()转换
print('------------------------')
time.sleep(1)
#暂停一秒再执行后续代码
print('【敌人】\n'+'血量:'+str(enemy_life)+'\n攻击:'+str(enemy_attack))
print('------------------------')

So far, we have completed randomly generating attributes and displaying attributes. Next, we will implement "automatic combat".
Insert image description here
How to achieve automatic combat? If you are confused, you can first try to find the rules from the artificial battle of version 1.0:

print('【玩家】 血量:130  攻击:50')  
print('【敌人】 血量:150  攻击:40')

print('你发起了攻击,【敌人】剩余血量100')  
print('敌人向你发起了攻击,【玩家】剩余血量90') 
print('------------------------')

print('你发起了攻击,【敌人】剩余血量50')  
print('敌人向你发起了攻击,【玩家】剩余血量70')
print('-----------------------')

print('你发起了攻击,【敌人】剩余血量0')  
print('敌人向你发起了攻击,【玩家】剩余血量40')
print('-----------------------')

print('敌人死翘翘了,你赢了!')

We can find that lines 4-6 are recurring structures. Except for the flexible changes in numbers, the rest are exactly the same.

At this time, based on the knowledge we have learned, what should we use to solve repetitive work?

loop statement.

Speaking of loops, we have to think about whether to use a for loop or a while loop.
Because now the health and attack of both sides are randomly generated, not fixed. So we don’t know exactly how many rounds we have to fight to determine the winner, that is, the number of loops is not clear, so we naturally need to use a while loop.

Let’s think further: What conditions should follow while, that is to say, under what conditions, the battle process will continue?

If the health of both sides is greater than 0, the battle will continue.

So we have now determined that the conditions that need to be met for the cycle to execute are - the blood volume of both parties is greater than zero, that is, there will be no end to the death.

Insert image description here
It can be seen that two conditions must be met after while, that is, these two conditions must be true at the same time, so we need to use and to connect, expressed in code:

while (player_life >= 0) and (enemy_life >= 0):
#and两边的条件分别用括号括起,是一种习惯,方便阅读

Now that we have determined the conditions for executing the while loop, the next step is to fill in the content inside the loop.

Based on the analysis just now, we hope that the content of the cycle will be the process of the two sides attacking each other and losing blood.

print('你发起了攻击,【敌人】剩余血量xxx')  
print('敌人向你发起了攻击,【玩家】剩余血量xxx') 
print('------------------------')

Among them, [enemy] remaining health = enemy's current health - player's attack, [player] remaining health = player's current health - enemy's attack.

In fact, we have defined these four variables before. Every time we damage each other, player_life (player health) and enemy_life (enemy health) will be reassigned, so the conversion logic is:

player_life = player_life - enemy_attack 
enemy_life = enemy_life - player_attack 
#赋值语句的执行顺序是先计算等号右边,再赋值给左边的变量

Okay, the basic logic of automatic attacks has been clarified. Let’s first merge the code we wrote before.

import time,random

# 生成随机属性
player_life = random.randint(100,150) 
player_attack = random.randint(30,50) 
enemy_life = random.randint(100,150) 
enemy_attack = random.randint(30,50) 

# 展示双方角色的属性
print('【玩家】\n'+'血量:'+str(player_life)+'\n攻击:'+str(player_attack))
#player_life和player_attack都是整数类型,所以拼接时需要先用str()转换
print('------------------------')
time.sleep(1)
print('【敌人】\n'+'血量:'+str(enemy_life)+'\n攻击:'+str(enemy_attack))
print('------------------------')
time.sleep(1)

while (player_life >0) and (enemy_life > 0):
    player_life = player_life - enemy_attack 
    enemy_life = enemy_life - player_attack 

Next, we only need to complete the while loop statement to loop the process of automatic combat and blood deduction between the two parties.
Sample code:

import time,random

player_life = random.randint(100,150) 
player_attack = random.randint(30,50) 
enemy_life = random.randint(100,150) 
enemy_attack = random.randint(30,50) 

print('【玩家】\n'+'血量:'+str(player_life)+'\n攻击:'+str(player_attack))
print('------------------------')
time.sleep(1)
print('【敌人】\n'+'血量:'+str(enemy_life)+'\n攻击:'+str(enemy_attack))
print('------------------------')
time.sleep(1)

while (player_life >0) and (enemy_life > 0):
    player_life = player_life - enemy_attack 
    enemy_life = enemy_life - player_attack 
    print('你发起了攻击,【敌人】剩余血量'+str(enemy_life))
    #player_life是整数,所以拼接时要先用str()转换
    print('敌人向你发起了攻击,【玩家】剩余血量'+str(player_life))
    print('------------------------')
    time.sleep(1.5)
    # 为了体现出战斗回合,这里停顿1.5秒    

Let's run it directly and see the results.

You should be able to feel that version 2.0 is finally looking decent and is slowly approaching our project goals.

However, it has not yet been implemented: the function of printing the results of each game, winning two out of three games, and printing the final result. This is what we are adding in version 3.0.

Let's conquer the last hill in one go.

Version 3.0: Print results, win two out of three games

Insert image description here
Compared with version 2.0, in version 3.0, the functions we want to add are: 1. Printing results: After each battle, different prompts are printed according to the result of victory, loss and draw; 2. Best of three: both sides fight three rounds , the one with the highest winning rate is the final winner.

Insert image description here
I repeatedly explain the new features because this way I can continuously clarify the phased goals of the project and allow myself to continue to focus on advancing the project.

Now please follow the prompts in the code area to add the function of "printing results" (single game) to the game.

Just like the tips I gave, there are three possibilities for the result, and the corresponding conditions are as shown in the figure below:

Insert image description here
Sample code:

import time,random

# 生成双方角色,并生成随机属性。
player_life = random.randint(100,150)
player_attack = random.randint(30,50)
enemy_life = random.randint(100,150)
enemy_attack = random.randint(30,50)

# 展示双方角色的属性
print('【玩家】\n'+'血量:'+str(player_life)+'\n攻击:'+str(player_attack))
print('------------------------')
time.sleep(1)
print('【敌人】\n'+'血量:'+str(enemy_life)+'\n攻击:'+str(enemy_attack))
print('------------------------')
time.sleep(1)

# 双方PK
while player_life > 0 and enemy_life > 0:
    player_life = player_life - enemy_attack
    enemy_life = enemy_life - player_attack
    print('你发起了攻击,【敌人】剩余血量'+str(enemy_life))
    print('敌人向你发起了攻击,【玩家】剩余血量'+str(player_life))
    print('-----------------------')
    time.sleep(1.5)

# 打印战果
if player_life > 0 and enemy_life <= 0:
    print('敌人死翘翘了,你赢了')
elif player_life <= 0 and enemy_life > 0:
    print('悲催,敌人把你干掉了!')
else:
    print('哎呀,你和敌人同归于尽了!')

Okay, let's move on. Version 3.0 only has the final "best of three games" left. Are you ready to face the final challenge?
Insert image description here
Similarly, we can split it into two parts: play three games first, and then determine the final outcome.

Insert image description here
First, let's look at it. The three-game battle is also a loopable structure, and the number of loops is fixed, so a for loop is used.

Here we can use the for i in range() structure. Let’s first review the range() function we learned before:

Insert image description here
Now, do you have an idea? Try typing out the code and let the battle cycle for three rounds. (No need to count the final results yet)

Two tips: 1. Think clearly about which codes should be nested in the for loop, that is, what information is included in a battle. After determining where to write for, all the information contained in a battle must be indented; 2. Details also need to be paid attention to, such as how to distinguish between rounds (time interval & printing number of rounds information)

If there are some obstacles, check whether there are any of the problems mentioned above: 1. Is the position of the for loop statement correct? The key is what information you want to be displayed in a loop. For example: If you mistakenly place the for loop statement between [Random Attribute] and [Auto-Battle], then the battle information in each round will be the same, and there will be no such thing as a best-of-three round.

2. After you finish writing the for loop statement, is the information that needs to be indented [as a whole] indented? If there is no indentation, an error may be reported, or only part of the combat information may be looped.

3. Have you noticed the details? There must be a clear gap between rounds, then we can use time.sleep() and print('This is the xth round') at the same time to perfectly solve this problem. In addition, if you encounter various errors, remember to search to see what error is reported, and try to solve it yourself first.

Okay, let's look at my answer now. Please focus on lines 3-5 (the following content should be placed inside the for loop), and then run it to see the effect.

import time,random

for i in range(1,4):
    time.sleep(1.5)  # 让局与局之间有较明显的有时间间隔
    print(' \n——————现在是第'+str(i)+'局,ready go!——————')  # 作为局的标记
 
    player_life = random.randint(100,150)
    player_attack = random.randint(30,50)
    enemy_life = random.randint(100,150)
    enemy_attack = random.randint(30,50)

    # 展示双方角色的属性
    print('【玩家】\n'+'血量:'+str(player_life)+'\n攻击:'+str(player_attack))
    print('------------------------')
    time.sleep(1)
    print('【敌人】\n'+'血量:'+str(enemy_life)+'\n攻击:'+str(enemy_attack))
    print('------------------------')
    time.sleep(1)

    # 双方PK
    while player_life > 0 and enemy_life > 0:
        player_life = player_life - enemy_attack
        enemy_life = enemy_life - player_attack
        print('你发起了攻击,【敌人】剩余血量'+str(enemy_life))
        print('敌人向你发起了攻击,【玩家】剩余血量'+str(player_life))
        print('-----------------------')
        time.sleep(1.5)

    # 打印战果
    if player_life > 0 and enemy_life <= 0:
        print('敌人死翘翘了,你赢了')

    elif player_life <= 0 and enemy_life > 0:
        print('悲催,敌人把你干掉了!')
    else:
        print('哎呀,你和敌人同归于尽了!')

OK, the requirement to play three games was also successful. Now we are only one step away from the final destination, and only the function of "statistical results of two wins out of three games" has not yet been implemented.

We can think about it, how do we usually count the results of games?

Insert image description here
Just like in a table tennis match, if one side wins a round, they turn over the scoreboard and add 1 to the number. Whichever side has the higher number in the end wins.

The same is true for computers: it relies on data to think, such as using data to do calculations, conditional judgments, loops, etc. So the key here is to give the computer data.

Then, following the approach of the scoreboard, our solution comes out: using a scoring method, one point is scored for a win, and no points are scored for a draw.

Therefore, we need to give the computer a blank "scoreboard" to store the scores of [player] and [enemy] in each round.

player_victory = 0
#存放玩家赢的局数。
enemy_victory = 0
#存放敌人赢的局数

Under what circumstances will these two variables change (+1)? Naturally, it has to be linked to the specific results of each game. At this time, we can look back at the conditional judgment statements for calculating winning or losing.

if player_life > 0 and enemy_life <= 0:  #玩家赢
    print('敌人死翘翘了,你赢了')
elif player_life <= 0 and enemy_life > 0: #敌人赢
    print('悲催,敌人把你干掉了!')
else:                                    #平局
    print('哎呀,你和敌人同归于尽了!')

Then, we calculate the number of rounds won by the enemy and the player:

player_victory = 0
enemy_victory = 0

if player_life > 0 and enemy_life <= 0:
    player_victory = player_victory + 1
    print('敌人死翘翘了,你赢了!')
elif player_life <= 0 and enemy_life > 0:
    enemy_victory  = enemy_victory + 1
    print('悲催,敌人把你干掉了!')
else:
    print('哎呀,你和敌人同归于尽了!')

After three rounds, player_victory and enemy_victory will be assigned new values. Here's a little trick for you: player_victory = player_victory + 1. It's a bit annoying to always write like this. We can write player_victory += 1. These two codes are equivalent. They both mean "if the condition after if is met, the variable is +1" ".

This is also a manifestation of programmers' pursuit of "minimalism". Okay, let's replace this code:

player_victory = 0
enemy_victory = 0

if player_life > 0 and enemy_life <= 0:
    player_victory += 1
    print('敌人死翘翘了,你赢了!')
elif player_life <= 0 and enemy_life > 0:
    enemy_victory  += 1
    print('悲催,敌人把你干掉了!')
else:
    print('哎呀,你和敌人同归于尽了!')

Now, we only need to use conditional judgment again and compare the sizes of the two variables to know who loses and who wins.

I will show you the thinking logic and then ask you to convert it into code. Pay attention and think: should this conditional judgment be indented?

Insert image description here
Now, please start typing out the code for the last step. Come on, victory is ahead!

Have you written it down? I think you should have no problem~ Let’s review the last step. Converting the thinking logic of conditional judgment into code logic is like this: So the reference answer is like this. It should be noted that the final judgment result must be placed
Insert image description here
in Outside the for loop, that is, no indentation is required.

import time,random

player_victory = 0
enemy_victory = 0

for i in range(1,4):
    time.sleep(2)  # 让局与局之间有较明显的有时间间隔
    print(' \n——————现在是第'+str(i)+'局——————')  # 作为局的标记
 
    player_life = random.randint(100,150)
    player_attack = random.randint(30,50)
    enemy_life = random.randint(100,150)
    enemy_attack = random.randint(30,50)

    # 展示双方角色的属性
    print('【玩家】\n'+'血量:'+str(player_life)+'\n攻击:'+str(player_attack))
    print('------------------------')
    time.sleep(1)
    print('【敌人】\n'+'血量:'+str(enemy_life)+'\n攻击:'+str(enemy_attack))
    print('------------------------')
    time.sleep(1)

    # 双方PK
    while player_life > 0 and enemy_life > 0:
        player_life = player_life - enemy_attack
        enemy_life = enemy_life - player_attack
        print('你发起了攻击,【敌人】剩余血量'+str(enemy_life))
        print('敌人向你发起了攻击,【玩家】剩余血量'+str(player_life))
        print('-----------------------')
        time.sleep(1.5)

    #打印最终战果
    if player_life > 0 and enemy_life <= 0:
        player_victory += 1
        print('敌人死翘翘了,你赢了!')
    elif player_life <= 0 and enemy_life > 0:
        enemy_victory += 1
        print('悲催,敌人把你干掉了!')
    else:
        print('哎呀,你和敌人同归于尽了!')

if player_victory > enemy_victory :
    time.sleep(1)
    print('【最终结果:你赢了!】')
elif enemy_victory > player_victory:
    print('【最终结果:你输了!】')
else: 
    print('【最终结果:平局!】')

We have finally written the final code! If you are a newbie learning from scratch, these forty lines of code may be the longest code you have ever typed, right? You're welcome, give yourself a round of applause!

However, this is not over yet. As a programmer, code is our business card. We will pursue more elegant code that is easier for others to read, so there is still some room for optimization in the above code.

Therefore, the following is Easter egg time. I will teach you a new knowledge point-[Formatting Strings] as the end of this level.

What do you mean? There are two lines of code above, which are used to display the attributes of both characters:

print('【玩家】\n'+'血量:'+str(player_life)+'\n攻击:'+str(player_attack))
print('【敌人】\n'+'血量:'+str(enemy_life)+'\n攻击:'+str(enemy_attack))

When we use + to splice strings and variables, we often need to consider what type of data the variable is. If it is not a string type, we need to convert it with the str() function first.

And a sentence often needs to be spliced ​​into several parts, and then we have to consider the starting position of each pair of quotation marks ' ', which is very troublesome. I believe you will have some experience.

Therefore, in order to more conveniently realize the splicing of different data types, using [format symbol %] is a more common and convenient way.

We can think of % as: a book used as a placeholder in the library. Take a position first and fill in the actual variables later. For example: The two writing methods below are the same. Please focus on the syntax of the second line.

print('血量:'+str(player_life)+' 攻击:'+str(player_attack))
print('血量:%s 攻击:%s' % (player_life,player_attack))

We see that there is a letter s after the format character %, which is a type code used to control the type of data display. %s means occupying a string type position first.

There are other common type codes as shown below:

Insert image description here
After occupying the position, we need to fill in the content to be filled in the form of %, so that we can avoid the trouble of converting types. If there are multiple data, put them in brackets, fill them in order, and separate them with commas.

For example, you can run this and compare the following output:

lucky = 8
print('我的幸运数字是%d' % lucky)
print('我的幸运数字是%d' % 8)
print('我的幸运数字是%s' % '小龙女的生日816')
print('我的幸运数字是%d和%d' % (8,16))

operation result:

我的幸运数字是8
我的幸运数字是8
我的幸运数字是小龙女的生日816
我的幸运数字是816

A little tip: What type code to use after % depends on what type you want the data at the position occupied by % to be displayed. If you want it to be displayed in string form, then write %s. If If you want it to be displayed as an integer, write %d.

This leads to some confusion. For example, please run the following code:

print('我的幸运数字是%d' % 8)  #8以整数展示
print('我的幸运数字是%s' % 8)  #8以字符串展示

print(8) #整数8与字符串'8'打印出来的结果是一样的
print('8')

operation result:

我的幸运数字是8
我的幸运数字是8
8
8

Different type codes are selected, but the printed results are the same. The reason has been clearly stated in the code comments: because the printed results of the integer 8 and the string '8' are the same, it is OK to choose both type codes. . However, this "all OK" situation is limited to integers and does not work for text, and an error will be reported.

Now you should have a better idea of ​​how to use this format string.

Let's look back at our previous code. If we replace all the strings spliced ​​with + at the beginning with the % format character, let's try replacing part of it first.

print(' \n——————现在是第'+str(i)+'局——————') #替换前
print('  \n——————现在是第 %s 局——————' % i) #替换后

print('【玩家】\n'+'血量:'+str(player_life)+'\n攻击:'+str(player_attack))  #替换前
print('【玩家】\n血量:%s\n攻击:%s' % (player_life,player_attack)) #替换后

print('敌人发起了攻击,【玩家】剩余血量'+str(player_life)) #替换前
print('敌人发起了攻击,【玩家】剩余血量%s' % player_life) #替换后

You may want to ask me whether %s here can be replaced with %d. The answer is "YES!" because the variables i, player_life, and player_attack here are all integers.

Okay, let’s choose to use %s this time and look at the complete code:

import time
import random

player_victory = 0
enemy_victory = 0

for i in range(1,4):
    time.sleep(1.5)
    print('  \n——————现在是第 %s 局——————' % i)
    #对比之前:(' \n——————现在是第'+str(i)+'局——————')
    player_life = random.randint(100,150)
    player_attack = random.randint(30,50)
    enemy_life = random.randint(100,150)
    enemy_attack = random.randint(30,50)

    print('【玩家】\n血量:%s\n攻击:%s' % (player_life,player_attack))
    print('------------------------')
    time.sleep(1)
    print('【敌人】\n血量:%s\n攻击:%s' % (enemy_life,enemy_attack))
    print('-----------------------')
    time.sleep(1)

    while player_life > 0 and enemy_life > 0:
        player_life = player_life - enemy_attack 
        enemy_life = enemy_life - player_attack
        print('你发起了攻击,【敌人】剩余血量%s' % enemy_life)
        print('敌人向你发起了攻击,【玩家】的血量剩余%s' % player_life)
        print('-----------------------')
        time.sleep(1.2)

    if player_life > 0 and enemy_life <= 0:
        player_victory += 1
        print('敌人死翘翘了,你赢了!')
    elif player_life <= 0 and enemy_life > 0:
        enemy_victory += 1
        print('悲催,敌人把你干掉了!')
    else:
        print('哎呀,你和敌人同归于尽了!')

if player_victory > enemy_victory :
    time.sleep(1)
    print('\n【最终结果:你赢了!】')
elif enemy_victory > player_victory:
    print('\n【最终结果:你输了!】')
else: 
    print('\n【最终结果:平局!】')

Does it look refreshed? It doesn’t matter if you are not used to this method of expression. The teacher will strengthen it in subsequent courses. Once you write it a few times, you will get used to it.

Now I promise that this is really the last step. Please run the following code directly and feel the results of our journey.

import time
import random

player_victory = 0
enemy_victory = 0

for i in range(1,4):
    time.sleep(1.5)
    print('  \n——————现在是第 %s 局——————' % i)
    player_life = random.randint(100,150)
    player_attack = random.randint(30,50)
    enemy_life = random.randint(100,150)
    enemy_attack = random.randint(30,50)

    print('【玩家】\n血量:%s\n攻击:%s' % (player_life,player_attack))
    print('------------------------')
    time.sleep(1)
    print('【敌人】\n血量:%s\n攻击:%s' % (enemy_life,enemy_attack))
    print('-----------------------')
    time.sleep(1)

    while player_life > 0 and enemy_life > 0:
        player_life = player_life - enemy_attack 
        enemy_life = enemy_life - player_attack
        print('你发起了攻击,【敌人】剩余血量%s' % enemy_life)
        print('敌人向你发起了攻击,【玩家】的血量剩余%s' % player_life)
        print('-----------------------')
        time.sleep(1.2)

    if player_life > 0 and enemy_life <= 0:
        player_victory += 1
        print('敌人死翘翘了,你赢了!')
    elif player_life <= 0 and enemy_life > 0:
        enemy_victory += 1
        print('悲催,敌人把你干掉了!')
    else:
        print('哎呀,你和敌人同归于尽了!')

if player_victory > enemy_victory :
    time.sleep(1)
    print('\n【最终结果:你赢了!】')
elif enemy_victory > player_victory:
    print('\n【最终结果:你输了!】')
else: 
    print('\n【最终结果:平局!】')

The above is our first practical project lesson. We mainly use the loop statements and conditional judgment statements we learned before. I wonder if you feel relaxed and happy when you see this, and have some sense of accomplishment?

What is more important is not what projects we have done, but whether we can use knowledge flexibly and master the methods of doing projects. I hope you now feel the same way about learning programming as I do.

Finally, let’s review the three steps of doing a project.

Insert image description here

If any students want to do more in-depth research on this game and pursue perfection, you can read this article: Implementing the "Word PK" mini game in Python (2)
Let's optimize this game and have a good time! ! !

For the next level, I will try to talk about "programming thinking" instead of continuing to talk about new knowledge so quickly.
I hope to be able to accompany you to further places on the road of learning and give you a broader perspective.

In programming learning, a broader perspective undoubtedly comes from the various thinking behind programming skills.

Therefore, in the next level, I will propose some solutions to the two major bottlenecks that students will encounter when learning Python. See you in the next level!

Guess you like

Origin blog.csdn.net/qq_41308872/article/details/132165787