用Python简陋模拟n阶魔方


Posted in Python onApril 17, 2021

一、前言

终于整完了毕业论文,忙里偷闲半小时摸了个魔方模拟程序,支持模拟任意阶魔方,自动打乱,输入指令旋转。显示方面不会弄3D的,用opencv整了个展开图。

用Python简陋模拟n阶魔方

二、效果

五阶魔方打乱20步

用Python简陋模拟n阶魔方

震撼人心50阶,打乱100步

用Python简陋模拟n阶魔方

三、代码

import cv2
import numpy as np
from random import randint


class Cube:
    def __init__(self, order=3, size=50):  # 魔方阶数、显示尺寸
        self.img = np.zeros((4 * size * order, 3 * size * order, 3), dtype=np.uint8)
        self.order = order
        self.size = size
        self.len = size * order
        self.top = [['y'] * order for _ in range(order)]
        self.front = [['r'] * order for _ in range(order)]
        self.left = [['b'] * order for _ in range(order)]
        self.right = [['g'] * order for _ in range(order)]
        self.back = [['o'] * order for _ in range(order)]
        self.bottom = [['w'] * order for _ in range(order)]
        self.axis_rotate = (self.base_rotate_x, self.base_rotate_y, self.base_rotate_z)
        self.color = {'y': (0, 255, 255), 'r': (0, 0, 255), 'b': (255, 0, 0),
                      'g': (0, 255, 0), 'o': (0, 128, 255), 'w': (255, 255, 255)}

    def check(self):  # 检测魔方是否还原
        for i in range(self.order):
            for j in range(self.order):
                if self.top[i][j] != self.top[0][0]:
                    return False
                if self.back[i][j] != self.back[0][0]:
                    return False
                if self.front[i][j] != self.front[0][0]:
                    return False
                if self.left[i][j] != self.left[0][0]:
                    return False
                if self.right[i][j] != self.right[0][0]:
                    return False
                if self.bottom[i][j] != self.bottom[0][0]:
                    return False
        return True

    def show(self, wait=0):  # 显示魔方展开图
        for i in range(self.order):
            for j in range(self.order):
                # back
                x, y = self.len + i * self.size, j * self.size
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), self.color[self.back[j][i]], -1)
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), (10, 10, 10), 1)
                # left
                x, y = i * self.size, self.len + j * self.size
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), self.color[self.left[j][i]], -1)
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), (10, 10, 10), 1)
                # top
                x, y = self.len + i * self.size, self.len + j * self.size
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), self.color[self.top[j][i]], -1)
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), (10, 10, 10), 1)
                # right
                x, y = 2 * self.len + i * self.size, self.len + j * self.size
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), self.color[self.right[j][i]], -1)
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), (10, 10, 10), 1)
                # front
                x, y = self.len + i * self.size, 2 * self.len + j * self.size
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), self.color[self.front[j][i]], -1)
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), (10, 10, 10), 1)
                # bottom
                x, y = self.len + i * self.size, 3 * self.len + j * self.size
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), self.color[self.bottom[j][i]], -1)
                cv2.rectangle(self.img, (x, y), (x + self.size, y + self.size), (10, 10, 10), 1)
        cv2.imshow('cube', self.img)
        cv2.waitKey(wait)

    def shuffle(self, times):  # 打乱魔方
        for _ in range(times):
            self.rotate(randint(0, 2), randint(0, self.order - 1), randint(0, 3))

    def rotate(self, axis, index, times):  # 旋转魔方:axis轴,第index层,逆时针times次
        for _ in range(times):
            self.axis_rotate[axis](index)

    def count(self, color='y'):
        count = 0
        for i in range(self.order):
            for j in range(self.order):
                if self.top[i][j] == color:
                    count += 1
        return count

    @staticmethod
    def _column_trans(surface, index, col):
        for i, r in enumerate(surface):
            r[index] = col[i]

    def base_rotate_x(self, index):
        if index == 0:
            self.left = [list(c) for c in zip(*self.left)][::-1]
        elif index == self.order - 1:
            self.right = [list(c)[::-1] for c in zip(*self.right)]
        temp = [r[index] for r in self.top]
        self._column_trans(self.top, index, [r[index] for r in self.front])
        self._column_trans(self.front, index, [r[index] for r in self.bottom])
        self._column_trans(self.bottom, index, [r[index] for r in self.back])
        self._column_trans(self.back, index, temp)

    def base_rotate_y(self, index):
        if index == 0:
            self.back = [list(c)[::-1] for c in zip(*self.back)]
        elif index == self.order - 1:
            self.front = [list(c) for c in zip(*self.front)][::-1]
        temp = self.left[index][::-1]
        self.left[index] = self.top[index]
        self.top[index] = self.right[index]
        self.right[index] = self.bottom[self.order - index - 1][::-1]
        self.bottom[self.order - index - 1] = temp

    def base_rotate_z(self, index):
        if index == 0:
            self.top = [list(c) for c in zip(*self.top)][::-1]
        elif index == self.order - 1:
            self.bottom = [list(c)[::-1] for c in zip(*self.bottom)]
        temp = self.front[index][::-1]
        self.front[index] = [r[self.order - index - 1] for r in self.left]
        self._column_trans(self.left, self.order - index - 1, self.back[self.order - index - 1][::-1])
        self.back[self.order - index - 1] = [r[index] for r in self.right]
        self._column_trans(self.right, index, temp)


