普通高中教材中关于二维数组内容的思考部分是做一个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