Python学习:方块消除游戏

【编程题:方块消除游戏】

emmmm..依然牛客网上的题,难度标识才一颗星,但是感觉自己看代码看了好久才理解实现的过程。

题目描述:如下图,有10*10个不同颜色的方块,每个方块可能是红、绿、蓝、黄、紫5种颜色之一。当点击其中某一个方块时,如果它有相邻的同颜色方块,则将所有与此方块连续同颜色相邻的方块消除;剩下的方块中,如果下方有空位则向下移动,如果左侧整列都为空位则向左移动。


输入

输入数据有多组,每组占一行,包括一个或多个正整数,取值范围为1~100。每个数代表一次点击,数值为点击的方块编号。
以下是各色方块以及方块位置地图的初始值:

RED = 0, GREEN = 1, BLUE = 2, YELLOW = 3, PURPLE = 4;

mp = [
[0, 0, 2, 2, 1, 3, 2, 3, 0, 4],
[1, 1, 1, 2, 0, 4, 0, 3, 3, 2],
[2, 0, 0, 3, 3, 4, 2, 1, 1, 2],
[3, 0, 2, 3, 2, 0, 4, 1, 1, 0],
[3, 0, 2, 2, 4, 1, 4, 0, 3, 2],
[4, 3, 0, 0, 3, 0, 4, 3, 0, 0],
[3, 3, 1, 4, 1, 0, 2, 3, 2, 1],
[0, 3, 2, 2, 3, 1, 4, 0, 2, 1],
[1, 1, 3, 3, 0, 0, 4, 2, 2, 1],
[4, 2, 0, 0, 4, 3, 2, 0, 0, 1]
]

输出

对于每个测试实例,要求输出连续各次点击全部完成之后,红、绿、蓝、黄、紫色方块的数量;每个测试实例的输出占一行。

eg:

INPUT

6

OUTPUT

26 18 22 21 13


具体代码及详解如下:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Name: demo26.py
# Author: zhuzhuzhu   time:2018/5/17
# Connect: [email protected]
# Desc:方块消除游戏(py2)
import Queue
import copy
dx = [-1, 1, 0, 0]
dy = [0, 0, 1, -1]
mp = [
    [0, 0, 2, 2, 1, 3, 2, 3, 0, 4],
    [1, 1, 1, 2, 0, 4, 0, 3, 3, 2],
    [2, 0, 0, 3, 3, 4, 2, 1, 1, 2],
    [3, 0, 2, 3, 2, 0, 4, 1, 1, 0],
    [3, 0, 2, 2, 4, 1, 4, 0, 3, 2],
    [4, 3, 0, 0, 3, 0, 4, 3, 0, 0],
    [3, 3, 1, 4, 1, 0, 2, 3, 2, 1],
    [0, 3, 2, 2, 3, 1, 4, 0, 2, 1],
    [1, 1, 3, 3, 0, 0, 4, 2, 2, 1],
    [4, 2, 0, 0, 4, 3, 2, 0, 0, 1]
]
# bfs搜索同色


def bfs(beg):
    global mp, dx, dy
    # 队列长度无限长
    q = Queue.Queue(maxsize=0)
    # 点击位置的x,y 坐标
    x = beg / 10
    y = (beg - 1) % 10
    block_color = mp[x][y]
    if block_color == -1:
        return False
 """    
  申请获得互斥锁,获得后,如果队列未满,则向队列中添加数据,并通知notify其它阻塞的某个线程,
释放互斥锁。由于队列无限长,这一步其实就是在添加数据。
  """
    q.put((x, y))
    cnt = 0
    # qsize判断队列长度,不为空则循环
    while q.qsize():
        # get从队列中获取任务,并且从队列中移除此任务。
        x, y = q.get()
        # 点击位置(x, y)的周围元素
        for i in range(4):
            s = dx[i] + x
            t = dy[i] + y
            # 维度不正确或者与点击位置不同色,则结束本次循环,进入下次循环
            if s < 0 or s > 9 or t < 0 or t > 9 or mp[s][t] != block_color:
                continue
            cnt += 1
            # 若同色,则将这个位置初始化为-1,被标记为-1的数就相当于被消除了
            mp[s][t] = -1
            # 将(s, t)加入队列
            q.put((s, t))
    # 经过同色消去的处理,点击元素的位置必然发生了变化,若无变化,只能说明出错啦
    if cnt == 1:
        mp[beg/10][(beg - 1) % 10] = block_color
        return False
    return True
# 紧凑map


def merge_map():
    # 初始化一个10行10列且每个元素均为-1的矩阵
    tmp_mp = [[-1 for i in range(10)] for j in range(10)]
    global mp
    for i in range(10):
        cnt = 0
        for j in range(10):
            # 这样可以判断有多少个同色
            if mp[i][j] == -1:
                cnt += 1
        if cnt != 10:
            for j in range(10):
                tmp_mp[i][j] = mp[i][j]
    mp = copy.deepcopy(tmp_mp)
    # print tmp_mp

    # 统计最终数量


def calc_block_num():
    red = 0
    green = 0
    blue = 0
    yellow = 0
    purple = 0
    # 统计红绿蓝黄紫各有多少个
    for i in range(10):
        for j in range(10):
            if mp[i][j] == 0:
                red += 1
            elif mp[i][j] == 1:
                green += 1
            elif mp[i][j] == 2:
                blue += 1
            elif mp[i][j] == 3:
                yellow += 1
            elif mp[i][j] == 4:
                purple += 1
    print str(red) + ' ' + str(green) + ' ' + str(blue) + ' ' + str(yellow) + ' ' + str(purple)


actions = map(str, raw_input())
for action in actions:
    if action != ' ':
        if bfs(int(action)):
            merge_map()
calc_block_num()

总结

目前代码理解这块儿基本没有什么大问题(大概能说服自己),但是如果要求上手敲可能还有些费劲,所以…明天再做一遍加深记忆。

猜你喜欢

转载自blog.csdn.net/in_nocence/article/details/80385416