cube = Cube(3, 50)
cube.shuffle(100)
while True:
    cube.show(1)
    cube.rotate(*(int(c) for c in input('axis,index,times:').split()))
    if cube.check():
        break
print('Congratulations')
cube.show(0)

到此这篇关于用Python简陋模拟n阶魔方的文章就介绍到这了,更多相关pytho模拟魔方内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python决策树和随机森林算法实例详解
Jan 30 Python
python学习笔记--将python源文件打包成exe文件(pyinstaller)
May 26 Python
python基础学习之如何对元组各个元素进行命名详解
Jul 12 Python
深入解析Python小白学习【操作列表】
Mar 23 Python
Python+threading模块对单个接口进行并发测试
Jun 25 Python
详解mac python+selenium+Chrome 简单案例
Nov 08 Python
利用keras加载训练好的.H5文件,并实现预测图片
Jan 24 Python
python GUI库图形界面开发之PyQt5美化窗体与控件(异形窗体)实例
Feb 25 Python
keras在构建LSTM模型时对变长序列的处理操作
Jun 29 Python
Python3爬虫mitmproxy的安装步骤
Jul 29 Python
基于Python组装jmx并调用JMeter实现压力测试
Nov 03 Python
Python 实现进度条的六种方式
Jan 06 Python
Python OpenCV快速入门教程
python小程序之飘落的银杏
Python Numpy之linspace用法说明
Apr 17 #Python
用Python的绘图库(matplotlib)绘制小波能量谱
用基于python的appium爬取b站直播消费记录
解决numpy数组互换两行及赋值的问题
Apr 17 #Python
用Python实现Newton插值法
Apr 17 #Python
You might like
mysql建立外键
2006/11/25 PHP
PHP 第二节 数据类型之字符串类型
2012/04/28 PHP
golang与PHP输出excel示例
2016/07/22 PHP
自己的js工具 Cookie 封装
2009/08/21 Javascript
js parseInt("08")未指定进位制问题
2010/06/19 Javascript
判断用户是否在线的代码
2011/03/05 Javascript
js 3秒后跳转页面的实现代码
2014/03/10 Javascript
我的Node.js学习之路(二)NPM模块管理
2014/07/06 Javascript
基于javascript的COOkie的操作实现只能点一次
2014/12/26 Javascript
JavaScript中setUTCFullYear()方法的使用简介
2015/06/12 Javascript
JavaScript基础篇(3)之Object、Function等引用类型
2015/11/30 Javascript
深入理解Ajax的get和post请求
2016/06/02 Javascript
js常用DOM方法详解
2017/02/04 Javascript
JavaScript数据结构中串的表示与应用实例
2017/04/12 Javascript
Javascript实现的StopWatch功能示例
2017/06/13 Javascript
原生JS+Canvas实现五子棋游戏实例
2017/06/19 Javascript
NodeJS收发GET和POST请求的示例代码
2017/08/25 NodeJs
发布Angular应用至生产环境的方法
2018/12/10 Javascript
分析Python的Django框架的运行方式及处理流程
2015/04/08 Python
python定时利用QQ邮件发送天气预报的实例
2017/11/17 Python
Python之批量创建文件的实例讲解
2018/05/10 Python
python实现图片批量压缩程序
2018/07/23 Python
简单了解python 生成器 列表推导式 生成器表达式
2019/08/22 Python
浅谈pandas dataframe对除数是零的处理
2020/07/20 Python
python自动打开浏览器下载zip并提取内容写入excel
2021/01/04 Python
如何写出高性能的JSP和Servlet
2013/01/22 面试题
找工作最新求职信
2013/12/22 职场文书
自我评价是什么
2014/01/04 职场文书
电子商务应届生自我鉴定
2014/01/13 职场文书
国际贸易求职信
2014/07/05 职场文书
逃出克隆岛观后感
2015/06/09 职场文书
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
2021/04/12 Python
springboot+VUE实现登录注册
2021/05/27 Vue.js
Vue实现tab导航栏并支持左右滑动功能
2021/06/28 Vue.js
MySQL之MyISAM存储引擎的非聚簇索引详解
2022/03/03 MySQL
pt-archiver 主键自增
2022/04/26 MySQL