关于使用Python实现简单五子棋的思路

普通高中教材中关于二维数组内容的思考部分是做一个5×5五子棋,包括下棋子,和判断输赢
但是我们毕竟不是什么普通人,所以我们要做就做20×20的,而且还要能判断输入是否合法,能判断输赢那么接下来就让我来简单讲解一下我的制作思路。

一.棋盘的创建和输出

首先我们要完成棋盘的创建和棋盘的输出,这边就用

a=[[0 for i in range(20)] for i in range(20)]

来创建棋盘,运行这段语句就可以创建一个20×20的棋盘,并且每一个格子都是0。这里说明一下0代表没有下棋子,1代表黑子,2代表白子。接下来就是输出棋盘,这里输出棋盘我用了一个循环让他直接一行行输出。

def printQP():  #棋盘标准化输出
    for i in range(20):
        print(qiPan[i])

运行函数的结果:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

但其实如果想要体验更好可以尝试输出的时候加入换行和行列提示,代码如下:

def printQP():  #棋盘标准化输出
    print("    ",end="")
    for i in range(20):     #这个判断为了保证输出的序号和棋盘是整齐的
        if i<10:
            print("0"+str(i),end=" ")
        else:
            print(i,end=" ")
    print(" (x)")
    for i in range(20):
        if i<10:        #这个判断为了保证输出的序号和棋盘是整齐的
            print("0"+str(i),qiPan[i])
        else:
            print(i,qiPan[i])
    if i<19: print()        #防止(y)和棋盘之间空出一行
    print("(y)")

这个代码当中有几段if i<10的地方,这些主要是为了让只有一位的数字前面加上一个零,这样可以在判断输入的时候省点事。
这段函数运行的结果是这样的:

    00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19  (x)
00 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
01 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
02 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
03 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
04 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
05 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
06 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
07 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
08 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
09 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
10 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
11 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
12 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
13 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
14 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
15 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
16 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
17 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
18 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
19 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
(y)

至此我们玩成了棋盘的创建和输出。

二.输入和输入是否合法判断

接下来就是关于输入和输入判断的内容了
书中对于输入判断的描述是:
请输入黑方落点:0 1
也就是输入的两个数字之间有一个空格。众所周知在python中是不会以空格键结束输入的,所以说要使用一些特殊的方法,以下我就提供两种种方法:
第一种:

zong=input()
inx,iny=zong.split()

输入:1 2
结果:inx=1 iny=2

第二种:

inx,iny=input().split()
inx,iny=int(inx),int(iny)

输入:1 2
结果:inx=1 iny=2

接下来是对输入的判断。
我对输入判断是否正确一直用的是两种方法
第一种:while+flag

Flag=True
while Flag:
    a=input()
    if a=="1":
        Flag=False

第二种:死循环+break

while True:
    a=input()
    if a=="1":
        break

这个代码运行之后程序会一直让你输入直到你输入的内容为1程序结束。所以我们其实只需要把if中的内容改成我们需要的判断就可以了。代码如下:

inFlag=True
while inFlag:
    printQP()
    if fang==1:
        print("请输入黑方落点(x y)",end=": ")
    else:
        print("请输入白方落点(x y)",end=": ")
    zong=input()
    if len(zong)!=5:    #判断输入长度是否大于5
        print("输入有问题,请重新输入吧(要把0也输进来),上次你输入的内容是:"+zong)
        continue    #直接进入下一次循环
    elif not("00"<=zong[:2:]<="99" and "00"<=zong[3::]<="99"):      #判断输入的是否是数字
        print("输入有问题,请重新输入吧(要把0也输进来),上次你输入的内容是:"+zong)
        continue
    iny,inx=zong.split(" ")
    intx=int(inx)
    inty=int(iny)
    if intx<0 or intx>19 or inty<0 or inty>19:      #判断输入是否在棋盘内
        print("输入有问题,请重新输入吧,上次你输入的内容是:"+zong)
        continue
    if qiPan[intx][inty]==0:    #判断该点是否有棋子
        qiPan[intx][inty]=fang  #如果没有棋子,就把该方棋子下在这里(fang代表下棋的一方,1黑,2白)
        inFlag=False
    else:
        print("这个位子已经有一个子啦,换一个地方吧")

(代码中的注释已经分清了每一部分代码的作用)

三.判断输赢的相关代码

接下来就是要写主要判断输赢的代码了
在20×20的棋盘中,判断输赢主要看的是落子的点在棋盘中的八个方向上是否有4颗(加上自己是5颗)与自己颜色相同连在一起的子。那么首先我们先定义一个函数:

def panDuan(x,y):

这就是我们函数的创建,接下来我们要将棋子的8个方向上是否有4颗与自己颜色相同连在一起的棋子,那我们就先用一个函数内的局部变量来记录这个子的颜色。
因为我们要判断的子一定是下过的子,所以不需要判断这个被记录的值是否为0。

