鱼C论坛

 找回密码
 立即注册
查看: 2744|回复: 46

[作品展示] 井字棋?安排!!

[复制链接]
发表于 2020-3-16 14:04:08 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 一个账号 于 2020-3-16 14:26 编辑

python小白来展示学习成果啦!!!! 希望各位帅气的小哥哥漂亮的小姐姐们能指点一下下

最近在看一本python入门书《python游戏编程快速上手》感觉这本书还是不错滴,很适合像我这个亚子的白白的小白

书里面有一个TicTacToe也就是井字棋游戏,看着书编了一遍又自己实现了一下下,好了废话不多说,先上波儿效果图(让我找找哈,不知道存哪了


井字棋1.png

井字棋2.png
第一次展示作品,不知道该说点啥。。。。

效果呢就上上面这两张图展示的那个亚子,是不是有点小失望呀,这TM是啥破游戏,连个正儿八经的界面都没。

emmmmmm刚开始学Python嘛,嘿嘿,等我以后学成归来,一定要把我的井字棋改成不同寻常的、高端大气上档次的....井字棋

下面我来稍微说一下这个小游戏吧,顺便复习一下。

有兴趣的童鞋们可以自己实现一下子呀,如果大家有啥想法或者发现我有哪里写的不好,欢迎评论交流呦

井字棋流程图.png

这个是书上给出的流程图,emmmm,是不是有点乱呀?! 不用怕,我自己又做了一张流程图(是不是莫名又开始恐慌了???hhhhh)

井字棋思路.png

没错,就是咱们的编辑神器IDLE,hhhhh,大概思路就是这样梓吧,然后就是按照写好的思路来编写程序了

首先呢,咱们稍微看下写好的流程,对于重复出现的操作可考虑一下函数之类的东东,比如咱们看到好多地方要展示游戏板,那就把这一块函数封装到一个函数里呗

就像这样
def draw_board(board, nums=[' ']*10):
    """展示游戏板"""
    # board 是一个含有十个元素的列表,第一个元素不用管,只是抵消差一行为
    print("    |    |")
    print(" " + board[7] + "  | " + board[8] + "  | " + board[9])
    print(nums[7], "  |", nums[8], " |", nums[9])
    print("----------------")
    print("    |    |")
    print(" " + board[4] + "  | " + board[5] + "  | " + board[6])
    print(nums[4], "  |", nums[5], " |", nums[6])
    print("----------------")
    print("    |    |")
    print(" " + board[1] + "  | " + board[2] + "  | " + board[3])
    print(nums[1], "  |", nums[2], " |", nums[3] )
说实话,这个游戏板是真的简陋。。。。

然后就像这样依次定义出别的、各种各样的函数,这里就不一一赘述了。

再然后呢,就是游戏的主要股骨架了,其实我感觉可以先写游戏骨架,最后再进行重构,把差不多的代码整到一块,这样是不是更好呢?
# 开始,骚话问候
print("呕吼~~~~决一死战吧,大帅哥!!!!")

# 显示原始游戏板
draw_board([' ']*10, range(0, 10))
print("这个是游戏板,有点简陋哈,不过也要按编号落子呦!!!!")


# 进入游戏主循环
while True:
    # 重置游戏板
    the_board = [' '] * 10
    player_letter, computer_letter = choose_chess() # 让玩家选自棋子类型(x 或 o)
    turn = first_go() # 随机决定谁先走
    if turn == 'computer':
        print("本电脑小哥哥先走,你一边呆着去。。。")
    else:
        print("你先走吧")
    playing = True   # 设定标志,保证游戏正常进行和中断

    # 进入一局游戏的循环
    while playing:
        if turn == 'player':
            # 轮到玩家
            move = get_player_move(the_board)
            make_move(the_board, move, player_letter) # 让玩家落子

            # 显示游戏板
            draw_board(the_board) 
            
            if is_winner(the_board, player_letter):
                # 判断是否获胜
                print("卧槽,你竟然赢了T_T\n我不服,敢不敢再来一局!?")
                playing = False
                
            elif is_full_board(the_board):
                # 判断是否平局(游戏板全装满,胜负未分)
                print("你的实力也就只配跟我打个平局吧,哼!¬︿̫̿¬")
                playing = False
                
            else:
                # 轮到电脑
                turn = 'computer'
        else:
            # 轮到电脑
            # 算法计算最佳落子位置
            move = get_computer_move(the_board, computer_letter)    
            make_move(the_board, move, computer_letter) # 让电脑落子

            # 显示游戏板
            draw_board(the_board)
            
            if is_winner(the_board, computer_letter):
                # 判断是否获胜
                print("呕吼,你怎么输了呢,大帅哥!!!\n啊哈哈哈哈哈~~~///(^v^)\\\~~~")
                playing = False
                
            elif is_full_board(the_board):
                # 判断是否平局
                print("你的实力也就只配跟我打个平局吧,哼!¬︿̫̿¬")
                playing = False
                
            else:
                # 轮到玩家
                turn = 'player'

    # 玩家是否要再玩一次,注意这里的缩进
    if not play_again():
        break

# 游戏结束,表达依依不舍之情
print("大帅哥,记着常来找我玩啊!!!(>人<)")

差不多就是这亚子了。

我把剩下的代码也放的这里吧,如果哪里做的还是不是很好,请在评论区留下宁宝贵的建议(此处身体弯成90度)
def choose_chess():
    """让玩家选择棋子类型"""
    print("\n请选择宁心仪的棋子类型(x 或 y) (反正选啥都得输,(¬︿̫̿¬☆))")
    letter = input().upper()
    # 防止玩家选别的字母
    while not (letter == 'X' or letter == 'Y'):
        print("骚凹瑞!宁只能在 X 和 Y 中选择一个呦!!!!")
        letter = input().upper()
    
    # 返回一个列表,第一个元素为玩家的棋子,第二个为电脑的棋子
    if letter == 'X':
        return ['X', 'Y']
    else:
        return ['Y', 'X']


def first_go():
    """随机决定谁先走"""
    if random.randint(0, 1) == 0:
        return 'player'
    else:
        return 'computer'


def is_free(board, move):
    """判断某位置是否为空, 如果为空就返回True"""
    copy = board[:] # 注意这里使用列表复制,防止更改原列表
    return copy[move] == ' '

    
def get_player_move(board):
    """获得玩家的落子位置"""
    print("\n大帅哥,到你了。请输入:(1 - 9)")
    print("快点!我还想早点把你打得落花流水呢!!!")
    move = input()

    # 确保玩家的输入合法
    while not ((move in [str(i) for i in range(1, 10)]) or is_free(board, int(move))): 
        print("你咋不按规矩出牌呢。。。")
        print("请重新输入吧!")
        move = input()
    return int(move)


def make_move(board, move, letter):
    """根据所给位置落子"""
    board[move] = letter # 注意这里能修改局部变量board[move] 的原因, 列表引用


def is_winner(bo, le):
    """判断玩家或电脑是否获胜"""
    # 用 bo 代替 board、le 代替 letter,比较方便
    return ((bo[7] == le and bo[8] == le and bo[9] == le) or # 判断最上面一行是否一致
            (bo[4] == le and bo[5] == le and bo[6] == le) or # 判断中间一行
            (bo[1] == le and bo[2] == le and bo[3] == le) or # 判断最下面一行
            (bo[7] == le and bo[4] == le and bo[1] == le) or # 判断最左边一列
            (bo[8] == le and bo[5] == le and bo[2] == le) or # 判断中间一列
            (bo[9] == le and bo[6] == le and bo[3] == le) or # 判断最右边一列
            (bo[7] == le and bo[5] == le and bo[3] == le) or # 判断主对角线
            (bo[1] == le and bo[5] == le and bo[9] == le)) # 判断副对角线


def is_full_board(board):
    """判断游戏板是否全装满,即是否平局"""
    copy = board[:]
    is_full = True
    
    for i in range(1, 10):
        if copy[i] == ' ':
            is_full = False
    return is_full


def get_computer_move(board, computer_letter):
    """计算最佳落子位置"""
    print("\n到我了,你离死亡不远了,啊哈哈哈哈(发出小月般的笑声)")
    if computer_letter == 'X':
        player_letter = 'Y'
    else:
        player_letter = 'X'

    # 通过模拟,判断是否有能让电脑获胜的位置
    for i in range(1, 10):
        copy = board[:]
        if is_free(copy, i):
            make_move(copy, i, computer_letter)
            if is_winner(copy, computer_letter):
                return i

    # 通过模拟,判断是否有能阻止玩家获胜的位置
    for i in range(1, 10):
        copy = board[:]
        if is_free(copy, i):
            make_move(copy, i, player_letter)
            if is_winner(copy, player_letter):
                return i

    # 判断是否还有角角是空的
    move = []
    for i in [1, 3, 7, 9]:
        if is_free(board, i):
            move.append(i)
    if move:
        return random.choice(move)

    # 判断中心是否是空的
    if is_free(board, 5):
        return 5

    # 判断剩余位置(每条边的中间)是否为空
    move = []
    for i in [2, 4, 6, 8]:
        if is_free(board, i):
            move.append(i)
    if move:
        return random.choice(move)


def play_again():
    """询问玩家是否要再玩一次"""
    print("\n再来一局呗!!!!(❤ ω ❤)")
    print("请输入: (yes or no)")
    return input().lower().startswith('y')

咸小鱼一号:What!!!!!!小先生二号,你这代码西一块东一块的着实把我整懵了。。。。

咸小鱼二号:那我要不再整个发一遍吧

咸小鱼一号:..............

(写在最后:感谢每一位在咸小鱼成长道路上每一位帮助过咸小鱼的人

等等,再让我说一句,如果大家需要这本《python游戏编程快速上手》的话,可以在评论区留言或者私信我哦!!!

不说了,要上课了 ,拜拜啦

井字棋游戏.zip

2.64 KB, 下载次数: 34

评分

参与人数 3荣誉 +14 鱼币 +11 贡献 +7 收起 理由
Stubborn + 4 + 3 + 3 鱼C有你更精彩^_^
liuzhengyuan + 5 + 3 + 1 真厉害
qiuyouzhi + 5 + 5 + 3 鼓励一下~~

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-3-16 14:10:41 | 显示全部楼层

回帖奖励 +1 鱼币

前排支持楼主!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2020-3-16 14:13:27 | 显示全部楼层

谢谢宁,第一次写作品展示贴,还以为没人看呢(嘿嘿)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2020-3-16 14:15:09 | 显示全部楼层

回帖奖励 +1 鱼币

加个界面就更好了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-16 14:18:56 | 显示全部楼层

嗯嗯,我努力学学,嘿嘿
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-16 14:19:59 | 显示全部楼层
时荒小先生 发表于 2020-3-16 14:18
嗯嗯,我努力学学,嘿嘿

加油!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-16 14:32:45 | 显示全部楼层

回帖奖励 +1 鱼币

逐渐小月化,加油
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-16 14:40:01 | 显示全部楼层

嘿嘿谢谢宁
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-16 14:52:24 | 显示全部楼层

回帖奖励 +1 鱼币

有意思
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-16 15:13:40 | 显示全部楼层

回帖奖励 +1 鱼币

博主太可爱了吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-16 15:52:37 | 显示全部楼层

回帖奖励 +1 鱼币

有意思
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-16 18:26:13 | 显示全部楼层

回帖奖励 +1 鱼币

这个是不会赢得吗?我完了好几局都没赢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-16 19:23:37 | 显示全部楼层
liuzhengyuan 发表于 2020-3-16 18:26
这个是不会赢得吗?我完了好几局都没赢

可以吧,虽然我也没赢几下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-16 19:30:17 | 显示全部楼层
时荒小先生 发表于 2020-3-16 19:23
可以吧,虽然我也没赢几下

游戏有 Bug,可以走自己或电脑走过的地方
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-16 20:20:06 | 显示全部楼层
一个账号 发表于 2020-3-16 19:30
游戏有 Bug,可以走自己或电脑走过的地方

啊???我都没试过走已经走过的地方,我赶紧改改
谢谢宁提醒了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-16 20:34:32 | 显示全部楼层
一个账号 发表于 2020-3-16 19:30
游戏有 Bug,可以走自己或电脑走过的地方

懂了,get_player_move函数有点问题,那个while语句可以改成这个
while (move not in [str(i) for i in range(1, 10)]) or (not is_free(board, int(move))):
我原来那个虽然not 只有一个,可是我加括号了呀
while not ((move in [str(i) for i in range(1, 10)]) or is_free(board, int(move))):
这个有点懵,那个is_free函数是空的时候返回True
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-16 20:52:33 | 显示全部楼层

回帖奖励 +1 鱼币

楼主有电子资源吗,小弟求一手1322055350@qq.com.另外,刚刚试了一下楼主的代码,出现了棋子可重复,而且九宫格的数字对应不是很清楚
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-16 21:26:20 | 显示全部楼层
beatlemay 发表于 2020-3-16 20:52
楼主有电子资源吗,小弟求一手.另外,刚刚试了一下楼主的代码,出现了棋子可重复,而且九宫格的数字对应不 ...

链接:https://pan.baidu.com/s/1Do7VKvyjQ755AzcQVU2-ZQ
提取码:rwsv

顺带安利一个网站:偶书,上面有好多资源都可免费下载

如果对你有用的话,麻烦好评支持一下呗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2020-3-16 23:06:34 | 显示全部楼层

回帖奖励 +1 鱼币

纯文字,好有耐心啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-17 08:25:46 | 显示全部楼层

回帖奖励 +1 鱼币

  want《python游戏编程快速上手》
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-26 08:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表