Python实现还原方阵游戏:基于NumPy的逻辑推理与矩阵操作详解

小岛来信
小岛来信
发布时间:2026-10-16 | 14人浏览过
原创

本文详细介绍如何利用Python的NumPy模块开发一款还原方阵游戏。通过生成随机矩阵并给出行列连续棋子计数,玩家需推理还原原始布局。教程涵盖环境配置、矩阵初始化、用户交互逻辑、胜负判定及计分系统,适合NumPy初学者进行逻辑编程训练。

一、前言

本文的创作灵感源自一次游戏经历。在某游戏中,有玩家构建了名为“还原方阵”的趣味关卡,其精巧的设计令人印象深刻。由此引发思考:Python中强大的矩阵处理能力是否可用于复现此类游戏?

经过实践验证,该项目的开发效率极高。相较于此前耗时一周完成的蜘蛛纸牌项目,本游戏仅用2小时即完成编码,这主要得益于前期积累的编程经验。

本文将逐步引导读者完成该小游戏的开发,旨在为NumPy初学者提供一个实用的练手案例。感谢阅读,欢迎支持。

二、游戏规则

该游戏暂无官方名称,此处为便于描述而自定。

核心规则如下:系统生成一个方阵,部分位置放置棋子,部分为空。程序会提供每行和每列中连续棋子的数量信息,玩家需根据这些线索还原出完整的方阵布局。若棋子之间存在空隙,则用空格分隔表示。例如一个3x3方阵的初始状态可能如下:

棋 空 空

棋 空 棋

空 空 棋

根据上述布局,第一列包含两个连续棋子,因此给出数值2;第二列无棋子,故不提供数值;第三列包含两个连续棋子,同样给出数值2。

对于行信息,第一行有一个棋子,给出数值1;第二行有一个棋子,隔一个空格后又有另一个棋子,故给出数值“1 1”;第三行有一个棋子,给出数值1。

玩家的任务是依据提供的行列线索,推导出正确的方阵布局。

该游戏旨在锻炼逻辑推理能力。为优化用户体验,程序提供另一个矩阵供玩家标注,当玩家标注的矩阵与系统生成的正确矩阵完全一致时,游戏判定为胜利。

三、numpy模块

在编写代码前,首先介绍核心依赖库NumPy。

NumPy是Python中专门用于矩阵运算的模块,提供了丰富的函数以简化矩阵相关操作。

安装NumPy需确保已安装Python环境及pip包管理工具(若未安装请自行查阅相关教程)。在Windows系统中,按Win+R键打开运行窗口,输入cmd启动命令行,随后执行以下命令:

pip install numpy

等待安装完成,若无报错信息,则表明安装成功。随后执行以下命令:

pip list

检查pip已安装的模块列表,若其中包含numpy,则说明安装成功。

NumPy在功能上类似于嵌套列表,但其操作便捷性远超后者,许多复杂操作是普通列表无法实现的。

NumPy应用广泛,因其不像其他库那样局限于游戏、网站或爬虫等特定领域,而是作为通用“金牌辅助”,在各类涉及矩阵计算的场景中均有重要地位。例如前文提到的蜘蛛纸牌游戏也使用了该库。

NumPy支持多种赋值方式。若需对特定位置赋值,需使用二级索引,其中第一个数字代表行号,第二个代表列号,且索引从0开始。例如,将名为a的矩阵第一行第二列的值设为0,代码为a[0][1]=0。

接下来,我们将开始编写程序。

四、第一步:大循环and获取规格

首先设定游戏规则:玩家需成功还原5次矩阵即可获胜。使用while循环构建主程序框架。

为支持不同规模的矩阵,程序需获取用户输入的规格以动态调整。

首先,通过while True和try-except结构对用户输入进行校验。

采用这两者的原因在于:try-except用于处理用户输入不符合规范的情况,而while True则确保在发生错误后能提示用户重新输入。

规定支持的规格为4种:输入3对应3x3矩阵,输入4对应4x4矩阵,输入5对应5x5矩阵,输入6对应6x6矩阵。用户输入的数字必须介于3到6之间。

