您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

python 2048游戏源码

时间:2019-10-10 10:30:28  来源:  作者:

import random

import curses

# 一开始生成两个方块

STARTUP_TILES = 2

# 随机生成的方块中出现4的概率

FOUR_POSSIBILITY = 0.1

# 游戏板

BOARD = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

# 游戏分数

SCORE = 0

# 是否有2048

HAS_2048 = False

# 是否已经不能动了

IS_STUCK = False

# 是否已经问过是否需要继续游戏了

ASKED_FOR_CONTINUE = False

# 方向

LEFT, RIGHT, UP, DOWN = 0, 1, 2, 3

# 用来代表是否可以结束游戏的常量

CAN_END = True

VECTOR = [[-1, 0], [1, 0], [0, -1], [0, 1]]

SUCCESS = True

FAILED = False

# curses相关

SCREEN = None

def clip(num, lowerbound, upperbound):

if num < lowerbound:

return lowerbound

elif num > upperbound:

return upperbound

else:

return num

def print_score():

global SCREEN

SCREEN.addstr(9, 0, ''.join(['本场游戏结束,得分:', str(SCORE), '。']))

def print_prompt(prompt):

global SCREEN

SCREEN.addstr(10, 0, prompt)

def get_user_input(prompt, requested_input):

global SCREEN

error_prompt_str = ''.join(

['请输入', ','.join([str(x) for x in requested_input]), '的其中之一。'])

print_prompt(prompt)

user_input = SCREEN.getkey()

while user_input not in requested_input:

print_prompt(error_prompt_str)

user_input = SCREEN.getkey()

return user_input

def get_random_tile_number():

return 4 if random.random() <= FOUR_POSSIBILITY else 2

def get_empty_pos():

result = []

for y, row in enumerate(BOARD):

for x, _ in enumerate(row):

if BOARD[y][x] == 0:

result.Append((x, y))

return result

def get_random_empty_pos():

# 因为get_empty_pos返回的是(x, y),对应横坐标(也就是列数)和横坐标(行数)

try:

col, row = random.choice(get_empty_pos())

return row, col

except IndexError:

return None

def gen_tile():

pos = get_random_empty_pos()

if pos is None:

return FAILED

row, col = pos

number = get_random_tile_number()

BOARD[row][col] = number

return SUCCESS

# 开始新游戏

def new_game():

global BOARD, SCORE, HAS_2048, IS_STUCK, ASKED_FOR_CONTINUE

# 将板和分数清空

BOARD = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

SCORE = 0

HAS_2048 = False

IS_STUCK = False

ASKED_FOR_CONTINUE = False

# 随机生成起始方块

for _ in range(STARTUP_TILES):

gen_tile()

while True:

print_board()

check_board()

if HAS_2048 and not ASKED_FOR_CONTINUE:

user_choice = get_user_input(

'你合并出了2048!还要继续吗?(输入Y继续,输入Q结束这盘游戏)[Y/Q]:',

['Y', 'Q', 'y', 'q']

)

if user_choice in 'yY':

print_prompt('好的,继续游戏……')

ASKED_FOR_CONTINUE = True

elif user_choice in 'qQ':

print_prompt('好的,结束游戏……')

break

elif IS_STUCK:

break

# 取用户输入

direction = get_user_input(

'请按方向键移动方块。(按Q放弃本盘游戏)',

['KEY_UP', 'KEY_DOWN', 'KEY_LEFT', 'KEY_RIGHT', 'Q', 'q']

)

if direction in 'qQ':

break

elif direction == 'KEY_LEFT':

direction = LEFT

elif direction == 'KEY_RIGHT':

direction = RIGHT

elif direction == 'KEY_UP':

direction = UP

elif direction == 'KEY_DOWN':

direction = DOWN

moved_result = move_tile(direction)

if moved_result:

gen_tile()

print_score()

# 这里是这样:整块板分为(1)顶部的边框和(2)数字和数字下面的边框。

