Capítulo 7: Cadenas y estructuras de datos comunes

Capítulo 7: Cadenas y estructuras de datos comunes

Consulte los artículos anteriores:
Capítulo 2: Elementos del lenguaje
Capítulo 3: Estructura de rama
Capítulo 4: Estructura de bucle
Capítulo 5: Construcción de lógica de programa
Capítulo 6: Uso de funciones y módulos
O vaya a la columna "Tutorial de Python" para ver


Directorio de recursos: Código (7)
Descarga de recursos del artículo: (1-15 capítulos)
Enlace: https://pan.baidu.com/s/1Mh1knjT4Wwt__7A9eqHmng?pwd=t2j3
Código de extracción: t2j3

usar cadena

La Segunda Guerra Mundial impulsó el nacimiento de las computadoras electrónicas modernas. Inicialmente, las computadoras se usaban para calcular las trayectorias de los misiles. Durante muchos años después del nacimiento de las computadoras, la información procesada por las computadoras era básicamente información numérica. La primera computadora electrónica del mundo se llama ENIAC (Electronic Numerical Integral Computer), que nació en la Universidad de Pensilvania en los Estados Unidos, y puede completar unas 5.000 operaciones de coma flotante por segundo. Con el paso del tiempo, aunque los cálculos numéricos siguen siendo una de las cosas más importantes en el trabajo diario de las computadoras, es posible que existan más datos procesados ​​por las computadoras de hoy en forma de texto, si queremos operar estos a través de programas Python para obtener información de texto, primero debe comprender el tipo de cadena y su conocimiento relacionado.

La llamada cadena es una secuencia finita que consta de cero o más caracteres, generalmente registrada como . En un programa de Python, si encerramos uno o varios caracteres con comillas simples o dobles, podemos representar una cadena.

s1 = 'hello, world!'
s2 = "hello, world!"
# 以三个双引号或单引号开头的字符串可以折行
s3 = """
hello, 
world!
"""
print(s1, s2, s3, end='')

\Puede usar (barra invertida) en la cadena para representar el escape, lo que significa que \los siguientes caracteres ya no tienen su significado original, por ejemplo: \nen lugar de representar una barra invertida y el carácter n, representa una nueva línea; en lugar de \trepresentar una barra invertida y el carácter t representar un carácter de tabulación en su lugar. 'Entonces, si desea expresarlo en una cadena , debe escribirlo \'como la expresión ideal . Puede ejecutar el siguiente código para ver cuál será el resultado.\\\

s1 = '\'hello, world!\''
s2 = '\n\\hello, world!\\\n'
print(s1, s2, end='')

También puede ir seguido \de un número octal o hexadecimal para representar caracteres. Por ejemplo, \141y \x61ambos representan letras minúsculas a. El primero es una notación octal y el segundo es una notación hexadecimal. También puede ir \seguido de una codificación de caracteres Unicode para representar un carácter, por ejemplo, \u9a86\u660arepresenta el chino "Luo Hao". Ejecute el siguiente código para ver cuál es el resultado.

s1 = '\141\142\143\x61\x62\x63'
s2 = '\u9a86\u660a'
print(s1, s2)

\Si no desea que se escape la expresión en la cadena , podemos ragregar una letra al comienzo de la cadena para explicarlo y luego ver qué generará el siguiente código.

s1 = r'\'hello, world!\''
s2 = r'\n\\hello, world!\\\n'
print(s1, s2, end='')

Python proporciona un conjunto muy rico de operadores para tipos de cadena. Podemos usar +operadores para concatenar cadenas. Podemos usar *operadores para repetir el contenido de una cadena. Podemos usar iny not inpara determinar si una cadena contiene otro carácter. cadena (operación de membresía) , también podemos usar el operador []AND [:]para extraer un determinado carácter o algunos caracteres de la cadena (operación de corte), el código es el siguiente.

s1 = 'hello ' * 3
print(s1) # hello hello hello 
s2 = 'world'
s1 += s2
print(s1) # hello hello hello world
print('ll' in s1) # True
print('good' in s1) # False
str2 = 'abc123456'
# 从字符串中取出指定位置的字符(下标运算)
print(str2[2]) # c
# 字符串切片(从指定的开始索引到指定的结束索引)
print(str2[2:5]) # c12
print(str2[2:]) # c123456
print(str2[2::2]) # c246
print(str2[::2]) # ac246
print(str2[::-1]) # 654321cba
print(str2[-3:-1]) # 45