若用户输入其他数字,程序应如何处理?

可通过条件判断,若数字不在3至6范围内,则使用raise抛出异常,程序跳转至except块处理。这是一种严谨的处理方式。

虽然代码量稍多,但这是排除非法输入并确保程序正确运行的最佳方案。

那么,如何退出该输入循环呢?

无需复杂逻辑,只要程序执行完毕未报错,即说明输入合法,直接添加break语句退出循环即可。

win=0#初始化变量
 
while win<=5:#主体程序大循环
    while True:#while True出山
        try:#try出山
            guige=int(input("输入规格,3x3输入3,4x4输入4,5x5输入5,6x6输入6"))#获取用户输入
            if guige<3 or guige>6:#输入必须在3到6的数字之间
                raise(VauleError())#否则直接报错
            break#如果程序到了最后还没有报错就退出循环,正常执行
        except:#如果报错
            print("请正确输入")#让用户重新输入

至此,第一步已完成。

五、第二步:初始化棋盘

前文提到需使用两个矩阵:一个用于存储正确答案,命名为yes_numpy;另一个用于存储玩家尝试结果,命名为try_numpy。其中,1代表有棋子,0代表无棋子。

对于try_numpy中尚未标记的位置,该如何处理?

此处需引入None值。

None是一个特殊值,转换为布尔类型时为False,它既不是0也不是空字符串,表示“无值”。例如,获取无返回值的函数结果时,通常得到None。

虽然矩阵元素不能为字符串,但可以为None。

需将矩阵所有元素初始化为None,可通过两层嵌套for循环实现赋值。

对于yes_numpy,其元素需在0和1之间随机生成,同样使用两层嵌套for循环进行赋值。

为简化代码,将numpy模块别名为np,random模块别名为r。

完整初始化代码如下:

import random as r#导入random模块
import numpy as np#导入numpy模块
print("正在生成题目…")#提示
yes_numpy=np.zeros((guige,guige))#yes_numpy为全0矩阵
try_numpy=np.zeros((guige,guige))#try_numpy为全0矩阵
for i in range(guige):#第一层循环为行
    for j in range(guige):#第二层循环为列
        try_numpy[i][j]=None#try_numpy全部赋值为None
print(try_numpy)#输出try_numpy
    
for i in range(guige):#第一层循环为行
    for j in range(guige):#第二层循环为列
        yes_numpy[i][j]=r.choice((1,0))#yes_numpy赋值为1 0随机数

六、第三步:标注矩阵功能(难)

接下来是程序的核心部分。

首先需获取用户执行的操作。目前支持5种操作:标注矩阵填1,查看标注矩阵填2,胜利侦测填3,查看行列信息填4,重新开始填5。

由于这些操作需重复执行,使用while True包裹主逻辑。

获取用户操作时,依然采用while True和try-except组合,并结合raise和break,思路与第一步一致。由于外层已有循环,可省略一层while,将break替换为continue。

首先实现标注矩阵功能,即修改try_numpy。当用户输入1时,执行以下逻辑。

随后需让用户输入要修改位置的行、列及目标值(0、1或None),这需再增加一层while True和try-except。

这也是为何强调添加注释和控制代码层级的重要性。此类程序常涉及多层循环嵌套,逻辑复杂,此处已达第五层嵌套。

如此设计的原因在于,此前开发的蜘蛛纸牌项目因结构复杂导致运行卡顿、耗时较长且易出错,甚至出现输入时自动弹出乱码导致报错的问题。吸取教训后,本程序采用了更严谨的结构。

需考虑两种异常:输入超出矩阵范围,或修改的值非0或1。将这些异常控制在初始阶段,确保用户输入合法。

修改矩阵逻辑简单,只需定位对应位置并赋值即可。

若上述逻辑难以理解,请结合代码进行对照:

