Block小结

Block小结

一、block的类型

  • GlobalBlock
  • StackBlock
  • MallocBlock

二、生成条件

GlobalBlcok:
如果一个block没有引用任何外部变量,此时block是一个GlobalBlock

StackBlock:
相对于GlobalBlock,如果一个block内部引用了外部变量
MRC:此时的block会是一个GlobalBlock
ARC:此时的block会是一个MallocBlock
Tips: ARC下会对GlobalBlock做优化,当创建一个block时会默认返回一个MallocBlock。但是在ARC中当block作为函数参数时,此时block是一个GlobalBlock。

MallocBlock:
MRC:对StackBlock copy得到MallocBlock
ARC:默认创建的Block,除了GlobalBlock都是MallocBlock

三、block的copy、retain、release操作

这些操作都是在MRC情况下

  • 对block进行copy、retain、release都不会改变retainCount,retainCount始终是1
  • GlobalBlock的retain、copy、release都无效
  • StackBlock的retain、release操作无效,StackBlock在函数返回后,block内存将会被回收
  • MallocBlock 支持retain、release,是retainCount始终是1

四、block对不同类型变量的存取

  1. 基本类型
    局部变量,在block中只读。block__定义__时,copy变量的值,在block中作为常量使用;static变量、全部变量,在内存中的位置是固定的,block在读取时会直接从内存中读出,获取到最新的值;被__block修饰的变量,基本类型的block变量等效于static变量;block被另一个block使用时,另一个block被copy到堆上时,被使用的block也会被copy。但是作为参数的block是不会copy的

  2. 引用类型
    局变量和static变量在内存中的位置是确定的,所以不会retain变量,_instanceObj在block中使用时,不会retain _instanceObj本身,但是会retain self,local在block中 时,会retain对象,增加引用计数;block obj在block copy时也不会retain

附带几个block的坑,分析在MRC和在ARC情况下都是否能执行

题目1.

void exampleA()
{
  char a = 'A';
  ^{
     printf("%c\n",a);
   }();
}

题目2.

void exampleB_addBlockToArray(NSMutableArray *array)
 {
  char b = 'B';
  [array addObject:^{
     printf("%c\n",b);
  }];
  }

void exampleB()
{
  NSMutableArray *array = [NSMutableArray array];
  exampleB_addBlockToArray(array);
  void(^block)() = [array objectAtIndex:0];
  block();
}

题目3.

void exampleC_addBlockToArray(NSMutableArray *array)
{
 [array addObject:^{
   printf("C\n");
  }];
}

void exampleC()
{
  NSMutableArray *array = [NSMutableArray array];
  exampleC_addBlockToArray(array);
  void(^block)() = [array objectAtIndex:0];
  block();
}

题目4.

typedef void(^dBlock)();

dBlock exampleD_getBlock() {
 chard = 'D';
 return^{
   printf("%c\n",d);
  };
}

void exampleD()
{
 exampleD_getBlock()();
}

题目5.

typedef void(^eBlock)();

eBlock exampleE_getBlock() {
 chare = 'E';
 void(^block)() = ^{
   printf("%c\n",e);
   };
 returnblock;
}

void exampleE()
{
 eBlock block = exampleE_getBlock();
 block();
}

答案是:1、3 在MRC和ARC情况下都能使用 2、4、5 只有在ARC情况下才能使用
提示:stackBlock 会在block返回后被释放,global则不需要关系释放的问题,mallocBlock会手动释放或arc自动管理,在arc情况下,不作为参数的stackBlock会被自动创建为mallocBlock