En Python también podemos completar el procesamiento de cadenas a través de una serie de métodos, el código es el siguiente.

str1 = 'hello, world!'
# 通过内置函数len计算字符串的长度
print(len(str1)) # 13
# 获得字符串首字母大写的拷贝
print(str1.capitalize()) # Hello, world!
# 获得字符串每个单词首字母大写的拷贝
print(str1.title()) # Hello, World!
# 获得字符串变大写后的拷贝
print(str1.upper()) # HELLO, WORLD!
# 从字符串中查找子串所在位置
print(str1.find('or')) # 8
print(str1.find('shit')) # -1
# 与find类似但找不到子串时会引发异常
# print(str1.index('or'))
# print(str1.index('shit'))
# 检查字符串是否以指定的字符串开头
print(str1.startswith('He')) # False
print(str1.startswith('hel')) # True
# 检查字符串是否以指定的字符串结尾
print(str1.endswith('!')) # True
# 将字符串以指定的宽度居中并在两侧填充指定的字符
print(str1.center(50, '*'))
# 将字符串以指定的宽度靠右放置左侧填充指定的字符
print(str1.rjust(50, ' '))
str2 = 'abc123456'
# 检查字符串是否由数字构成
print(str2.isdigit())  # False
# 检查字符串是否以字母构成
print(str2.isalpha())  # False
# 检查字符串是否以数字和字母构成
print(str2.isalnum())  # True
str3 = '  [email protected] '
print(str3)
# 获得字符串修剪左右两侧空格之后的拷贝
print(str3.strip())

Como dijimos antes, la cadena de salida se puede formatear de las siguientes maneras.

a, b = 5, 10
print('%d * %d = %d' % (a, b, a * b))

Por supuesto, también podemos usar el método provisto por la cadena para completar el formato de la cadena, el código es el siguiente.

a, b = 5, 10
print('{0} * {1} = {2}'.format(a, b, a * b))

Después de Python 3.6, hay una forma más concisa de escribir cadenas formateadas, que es agregar letras antes de la cadena fPodemos usar el siguiente azúcar sintáctico para simplificar el código anterior.

a, b = 5, 10
print(f'{a} * {b} = {a * b}')

Además de cadenas, Python también tiene una variedad de estructuras de datos integradas. Si desea guardar y manipular datos en un programa, la mayoría de las veces puede usar estructuras de datos existentes para lograrlo. Las más utilizadas incluyen listas , tuplas, conjuntos y diccionario.

lista de uso

No sé si habrás notado que hay algunas diferencias entre el tipo de cadena ( str) que acabamos de mencionar y el tipo numérico ( inty ) del que hablamos antes. floatEl tipo numérico es un tipo escalar, lo que significa que los objetos de este tipo no tienen una estructura interna accesible, el tipo cadena es un tipo estructurado, no escalar, por lo que tiene una serie de propiedades y métodos. La lista ( ) que presentaremos a continuación listtambién es un tipo estructurado, no escalar. Es una secuencia ordenada de valores. Cada valor se puede identificar mediante un índice. La lista de definición puede colocar los elementos de la lista []en ,separados por , puede usar forun bucle para recorrer los elementos de la lista, o puede usar el operador []OR [:]para extraer uno o más elementos de la lista.

El siguiente código demuestra cómo definir una lista, cómo recorrer la lista y la operación de subíndice de la lista.

list1 = [1, 3, 5, 7, 100]
print(list1) # [1, 3, 5, 7, 100]
# 乘号表示列表元素的重复
list2 = ['hello'] * 3
print(list2) # ['hello', 'hello', 'hello']
# 计算列表长度(元素个数)
print(len(list1)) # 5
# 下标(索引)运算
print(list1[0]) # 1
print(list1[4]) # 100
# print(list1[5])  # IndexError: list index out of range
print(list1[-1]) # 100
print(list1[-3]) # 5
list1[2] = 300
print(list1) # [1, 3, 300, 7, 100]
# 通过循环用下标遍历列表元素
for index in range(len(list1)):
    print(list1[index])
# 通过for循环遍历列表元素
for elem in list1:
    print(elem)
# 通过enumerate函数处理列表之后再遍历可以同时获得元素索引和值
for index, elem in enumerate(list1):
    print(index, elem)

