charlian 发表于 2022-6-14 17:06

python猜数字游戏

本帖最后由 charlian 于 2022-6-15 13:39 编辑

from os import write
import random
from statistics import mode
import string
import os
import pyautogui

# 根据游戏级别埋藏数字
def burynumber(lv):
    number = 0
    for i in range(10):
      if i + 1 == lv:
            number = random.randint(1, lv * 100)
    return number

#根据游戏积分提升游戏级别
def uplevel(integral):
    lv = 1
    for i in range(10):
      if integral >= 100:
            lv = 10
            break
      elif integral >= (lv + i) * 10 and integral <= (lv + i + 1) * 10:
                lv = lv + i
    return lv

# 游戏说明
def gamecaption():
    print("游戏时可输入以下游戏指令:")
    print("exit 或 quit 退出游戏(不保存游戏数据)。")
    print("save 保存游戏数据的同时退出游戏。")
    print('reset 游戏数据重置。')
    print("hint,消耗5点游戏积分购买埋藏数字区间提示(上下区间均为1~25)。")
    print("buy,消耗2点游戏积分购买额外猜数次数(未消耗永久有效),额外猜数次数上限为10次,需消耗低于10次才能再次购买。")
    print("buy2,消耗10点游戏积分购买永久猜数次数(永久有效),永久猜数次数上限为3次。")
    print("cls,清空屏幕!\n")

