一、前言
阅读这篇文章前,需要掌握的知识:
- python的基础语法
- python列表
- 函数的定义和调用
- 字典的定义及添加键值对
- while循环和if语句
(如果没掌握也没关系,我会尽力解释清楚)
二、问题描述
某天上语文课时实在无聊,就研究起了语文老师点人回答问题的方法:
(语文老师姓李,且年龄比较大,我们称之为“老李”,因此这种点人的方法姑且被我称为“老李算法”)
- 先随机抽取一个学号(记作学生A),然后随机选一个方向,如“5号的右边”。
- 然后找到5号右边的学生B回答问题。
- 询问学生B的学号(如16号),则从6号、26号和36号中选择一个学号的某个方向(如26号的后面),找到对应的学生C回答下一个问题。
- 循环进行第三步,每次都取回答问题的学生的学号的末位并以此末位为个位,进行下一次抽取
- 如果抽到的学生A在教室边缘位置,而随机的方向上恰好没有学生(如第一排的前面),则选择学生A本人回答问题。
- (语文不太好,有点难以形容,举个简单的例子)
上图是一个简单的座位表,点人方式如下:
- 36号的前面:8号
- 18号的右边:18号
- 38号的前面:33号
- 以此类推
三、整体思路
1.座位表
为了简化问题(能力有限),假设班里有40个同学,每十人一行坐成四行,则可以用列表的方式模拟出一个座位表。
#模拟座位表
stu_line0 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
stu_line1 = [ 0,20,12, 1,11,19,34,15, 6,25,16, 0]
stu_line2 = [ 0, 3, 5,40,27, 2,14,29,22,39,33, 0]
stu_line3 = [ 0,24, 4,30,21, 8, 9,37,32,26,38, 0]
stu_line4 = [ 0,17,35,10,31,36,13,28, 7,23,18, 0]
stu_line5 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
stu_group = [stu_line0,stu_line1,stu_line2,stu_line3,stu_line4,stu_line5]
- 猜猜为什么要围一圈0?往后看就知道啦
2.准备工作
import random #导入random模块用于生成随机数
student = {} #定义一个空字典student
m = 0 #计数器
3.抽取第一个学号(学生A)和方向
def select_stu():
"""随机取值取向"""
stu_num = random.randint(1,40)
stu_dir = random.randint(1,4)
if stu_dir ==1:
s_direction = "左边"
if stu_dir ==2:
s_direction = "右边"
if stu_dir ==3:
s_direction = "前面"
if stu_dir ==4:
s_direction = "后面"
student["number"] = stu_num
student["direction"] = s_direction
print("•",stu_num,"号的",s_direction)
- 随机生成了一个1到40之间的整数,即学生A的学号,然后指定一个随机的方向,分别存储到字典student中并用print()输出。
- print()里面的"•"是用来美化输出结果的,对程序无影响。
4.找到学生B
def stu_position():
"""定位找值"""
if student["number"] in stu_line1:
stu_line = stu_line1
pos_x = 1
if student["number"] in stu_line2:
stu_line = stu_line2
pos_x = 2
if student["number"] in stu_line3:
stu_line = stu_line3
pos_x = 3
if student["number"] in stu_line4:
stu_line = stu_line4
pos_x = 4
student["x"] = pos_x
student["y"] = stu_line.index(student["number"])
"""按向找值"""
if student["direction"] == "左边":
next_student = stu_line[student["y"] - 1]
if student["direction"] == "右边":
next_student = stu_line[student["y"] + 1]
if student["direction"] == "前面":
next_studen_line = stu_group[student["x"] - 1]
next_student = next_studen_line[student["y"]]
if student["direction"] == "后面":
next_studen_line = stu_group[student["x"] + 1]
next_student = next_studen_line[student["y"]]
#防止边界取向
if next_student == 0:
next_student = student["number"]
student["number"] = next_student
- 确定学生A的位置:先用一大串if语句确定学生A在哪一个列表里,即学生A在哪一行,把这一行的列表关联到列表stu_line备用,把学生A在第几行记作pos_x(可以理解成x轴的坐标),然后存储到字典student中;在第16行,使用index()方法确定元素student["number"](即学生A的学号)的索引,记作pos_y(可以理解为y轴坐标),同样存储到字典student中。
- 找到学生B:如果是左右的话,只要把学生A在列表stu_line里的索引加上或减去一即可;如果是前后的话,学生A的行数(student["x"])就是前面列表stu_group中的索引,将其加上或减去一,得到学生B所在的那一行,访问其中索引为y的值即为学生B的学号。
(开始乱起来了,语文不行有点难描述清楚,凑合着看吧) - 这个时候前面那一圈0就有用了,如果按上面操作得到学生B的学号为0时,表明符合“问题描述”中第五点的情况,因此仍将学生A的学号赋给学生B,表明此时学生B即为学生A。
5.抽取下一位学生C
def next_stu():
"""抽取下一个值"""
selected_list = list(str(student["number"]))
end_number =selected_list[-1]
a = int(end_number)
next_list = [a,a+10,a+20,a+30]
index = random.randint(0,3)
next_number = next_list[index]
while next_number == student["number"]:
index = random.randint(0,3)
next_number = next_list[index]
"""抽取下一个方向"""
next_direction = random.randint(1,4)
if next_direction == 1:
s_direction = "左边"
if next_direction == 2:
s_direction = "右边"
if next_direction == 3:
s_direction = "前面"
if next_direction == 4:
s_direction = "后面"
student["number"] = next_number
student["direction"] = s_direction
print("•",next_number,"号的",s_direction)
- 将学生B的学号先用函数str()转换成字符串,然后用函数list()拆成列表,索引-1表示列表末位元素,然后转成整数方便后面的加法操作。
- 根据前面得到的末位构建一个列表next_list,(其中的元素相当于“问题描述”中举例的6号,16号,26号和36号)然后用用一个while循环防止再次取到学生B的学号。
- 然后抽取一个方向,和函数select_stu()结构类似,不做赘述。
6.实现循环抽号
stu_amount = int(input("Number of student:"))
if stu_amount < 1:
print("学生人数应大于零!")
else:
#抽取第一个学生
select_stu()
stu_position()
print(" 即",student["number"],"号")
m += 1
#抽取其余学生
while m < stu_amount:
next_stu()
stu_position()
print(" 即",student["number"],"号")
m += 1
- 使用函数input()获取需要抽取的总学生数。
- 第一个学生使用函数select_stu()抽号,并使用函数stu_position()找到,用print()输出结果。
- 其他的学生使用函数next_stu()抽号,并使用函数stu_position()找到,用print()输出结果。
四、总结
整个程序的代码如下:
#模拟座位表
stu_line0 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
stu_line1 = [ 0,20,12, 1,11,19,34,15, 6,25,16, 0]
stu_line2 = [ 0, 3, 5,40,27, 2,14,29,22,39,33, 0]
stu_line3 = [ 0,24, 4,30,21, 8, 9,37,32,26,38, 0]
stu_line4 = [ 0,17,35,10,31,36,13,28, 7,23,18, 0]
stu_line5 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
stu_group = [stu_line0,stu_line1,stu_line2,stu_line3,stu_line4,stu_line5]
#准备
import random
student = {}
m = 0
#函数部分
def select_stu():
"""随机取值取向"""
stu_num = random.randint(1,40)
stu_dir = random.randint(1,4)
if stu_dir ==1:
s_direction = "左边"
if stu_dir ==2:
s_direction = "右边"
if stu_dir ==3:
s_direction = "前面"
if stu_dir ==4:
s_direction = "后面"
student["number"] = stu_num
student["direction"] = s_direction
print("•",stu_num,"号的",s_direction)
def stu_position():
"""定位找值"""
if student["number"] in stu_line1:
stu_line = stu_line1
pos_x = 1
if student["number"] in stu_line2:
stu_line = stu_line2
pos_x = 2
if student["number"] in stu_line3:
stu_line = stu_line3
pos_x = 3
if student["number"] in stu_line4:
stu_line = stu_line4
pos_x = 4
student["x"] = pos_x
student["y"] = stu_line.index(student["number"])
"""按向找值"""
if student["direction"] == "左边":
next_student = stu_line[student["y"] - 1]
if student["direction"] == "右边":
next_student = stu_line[student["y"] + 1]
if student["direction"] == "前面":
next_studen_line = stu_group[student["x"] - 1]
next_student = next_studen_line[student["y"]]
if student["direction"] == "后面":
next_studen_line = stu_group[student["x"] + 1]
next_student = next_studen_line[student["y"]]
#防止边界取向
if next_student == 0:
next_student = student["number"]
student["number"] = next_student
def next_stu():
"""抽取下一个值"""
selected_list = list(str(student["number"]))
end_number =selected_list[-1]
a = int(end_number)
next_list = [a,a+10,a+20,a+30]
index = random.randint(0,3)
next_number = next_list[index]
while next_number == student["number"]:
index = random.randint(0,3)
next_number = next_list[index]
"""抽取下一个方向"""
next_direction = random.randint(1,4)
if next_direction == 1:
s_direction = "左边"
if next_direction == 2:
s_direction = "右边"
if next_direction == 3:
s_direction = "前面"
if next_direction == 4:
s_direction = "后面"
student["number"] = next_number
student["direction"] = s_direction
print("•",next_number,"号的",s_direction)
#循环部分
stu_amount = int(input("Number of student:"))
if stu_amount < 1:
print("学生人数应大于零!")
else:
#抽取第一个学生
select_stu()
stu_position()
print(" 即",student["number"],"号")
m += 1
#抽取其余学生
while m < stu_amount:
next_stu()
stu_position()
print(" 即",student["number"],"号")
m += 1
冒着宕机的风险运行了一下,所幸没出什么大岔子,运行结果如下:
Number of student:10
• 34 号的 前面
即 34 号
• 4 号的 右边
即 30 号
• 30 号的 前面
即 40 号
• 30 号的 右边
即 21 号
• 1 号的 左边
即 12 号
• 22 号的 前面
即 6 号
• 16 号的 左边
即 25 号
• 35 号的 左边
即 17 号
• 37 号的 右边
即 32 号
• 12 号的 后面
即 5 号
对照座位表验证一遍,程序成功运行,没有逻辑错误。
五、结束语
感谢每一个坚持看到这里的小伙伴!
把自己的思路说出来并让人明白并不容易,而我也正在努力做到这一点。
本人正在读高二,用来学python的时间不多,难免有错误和偏颇之处,还请各位多多包涵,不吝指教。
如果觉得这篇文章用的话,请点一个小小的赞吧~