开学后,python老师就上了两节课,几乎是一点语法也不会,老师就布置了这个井字棋游戏。虽然提供了模板,但还是不大能做出来,之后我只能一步步模仿别人的代码,来搞懂过程,从代码中学习语法(好惭愧。。。。。)
敲完之后还有不懂的地方,写篇文章再从头来一遍。
基本就是照搬这位前辈的代码(只实现双人游戏,而且还有bug,,就是X或O赢了,不能输出谁赢。。。)
这位前辈的代码
1.棋盘的设计(我不懂前辈的这块代码后部分什么意思—希望帮忙)
我觉得board[‘x’]指的是棋盘棋子的空格。
def display_board(board):
print(board['1']+"|"+board['2']+"|"+board['3'])
print('-+-+-')
print(board['4']+"|"+board['5']+"|"+board['6'])
print('-+-+-')
print(board['7']+"|"+board['8']+"|"+board['9'])
2.棋子的选择
这里的while循环倒是和C语言类似,其他的区别不大
def player_input():
player1=input('请输入你的棋子选择:(X or O)')
while player1 not in ['X','O']:
player1=input('请重新输入你的棋子选择:(X or O)')
player2 = 'O' if player1 == 'X' else 'X'
return player1,player2
3.然后是先后手的选择,也类似C语言
def chooseFirst():
turn=random.choice(['X','O'])
print('\n'+turn+' go first!')
return turn
correctInput是指1~9正确的输入的数字,二turn指首先下棋的棋子(X or O)
如不是1~9,则重新输入。
例如输入1,则将board[1]用remove()函数清除,move代表board[1],返回move的值。
def place_marker(correctInput,turn):#记录落子
move=input('落子'+turn+'例如:1,2:')
while move not in correctInput:
print('\n重新输入落子:')
move=input('\n落子'+turn+'e.g.1.2:')
correctInput.remove(move)#remove() 函数用于移除列表中某个值的第一个匹配项。move是移除的对象
return move
5.这里用到了三阶幻方,还有好多函数,才慢慢查资料知道。。。
这里for循环很重要,看了好久tempBoard[str(magic3[j])]=tempBoard.pop(i)
4 9 2
3 5 7
8 1 6
就是将棋盘上的棋子转换为三阶幻方对应的数字
def board2magic(board):
# 将棋盘位置转换为用三阶幻方同位置上数字表示
tempBoard=board.copy()#字典的copy()方法相当于一种深复制,即将原本的字典dic1复制出一个内容一模一样的字典给另一个字典变量dic2,dic1和dic2的内容完全相同,但内存地址不同,不是共享引用,其中任何一方做出改变,另外一方不受影响
magic3=[4,9,2,3,5,7,8,1,6]
j=0
for i in list(tempBoard.keys()):#keys()返回一个字典所有的键。调用list()返回列表值。
tempBoard[str(magic3[j])]=tempBoard.pop(i)
#str()对象转化为适于人阅读的形式,返回string.可以将非字符串类型转换成字符串;
#pop() 函数用于移除列表中的第i个元素(默认最后一个元素),并且返回该元素的值,列表从零计数
j=j+1
return tempBoard
还是继续学习新的函数。。。
功能就是计算棋盘落子对应的数字中的行,列,对角线相加判断是否为15。itertools.combinations(pieces, 3)可以解决对角线数字相加的问题。
list(itertools.combinations(pieces, 3))应该是将各行各列及两条对角线数字相加形成一个新的序列。
最后返回bool型isWin。
#sum() 方法对系列进行求和计算。sum(iterable[, start])iterable -- 可迭代对象,如:列表、元组、集合。start -- 指定相加的参数,如果没有设置这个值,默认为0。
#combinations(iterable, r):
#创建一个迭代器,返回iterable中所有长度为r的子序列,返回的子序列中的项按输入iterable中的顺序排序:
def checkWin_sub(pieces):
# 判断是否获胜的子程序,返回判断结果
comb = list(itertools.combinations(pieces, 3))
isWin = True if 15 in [sum(i) for i in comb] else False
return isWin
tempBoard是转换为数字后的棋盘,之后两步没看懂(Xpiece,Opiece),不过应该是得到棋盘的各行各列及两条对角线的数字相加形成的一个新的序列。再用checkWin_sub()来判断是否有15.
返回bool型winner
#Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组。
#dict.items()
#返回可遍历的(键, 值) 元组数组。
def checkWin(board):
# 判断是否有获胜方
tempBoard = board2magic(board)
Xpieces = [int(x[0]) for x in tempBoard.items() if 'X' in x[1]]
Opieces = [int(x[0]) for x in tempBoard.items() if 'O' in x[1]]
Xwin = checkWin_sub(Xpieces)
Owin = checkWin_sub(Opieces)
winner = 'N'
if Xwin == True:
winner = 'X'
elif Owin == True:
winner = 'O'
return winner
8.最后是主函数了。
def main():
while True:
theBoard={'1':' ','2':' ','3':' ','4':' ','5':' ','6':' ','7':' ','8':' ','9':' '}#建立棋盘。1~9
correctInput=list(theBoard.keys())#获取正确输入形式(1~9)
player1, player2 = player_input()#双人用户输入
turn=chooseFirst()#turn为先手
for rounds in range(9):#循环
display_board(theBoard)#输出棋盘
move=place_marker(correctInput,turn)#move为按照输入的数字来确定棋盘的棋子在哪
theBoard[move]=turn#将棋子'X'或'O'放到棋盘上
turn='O' if turn=='X' else 'X'#换人落子
winner=checkWin(theBoard)#判断是否有胜者,即转换后的序列有15数字
if winner=='N':
if rounds==8:#rounds我在第一步就没搞懂
print('\nDraw')
else:
print("\n'"+winner+"'wins!")
break
display_board(theBoard)#落子后棋盘的输出
if input('按"y"键再来一盘游戏,其他键则结束游戏') != 'y':
break
main()
全部代码:
from IPython.display import clear_output
import itertools
import random
def display_board(board):
print(board['1']+"|"+board['2']+"|"+board['3'])
print('-+-+-')
print(board['4']+"|"+board['5']+"|"+board['6'])
print('-+-+-')
print(board['7']+"|"+board['8']+"|"+board['9'])
def player_input():
player1=input('请输入你的棋子选择:(X or O)')
while player1 not in ['X','O']:
player1=input('请重新输入你的棋子选择:(X or O)')
player2 = 'O' if player1 == 'X' else 'X'
return player1,player2
def chooseFirst():
turn=random.choice(['X','O'])
print('\n'+turn+' go first!')
return turn
def place_marker(correctInput,turn):#记录落子
move=input('落子'+turn+'例如:1,2:')
while move not in correctInput:
print('\n重新输入落子:')
move=input('\n落子'+turn+'e.g.1.2:')
correctInput.remove(move)#remove() 函数用于移除列表中某个值的第一个匹配项。move是移除的对象
return move
def board2magic(board):
# 将棋盘位置转换为用三阶幻方同位置上数字表示
tempBoard=board.copy()#字典的copy()方法相当于一种深复制,即将原本的字典dic1复制出一个内容一模一样的字典给另一个字典变量dic2,dic1和dic2的内容完全相同,但内存地址不同,不是共享引用,其中任何一方做出改变,另外一方不受影响
magic3=[4,9,2,3,5,7,8,1,6]
j=0
for i in list(tempBoard.keys()):#keys()返回一个字典所有的键。调用list()返回列表值。
tempBoard[str(magic3[j])]=tempBoard.pop(i)
#str()对象转化为适于人阅读的形式,返回string.可以将非字符串类型转换成字符串;
#pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值,列表从零计数
j=j+1
return tempBoard
#sum() 方法对系列进行求和计算。sum(iterable[, start])iterable -- 可迭代对象,如:列表、元组、集合。
#start -- 指定相加的参数,如果没有设置这个值,默认为0。
#combinations(iterable, r):
#创建一个迭代器,返回iterable中所有长度为r的子序列,返回的子序列中的项按输入iterable中的顺序排序:
def checkWin_sub(pieces):
comb = list(itertools.combinations(pieces, 3))
isWin = True if 15 in [sum(i) for i in comb] else False
return isWin
#Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组。
#语法:
#dict.items()
#返回可遍历的(键, 值) 元组数组。
def checkWin(board):
# 判断是否有获胜方
tempBoard = board2magic(board)
Xpieces = [int(x[0]) for x in tempBoard.items() if 'X' in x[1]]
Opieces = [int(x[0]) for x in tempBoard.items() if 'O' in x[1]]
Xwin = checkWin_sub(Xpieces)
Owin = checkWin_sub(Opieces)
winner = 'N'
if Xwin == True:
winner = 'X'
elif Owin == True:
winner = 'O'
return winner
def main():
while True:
theBoard={'1':' ','2':' ','3':' ','4':' ','5':' ','6':' ','7':' ','8':' ','9':' '}
correctInput=list(theBoard.keys())
player1, player2 = player_input()
turn=chooseFirst()
for rounds in range(9):
display_board(theBoard)
move=place_marker(correctInput,turn)
theBoard[move]=turn
turn='O' if turn=='X' else 'X'
winner=checkWin(theBoard)
if winner=='N':
if rounds==8:
print('\nDraw')
else:
print("\n'"+winner+"'wins!")
break
display_board(theBoard)
if input('按"y"键再来一盘游戏,其他键则结束游戏') != 'y':
break
main()