def game():
    bret = 0
    try:
      f = open("gamedata.txt")
      bret = True
      f.close()
    except IOError:
      bret = False
      print("游戏数据为空,新建游戏数据……")
      f = open("gamedata.txt", 'w')
      f.close()
    integral = 10# 游戏积分,初始为10
    ncount = 10# 猜数字次数,初始为10
    lv = 1# 游戏级别,初始为1
    gamestate = 0# 游戏状态,根据不同值处理不同事件    1:保存游戏数据退出游戏 2:不玩了 3:游戏积分小于0 GAME OVER 4:游戏数据重置 重新开始
    buyncount = 0# 额外猜数次数,初始为0,未消耗永久有效
    buyncount2 = 0# 额外永久猜数次数,初始为0,永久有效
    num = ' '# 猜的数字
    count = 0# 第几轮猜数游戏
    if bret == False:
      # 文件不存在,写入初始数据
      integral_str = '游戏积分:' + '%d' % integral
      lv_str = '游戏级别:' + '%d' % lv
      buyncount_str = '额外猜数次数:' + '%d' % buyncount
      buyncount2_str = '额外永久猜数次数:' + '%d' % buyncount2
      with open("gamedata.txt", "w") as f:
            f.write(integral_str)
            f.write('\n')
            f.write(lv_str)
            f.write('\n')
            f.write(buyncount_str)
            f.write('\n')
            f.write(buyncount2_str)
            f.write('\n')
            f.close()
    else:
      # 读取游戏数据
      with open("gamedata.txt", 'r') as f:
            str = f.readlines()
            f.close()
            # print(str)
            integral_str = str.split(':').replace('\n', '')
            lv_str = str.split(':').replace('\n', '')
            buyncount_str = str.split(':').replace('\n', '')
            buyncount2_str = str.split(':').replace('\n', '')
            # print('游戏积分:%s' % integral_str)
            # print('游戏级别:%s' % lv_str)
            # print('额外猜数次数:%s' % buyncount_str)
            # print('额外永久猜数次数:%s' % buyncount_str)
            integral = int(integral_str)
            lv = int(lv_str)
            buyncount = int(buyncount_str)
            buyncount2 = int(buyncount2_str)

    while integral >= 0:
      count += 1
      print('\n-----------------------第%d轮猜数游戏-----------------------' % count)
      gamecaption()
      ncount = 10
      lv = uplevel(integral)
      print('您目前游戏积分:%d' % integral)
      print('您目前游戏级别:%d' % lv)
      print('您目前额外猜数次数:%d' % buyncount)
      print('您目前永久猜数次数:%d' % buyncount2)
      number = burynumber(lv)
       # print("埋藏的数字为:%d" % number)
      if buyncount != 0:
            ncount += buyncount
      if buyncount2 != 0:
            ncount += buyncount2
      print('您目前游戏级别:%d级,游戏积分达到升级条件时会自动升级,游戏级别限制为10级' % lv)
      print('已埋藏好数字,数字区间范围在1~%d之间,您有%d次猜数次数。\n猜对奖励10点游戏积分,未猜对扣除1点游戏积分。'
            '\n每轮猜数游戏结束将判定游戏积分,游戏积分低于0,则GAME OVER!' % (
                  lv * 100, ncount))
      while ncount != 0:
            print('剩余猜数次数:%d' % ncount)
            num = input('请猜数:')
            if num == 'buy':
                n = int(input('2点游戏积分 / 额外猜数次数,您想买多少次:'))
                if n * 2 <= integral:
                  if buyncount + n > 10:
                        if buyncount + n < 10:
                            print('购买失败!额外猜数次数存储上限为10次!您目前额外猜数次数:%d,还可购买%d次额外猜数次数' % (buyncount, 10 - buyncount))
                        else:
                            print('您目前额外猜数次数已达上限,无法继续购买!')
                  else:
                        if integral - n * 2 < 11:
                            print('购买失败!请预留至少10点游戏积分!您目前游戏积分:%d' % integral)
                        else:
                            integral -= n * 2
                            buyncount += n
                            ncount += buyncount
                            print('您消耗%d点游戏积分购买%d次额外猜数次数,您目前游戏积分:%d' % (n * 2, n, integral))
                else:
                  print('游戏积分不足,购买失败!')
            if num == 'buy2':
                n = int(input('请输入购买次数, 10点游戏积分 / 额外永久猜数次数:'))
                if n * 2 <= integral:
                  if buyncount2 + n > 3:
                        print('购买失败!额外永久猜数次数存储上限为3次!您目前额外永久猜数次数:%d,还可购买%d次额外永久猜数次数' % buyncount2, 10 - buyncount2)
                  else:
                        if integral - n * 10 < n * 10 + 10:
                            print('购买失败!请预留至少10点游戏积分!您目前游戏积分:%d' % integral)
                        else:
                            integral -= n * 2
                            buyncount2 += n
                            ncount += buyncount2
                            print('您消耗%d点游戏积分购买%d次额外永久猜数次数,您目前游戏积分:%d' % (int(n) * 2, int(n), integral))
                else:
                  print('游戏积分不足,购买失败!')
            if num == 'save':
                integral_str = '游戏积分:' + '%d' % integral
                lv_str = '游戏级别:' + '%d' % lv
                buyncount_str = '额外猜数次数:' + '%d' % buyncount
                buyncount_str2 = '额外永久猜数次数:' + '%d' % buyncount2
                with open("gamedata.txt", "w") as f:
                  f.write(integral_str)
                  f.write('\n')
                  f.write(lv_str)
                  f.write('\n')
                  f.write(buyncount_str)
                  f.write('\n')
                  f.write(buyncount_str2)
                  f.write('\n')
                  f.close()
                gamestate = 1
                break
            elif num == 'exit' or num == 'quit':
                gamestate = 2
                break
            elif num == 'reset':
                gamestate = 4
                os.remove('gamedata.txt')
                break
            elif num == 'hint':
                min = random.randint(1, 25)
                max = random.randint(1, 25)
                number_min = number - min
                number_max = number + max
                while number_min < 0:
                  min = random.randint(1, 25)
                  number_min = number - min
                integral -= 5
                print('消耗5点游戏积分获取埋藏数字区间提示:埋藏的数字在「%d~%d」之间,剩余游戏积分:%d' % (number_min, number_max, integral))
                ncount += 1
            elif num == 'cls':
                #Pycharm 实现代码清除run标签页(程序输出)界面
                #https://blog.csdn.net/u011699626/article/details/122139919
                #pyautogui.hotkey('Alt', 'c')
                os.system('cls')
                ncount += 1
            else:
                if num.isdigit():
                  num = int(num)
                  if num < number:
                        integral -= 1
                        print('您猜的数太小了!扣除1点游戏积分,剩余游戏积分:%d' % integral)
                  elif num > number:
                        integral -= 1
                        print('您猜的数太大了!扣除1点游戏积分,剩余游戏积分:%d' % integral)
                  else:
                        integral += 10
                        print('神啦!您居然猜对了!埋藏的数确实是:%d。奖励10点游戏积分,剩余游戏积分:%d' % (number, integral))
                        gamestate = 0
                        break
                else:
                  ncount += 1

            ncount -= 1
            if ncount == 0:
                if buyncount != 0:
                  buyncount = 0
                print('很遗憾!您没有猜对数字!埋藏的数字为:%d' % number)
            else:
                n = ncount - buyncount
                if n == 0 and buyncount != 0:
                  buyncount -= 1
            if integral < 0:
                gamestate = 3
      if gamestate == 1:
            print('游戏数据已保存,ByeBye!')
            break
      elif gamestate == 2:
            print('ByeBye!')
            break
      elif gamestate == 3:
            print('您的游戏积分小于0,GAME OVER!')
            break
      elif gamestate == 4:
            print('游戏数据已重置,请重新打开游戏!')
            break