El código siguiente muestra cómo agregar y quitar elementos de una lista.

list1 = [1, 3, 5, 7, 100]
# 添加元素
list1.append(200)
list1.insert(1, 400)
# 合并两个列表
# list1.extend([1000, 2000])
list1 += [1000, 2000]
print(list1) # [1, 400, 3, 5, 7, 100, 200, 1000, 2000]
print(len(list1)) # 9
# 先通过成员运算判断元素是否在列表中,如果存在就删除该元素
if 3 in list1:
	list1.remove(3)
if 1234 in list1:
    list1.remove(1234)
print(list1) # [1, 400, 5, 7, 100, 200, 1000, 2000]
# 从指定的位置删除元素
list1.pop(0)
list1.pop(len(list1) - 1)
print(list1) # [400, 5, 7, 100, 200, 1000]
# 清空列表元素
list1.clear()
print(list1) # []

Al igual que las cadenas, las listas también se pueden cortar. Al cortar, podemos copiar la lista o sacar una parte de la lista para crear una nueva lista. El código es el siguiente.

fruits = ['grape', 'apple', 'strawberry', 'waxberry']
fruits += ['pitaya', 'pear', 'mango']
# 列表切片
fruits2 = fruits[1:4]
print(fruits2) # apple strawberry waxberry
# 可以通过完整切片操作来复制列表
fruits3 = fruits[:]
print(fruits3) # ['grape', 'apple', 'strawberry', 'waxberry', 'pitaya', 'pear', 'mango']
fruits4 = fruits[-3:-1]
print(fruits4) # ['pitaya', 'pear']
# 可以通过反向切片操作来获得倒转后的列表的拷贝
fruits5 = fruits[::-1]
print(fruits5) # ['mango', 'pear', 'pitaya', 'waxberry', 'strawberry', 'apple', 'grape']

El siguiente código implementa la operación de clasificación en la lista.

list1 = ['orange', 'apple', 'zoo', 'internationalization', 'blueberry']
list2 = sorted(list1)
# sorted函数返回列表排序后的拷贝不会修改传入的列表
# 函数的设计就应该像sorted函数一样尽可能不产生副作用
list3 = sorted(list1, reverse=True)
# 通过key关键字参数指定根据字符串长度进行排序而不是默认的字母表顺序
list4 = sorted(list1, key=len)
print(list1)
print(list2)
print(list3)
print(list4)
# 给列表对象发出排序消息直接在列表对象上进行排序
list1.sort(reverse=True)
print(list1)

Generativos y Generadores

También podemos usar la sintaxis generativa de listas para crear listas, como se muestra en el código a continuación.

f = [x for x in range(1, 10)]
print(f)
f = [x + y for x in 'ABCDE' for y in '1234567']
print(f)
# 用列表的生成表达式语法创建列表容器
# 用这种语法创建列表之后元素已经准备就绪所以需要耗费较多的内存空间
f = [x ** 2 for x in range(1, 1000)]
print(sys.getsizeof(f))  # 查看对象占用内存的字节数
print(f)
# 请注意下面的代码创建的不是一个列表而是一个生成器对象
# 通过生成器可以获取到数据但它不占用额外的空间存储数据
# 每次需要数据的时候就通过内部的运算得到数据(需要花费额外的时间)
f = (x ** 2 for x in range(1, 1000))
print(sys.getsizeof(f))  # 相比生成式生成器不占用存储数据的空间
print(f)
for val in f:
    print(val)

Además de la sintaxis del generador mencionada anteriormente, existe otra forma de definir un generador en Python, que consiste en yieldtransformar una función ordinaria en una función de generador a través de palabras clave. El código siguiente muestra cómo implementar un generador que produce números de Fibonacci . La llamada sucesión de Fibonacci se puede definir mediante el siguiente método recursivo :

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y subirla directamente (img-Noio6FlR-1679199422415)(./res/fibonacci-blocks.png)]

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
        yield a


def main():
    for val in fib(20):
        print(val)


if __name__ == '__main__':
    main()

usar tupla

Una tupla en Python también es un tipo de datos contenedor similar a una lista. Puede usar una variable (objeto) para almacenar múltiples datos. La diferencia es que los elementos de la tupla no se pueden modificar. Lo hemos usado más de una vez en el tuplas de código anteriores también. Como su nombre lo indica, combinamos varios elementos para formar una tupla, por lo que puede contener múltiples datos como una lista. El siguiente código demuestra cómo definir y usar tuplas.