# 横向同理,分为(1)左边的边框和(2)数字和数字右边的边框。

def print_board():

# 顶部边框

SCREEN.addstr(0, 0, '+----+----+----+----+')

for y, row in enumerate(BOARD):

# 左边边框

SCREEN.addstr(y * 2 + 1, 0, '|')

# the number

for x, num in enumerate(row):

# 我们用0表示当前位置没有方块

numstr = str(num) if num != 0 else ''

SCREEN.addstr(y * 2 + 1, x * 5 + 1, numstr +

(' ' * (4 - len(numstr))) + '|')

# 数字下面的边框

SCREEN.addstr(y * 2 + 2, 0, '+----+----+----+----+')

def move_tile(direction):

global SCORE

def get_line(offset: int, direction: int):

'''

取direction上offset一行/列的所有方块。例如,当需要将第2行左移时,用

get_line(1, LEFT)获得这一行。

'''

global BOARD

if direction == LEFT:

return BOARD[offset]

elif direction == RIGHT:

return list(reversed(BOARD[offset]))

elif direction == UP:

return [BOARD[y][offset] for y in range(4)]

elif direction == DOWN:

return [BOARD[y][offset] for y in range(3, -1, -1)]

def put_line(line: list, offset: int, direction: int):

'''

将一条方块按照direction所指的方向放进游戏板中。

'''

global BOARD

if direction == LEFT:

BOARD[offset] = line

elif direction == RIGHT:

BOARD[offset] = list(reversed(line))

elif direction == UP:

for y in range(4):

BOARD[y][offset] = line[y]

elif direction == DOWN:

for y in range(4):

BOARD[y][offset] = line[3 - y]

def move(line: list):

'''

移动一条方块。

'''

new_line = []

gained_score = 0

i = 0

while i < 4:

if line[i] == 0:

i += 1

else:

old_tile = line[i]

i += 1

while i < 4 and line[i] == 0:

i += 1

if i >= 4 or line[i] != old_tile:

new_line.append(old_tile)

else:

gained_score += line[i] + old_tile

new_line.append(line[i] + old_tile)

i += 1

while len(new_line) < 4:

new_line.append(0)

# 这里有三种情况:

# 1. 移动不了。

# 2. 移动了,但是没有得分。

# 3. 移动了,也得分了。

# 在这里,出现第一种情况时返回None,第二/三种情况返回移动好的方块和

# 本次移动获得的分。

if new_line == line:

return None

else:

return new_line, gained_score

board_moved = False

for offset in range(4):

line = get_line(offset, direction)

moved_line = move(line)

if moved_line is not None:

board_moved = True

line, gained_score = moved_line

put_line(line, offset, direction)

SCORE += gained_score

put_line(line, offset, direction)

# 在这里,对于整个游戏板,有两种情况:

# 1. 有至少一行/一列移动了。

# 2. 没有。全部都没有移动。

# 在第二种下是不应该生成新的方块的。在这里返回游戏板有没有移动:

return board_moved

def get_neighbour(x, y, width, height):

global VECTOR

result = []

for vec in VECTOR:

new_x = x + vec[0]

new_y = y + vec[1]

if 0 <= new_x < width and 0 <= new_y < height:

result.append((new_x, new_y))

return result

def check_board():

global BOARD, HAS_2048, IS_STUCK

for y, row in enumerate(BOARD):

for x, num in enumerate(row):

# 如果有2048,那么就记住有2048。

if num == 2048:

HAS_2048 = True

return

# 如果有空位,那么就可以继续移动。

elif num == 0:

IS_STUCK = False

return

else:

for new_x, new_y in get_neighbour(x, y, 4, 4):

if BOARD[new_y][new_x] == num:

IS_STUCK = False

return

IS_STUCK = True

return

def main(stdscr):

global SCREEN

SCREEN = stdscr

while True:

SCREEN.clear()

new_game()

user_choice = get_user_input(

'是否开始下一盘?(输入Y开始下一盘,输入Q退出)[Y/Q]', ['Y', 'Q', 'y', 'q'])

