【python大作业】pygame实战(python编写2048小游戏)

编程入门 行业动态 更新时间:2024-10-06 18:25:28

【python大<a href=https://www.elefans.com/category/jswz/34/1771149.html style=作业】pygame实战(python编写2048小游戏)"/>

【python大作业】pygame实战(python编写2048小游戏)

本文介绍基于pygame编写的2048小游戏程序
包含四个文件

运行效果:

点击此处下载完整程序,下载即可运行

config.py

其中config.py用于设置游戏参数
包括游戏窗口大小,刷新率,方块颜色等

class Base:WINDOW_W = 700WINDOW_H = 550GAME_WH = 500SIZE = 4FPS = 60DEBUG = FalseCOLORS = {'0': (205, 193, 180),'2': (238, 228, 218),'4': (237, 224, 200),'8': (242, 177, 121),'16': (245, 149, 99),'32': (246, 124, 95),'64': (246, 94, 59),'128': (237, 207, 114),'256': (237, 204, 97),'512': (237, 200, 80),'1024': (237, 197, 63),'2048': (255, 0, 0)}

game

game.py中定义了游戏实现的函数,设置方块的产生,移动与计算,并判断游戏进行的程度,判断游戏是否完成或结束。

import random
import numpy as np
class Grid:size = 4tiles = []max_tile = 0def __init__(self, size=4):self.size = sizeself.score = 0self.tiles = np.zeros((size, size)).astype(np.int32)def is_zero(self, x, y):return self.tiles[y][x] == 0def is_full(self):return 0 not in self.tiles# 设置瓷砖def set_tiles(self, xy, number):self.tiles[xy[1]][xy[0]] = number# 获取一个随机的空坐标def get_random_xy(self):if not self.is_full():while 1:x, y = random.randint(0, self.size - 1), random.randint(0, self.size - 1)if self.is_zero(x, y):return x, yreturn -1, -1# 初始设置瓷砖def add_tile_init(self):self.add_random_tile()self.add_random_tile()# 添加一个随机的瓷砖def add_random_tile(self):if not self.is_full():# 产生2的概率为0.9# q = 0.9# for i in range(1,50):#     if random.random() < q or i==50-1:#         value = 2**i#         breakvalue = 2 if random.random() < 0.9 else 4self.set_tiles(self.get_random_xy(), value)def run(self, direction, is_fake=False):if isinstance(direction, int):direction = nmap[direction]self.score = 0if is_fake:t = self.tiles.copy()else:t = self.tilesif direction == 'U':for i in range(self.size):self.move_hl(t[:, i])elif direction == 'D':for i in range(self.size):self.move_hl(t[::-1, i])elif direction == 'L':for i in range(self.size):self.move_hl(t[i, :])elif direction == 'R':for i in range(self.size):self.move_hl(t[i, ::-1])return self.score# 移动某一行或某一列def move_hl(self, hl):'''移动某一行或某一列对于hl,从大往小移动:return: 移动后的列表'''len_hl = len(hl)for i in range(len_hl - 1):if hl[i] == 0:for j in range(i + 1, len_hl):if hl[j] != 0:hl[i] = hl[j]hl[j] = 0self.score += 1breakif hl[i] == 0:breakfor j in range(i + 1, len_hl):if hl[j] == hl[i]:hl[i] += hl[j]self.score += hl[j]hl[j] = 0breakif hl[j] != 0:breakreturn hl# 判断是否结束def is_over(self):if not self.is_full():return Falsefor y in range(self.size - 1):for x in range(self.size - 1):if self.tiles[y][x] == self.tiles[y][x + 1] or self.tiles[y][x] == self.tiles[y + 1][x]:return Falsereturn True# 判断是否胜利def is_win(self):if self.max_tile > 0:return self.max_tile in self.tileselse:return Falsedef __str__(self):str_ = '====================\n'for row in self.tiles:str_ += '-' * (5 * self.size + 1) + '\n'for i in row:str_ += '|{:4d}'.format(int(i))str_ += '|\n'str_ += '-' * (5 * self.size + 1) + '\n'str_ += '==================\n'return str_
nmap = {0: 'U', 1: 'R', 2: 'D', 3: 'L'}
fmap = dict([val, key] for key, val in nmap.items())
class Game:score = 0env = 'testing'state = 'start'grid = Nonedef __init__(self, grid_size=4, env='production'):self.env = envself.grid_size = grid_sizeself.start()# 开始或重新开始def start(self):self.grid = Grid(self.grid_size)if self.env == 'production':self.grid.add_tile_init()self.state = 'run'# 运行一步def run(self, direction):if self.state in ['over', 'win']:return Noneif isinstance(direction, int):direction = nmap[direction]self.grid.run(direction)self.score += self.grid.scoreif self.grid.is_over():self.state = 'over'if self.grid.is_win():self.state = 'win'# 产生新方块if self.env == 'production':self.grid.add_random_tile()return self.griddef printf(self):print(self.grid)