# 定义元组
t = ('骆昊', 38, True, '四川成都')
print(t)
# 获取元组中的元素
print(t[0])
print(t[3])
# 遍历元组中的值
for member in t:
    print(member)
# 重新给元组赋值
# t[0] = '王大锤'  # TypeError
# 变量t重新引用了新的元组原来的元组将被垃圾回收
t = ('王大锤', 20, True, '云南昆明')
print(t)
# 将元组转换成列表
person = list(t)
print(person)
# 列表是可以修改它的元素的
person[0] = '李小龙'
person[1] = 25
print(person)
# 将列表转换成元组
fruits_list = ['apple', 'banana', 'orange']
fruits_tuple = tuple(fruits_list)
print(fruits_tuple)

Aquí hay una pregunta que vale la pena explorar: ya tenemos una estructura de datos como una lista, ¿por qué necesitamos un tipo como una tupla?

  1. Los elementos de la tupla no se pueden modificar, de hecho, es posible que prefiramos usar esos objetos inmutables en el proyecto, especialmente en el entorno multiproceso (que se describe más adelante) (por un lado, porque el estado del objeto no se puede modificar, puede evitarse Los errores de programa innecesarios causados ​​por esto simplemente significan que un objeto inmutable es más fácil de mantener que un objeto mutable; por otro lado, debido a que ningún subproceso puede modificar el estado interno de un objeto inmutable, un objeto inmutable automáticamente es subproceso- seguro, lo que ahorra la sobrecarga del manejo de la sincronización. Un objeto inmutable se puede compartir fácilmente). Entonces, la conclusión es: si no necesita agregar, eliminar o modificar elementos, puede considerar usar tuplas. Por supuesto, si un método necesita devolver múltiples valores, usar tuplas también es una buena opción.
  2. Las tuplas son superiores a las listas en términos de tiempo y espacio de creación. Podemos usar la función getsizeof del módulo sys para verificar cuánto espacio de memoria ocupan las tuplas y las listas que almacenan los mismos elementos, lo cual es fácil de hacer. También podemos usar el comando mágico %timeit en ipython para analizar el tiempo que lleva crear tuplas y listas con el mismo contenido.La siguiente figura es el resultado de la prueba en mi sistema macOS.

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y cargarla directamente (img-GvIwmE6A-1679199422418)(./res/ipython-timeit.png)]

colección de uso

Los conjuntos en Python son consistentes con los conjuntos matemáticos, no se permiten elementos repetidos y se pueden realizar operaciones como intersección, unión y diferencia.

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y cargarla directamente (img-KsHVHAxA-1679199422419)(./res/python-set.png)]

Las colecciones se pueden crear y usar como se muestra en el código a continuación.

# 创建集合的字面量语法
set1 = {1, 2, 3, 3, 3, 2}
print(set1)
print('Length =', len(set1))
# 创建集合的构造器语法(面向对象部分会进行详细讲解)
set2 = set(range(1, 10))
set3 = set((1, 2, 3, 3, 2, 1))
print(set2, set3)
# 创建集合的推导式语法(推导式也可以用于推导集合)
set4 = {num for num in range(1, 100) if num % 3 == 0 or num % 5 == 0}
print(set4)

Agrega elementos y elimina elementos de una colección.

set1.add(4)
set1.add(5)
set2.update([11, 12])
set2.discard(5)
if 4 in set2:
    set2.remove(4)
print(set1, set2)
print(set3.pop())
print(set3)

Establecer pertenencia, intersección, unión, diferencia y otras operaciones.

# 集合的交集、并集、差集、对称差运算
print(set1 & set2)
# print(set1.intersection(set2))
print(set1 | set2)
# print(set1.union(set2))
print(set1 - set2)
# print(set1.difference(set2))
print(set1 ^ set2)
# print(set1.symmetric_difference(set2))
# 判断子集和超集
print(set2 <= set1)
# print(set2.issubset(set1))
print(set3 <= set1)
# print(set3.issubset(set1))
print(set1 >= set2)
# print(set1.issuperset(set2))
print(set1 >= set3)
# print(set1.issuperset(set3))