if user_choice in 'qQ':

print_prompt('正在退出……')

break

elif user_choice in 'yY':

print_prompt('开始下一盘……')

continue

# don't start the thing when loading in interactive mode.

if __name__ == '__main__':

curses.wrapper(main)



Tags:python 2048游戏   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
import randomimport curses# 一开始生成两个方块STARTUP_TILES = 2# 随机生成的方块中出现4的概率FOUR_POSSIBILITY = 0.1# 游戏板BOARD = [[0, 0, 0, 0], [0, 0, 0, 0], [...【详细内容】
2019-10-10  Tags: python 2048游戏  点击:(86)  评论:(0)  加入收藏
▌简易百科推荐
大家好,我是菜鸟哥,今天跟大家一起聊一下Python4的话题! 从2020年的1月1号开始,Python官方正式的停止了对于Python2的维护。Python也正式的进入了Python3的时代。而随着时间的...【详细内容】
2021-12-28  菜鸟学python    Tags:Python4   点击:(1)  评论:(0)  加入收藏
学习Python的初衷是因为它的实践的便捷性,几乎计算机上能完成的各种操作都能在Python上找到解决途径。平时工作需要在线学习。而在线学习的复杂性经常让人抓狂。费时费力且效...【详细内容】
2021-12-28  风度翩翩的Python    Tags:Python   点击:(1)  评论:(0)  加入收藏
Python 是一个很棒的语言。它是世界上发展最快的编程语言之一。它一次又一次地证明了在开发人员职位中和跨行业的数据科学职位中的实用性。整个 Python 及其库的生态系统使...【详细内容】
2021-12-27  IT资料库    Tags:Python 库   点击:(2)  评论:(0)  加入收藏
菜单驱动程序简介菜单驱动程序是通过显示选项列表从用户那里获取输入并允许用户从选项列表中选择输入的程序。菜单驱动程序的一个简单示例是 ATM(自动取款机)。在交易的情况下...【详细内容】
2021-12-27  子冉爱python    Tags:Python   点击:(4)  评论:(0)  加入收藏
有不少同学学完Python后仍然很难将其灵活运用。我整理15个Python入门的小程序。在实践中应用Python会有事半功倍的效果。01 实现二元二次函数实现数学里的二元二次函数:f(x,...【详细内容】
2021-12-22  程序汪小成    Tags:Python入门   点击:(32)  评论:(0)  加入收藏
Verilog是由一个个module组成的,下面是其中一个module在网表中的样子,我只需要提取module名字、实例化关系。module rst_filter ( ...); 端口声明... wire定义......【详细内容】
2021-12-22  编程啊青    Tags:Verilog   点击:(9)  评论:(0)  加入收藏
运行环境 如何从 MP4 视频中提取帧 将帧变成 GIF 创建 MP4 到 GIF GUI ...【详细内容】
2021-12-22  修道猿    Tags:Python   点击:(6)  评论:(0)  加入收藏
面向对象:Object Oriented Programming,简称OOP,即面向对象程序设计。类(Class)和对象(Object)类是用来描述具有相同属性和方法对象的集合。对象是类的具体实例。比如,学生都有...【详细内容】
2021-12-22  我头秃了    Tags:python   点击:(9)  评论:(0)  加入收藏
所谓内置函数,就是Python提供的, 可以直接拿来直接用的函数,比如大家熟悉的print,range、input等,也有不是很熟,但是很重要的,如enumerate、zip、join等,Python内置的这些函数非常...【详细内容】
2021-12-21  程序员小新ds    Tags:python初   点击:(5)  评论:(0)  加入收藏
Hi,大家好。我们在接口自动化测试项目中,有时候需要一些加密。今天给大伙介绍Python实现各种 加密 ,接口加解密再也不愁。目录一、项目加解密需求分析六、Python加密库PyCrypto...【详细内容】
2021-12-21  Python可乐    Tags:Python   点击:(8)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条