main

主函数,直接运行此程序即可开始游戏。
此程序负责编辑游戏界面,获取游戏输入,通过判断游戏运行状况与输入指令,通过调用以编写的函数,完成游戏的运行

config = SupperFast()
FPS = config.FPS
SIZE = config.SIZE
DEBUG = config.DEBUG
colors = config.COLORS
GAME_WH = config.GAME_WH
WINDOW_W = config.WINDOW_W
WINDOW_H = config.WINDOW_H
# 格子中的字体
font_h_w = 2 / 1
g_w = GAME_WH / SIZE * 0.9
# font = pygame.font.SysFont('microsoftyahei', 20)
class Main():def __init__(self):global FPSpygame.init()os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (100, 50)self.set_win_wh(WINDOW_W, WINDOW_H, title='2048')self.state = 'start'self.fps = FPSself.catch_n = 0self.clock = pygame.time.Clock()self.game = Game(SIZE)self.ai = Ai()self.step_time = config.STEP_TIMEself.next_f = ''self.last_time = time.time()self.start_time = time.time()self.run_time = time.time() - self.start_timeself.jm = -1def start(self):# 加载按钮self.button_list = [Button('start', '重新开始', (GAME_WH + 50, 150)),Button('ai', '电脑托管', (GAME_WH + 50, 250)),]self.run()def run(self):while self.state != 'exit':if self.game.state in ['over', 'win']:self.state = self.game.stateself.my_event()if self.next_f != '' and (self.state == 'run' or self.state == 'ai' and time.time() - self.last_time > self.step_time):self.game.run(self.next_f)self.next_f = ''self.last_time = time.time()elif self.state == 'start':self.start_time = time.time()self.game.start()self.state = 'run'self.set_bg((101, 194, 148))self.draw_info()self.draw_button(self.button_list)self.draw_map()self.draw_time()self.update()print('退出游戏')def draw_time(self):if self.state!='over' and self.state!='win':self.run_time = time.time()-self.start_timeself.draw_text('游戏时间:{}分{}秒'.format(int(self.run_time/60),int(self.run_time%60)), (GAME_WH + 10, 10))def draw_map(self):for y in range(SIZE):for x in range(SIZE):self.draw_block((x, y), self.game.grid.tiles[y][x])if self.state == 'over':pygame.draw.rect(self.screen, (0, 0, 0, 0.5),(0, 0, GAME_WH, GAME_WH))self.draw_text('游戏结束!', (GAME_WH / 2, GAME_WH / 2), size=25, center='center')elif self.state == 'win':pygame.draw.rect(self.screen, (0, 0, 0, 0.5),(0, 0, GAME_WH, GAME_WH))self.draw_text('胜利!', (GAME_WH / 2, GAME_WH / 2), size=25, center='center')# 画一个方格def draw_block(self, xy, number):one_size = GAME_WH / SIZEdx = one_size * 0.05x, y = xy[0] * one_size, xy[1] * one_size# print(colors[str(int(number))])color = colors[str(int(number))] if number <= 2048 else (0, 0, 255)pygame.draw.rect(self.screen, color,(x + dx, y + dx, one_size - 2 * dx, one_size - 2 * dx))color = (20, 20, 20) if number <= 4 else (250, 250, 250)if number != 0:ln = len(str(number))if ln == 1:size = one_size * 1.2 / 2elif ln <= 3:size = one_size * 1.2 / lnelse:size = one_size * 1.5 / lnself.draw_text(str(int(number)), (x + one_size * 0.5, y + one_size * 0.5 - size / 2), color, size, 'center')def draw_info(self):self.draw_text('分数:{}'.format(self.game.score), (GAME_WH + 50, 40))if self.state == 'ai':self.draw_text('间隔:{}'.format(self.step_time), (GAME_WH + 50, 60))self.draw_text('评分:{}'.format(self.jm), (GAME_WH + 50, 80))def set_bg(self, color=(255, 255, 255)):self.screen.fill(color)def catch(self, filename=None):if filename is None:filename = "./catch/catch-{:04d}.png".format(self.catch_n)pygame.image.save(self.screen, filename)self.catch_n += 1def draw_button(self, buttons):for b in buttons:if b.is_show:pygame.draw.rect(self.screen, (180, 180, 200),(b.x, b.y, b.w, b.h))self.draw_text(b.text, (b.x + b.w / 2, b.y + 9), size=18, center='center')def draw_text(self, text, xy, color=(0, 0, 0), size=18, center=None):font = pygame.font.SysFont('simhei', round(size))text_obj = font.render(text, 1, color)text_rect = text_obj.get_rect()if center == 'center':text_rect.move_ip(xy[0] - text_rect.w // 2, xy[1])else:text_rect.move_ip(xy[0], xy[1])# print('画文字:',text,text_rect)self.screen.blit(text_obj, text_rect)# 设置窗口大小def set_win_wh(self, w, h, title='python游戏'):self.screen2 = pygame.display.set_mode((w, h), pygame.DOUBLEBUF, 32)self.screen = self.screen2.convert_alpha()pygame.display.set_caption(title)def update(self):self.screen2.blit(self.screen, (0, 0))# 刷新画面# pygame.display.update()pygame.display.flip()time_passed = self.clock.tick(self.fps)# 侦听事件def my_event(self):if self.state == 'ai' and self.next_f == '':self.next_f, self.jm = self.ai.get_next(self.game.grid.tiles)for event in pygame.event.get():if event.type == QUIT:self.state = 'exit'if event.type == KEYDOWN:if event.key == K_ESCAPE:self.state = 'exit'elif event.key in [K_LEFT, K_a] and self.state == 'run':self.next_f = 'L'elif event.key in [K_RIGHT, K_d] and self.state == 'run':self.next_f = 'R'elif event.key in [K_DOWN, K_s] and self.state == 'run':self.next_f = 'D'elif event.key in [K_UP, K_w] and self.state == 'run':self.next_f = 'U'elif event.key in [K_k, K_l] and self.state == 'ai':if event.key == K_k and self.step_time > 0:self.step_time *= 0.9if event.key == K_l and self.step_time < 10:if self.step_time != 0:self.step_time *= 1.1else:self.step_time = 0.01if self.step_time < 0:self.step_time = 0if event.type == MOUSEBUTTONDOWN:for i in self.button_list:if i.is_click(event.pos):self.state = i.nameif i.name == 'ai':i.name = 'run'i.text = '取消托管'elif i.name == 'run':i.name = 'ai'i.text = '电脑托管'break
def run():Main().start()
# 按钮类
class Button(pygame.sprite.Sprite):def __init__(self, name, text, xy, size=(100, 50)):pygame.sprite.Sprite.__init__(self)self.name = nameself.text = textself.x, self.y = xy[0], xy[1]self.w, self.h = sizeself.is_show = Truedef is_click(self, xy):return (self.is_show andself.x <= xy[0] <= self.x + self.w andself.y <= xy[1] <= self.y + self.h)