qi=qiPan[x][y]

这就记录了棋盘的第[x][y]上的棋子的序号(1黑,2白),接下来就要判断他的8个方向上是否有连在一起的和自己颜色相同4颗子,这个地方可以使用for循环。如果判断确实有四颗子连成了就返回棋子的编号(黑1,白2)(以向上判断为例):

qiShu=0     #计数变量
for i in range(5):
    if qiPan[x-i][y]==qi:
        qiShu+=1
if qiShu>=4:
    return qi

那么这样一个判断上方是否有连着的4颗子的代码就写好了,但是这样的代码有个问题,如果x<4的话,那x-i就会越界,所以我们还加上一个判断,来确保数组不越界:

#竖着向上判断
qiShu=0
if x-4>=0:
    for i in range(5):
        if qiPan[x-i][y]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi

接下来以此类推可以写出剩下三个正方向(向下,向左,向右)的判断代码:

#竖着向上判断
qiShu=0
if x-4>=0:
    for i in range(5):
        if qiPan[x-i][y]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi
    
#竖着向下判断
qiShu=0
if x+4<20:
    for i in range(5):
        if qiPan[x+i][y]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi        
#横着向左判断
qiShu=0
if y-4>=0:
    for i in range(5):
        if qiPan[x][y-i]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi
        
#横着向右判断
qiShu=0
if y+4<20:
    for i in range(5):
        if qiPan[x][y+i]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi

接下来就是四个斜着方向的判断。
斜着方向的判断和四个方向基本没有区别,只不过在判断数组是否越界的时候要多加一个条件,由此写出剩下四个斜的方向的代码:

#向左上判断
qiShu=0
if x-4>=0 and y-4>=0:
    for i in range(5):
        if qiPan[x-i][y-i]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi

#向左下判断
qiShu=0
if x-4>=0 and y+4<20:
    for i in range(5):
        if qiPan[x-i][y+i]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi
    
#向右上判断
qiShu=0
if x+4<20 and y-4>=0:
    for i in range(5):
        if qiPan[x+i][y-i]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi

#向右下判断
qiShu=0
if x+4<20 and y+4<20:
    for i in range(5):
        if qiPan[x+i][y+i]==qi:
            qiShu+=1
    if qiShu>=4:
        return qi

return -1   #当没有人赢的时候返回-1(老习惯了)

函数的代码就写完了,以下是函数全代码:

def panDuan(x,y):     #判断输赢
    qi=qiPan[x][y]

    #竖着向上判断
    qiShu=0
    if x-4>=0:
        for i in range(5):
            if qiPan[x-i][y]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    
    #竖着向下判断
    qiShu=0
    if x+4<20:
        for i in range(5):
            if qiPan[x+i][y]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
        
    #横着向左判断
    qiShu=0
    if y-4>=0:
        for i in range(5):
            if qiPan[x][y-i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
        
    #横着向右判断
    qiShu=0
    if y+4<20:
        for i in range(5):
            if qiPan[x][y+i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
        
    #向左上判断
    qiShu=0
    if x-4>=0 and y-4>=0:
        for i in range(5):
            if qiPan[x-i][y-i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi

    #向左下判断
    qiShu=0
    if x-4>=0 and y+4<20:
        for i in range(5):
            if qiPan[x-i][y+i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
        
    #向右上判断
    qiShu=0
    if x+4<20 and y-4>=0:
        for i in range(5):
            if qiPan[x+i][y-i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi

    #向右下判断
    qiShu=0
    if x+4<20 and y+4<20:
        for i in range(5):
            if qiPan[x+i][y+i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi

    return -1

四.主程序部分

最后的主程序部分就是游戏运行的底层代码。
游戏中,如果没有人胜利,就要一直运行下去,也就是要一直循环下去,这里可以用之前输入讲过的方法用一个flag变量,举个例子:

print("========五子棋开始========")
noEnd=True
while noEnd:
    <游戏代码>
        noEnd=False

这里就是当noEnd=False的时候游戏停止运行,这样可以让游戏一直循环下去。
接下来就是游戏的输入,之前已经讲过了。
输入完毕之后就要调用判断函数来判断输赢了吧,我们要声明一个变量代表现在下棋的一方(1黑,2白)。

fang=1  #白色为1黑色为2
fTemp=2

fang是用来表示哪一方下棋的,那fTemp呢?
fTemp是用来和fang护换值的,举个例子直白一点:
因为五子棋是要在黑方和白方之间来回切换的,所以说方在变幻的时候如果是1就要变成2,如果是2就要变成1,那么如果只有方一个变量的话就要这么写

fang=1
<游戏代码>
if fang==1:     #切换fang的状态
    fang=2
else:
    fang=1

但是如果引入了fTemp:

fang=1
fTemp=2
<游戏代码>
fang,fTemp=fTemp,fang     #切换fang的状态

这样的方法可以省略很多代码写起来更方便(但是如果你一定要写第一种,我也拦不住你)
回归正题,要判断是否赢了,就要调用函数panDuan(x,y)这里的x就是之前输入的inx,y就是输入的iny。所以在调用的时候直接写成

panDuan(inx,iny)

就可以了。
因为函数panDuan(x,y)返回的值是棋子的编号(黑1,白2)所以只要返回的值=此时的fang的话就证明fang的那一方赢了,所以判断的代码就是:

if panDuan(intx,inty)==fang:
    printQP()
    if fang==1:
        print("===黑方胜利,游戏结束===")
    else:
        print("===白方胜利,游戏结束===")
    noEnd=False

当然如果没有人赢的话就要切换fang的状态:

if panDuan(intx,inty)==fang:
    printQP()
    if fang==1:
        print("===黑方胜利,游戏结束===")
    else:
        print("===白方胜利,游戏结束===")
    noEnd=False
else:
    fang,fTemp=fTemp,fang
    print()

全代码:

(里面有部分我的调试代码,忽略就好了)

qiPan=[[0 for i in range(20)] for j in range(20)]

def printQP():  #棋盘标准化输出
    print("    ",end="")
    for i in range(20):     #这个判断为了保证输出的序号和棋盘是整齐的
        if i<10:
            print("0"+str(i),end=" ")
        else:
            print(i,end=" ")
    print(" (x)")
    for i in range(20):
        if i<10:        #这个判断为了保证输出的序号和棋盘是整齐的
            print("0"+str(i),qiPan[i])
        else:
            print(i,qiPan[i])
    if i<19: print()        #防止(y)和棋盘之间空出一行
    print("(y)")

def panDuan(x,y):     #判断输赢
    qi=qiPan[x][y]

    #竖着向上判断
    qiShu=0
    if x-4>=0:
        for i in range(5):
            if qiPan[x-i][y]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    #print("竖着向上判断",qiShu)
    
    #竖着向下判断
    qiShu=0
    if x+4<20:
        for i in range(5):
            if qiPan[x+i][y]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    #print("竖着向下判断",qiShu)
        
    #横着向左判断
    qiShu=0
    if y-4>=0:
        for i in range(5):
            if qiPan[x][y-i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    #print("竖着向左判断",qiShu)
        
    #横着向右判断
    qiShu=0
    if y+4<20:
        for i in range(5):
            if qiPan[x][y+i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    #print("竖着向右判断",qiShu)
        
    #向左上判断
    qiShu=0
    if x-4>=0 and y-4>=0:
        for i in range(5):
            if qiPan[x-i][y-i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    #print("左上判断",qiShu)

    #向左下判断
    qiShu=0
    if x-4>=0 and y+4<20:
        for i in range(5):
            if qiPan[x-i][y+i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    #print("左下判断",qiShu)
        
    #向右上判断
    qiShu=0
    if x+4<20 and y-4>=0:
        for i in range(5):
            if qiPan[x+i][y-i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    #print("右上判断",qiShu)

    #向右下判断
    qiShu=0
    if x+4<20 and y+4<20:
        for i in range(5):
            if qiPan[x+i][y+i]==qi:
                qiShu+=1
        if qiShu>=4:
            return qi
    #print("右下判断",qiShu)

    return -1


print("========五子棋开始========")
noEnd=True
fang=1  #白色为1黑色为2
fTemp=2
while noEnd:
    inFlag=True
    while inFlag:
        printQP()
        if fang==1:
            print("请输入黑方落点(x y)",end=": ")
        else:
            print("请输入白方落点(x y)",end=": ")
        zong=input()
#        print(len(zong))
        if len(zong)!=5:
            print("输入有问题,请重新输入吧(要把0也输进来),上次你输入的内容是:"+zong)
            continue
        elif not("00"<=zong[:2:]<="99" and "00"<=zong[3::]<="99"):
            print("输入有问题,请重新输入吧(要把0也输进来),上次你输入的内容是:"+zong)
            continue
        iny,inx=zong.split(" ")
        intx=int(inx)
        inty=int(iny)
        if intx<0 or intx>19 or inty<0 or inty>19:
            print("输入有问题,请重新输入吧,上次你输入的内容是:"+zong)
            continue
        if qiPan[intx][inty]==0:
            qiPan[intx][inty]=fang
            inFlag=False
        else:
            print("这个位子已经有一个子啦,换一个地方吧")
    if panDuan(intx,inty)==fang:
        printQP()
        if fang==1:
            print("===黑方胜利,游戏结束===")
        else:
            print("===白方胜利,游戏结束===")
        noEnd=False
    else:
        fang,fTemp=fTemp,fang
        print()

——作者:DeltHT