文章参考:https://www.zybuluo.com/MicroCai/note/57603
http://blog.parse.com/learn/engineering/objective-c-blocks-quiz/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以给你一个简单的游戏示例,使用Python和Pygame库设计一个俄罗斯方块游戏。以下是代码: ```python import pygame import random # 初始化Pygame pygame.init() # 游戏窗口尺寸 WINDOW_WIDTH = 400 WINDOW_HEIGHT = 600 # 方块大小 BLOCK_SIZE = 20 # 方块颜色 BLOCK_COLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255), (0, 255, 255), (128, 0, 128)] # 游戏区域尺寸 GAME_WIDTH = 10 * BLOCK_SIZE GAME_HEIGHT = 20 * BLOCK_SIZE # 游戏区域位置 GAME_X = (WINDOW_WIDTH - GAME_WIDTH) // 2 GAME_Y = WINDOW_HEIGHT - GAME_HEIGHT - 10 # 游戏区域背景颜色 GAME_BG_COLOR = (255, 255, 255) # 方块类型及形状 BLOCK_TYPES = [ [[1, 1, 1, 1]], [[1, 1, 1], [0, 1, 0]], [[0, 1, 1], [1, 1, 0]], [[1, 1, 0], [0, 1, 1]], [[1, 0, 0], [1, 1, 1]], [[0, 0, 1], [1, 1, 1]], [[1, 0, 0], [1, 0, 0], [1, 1, 0]] ] # 游戏帧率 FPS = 30 # 创建游戏窗口 screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) # 设置游戏标题 pygame.display.set_caption('俄罗斯方块') # 创建字体对象 font = pygame.font.SysFont('arial', 36) class Block: def __init__(self): self.type = random.randint(0, len(BLOCK_TYPES) - 1) self.color = random.choice(BLOCK_COLORS) self.shape = BLOCK_TYPES[self.type] self.x = GAME_X + GAME_WIDTH // 2 - len(self.shape[0]) * BLOCK_SIZE // 2 self.y = GAME_Y - len(self.shape) * BLOCK_SIZE self.rotate = 0 def draw(self): for row in range(len(self.shape)): for col in range(len(self.shape[row])): if self.shape[row][col]: pygame.draw.rect(screen, self.color, (self.x + col * BLOCK_SIZE, self.y + row * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 0) def move(self, dx, dy): self.x += dx self.y += dy def rotate_left(self): self.rotate = (self.rotate - 1) % 4 self.shape = self.get_shape() def rotate_right(self): self.rotate = (self.rotate + 1) % 4 self.shape = self.get_shape() def get_shape(self): return list(zip(*self.shape[::-1])) if self.rotate % 2 else self.shape[::-1] class Game: def __init__(self): self.score = 0 self.block = None self.next_block = Block() self.is_game_over = False self.game_board = [[None] * 10 for _ in range(20)] def draw_game_board(self): pygame.draw.rect(screen, GAME_BG_COLOR, (GAME_X, GAME_Y, GAME_WIDTH, GAME_HEIGHT), 0) for row in range(len(self.game_board)): for col in range(len(self.game_board[row])): if self.game_board[row][col]: pygame.draw.rect(screen, self.game_board[row][col], (GAME_X + col * BLOCK_SIZE, GAME_Y + row * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 0) def draw_score(self): text = font.render(f'Score: {self.score}', True, (0, 0, 0)) screen.blit(text, (10, 10)) def draw_next_block(self): pygame.draw.rect(screen, GAME_BG_COLOR, (WINDOW_WIDTH - 100, 50, 80, 80), 0) next_block = self.next_block.get_shape() for row in range(len(next_block)): for col in range(len(next_block[row])): if next_block[row][col]: pygame.draw.rect(screen, self.next_block.color, (WINDOW_WIDTH - 100 + col * BLOCK_SIZE, 50 + row * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 0) def check_collision(self, block, dx=0, dy=0): for row in range(len(block.shape)): for col in range(len(block.shape[row])): if block.shape[row][col]: new_x = block.x + col * BLOCK_SIZE + dx new_y = block.y + row * BLOCK_SIZE + dy if new_x < GAME_X or new_x >= GAME_X + GAME_WIDTH or new_y >= GAME_Y + GAME_HEIGHT or (new_y >= GAME_Y and self.game_board[(new_y - GAME_Y) // BLOCK_SIZE][(new_x - GAME_X) // BLOCK_SIZE]): return True return False def add_block_to_board(self, block): for row in range(len(block.shape)): for col in range(len(block.shape[row])): if block.shape[row][col]: self.game_board[(block.y - GAME_Y) // BLOCK_SIZE + row][(block.x - GAME_X) // BLOCK_SIZE + col] = block.color def remove_full_rows(self): rows_to_remove = [] for row in range(len(self.game_board)): if None not in self.game_board[row]: rows_to_remove.append(row) for row in rows_to_remove: self.game_board.pop(row) self.game_board.insert(0, [None] * 10) self.score += len(rows_to_remove) ** 2 def start(self): clock = pygame.time.Clock() self.block = Block() while not self.is_game_over: for event in pygame.event.get(): if event.type == pygame.QUIT: self.is_game_over = True elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT and not self.check_collision(self.block, dx=-BLOCK_SIZE): self.block.move(-BLOCK_SIZE, 0) elif event.key == pygame.K_RIGHT and not self.check_collision(self.block, dx=BLOCK_SIZE): self.block.move(BLOCK_SIZE, 0) elif event.key == pygame.K_DOWN and not self.check_collision(self.block, dy=BLOCK_SIZE): self.block.move(0, BLOCK_SIZE) elif event.key == pygame.K_SPACE: self.block.rotate_right() if self.check_collision(self.block): self.block.rotate_left() elif event.key == pygame.K_UP: self.block.rotate_left() if self.check_collision(self.block): self.block.rotate_right() if self.check_collision(self.block, dy=BLOCK_SIZE): self.add_block_to_board(self.block) self.remove_full_rows() self.block = self.next_block self.next_block = Block() if self.check_collision(self.block): self.is_game_over = True else: self.block.move(0, BLOCK_SIZE) screen.fill((255, 255, 255)) self.draw_score() self.draw_game_board() self.block.draw() self.draw_next_block() pygame.display.update() clock.tick(FPS) pygame.quit() if __name__ == '__main__': game = Game() game.start() ``` 这个游戏的玩法是:控制方块下落,填满一行或多行后自动消除并得分,当方块堆积到屏幕顶部时游戏结束。你可以根据自己的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值