ai

自动游戏模块,即托管。此部分根据进行上下左右操作后形成的局面进行评分,评分依赖数字的位置,通常,大数字越靠近右下角,评分越高。该程序会选择评分更高的操作。
该部分不是很智能,很多情况下不能自主完成游戏。

def get_grid(tiles, directions):g = Grid(config.SIZE)g.tiles = tiles.copy()for direction in directions:g.run(direction)g.add_random_tile()return g.tiles
def printf(tiles):for row in tiles:for i in row:print("{:^6}".format(i), end='')print()
def my_log2(z):if z == 0:return 0else:return z# return np.math.log2(z)
class Ai:def __init__(self):self.g = Grid(config.SIZE)def get_next(self, tiles):score_list = []tn = self.get_tile_num(tiles)if tn >= self.g.size ** 2 / 3:return "RD"[np.random.randint(0, 2)], 0kn = min(max(tn ** 2, 20), 40)for directions in itertools.product("ULRD", repeat=3):fen = []for i in range(kn):t_g = get_grid(tiles, directions)fen.append(self.get_score(t_g))print(directions, min(fen))score_list.append([directions, min(fen)])score_list = sorted(score_list, key=(lambda x: [x[1]]))# print(score_list)for d in score_list[::-1]:self.g.tiles = tiles.copy()if self.g.run(d[0][0], is_fake=False) != 0:return d[0][0], d[1] / knself.g.tiles = tiles.copy()# print('===',score_list[-1][0][0])return score_list[-1][0][0], score_list[-1][1] / kndef get_score(self, tiles):# 格子数量(越少越好)  金角银边()# bjs = [self.get_bj2(tiles)[i] * 2.8 + self.get_bj(tiles)[i] for i in range(4)]# return max(bjs)a = self.get_bj2__4(tiles)b = self.get_bj__4(tiles)print(a, b)return a * 2.8 + bdef debug(self, tiles):print('\n=======开始判断========')print('移动前棋盘:')printf(tiles)score_list = []for directions in itertools.product("ULRD", repeat=2):t_g = get_grid(tiles, directions)fen = self.get_score(t_g)score_list.append([directions, fen])print('==={}=={}=='.format(directions, fen))printf(t_g)score_list = sorted(score_list, key=(lambda x: [x[1]]))# print(score_list)for d in score_list[::-1]:# print('-->',d)self.g.tiles = tiles.copy()# print(self.g.run(d[0][0],is_fake=True))if self.g.run(d[0][0], is_fake=True) != 0:# print('---异动前:')# print(self.g.tiles)# print('---异动后:')self.g.run(d[0][0])# print(self.g.tiles)return d[0][0]# print('===',score_list[-1][0][0])return score_list[-1][0][0]# 空格子数量def get_tile_num(self, tiles):# l = len(tiles)n = 0for row in tiles:for i in row:if i == 0:n += 1return n# return np.bincount(tiles)[0]def get_bj(self, tiles):gjs = [self.get_bj__1(tiles),self.get_bj__2(tiles),self.get_bj__3(tiles),self.get_bj__4(tiles)]return gjsdef get_bj__4(self, tiles):bj = 0l = len(tiles)size = self.g.size - 1for y in range(l):for x in range(l):z = tiles[y][x]if z != 0:z_log = z - 2bj += z_log * (x + y - (size * 2 - 1))else:bj += (100 - 20 * (x + y - (size * 2 - 1)))# print(z, "-- ", bj)return bjdef get_bj__3(self, tiles):bj = 0l = len(tiles)size = self.g.size - 1for y in range(l):for x in range(l):z = tiles[y][x]if z != 0:z_log = z - 2bj += z_log * ((size - x) + y - (size * 2 - 1))else:bj += (100 - 20 * ((size - x) + y - (size * 2 - 1)))return bjdef get_bj__2(self, tiles):bj = 0l = len(tiles)size = self.g.size - 1for y in range(l):for x in range(l):z = tiles[y][x]if z != 0:z_log = z - 2bj += z_log * ((size - x) + (size - y) - (size * 2 - 1))else:bj += (100 - 20 * ((size - x) + (size - y) - (size * 2 - 1)))return bjdef get_bj__1(self, tiles):bj = 0l = len(tiles)size = self.g.size - 1for y in range(l):for x in range(l):z = tiles[y][x]if z != 0:z_log = z - 2bj += z_log * (x + (size - y) - (size * 2 - 1))else:bj += (100 - 20 * (x + (size - y) - (size * 2 - 1)))return bjdef get_bj2(self, tiles):gjs = [self.get_bj2__1(tiles),self.get_bj2__2(tiles),self.get_bj2__3(tiles),self.get_bj2__4(tiles)]return gjsdef get_bj2__1(self, tiles):bj = 0l = len(tiles)for y in range(0, l - 1, 1):for x in range(l - 1, 0, -1):z = tiles[y][x]if tiles[y][x] < tiles[y][x - 1]:bj -= abs(my_log2(tiles[y][x - 1]) - z)if tiles[y][x] < tiles[y + 1][x]:bj -= abs(my_log2(tiles[y + 1][x]) - z)if tiles[y][x] < tiles[y + 1][x - 1]:bj -= abs(my_log2(tiles[y + 1][x - 1]) - z)return bjdef get_bj2__2(self, tiles):bj = 0l = len(tiles)for y in range(0, l - 1):for x in range(0, l - 1):z = tiles[y][x]if tiles[y][x] < tiles[y][x + 1]:bj -= abs(my_log2(tiles[y][x + 1]) - z)if tiles[y][x] < tiles[y + 1][x]:bj -= abs(my_log2(tiles[y + 1][x]) - z)if tiles[y][x] < tiles[y + 1][x + 1]:bj -= abs(my_log2(tiles[y + 1][x + 1]) - z)return bjdef get_bj2__3(self, tiles):bj = 0l = len(tiles)for y in range(l - 1, 0, -1):for x in range(0, l - 1):z = tiles[y][x]if tiles[y][x] < tiles[y][x + 1]:bj -= abs(my_log2(tiles[y][x + 1]) - z)if tiles[y][x] < tiles[y - 1][x]:bj -= abs(my_log2(tiles[y - 1][x]) - z)if tiles[y][x] < tiles[y - 1][x + 1]:bj -= abs(my_log2(tiles[y - 1][x + 1]) - z)return bjdef get_bj2__4(self, tiles):bj = 0l = len(tiles)for y in range(l - 1, 0, -1):for x in range(l - 1, 0, -1):z = tiles[y][x]if z < tiles[y][x - 1]:bj -= abs(my_log2(tiles[y][x - 1]) - z)if z < tiles[y - 1][x]:bj -= abs(my_log2(tiles[y - 1][x]) - z)if z < tiles[y - 1][x - 1]:bj -= abs(my_log2(tiles[y - 1][x - 1]) - z)return bj

完整程序点此下载,运行main.py文件即可运行游戏

更多推荐

【python大作业】pygame实战(python编写2048小游戏)

本文发布于:2024-03-12 14:36:57,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1731736.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:作业   小游戏   实战   python   pygame

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!