简单改进俄罗斯方块
对俄罗斯方块进行一部分优化:
参考地址:https://www.cnblogs.com/27dCnc/p/18568655
一、作业要求:从网上寻找一个项目或者小游戏,找出里面存在的不足之处,并且将它的不足之处优化。
二、运行环境:Windows
三、编译器:VSCODE
四、源代码*
点击查看代码
import sys import pygame from pygame.locals import * import randomclass Block:
blk_color = [(255, 255, 255),(255, 255, 0),(255, 0, 255),(0, 255, 255),(255, 0, 0),(0, 255, 0),(0, 0, 255),(32,32,32)]
BLANK = 7
type_coord=[[[-1,0],[0,0],[1,0],[2,0]]
,[[-1,0],[0,0],[1,0],[0,1]]
,[[-1,0],[0,0],[-1,1],[0,1]]
,[[-1,0],[0,0],[0,1],[1,1]]
,[[0,0],[1,0],[-1,1],[0,1]]
,[[-1,0],[0,0],[1,0],[1,1]]
,[[-1,0],[0,0],[1,0],[-1,1]]]
type_rotate = []
def __init__(self,x,y,blk,angle):
self.x = x
self.y = y
self.blk = blk
self.angle = angle
@staticmethod
def rotate(no):
rt_all = []
rt = Block.type_coord[no][:]
cx,cy=0,0
for b in range(4):
rt[b][0],rt[b][1] = rt[b][0]*4,rt[b][1]*4
cx += rt[b][0]
cy += rt[b][1]
cx = (cx)//8*2 if no !=6 else (cx+4)//8*2
cy = (cy)//8*2 if no !=6 else (cy-4)//8*2
rt_all.append(rt)
for r in range(3):
rt_new = []
for b in range(4):
rt_new.append([cx + (cy-rt[b][1]),cy-(cx-rt[b][0])])
rt_all.append(rt_new)
rt = rt_new
for r in range(4):
for b in range(4):
rt_all[r][b][0] //= 4
rt_all[r][b][1] //= 4
return rt_all
@staticmethod
def init_rotate():
for r in range(7):
Block.type_rotate.append(Block.rotate(r))
class TRS:
screen = None
map = [[Block.BLANK]*10 for i in range(20)]
STATUS = 0
cbk = None
def __init__(self,screen):
TRS.screen = screen
@staticmethod
def action(key_pressed):
if(key_pressed[K_LEFT] and TRS.check_action(TRS.cbk.x-1,TRS.cbk.y,TRS.cbk.blk,TRS.cbk.angle)):
TRS.cbk.x -= 1
elif (key_pressed[K_RIGHT] and TRS.check_action(TRS.cbk.x+1,TRS.cbk.y,TRS.cbk.blk,TRS.cbk.angle)):
TRS.cbk.x += 1
elif (key_pressed[K_UP] and TRS.check_action(TRS.cbk.x,TRS.cbk.y,TRS.cbk.blk,TRS.cbk.angle+1)):
TRS.cbk.angle += 1
elif (key_pressed[K_DOWN] and TRS.check_action(TRS.cbk.x,TRS.cbk.y+1,TRS.cbk.blk,TRS.cbk.angle)):
TRS.cbk.y += 1
@staticmethod
def new_blk():
TRS.cbk = Block(5,0,random.randint(0,6),0)
@staticmethod
def check_action(x,y,blk,angle):
tr = Block.type_rotate[blk][angle%4]
for b in range(4):
bx,by = x + tr[b][0],y + tr[b][1]
if(bx<0 or bx>9 or by <0 or by>19 or TRS.map[by][bx]!=Block.BLANK):
return False
return True
@staticmethod
def check_drop():
if TRS.check_action(TRS.cbk.x,TRS.cbk.y+1,TRS.cbk.blk,TRS.cbk.angle):
TRS.cbk.y += 1
else:
TRS.STATUS = 2
@staticmethod
def check_clear():
blk = Block.type_rotate[TRS.cbk.blk][TRS.cbk.angle%4]
row = list({TRS.cbk.y + blk[i][1] for i in range(4)})
row.sort()
row.reverse()
for b in range(4):
TRS.map[TRS.cbk.y + blk[b][1]][TRS.cbk.x + blk[b][0]] = TRS.cbk.blk
del_rows = 0
for r in row:
if not (Block.BLANK in TRS.map[r]):
TRS.map.pop(r)
del_rows += 1
for d in range(del_rows):
TRS.map.insert(0,[Block.BLANK for i in range(10)])
@staticmethod
def print_game():
TRS.screen.fill((0, 0, 0))
for row in range(20):
for col in range(10):
pygame.draw.rect(TRS.screen, Block.blk_color[TRS.map[row][col]], ((col*21,row*21), (20, 20)), 0)
blk = Block.type_rotate[TRS.cbk.blk][TRS.cbk.angle%4]
for b in range(4):
pygame.draw.rect(TRS.screen, Block.blk_color[TRS.cbk.blk], (((TRS.cbk.x+blk[b][0])*21,(TRS.cbk.y+blk[b][1])*21), (20, 20)), 0)
class App:
def init(self):
pygame.init()
screen = pygame.display.set_mode((300,430))
Block.init_rotate()
TRS(screen)
def main(self):
clock = pygame.time.Clock() # 创建游戏时钟
count = 1
# 进入游戏循环
while True:
# 设置刷新帧率
clock.tick(15)
# 事件检测
for event in pygame.event.get():
if event.type == pygame.QUIT: # 退出事件
sys.exit()
if TRS.STATUS == 0:
TRS.new_blk()
if TRS.check_action(TRS.cbk.x,TRS.cbk.y,TRS.cbk.blk,TRS.cbk.angle):
TRS.STATUS = 1
else:
TRS.STATUS = 3
print("GAME OVER")
elif TRS.STATUS == 1:
TRS.action(pygame.key.get_pressed())
if count % 10 == 0:
TRS.check_drop()
elif TRS.STATUS == 2:
TRS.check_clear()
TRS.STATUS = 0
TRS.print_game()
pygame.display.update() #刷新屏幕
count += 1
App().main()
六、代码优化:由于源代码无法显示得分以及用户用时情况,故优化一个计时以及得分牌子,来反映用户实时情况;
代码:
点击查看代码
import sys
import pygame
from pygame.locals import *
import random
import time
class Block:
blk_color = [(255, 255, 255),(255, 255, 0),(255, 0, 255),(0, 255, 255),(255, 0, 0),(0, 255, 0),(0, 0, 255),(32,32,32)]
BLANK = 7
type_coord=[[[-1,0],[0,0],[1,0],[2,0]]\
,[[-1,0],[0,0],[1,0],[0,1]]\
,[[-1,0],[0,0],[-1,1],[0,1]]\
,[[-1,0],[0,0],[0,1],[1,1]]\
,[[0,0],[1,0],[-1,1],[0,1]]\
,[[-1,0],[0,0],[1,0],[1,1]]\
,[[-1,0],[0,0],[1,0],[-1,1]]]
type_rotate = []
def __init__(self,x,y,blk,angle):
self.x = x
self.y = y
self.blk = blk
self.angle = angle
@staticmethod
def rotate(no):
rt_all = []
rt = Block.type_coord[no][:]
cx,cy=0,0
for b in range(4):
rt[b][0],rt[b][1] = rt[b][0]*4,rt[b][1]*4
cx += rt[b][0]
cy += rt[b][1]
cx = (cx)//8*2 if no !=6 else (cx+4)//8*2
cy = (cy)//8*2 if no !=6 else (cy-4)//8*2
rt_all.append(rt)
for r in range(3):
rt_new = []
for b in range(4):
rt_new.append([cx + (cy-rt[b][1]),cy-(cx-rt[b][0])])
rt_all.append(rt_new)
rt = rt_new
for r in range(4):
for b in range(4):
rt_all[r][b][0] //= 4
rt_all[r][b][1] //= 4
return rt_all
@staticmethod
def init_rotate():
for r in range(7):
Block.type_rotate.append(Block.rotate(r))
class TRS:
screen = None
map = [[Block.BLANK]*10 for i in range(20)]
STATUS = 0
cbk = None
score = 0 # Added score variable
start_time = time.time() # Added timer variable
def __init__(self,screen):
TRS.screen = screen
@staticmethod
def action(key_pressed):
if(key_pressed[K_LEFT] and TRS.check_action(TRS.cbk.x-1,TRS.cbk.y,TRS.cbk.blk,TRS.cbk.angle)):
TRS.cbk.x -= 1
elif (key_pressed[K_RIGHT] and TRS.check_action(TRS.cbk.x+1,TRS.cbk.y,TRS.cbk.blk,TRS.cbk.angle)):
TRS.cbk.x += 1
elif (key_pressed[K_UP] and TRS.check_action(TRS.cbk.x,TRS.cbk.y,TRS.cbk.blk,TRS.cbk.angle+1)):
TRS.cbk.angle += 1
elif (key_pressed[K_DOWN] and TRS.check_action(TRS.cbk.x,TRS.cbk.y+1,TRS.cbk.blk,TRS.cbk.angle)):
TRS.cbk.y += 1
@staticmethod
def new_blk():
TRS.cbk = Block(5,0,random.randint(0,6),0)
@staticmethod
def check_action(x,y,blk,angle):
tr = Block.type_rotate[blk][angle%4]
for b in range(4):
bx,by = x + tr[b][0],y + tr[b][1]
if(bx<0 or bx>9 or by <0 or by>19 or TRS.map[by][bx]!=Block.BLANK):
return False
return True
@staticmethod
def check_drop():
if TRS.check_action(TRS.cbk.x,TRS.cbk.y+1,TRS.cbk.blk,TRS.cbk.angle):
TRS.cbk.y += 1
else:
TRS.STATUS = 2
@staticmethod
def check_clear():
blk = Block.type_rotate[TRS.cbk.blk][TRS.cbk.angle%4]
row = list({TRS.cbk.y + blk[i][1] for i in range(4)})
row.sort()
row.reverse()
for b in range(4):
TRS.map[TRS.cbk.y + blk[b][1]][TRS.cbk.x + blk[b][0]] = TRS.cbk.blk
del_rows = 0
for r in row:
if not (Block.BLANK in TRS.map[r]):
TRS.map.pop(r)
del_rows += 1
for d in range(del_rows):
TRS.map.insert(0,[Block.BLANK for i in range(10)])
# Update score based on the number of rows cleared
if del_rows > 0:
TRS.score += del_rows * 100 # 100 points per cleared row
@staticmethod
def print_game():
TRS.screen.fill((0, 0, 0))
for row in range(20):
for col in range(10):
pygame.draw.rect(TRS.screen, Block.blk_color[TRS.map[row][col]], ((col*21,row*21), (20, 20)), 0)
blk = Block.type_rotate[TRS.cbk.blk][TRS.cbk.angle%4]
for b in range(4):
pygame.draw.rect(TRS.screen, Block.blk_color[TRS.cbk.blk]], (((TRS.cbk.x+blk[b][0])*21,(TRS.cbk.y+blk[b][1])*21), (20, 20)), 0)
# Display score and timer
font = pygame.font.SysFont("Arial", 24)
score_text = font.render(f"Score: {TRS.score}", True, (255, 255, 255))
elapsed_time = int(time.time() - TRS.start_time)
timer_text = font.render(f"Time: {elapsed_time}s", True, (255, 255, 255))
TRS.screen.blit(score_text, (10, 430 - 50))
TRS.screen.blit(timer_text, (10, 430 - 30))
class App:
def __init__(self):
pygame.init()
screen = pygame.display.set_mode((300,430))
Block.init_rotate()
TRS(screen)
def main(self):
clock = pygame.time.Clock() # 创建游戏时钟
count = 1
# 进入游戏循环
while True:
# 设置刷新帧率
clock.tick(15)
# 事件检测
for event in pygame.event.get():
if event.type == pygame.QUIT: # 退出事件
sys.exit()
if TRS.STATUS == 0:
TRS.new_blk()
if TRS.check_action(TRS.cbk.x,TRS.cbk.y,TRS.cbk.blk,TRS.cbk.angle):
TRS.STATUS = 1
else:
TRS.STATUS = 3
print("GAME OVER")
elif TRS.STATUS == 1:
TRS.action(pygame.key.get_pressed())
if count % 10 == 0:
TRS.check_drop()
elif TRS.STATUS == 2:
TRS.check_clear()
TRS.STATUS = 0
TRS.print_game()
pygame.display.update() #刷新屏幕
count += 1
App().main()
注意事项:得分和计时器显示在屏幕底部。
当新方块无法放置在网格顶部时,游戏结束,并在控制台打印“游戏结束”。
你可以截取运行中的游戏画面以查看视觉效果。类和方法解释
Block 类:
代表游戏中的方块。
blk_color 定义了不同方块的颜色。
type_coord 定义了不同形状方块的坐标。
rotate 方法用于计算方块的旋转后的坐标。
init_rotate 方法初始化所有形状的旋转状态。
TRS 类:
代表整个游戏的状态和控制。
screen 是游戏的显示屏幕。
map 是游戏板的当前状态,用于存储每个位置是否有方块以及方块的颜色。
action 方法处理玩家的输入(移动和旋转方块)。
new_blk 方法生成一个新的方块。
check_action 方法检查玩家想要进行的动作(移动或旋转)是否合法。
七、心得体会:对博客园有了一个初步认识,并且简单了解了一下部分小游戏的代码,并且体验了一把开发游戏权限的部分乐趣。主要难点在于如何在不影响整体局面布局以及不影响游戏进行的情况下对游戏进行优化。计时机制应确保在游戏过程中实时更新,不影响游戏流畅性。得分机制应该要合理,并且也需要实时更新。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了