Python实现卡片横向网格中Runs与Groups的检测
实现方案
1. 网格格式转换
首先把字典形式的网格转成二维列表,方便按行/列遍历处理。10行21列的网格,字典键的计算规则是行号*21 + 列号,转换代码如下:
# 假设输入网格为grid_dict grid = [] for row_idx in range(10): current_row = [] for col_idx in range(21): current_row.append(grid_dict[row_idx * 21 + col_idx]) grid.append(current_row)
2. 检测横向顺子(Runs)
规则匹配逻辑
- 同一行内连续3张及以上非空位卡片
- 所有卡片颜色相同
- 数值构成连续的奇数序列(如3,5,7,步长为2,全奇数)或连续的偶数序列(如2,4,6,步长为2,全偶数)
实现代码
def detect_runs(grid): runs = [] for row_idx, row in enumerate(grid): current_run = [] for col_idx, card in enumerate(row): if card is None: # 空位中断当前序列,检查是否符合Runs条件 if len(current_run) >= 3: same_color = all(c['color'] == current_run[0]['color'] for c in current_run) if not same_color: current_run = [] continue # 验证数值是连续奇偶序列 vals = [c['value'] for c in current_run] same_parity = all(v % 2 == vals[0] % 2 for v in vals) is_consecutive = vals == list(range(vals[0], vals[-1]+1, 2)) if same_parity and is_consecutive: runs.append({ 'type': 'Run', 'row': row_idx, 'columns': [col_idx - len(current_run) + i for i in range(len(current_run))], 'color': current_run[0]['color'], 'values': vals }) current_run = [] else: current_run.append(card) # 处理行末尾的剩余序列 if len(current_run) >= 3: same_color = all(c['color'] == current_run[0]['color'] for c in current_run) if same_color: vals = [c['value'] for c in current_run] same_parity = all(v % 2 == vals[0] % 2 for v in vals) is_consecutive = vals == list(range(vals[0], vals[-1]+1, 2)) if same_parity and is_consecutive: runs.append({ 'type': 'Run', 'row': row_idx, 'columns': [21 - len(current_run) + i for i in range(len(current_run))], 'color': current_run[0]['color'], 'values': vals }) return runs
3. 检测组(Groups)
规则匹配逻辑
- 连续3张及以上非空位卡片(支持横向或纵向连续)
- 所有卡片数值相同
- 所有卡片颜色互不重复
实现代码
def detect_groups(grid): groups = [] rows = len(grid) cols = len(grid[0]) if rows > 0 else 0 # 检测横向Groups for row_idx in range(rows): current_group = [] for col_idx in range(cols): card = grid[row_idx][col_idx] if card is None: if len(current_group) >= 3: same_value = all(c['value'] == current_group[0]['value'] for c in current_group) if not same_value: current_group = [] continue colors = [c['color'] for c in current_group] if len(set(colors)) == len(colors): groups.append({ 'type': 'Group', 'row': row_idx, 'columns': [col_idx - len(current_group) + i for i in range(len(current_group))], 'value': current_group[0]['value'], 'colors': colors }) current_group = [] else: current_group.append(card) # 处理行末尾的剩余序列 if len(current_group) >= 3: same_value = all(c['value'] == current_group[0]['value'] for c in current_group) if same_value: colors = [c['color'] for c in current_group] if len(set(colors)) == len(colors): groups.append({ 'type': 'Group', 'row': row_idx, 'columns': [cols - len(current_group) + i for i in range(len(current_group))], 'value': current_group[0]['value'], 'colors': colors }) # 检测纵向Groups for col_idx in range(cols): current_group = [] for row_idx in range(rows): card = grid[row_idx][col_idx] if card is None: if len(current_group) >= 3: same_value = all(c['value'] == current_group[0]['value'] for c in current_group) if not same_value: current_group = [] continue colors = [c['color'] for c in current_group] if len(set(colors)) == len(colors): groups.append({ 'type': 'Group', 'row_start': row_idx - len(current_group), 'row_end': row_idx - 1, 'column': col_idx, 'value': current_group[0]['value'], 'colors': colors }) current_group = [] else: current_group.append(card) # 处理列末尾的剩余序列 if len(current_group) >= 3: same_value = all(c['value'] == current_group[0]['value'] for c in current_group) if same_value: colors = [c['color'] for c in current_group] if len(set(colors)) == len(colors): groups.append({ 'type': 'Group', 'row_start': rows - len(current_group), 'row_end': rows - 1, 'column': col_idx, 'value': current_group[0]['value'], 'colors': colors }) return groups
4. 结果打印
调用上述函数并格式化输出结果:
# 假设你的网格字典是grid_dict grid = [] for row_idx in range(10): current_row = [] for col_idx in range(21): current_row.append(grid_dict[row_idx * 21 + col_idx]) grid.append(current_row) # 检测并打印Runs print("=== 横向顺子(Runs) ===") runs = detect_runs(grid) if not runs: print("未检测到符合条件的顺子") else: for idx, run in enumerate(runs, 1): print(f"顺子 {idx}: 第{run['row']}行,列{run['columns'][0]}至{run['columns'][-1]} | 颜色:{run['color']} | 数值:{run['values']}") # 检测并打印Groups print("\n=== 组(Groups) ===") groups = detect_groups(grid) if not groups: print("未检测到符合条件的组") else: for idx, group in enumerate(groups, 1): if 'columns' in group: # 横向组 print(f"组 {idx}: 第{group['row']}行,列{group['columns'][0]}至{group['columns'][-1]} | 数值:{group['value']} | 颜色:{group['colors']}") else: # 纵向组 print(f"组 {idx}: 第{group['row_start']}至{group['row_end']}行,列{group['column']} | 数值:{group['value']} | 颜色:{group['colors']}")
注意事项
- 如果对Runs的“连续奇数/偶数序列”理解有误(比如实际是指数值连续整数且全奇/全偶,但这种情况连续3个数不可能),可以调整
is_consecutive的判断逻辑,比如改为检查数值是否是连续整数:vals == list(range(vals[0], vals[-1]+1)),再结合奇偶性判断。 - 代码中默认支持横向和纵向的Groups,若需求仅需横向,可删除纵向检测部分。
内容的提问来源于stack exchange,提问作者Jattboy2
相关产品推荐
相关产品推荐