Explicación: Python permite algunos métodos especiales para personalizar operadores para un determinado tipo o estructura de datos (descritos en capítulos posteriores). En el código anterior, cuando operamos en un conjunto, podemos llamar al método del objeto conjunto. También puede usar el operador correspondiente directamente. Por ejemplo, &el operador tiene el mismo efecto que el método de intersección, pero usar el operador hace que el código sea más intuitivo.

usa un diccionario

Los diccionarios son otro modelo de contenedor de variables. Los diccionarios en Python son los mismos que los diccionarios que usamos en nuestras vidas. Pueden almacenar cualquier tipo de objeto. A diferencia de las listas y los conjuntos, cada elemento de un diccionario consta de un "par clave-valor". que consta de una clave y un valor, separados por dos puntos. El código siguiente muestra cómo definir y utilizar un diccionario.

# 创建字典的字面量语法
scores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82}
print(scores)
# 创建字典的构造器语法
items1 = dict(one=1, two=2, three=3, four=4)
# 通过zip函数将两个序列压成字典
items2 = dict(zip(['a', 'b', 'c'], '123'))
# 创建字典的推导式语法
items3 = {num: num ** 2 for num in range(1, 10)}
print(items1, items2, items3)
# 通过键可以获取字典中对应的值
print(scores['骆昊'])
print(scores['狄仁杰'])
# 对字典中所有键值对进行遍历
for key in scores:
    print(f'{key}: {scores[key]}')
# 更新字典中的元素
scores['白元芳'] = 65
scores['诸葛王朗'] = 71
scores.update(冷面=67, 方启鹤=85)
print(scores)
if '武则天' in scores:
    print(scores['武则天'])
print(scores.get('武则天'))
# get方法也是通过键获取对应的值但是可以设置默认值
print(scores.get('武则天', 60))
# 删除字典中的元素
print(scores.popitem())
print(scores.popitem())
print(scores.pop('骆昊', 100))
# 清空字典
scores.clear()
print(scores)

práctica

Ejercicio 1: Muestre el texto de la marquesina en la pantalla.

Respuesta de referencia:

import os
import time


def main():
    content = '北京欢迎你为你开天辟地…………'
    while True:
        # 清理屏幕上的输出
        os.system('cls')  # os.system('clear')
        print(content)
        # 休眠200毫秒
        time.sleep(0.2)
        content = content[1:] + content[0]


if __name__ == '__main__':
    main()

Ejercicio 2: Diseñar una función para generar un código de verificación de una longitud específica.El código de verificación está compuesto por letras mayúsculas, minúsculas y números.

Respuesta de referencia:

import random


def generate_code(code_len=4):
    """
    生成指定长度的验证码

    :param code_len: 验证码的长度(默认4个字符)

    :return: 由大小写英文字母和数字构成的随机验证码
    """
    all_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    last_pos = len(all_chars) - 1
    code = ''
    for _ in range(code_len):
        index = random.randint(0, last_pos)
        code += all_chars[index]
    return code

Ejercicio 3: Diseñe una función para devolver el sufijo de un nombre de archivo dado.

Respuesta de referencia:

def get_suffix(filename, has_dot=False):
    """
    获取文件名的后缀名

    :param filename: 文件名
    :param has_dot: 返回的后缀名是否需要带点
    :return: 文件的后缀名
    """
    pos = filename.rfind('.')
    if 0 < pos < len(filename) - 1:
        index = pos if has_dot else pos + 1
        return filename[index:]
    else:
        return ''

Ejercicio 4: Diseñe una función que devuelva el valor del elemento más grande y el segundo más grande en la lista aprobada.

Respuesta de referencia:

def max2(x):
    m1, m2 = (x[0], x[1]) if x[0] > x[1] else (x[1], x[0])
    for index in range(2, len(x)):
        if x[index] > m1:
            m2 = m1
            m1 = x[index]
        elif x[index] > m2:
            m2 = x[index]
    return m1, m2

Ejercicio 5: Calcular la fecha del año que corresponde al año, mes y día especificados.

Respuesta de referencia:

def is_leap_year(year):
    """
    判断指定的年份是不是闰年

    :param year: 年份
    :return: 闰年返回True平年返回False
    """
    return year % 4 == 0 and year % 100 != 0 or year % 400 == 0