while True:#游戏开始
    try:#还是熟悉的try
        caozuo=int(input("输入操作,标注矩阵填1,查看目前改变矩阵填2,胜利侦测填3,查看行列信息填4,重新开始填5。"))#询问操作
        if caozuo<1 or caozuo>4:#必须1到4之内
            raise(ValueError())#报错
    except:#如果错误
        print("请正确输入")#提示
        continue#从头开始
        
    if caozuo==1:#如果操作是1
        while True:
            try:#老两样
                gai_hang,gai_lie,gai_neirong=map(int,input("输入标注位置的行、列(下标),以及改变成0还是1(用空格隔开三个值)\n").split())#询问三个标注信息
                if gai_neirong<0 or gai_neirong>1:#内容非0即1
                    print("只能改变成0和1,",end="")#提示
                    raise(ValueError())#报错
                if gai_hang>=guige or gai_lie>=guige:#行列不能超出矩阵规格
                    print("输入超出规格,",end="")#提示
                    raise(ValueError())#报错
                break#如果没有异常就退出循环
            except:#如果异常
                print("请正确输入")#提示
                
        try_numpy[gai_hang][gai_lie]=gai_neirong#赋值
        print("标注成功")#提示
        continue#从头开始,节约时间

此部分较为复杂,建议仔细理解并消化。

七、第四步:查看标注矩阵功能

接下来实现查看标注矩阵的功能。

该功能实质上是输出try_numpy的内容。

if caozuo==2:#如果要查看标注矩阵
    print(try_numpy)#直接输出
    continue#从头开始,节约时间

实现起来相对简单。

八、第五步:胜利侦测

为节省运行时间,胜利侦测仅在用户输入3时触发。

不能直接比较两个矩阵是否相等,需使用NumPy提供的all()函数。将两个矩阵通过等号连接进行比较,返回True或False。

if caozuo==3:#如果要检测是否胜利
    if np.all(yes_numpy==try_numpy):#如果两个矩阵全部相等
        print("你胜利了!")#提示
        zhuangtai="win"#改变变量
        break#退出循环
    else:#否则
        print("还不对哦!")#提示
        continue#从头开始

这些代码位于while True循环内,因此可使用break退出,并返回至win<5的外层循环。建议结合完整代码理解。

此处新建变量zhuangtai,是为了后续区分玩家是因获胜还是因重新开始而退出大循环。

九、第六步:查看行列信息(难)

接下来实现查看行列信息的程序。

由于矩阵完全随机,程序需自行侦测并输出行列信息。

设置一个计数变量shu。

逻辑如下:若侦测到1,则shu自增。

若侦测到0且前一项为1,则输出shu加空格,随后将shu清零。

若侦测到0且前一项为0,则不输出,可忽略侦测。

若遍历结束后shu不为0,则输出shu并换行。

逐行逐列进行侦测并输出结果。

具体程序如下,请仔细消化:

shu=0
 
if caozuo==4:#如果要查看行列信息
    for i in range(guige):#每一行
        print("第",i,"行:")#提示到底是第几行
        for j in range(guige):#每一列
            if yes_numpy[i][j]==1:#如果矩阵的这一格为1
                shu+=1#shu自增
            if yes_numpy[i][j]==0:#如果矩阵的这一格为0
                if shu!=0:#且前一格不是0(直接侦测shu的状态效果一样)
                    print(shu,end="")#输出shu
                shu=0#shu清零
        if shu!=0:#如果结束之后shu不为0
            print(shu)#输出shu要换行
        shu=0#shu清零
        print()#输出空行之后显示列
    shu=0#初始化变量
    #以下程序是把遍历行列进行交换,来达到不用改变主体侦测矩阵列的效果
    for j in range(guige):
        print("第",j,"列:")
        for i in range(guige):
            if yes_numpy[i][j]==1:
                shu+=1
            if yes_numpy[i][j]==0:
                if shu!=0:
                    print(shu,end="")
                shu=0
        if shu!=0:
            print(shu)
        shu=0
        print()

十、第七步:重新开始功能

矩阵重新开始只需break,但需调整zhuangtai变量。

#内层循环的程序
if caozuo==5:#如果操作是5
        zhuangtai="0"#状态区分
        break#直接退出循环
#这里是最外层循环的程序
if zhuangtai=="win":#如果是因为获胜退出的循环
    win+=1#win自增

