zoukankan      html  css  js  c++  java
  • Python学习笔记(一):命令行界面扫雷(详细)

    起因

    因为最近刚刚开始学习Python,想编点东西来熟悉一下语法,想起来之前用C语言编过一个简单的命令行界面的扫雷,故用Python来重新编一个,大致效果如下图,我会在文章中梳理一下我当时的大致思路。
    最终效果

    过程

    首先我们需要构建出来一个雷阵,我们需要的参数有两个,一个是雷阵的大小,另一个就是雷数。

        n = eval(input("请输入雷阵的大小"))
        m = eval(input("请输入雷的个数"))
    

    我们首先要定义一个二维数组(行列数应比雷阵大一“圈”)

        mine = [([0] * (n + 2)) for i in range(0, n + 2)]  # 雷阵
    

    因为我们需要一个数组给玩家看,所以需要再定义一个一样大数组,而且该数组到时候需要判断是否开过雷,为防止函数运用到数组之外的地方,因此数组最外一圈初始化为0.

        user = [(['#'] * (n + 2)) for i in range(0, n + 2)]  # 用户
        for i in range(0, n+2):
            user[0][i] = 0
            user[n + 1][i] = 0
            user[i][0] = 0
            user[i][n + 1] = 0
    

    之后,我们就可以初始化 雷阵 了,该过程需要埋下雷,和使不是雷的方块可以显示四周方块中雷的个数

    def build(list1, num1, num2):    # 雷阵初始化
        i = 0                        # list1为雷阵,num1为雷阵大小,num2为雷数
        while i < num2:              # 循环布雷
            m = randint(1, num1)
            n = randint(1, num1)
            if list1[m][n] != '*':
                list1[m][n] = '*'
                i += 1
            else:
                continue
        for m in range(1, num1 + 1):            # 为每一个非雷方块确定周围的雷数
            for n in range(1, num1 + 1):        # m代表数组的行数,n代表列数
                if list1[m][n] != '*':
                    if list1[m - 1][n - 1] == '*':
                        list1[m][n] += 1
                    if list1[m - 1][n] == '*':
                        list1[m][n] += 1
                    if list1[m - 1][n + 1] == '*':
                        list1[m][n] += 1
                    if list1[m][n - 1] == '*':
                        list1[m][n] += 1
                    if list1[m][n + 1] == '*':
                        list1[m][n] += 1
                    if list1[m + 1][n - 1] == '*':
                        list1[m][n] += 1
                    if list1[m + 1][n] == '*':
                        list1[m][n] += 1
                    if list1[m + 1][n + 1] == '*':
                        list1[m][n] += 1
    

    之后我们就有了一个已经布好了雷的雷阵。接下去我们需要一个函数,它可以帮我们把我们打印出我们输出数组。因为游戏进行的过程中需要用到横纵坐标,因此我们在输出数组的时候,用第一排和第一列来表示横纵坐标。而且输出数组的时候出于美观,将0输出为空格。

    def print_mine(list2, num):             # list2为要输出的数组,num为数组的大小
        for m in range(0, num + 1):
            for n in range(0, num + 1):
                if m == 0:                  # 横坐标
                    print(n, end='  ')
                    continue
                if n == 0:                  # 纵坐标
                    print(m, end='  ')
                    continue
                if list2[m][n] == 0:        # 将对应为0的元素用空格代替
                    print('  ', end=' ')
                else:
                    print(list2[m][n], end='  ')
            print('')
    

    OK,现在我们就可以编写进行游戏的部分了。我们将进行游戏的主体部分交给函数来处理,这里命名为win,此函数的主要功能就是判断胜负,和进行游戏,其中落子的部分由play函数来处理。所以此函数需要自我调用,这里用flag== 0来表示输了,随即结束游戏;flag==1表示游戏可以继续进行。

    def win(list_user, list_mine, num, flag, mine):        # 判断胜负
        i = 0                                              # num为数组的大小,mine为雷数
        print_mine(list_user, num)
        if flag == 1:                                      # 继续游戏
            for m in range(0, num+2):
                for n in range(0, num+2):
                    if list_user[m][n] == "#" or list_user[m][n] == '@':
                        i += 1
            if i == mine:                                  # 当数组中未展开或者标记的元素等于雷数,宣布胜利
                print("你赢了!")   
                return 1
            else:
                a = play(list_user, list_mine, num)        # 进行一次落子
                win(list_user, list_mine, num, a, mine)    # 进行下一次判断
        else:                                              # 游戏结束
            print("你输了!")
            return 0
    

    接下来编写play函数,play函数的功能有落子和标记,落子后需要判断落到的地方是否为雷,若不是,则调用open函数进行开雷处理;若是,则返回0。

    def play(list_user, list_mine, num):                 # 落子函数
        m = input("请输入横坐标(需要标记请按@)")
        n = input("请输入纵坐标(需要标记请按@)")
        if m == '@' or n == '@':                         # 触发标记功能
            m1 = eval(input("请输入要标记的横坐标"))
            n1 = eval(input("请输入要标记的纵坐标"))
            list_user[m1][n1] = '@'
            print_mine(list_user, num)
            play(list_user, list_mine, num)
            return 1
        elif int(m) > num or int(n) > num:               # 数据不合理重新输入
            print("请重新输入")
            play(list_user, list_mine, num)
            return 1
        else:
            if list_mine[int(m)][int(n)] == '*':         # 踩雷了
                return 0
            else:
                open_user(list_user, list_mine, int(m), int(n))    # 开雷
                return 1
    
    

    然后进行开雷函数的编写,开雷函数是将user数组中的’#'显示成mine数组中对应元素的数值,若为0,则向四周执行open函数,达到开雷的效果。

    def open_user(list_user, list_mine, m, n):                    # 开雷函数
        if list_user[m][n] == '#' or list_user[m][n] == '@':
            if list_mine[m][n] == 0:
                list_user[m][n] = list_mine[m][n]
                open_user(list_user, list_mine, m - 1, n - 1)     # 向四周扩散
                open_user(list_user, list_mine, m - 1, n)
                open_user(list_user, list_mine, m - 1, n + 1)
                open_user(list_user, list_mine, m, n + 1)
                open_user(list_user, list_mine, m, n - 1)
                open_user(list_user, list_mine, m + 1, n - 1)
                open_user(list_user, list_mine, m + 1, n)
                open_user(list_user, list_mine, m + 1, n + 1)
            else:
                list_user[m][n] = list_mine[m][n]
    

    最后,因为想不结束程序而重新进入游戏,所以将游戏初始化的部分设置为一个函数。

    def begin():                                             # 游戏进行
        n = eval(input("请输入雷阵的大小"))
        m = eval(input("请输入雷的个数"))
        mine = [([0] * (n + 2)) for i in range(0, n + 2)]    # 雷阵
        user = [(['#'] * (n + 2)) for i in range(0, n + 2)]  # 用户
        for i in range(0, n+2):
            user[0][i] = 0
            user[n + 1][i] = 0
            user[i][0] = 0
            user[i][n + 1] = 0
        build(mine, n, m)
        win(user, mine, n, 1, m)
    

    最后

    begin()
    if (input("是否重来(y/n)")) == 'y':
        begin()
    

    完整代码如下

    from random import *
    
    
    def build(list1, num1, num2):    # 雷阵初始化
        i = 0                        # list1为雷阵,num1为雷阵大小,num2为雷数
        while i < num2:              # 循环布雷
            m = randint(1, num1)
            n = randint(1, num1)
            if list1[m][n] != '*':
                list1[m][n] = '*'
                i += 1
            else:
                continue
        for m in range(1, num1 + 1):            # 为每一个非雷方块确定周围的雷数
            for n in range(1, num1 + 1):        # m代表数组的行数,n代表列数
                if list1[m][n] != '*':
                    if list1[m - 1][n - 1] == '*':
                        list1[m][n] += 1
                    if list1[m - 1][n] == '*':
                        list1[m][n] += 1
                    if list1[m - 1][n + 1] == '*':
                        list1[m][n] += 1
                    if list1[m][n - 1] == '*':
                        list1[m][n] += 1
                    if list1[m][n + 1] == '*':
                        list1[m][n] += 1
                    if list1[m + 1][n - 1] == '*':
                        list1[m][n] += 1
                    if list1[m + 1][n] == '*':
                        list1[m][n] += 1
                    if list1[m + 1][n + 1] == '*':
                        list1[m][n] += 1
    
    
    def print_mine(list2, num):             # list2为要输出的数组,num为数组的大小
        for m in range(0, num + 1):
            for n in range(0, num + 1):
                if m == 0:                  # 横坐标
                    print(n, end='  ')
                    continue
                if n == 0:                  # 纵坐标
                    print(m, end='  ')
                    continue
                if list2[m][n] == 0:        # 将对应为0的元素用空格代替
                    print('  ', end=' ')
                else:
                    print(list2[m][n], end='  ')
            print('')
    
    
    def open_user(list_user, list_mine, m, n):                    # 开雷函数
        if list_user[m][n] == '#' or list_user[m][n] == '@':
            if list_mine[m][n] == 0:
                list_user[m][n] = list_mine[m][n]
                open_user(list_user, list_mine, m - 1, n - 1)     # 向四周扩散
                open_user(list_user, list_mine, m - 1, n)
                open_user(list_user, list_mine, m - 1, n + 1)
                open_user(list_user, list_mine, m, n + 1)
                open_user(list_user, list_mine, m, n - 1)
                open_user(list_user, list_mine, m + 1, n - 1)
                open_user(list_user, list_mine, m + 1, n)
                open_user(list_user, list_mine, m + 1, n + 1)
            else:
                list_user[m][n] = list_mine[m][n]
    
    
    def play(list_user, list_mine, num):                 # 落子函数
        m = input("请输入横坐标(需要标记请按@)")
        n = input("请输入纵坐标(需要标记请按@)")
        if m == '@' or n == '@':                         # 触发标记功能
            m1 = eval(input("请输入要标记的横坐标"))
            n1 = eval(input("请输入要标记的纵坐标"))
            list_user[m1][n1] = '@'
            print_mine(list_user, num)
            play(list_user, list_mine, num)
            return 1
        elif int(m) > num or int(n) > num:               # 数据不合理重新输入
            print("请重新输入")
            play(list_user, list_mine, num)
            return 1
        else:
            if list_mine[int(m)][int(n)] == '*':         # 踩雷了
                return 0
            else:
                open_user(list_user, list_mine, int(m), int(n))    # 开雷
                return 1
    
    
    def win(list_user, list_mine, num, flag, mine):        # 判断胜负
        i = 0                                              # num为数组的大小,mine为雷数
        print_mine(list_user, num)
        if flag == 1:                                      # 继续游戏
            for m in range(0, num+2):
                for n in range(0, num+2):
                    if list_user[m][n] == "#" or list_user[m][n] == '@':
                        i += 1
            if i == mine:                                  # 当数组中未展开或者标记的元素等于雷数,宣布胜利
                print("你赢了!")
                return 1
            else:
                a = play(list_user, list_mine, num)        # 进行一次落子
                win(list_user, list_mine, num, a, mine)    # 进行下一次判断
        else:                                              # 游戏结束
            print("你输了!")
            return 0
    
    
    def begin():                                             # 游戏进行
        n = eval(input("请输入雷阵的大小"))
        m = eval(input("请输入雷的个数"))
        mine = [([0] * (n + 2)) for i in range(0, n + 2)]    # 雷阵
        user = [(['#'] * (n + 2)) for i in range(0, n + 2)]  # 用户
        for i in range(0, n+2):
            user[0][i] = 0
            user[n + 1][i] = 0
            user[i][0] = 0
            user[i][n + 1] = 0
        build(mine, n, m)
        win(user, mine, n, 1, m)
    
    
    begin()
    if (input("是否重来(y/n)")) == 'y':
        begin()
    

    后记

    这是第一次在CSDN上写博客,对Python的学习也才刚刚开始,其中难免有些错误,多多包容。

    下一步的打算是使雷阵在每次操作完可以刷新,而不是重新输出一个。还有将该游戏图形化的打算。(等我学到了再说)

  • 相关阅读:
    hello word
    HDU 1006 Tick and Tick
    HDU 1005 Number Sequence
    HDU 1004 Let the Balloon Rise
    HDU 1003 Max Sum
    HDU 1002 A + B Problem II
    HDU 1001 Sum Problem
    HDU 1000 A + B Problem
    POJ 2253 Frogger
    POJ 2387 Til the Cows Come Home
  • 原文地址:https://www.cnblogs.com/cnsec/p/11879410.html
Copyright © 2011-2022 走看看