def which_day(year, month, date):
    """
    计算传入的日期是这一年的第几天

    :param year: 年
    :param month: 月
    :param date: 日
    :return: 第几天
    """
    days_of_month = [
        [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
        [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    ][is_leap_year(year)]
    total = 0
    for index in range(month - 1):
        total += days_of_month[index]
    return total + date


def main():
    print(which_day(1980, 11, 28))
    print(which_day(1981, 12, 31))
    print(which_day(2018, 1, 1))
    print(which_day(2016, 3, 1))


if __name__ == '__main__':
    main()

Ejercicio 6: Imprima el triángulo Yang Hui .

Respuesta de referencia:

def main():
    num = int(input('Number of rows: '))
    yh = [[]] * num
    for row in range(len(yh)):
        yh[row] = [None] * (row + 1)
        for col in range(len(yh[row])):
            if col == 0 or col == row:
                yh[row][col] = 1
            else:
                yh[row][col] = yh[row - 1][col] + yh[row - 1][col - 1]
            print(yh[row][col], end='\t')
        print()


if __name__ == '__main__':
    main()

Caso integral

Caso 1: Selección de bolas de dos colores.

from random import randrange, randint, sample


def display(balls):
    """
    输出列表中的双色球号码
    """
    for index, ball in enumerate(balls):
        if index == len(balls) - 1:
            print('|', end=' ')
        print('%02d' % ball, end=' ')
    print()


def random_select():
    """
    随机选择一组号码
    """
    red_balls = [x for x in range(1, 34)]
    selected_balls = []
    selected_balls = sample(red_balls, 6)
    selected_balls.sort()
    selected_balls.append(randint(1, 16))
    return selected_balls


def main():
    n = int(input('机选几注: '))
    for _ in range(n):
        display(random_select())


if __name__ == '__main__':
    main()

Explicación: La función de muestra del módulo aleatorio se usa arriba para seleccionar n elementos que no se repiten de la lista.

Caso Integral 2: El Problema del Anillo de Joseph .

"""
《幸运的基督徒》
有15个基督徒和15个非基督徒在海上遇险,为了能让一部分人活下来不得不将其中15个人扔到海里面去,有个人想了个办法就是大家围成一个圈,由某个人开始从1报数,报到9的人就扔到海里面,他后面的人接着从1开始报数,报到9的人继续扔到海里面,直到扔掉15个人。由于上帝的保佑,15个基督徒都幸免于难,问这些人最开始是怎么站的,哪些位置是基督徒哪些位置是非基督徒。
"""


def main():
    persons = [True] * 30
    counter, index, number = 0, 0, 0
    while counter < 15:
        if persons[index]:
            number += 1
            if number == 9:
                persons[index] = False
                counter += 1
                number = 0
        index += 1
        index %= 30
    for person in persons:
        print('基' if person else '非', end='')


if __name__ == '__main__':
    main()

Caso Integral 3: Juego Tic Tac Toe .

import os


def print_board(board):
    print(board['TL'] + '|' + board['TM'] + '|' + board['TR'])
    print('-+-+-')
    print(board['ML'] + '|' + board['MM'] + '|' + board['MR'])
    print('-+-+-')
    print(board['BL'] + '|' + board['BM'] + '|' + board['BR'])


def main():
    init_board = {
        'TL': ' ', 'TM': ' ', 'TR': ' ',
        'ML': ' ', 'MM': ' ', 'MR': ' ',
        'BL': ' ', 'BM': ' ', 'BR': ' '
    }
    begin = True
    while begin:
        curr_board = init_board.copy()
        begin = False
        turn = 'x'
        counter = 0
        os.system('clear')
        print_board(curr_board)
        while counter < 9:
            move = input('轮到%s走棋, 请输入位置: ' % turn)
            if curr_board[move] == ' ':
                counter += 1
                curr_board[move] = turn
                if turn == 'x':
                    turn = 'o'
                else:
                    turn = 'x'
            os.system('clear')
            print_board(curr_board)
        choice = input('再玩一局?(yes|no)')
        begin = choice == 'yes'


if __name__ == '__main__':
    main()

Explicación: El último caso proviene del libro "Python Programming Quick Start: Automating Trivial Work" (este libro sigue siendo una buena opción para aquellos que tienen una base de programación y quieren usar rápidamente Python para automatizar el trabajo diario), y el código ha sido Listo. Pequeños ajustes.

Supongo que te gusta

Origin blog.csdn.net/xyx2023/article/details/129649059
Recomendado
Clasificación