if __name__ == "__main__":
    game()

修复了2个小bug,已打包成exe,可直接运行。
下载地址:
https://wwt.lanzoum.com/iVs6X06g1dsf
密码:h1ms

hans7 发表于 2022-7-23 02:28

我试着逆了一下lz的exe,过程挺曲折的,在此贴出供参考。首先
python pyinstxtractor.py 猜数字游戏.exe
可以看到pyinstxtractor为我们分析出了可能的入口文件:[+] Possible entry point: 猜数字游戏.pyc。接着
uncompyle6 猜数字游戏.pyc > 猜数字游戏.py
报错`ValueError: bad marshal data (unknown type code)`。百度可知解决方案:

`struct.pyc`的magic number肯定是对的,以它为准,替换掉`猜数字游戏.pyc`的magic number即可。

接下来发现这个pyc是python3.10的,所以我们要换用pycdc工具。
./pycdc 猜数字游戏.pyc > 1.py
我们遇到了以下异常:`Unsupported opcode: JUMP_IF_NOT_EXC_MATCH`。反编译得到的代码很少。
根据参考链接1,我们给不支持的opcode加上对应的处理代码,就可以让程序不退出了。
ASTree.cpp
      // temporary solution
      case Pyc::JUMP_IF_NOT_EXC_MATCH_A:
      case Pyc::RERAISE_A:
      case Pyc::WITH_EXCEPT_START:
            break;
但是这种做法得到的代码错误太多了,并不可靠。如果想进行下一步的分析,只能:
1. 等pycdc的维护者更新代码。
2. 成为pycdc的维护者&#128545;。
3. 用pycdas拿到反汇编码,自己读:`./pycdas 猜数字游戏.pyc > 1.txt`。

最后我看了一下得到的代码,基本上和lz给出的源码吻合。

neteast 发表于 2022-7-24 08:55

非常感谢提供的代码,我学习了一下。
# 根据游戏级别埋藏数字
def burynumber(lv):
    number = 0
    for i in range(10):
      if i + 1 == lv:
            number = random.randint(1, lv * 100)
    return number

不知道这个for循环的意义是什么。

ytlk0535 发表于 2022-6-14 18:49

感谢分享,页面能有独立的窗口就更好了

liu2514 发表于 2022-6-14 18:58

猜数游戏还能这样玩,学习了!感谢大佬热心分享!在我的记忆中猜数游戏是“PYTHON从入门到精通”里的那个小小游戏,是我肤浅了。。。

XiaoZouYu 发表于 2022-6-14 19:47

liu2514 发表于 2022-6-14 18:58
猜数游戏还能这样玩,学习了!感谢大佬热心分享!在我的记忆中猜数游戏是“PYTHON从入门到精通”里的那个小 ...

同,我也以为是哪个

alongzhenggang 发表于 2022-6-14 20:31

xxxxx小小学习下寻Thanks♪(・ω・)ノ

pojieit 发表于 2022-6-14 21:33

有没有编译好的哇?

arq2020 发表于 2022-6-14 22:43

拿回去跑跑,谢谢了

kongdang1 发表于 2022-6-14 23:18

非常不错,值得学习

sdrzlg1987 发表于 2022-6-15 08:13

这个还是用易语言 VB做比较友好

uouobb 发表于 2022-7-5 17:27

本帖最后由 uouobb 于 2022-7-5 17:29 编辑

请猜数:100
您猜的数太小了!扣除1点游戏积分,剩余游戏积分:12
剩余猜数次数:1
请猜数:

是级别问题。。。
页: [1] 2
查看完整版本: python猜数字游戏