十一、得分与完善and完整代码

可添加得分功能以完善程序,使用变量defen记录分数,提升玩家成就感。

整合上述程序并修复各种Bug,最终代码如下:

import numpy as np
import random as r
 
win=0
defen=500
shu=0
 
print("游戏开始。游戏规则:我会给出一个矩阵,并且给出每行每列有几个1的个数信息,如果有两个数字代表有两个空,举个例子:\n[[ 1,1,1]\n[0,0,1]\n[1,0,0]]\n在这个列表中,例如第0列为1,0,1,有两个间断的1那我就给出1 1,第1列有1 0 0,那我就给出1,第2列为1,1,0,有两个不间断的1那我就给出2。\p,请复原这个矩阵。\n另外还有分数系统,标注错一次-10分,标注对一次+10分,初始500分,获胜了+规格x50分。\n胜5局即可胜利。\n")
    
while win<=5:
    while True:
        try:
            guige=int(input("输入规格,3x3输入3,4x4输入4,5x5输入5,6x6输入6"))
            if guige<3 or guige>6:
                raise(VauleError())
            break
        except:
            print("请正确输入")
    
    print("正在生成题目…")
    yes_numpy=np.zeros((guige,guige))
    try_numpy=np.zeros((guige,guige))
    for i in range(guige):
        for j in range(guige):
            try_numpy[i][j]=None
    print(try_numpy)
    
    for i in range(guige):
        for j in range(guige):
            yes_numpy[i][j]=r.choice((1,0))
    print(yes_numpy)
    while True:#游戏开始
    
        try:
            caozuo=int(input("输入操作,标注矩阵填1,查看目前改变矩阵填2,胜利侦测填3,查看行列信息填4,重新开始填5。"))
            if caozuo<1 or caozuo>4:
                raise(ValueError())
        except:
            print("请正确输入")
            continue
        
        if caozuo==1:
            
            while True:
                try:
                    gai_hang,gai_lie,gai_neirong=map(int,input("输入标注位置的行、列(下标),以及改变成0还是1(用空格隔开三个值)\n").split())
                    if gai_neirong<0 or gai_neirong>1:
                        print("只能改变成0和1,",end="")
                        raise(ValueError())
                    if gai_hang>=guige or gai_lie>=guige:
                        print("输入超出规格,",end="")
                        raise(ValueError())
                    break
                except:
                    print("请正确输入")
                
            try_numpy[gai_hang][gai_lie]=gai_neirong
            if try_numpy[gai_hang][gai_lie]==yes_numpy[gai_hang][gai_lie]:
                defen+=10
            else:
                defen-=10
            print("标注成功")
            continue
        
        if caozuo==2:
            print(try_numpy)
            continue
        if caozuo==3:
            if np.all(yes_numpy==try_numpy):
                print("你胜利了!")
                zhuangtai="win"
                defen+=200
                break
            else:
                print("还不对哦!")
                continue
        if caozuo==4:
            for i in range(guige):
                print("第",i,"行:")
                for j in range(guige):
                    if yes_numpy[i][j]==1:
                        shu+=1
                    if yes_numpy[i][j]==0:
                        if shu!=0:
                            print(shu,end="")
                        shu=0
                if shu!=0:
                    print(shu)
                shu=0
                print()
            shu=0
            for j in range(guige):
                print("第",j,"列:")
                for i in range(guige):
                    if yes_numpy[i][j]==1:
                        shu+=1
                    if yes_numpy[i][j]==0:
                        if shu!=0:
                            print(shu,end="")
                        shu=0
                if shu!=0:
                    print(shu)
                shu=0
                print()
        if caozuo==5:
            zhuangtai= "0 "
            break
    if zhuangtai=="win":
        win+=1
print("获胜达到5局!你真厉害!目前的分:",defen)

注:代码第26和31行为了方便测试直接输出了两个矩阵,正式游玩时请删除这两行代码。

至此,关于利用Python还原方阵游戏的详解文章结束。更多相关Python内容请搜索本站往期文章或继续浏览相关文章,希望大家多多支持本站!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表