您好,欢迎来到步遥情感网。
搜索
您的当前位置:首页C++大作业

C++大作业

来源:步遥情感网
C++程序设计大作业

班 级:

姓 名:

学 号:

邮 箱:

任课教师:

上交时间:

目 录

1. 第一次上机作业……………………2

1.1 作业要求………………………………………………2

1.2 核心代码说明…………………………………………2

1.3 程序运行结果…………………………………………3

2. 第二次上机作业……………………4

2.1 作业要求………………………………………………4

2.2 核心代码说明…………………………………………4

2.3 程序运行结果…………………………………………6

3. 第三次上机作业……………………7

3.1 作业要求………………………………………………7

3.2 核心代码说明…………………………………………7

3.3 程序运行结果…………………………………………9

1

4. 第四次上机作业……………………11

4.1 作业要求………………………………………………11

4.2 核心代码说明…………………………………………11

4.3 程序运行结果…………………………………………22

5. 结课大作业…………………………22

5.1 作业要求………………………………………………22

5.2 核心代码说明…………………………………………22

5.3 程序运行结果…………………………………………45

6. 课程总结……………………………47

1. 第一次上机作业

1.1 作业要求:1.1.1、将一个十进制整型或浮点型转换成二进制

1.1.2、将一个位二进制整数用十进制表示

1.2 核心代码说明

2

1.2.1

int main()

{ double b,x;

int i,j,m=0,zs[50]={0},xs[50]={0}; // zs为整数部分,xs为小数部分

long a;

cout<<\"输入一个十进制整型或浮点型:\";

cin>>x;

a=(long)x; //取x的整数部分

b=x-a;

for(i=0,m=0;a!=0&&i<50;i++) //将整数部分进行转换

{

m++;

zs[i]=a%2;

3

a=a/2;

}

cout<<\"该数的二进制表示为:\";

if((long)x==0) cout<<\"0\";

for(i=m-1;i>=0;i--)

cout<if(b!=0)

cout<<'.';

for(j=0;b!=0&&j<50;j++) {

b=b*2;

xs[j]=(int)b;

//如果x的小数

//将小数进行转换

4

b=b-xs[j];

cout<}

cout<return 0;

}

1.2.2

int main()

{ char c[65];

cout<<\"输入一个位二进制整数:\";

cin>>c;

long s=0,k;

int i;

5

for(i=0;c[i]!='\\0';i++); //将位置移到二进制右边第一位

for(--i,k=1;i>=0;i--) //进行转换

{ if(c[i]=='1')

s=s+k;

k*=2;

}

cout<<\"该二进制整数的十进制表示为:\"<return 0;

}

1.3 程序运行结果

1.3.1

6

1.3.2

2. 第二次上机作业

2.1 作业要求:字符串的解析:输入一个字符串,如“expX”,对其进行解析,解析成相应的函数

2.2核心代码说明

using namespace std;

int main()

7

{

char Equation[20]; //存储输入算式的

char RPn[200], stack[200],ch; //stack栈存的是普通序列,RPn为逆波兰序列

float Stack[200],X; //通过逆波兰进行计算的时候需要的一个操作栈

int priority[256];

int i = 0, j = 0, top = 0,E_long, R_long; //这个用来存储符号的优先级

//下面就是初始化一下一系列符号的优先级

priority[')'] = priority['('] = -1;

priority['+'] = priority['-'] = 0;

priority['*'] = priority['/'] = priority['s'] = priority['c'] = priority['t'] = priority['e'] = 1;

priority['s'] = priority['c'] = priority['t'] = priority['e'] = 2;

8

//输入部分

cout<<\"Please input Equation:\\n\";

cin>>Equation; //输入等式

cout<<\"input X = \"; 式.....

cin>>X;

E_long = strlen(Equation);

//转换成逆波兰的部分

while(E_long --){

ch = Equation[i++];

switch(ch){

case '(' :

stack[top++] = ch;

break;

9

//输入变量X,只是个数字,别输入算

case ')' :

while(stack[top-1]!='('){

RPn[j++] = stack[--top];

}

top --;

break;

case '+':

case '-':

if (priority[stack[top-1]] > 0)

RPn[j++] = stack[--top];

if (Equation[i-2]!='X')

stack[top++] = 'p';

else stack[top++] = ch;

10

break;

case '*':case '/':

if (priority[stack[top-1]] > 1)

RPn[j++] = stack[--top];

stack[top++] = ch;

break;

case's':case'c':case't':case'e':

i+=2;

stack[top++] = ch;

break;

case 'X':

RPn[j++] = ch;

break;

11

}

}

while(top){

RPn[j++] = stack[--top];

}

RPn[j] = 0;

for (int p = 0;p < strlen(RPn); p++)

cout<< RPn[p]<<\"\\n\";

R_long = strlen(RPn);

top = 0;j=0;

//通过已经获得的逆波兰序列进行计算的部分

while(R_long--){

ch = RPn[j++];

12

switch(ch){

case 'X':

Stack[top++] = X;

break;

case '+':

Stack[top-2] = Stack[top-2] + Stack[top-1];

top--;

break;

case '-':

Stack[top-2] = Stack[top-2] - Stack[top-1];

top--;

break;

case '*':

13

Stack[top-2] = Stack[top-2] * Stack[top-1];

top--;

break;

case '/':

Stack[top-2] = Stack[top-2] / Stack[top-1];

top--;

break;

case 's':

Stack[top-1] = sin(Stack[top-1]);

break;

case 'c':

Stack[top-1] = cos(Stack[top-1]);

break;

14

case 't':

Stack[top-1] = tan(Stack[top-1]);

break;

case 'e':

Stack[top-1] = exp(Stack[top-1]);

break;

case 'p':

Stack[top-1] = -Stack[top-1];

break;

}

}

cout<<\"The result is \"<return 0;

15

注:解析函数,输入一个简单的函数,以字符串的形式输入,然后对字符进行检索,检索完后转换成算式的形式进行运算,其中用到逆波兰数列,还有栈存储的方式。最后输出结果即可。

2.3 程序运行结果

3. 第三次上机作业

3.1、题目要求:任给一组数,利用二叉树进行排序、查询、插入、删除、查询出这组数中比首位数大的数的个数。

3.2、核心代码说明:

1)、查询函数

int Search(BiTree T,TElemType key,BiTree f,BiTree *p)

16

//在二叉树中查询被指定的数据,如果该数据存在,返回TRUE,否则返回FALSE。

{

if(!T) //判断T是否为空树

{

*p=f;

return FALSE;

}

else if(T->data==key) {

*p=T;

return TRUE;

}

else if(keydata) //判断该结点指向的数据是否为要查询的数据

17

return Search(T->lchild,key,T,p); //在左子树中继续寻找,找后继结点

else

return Search(T->rchild,key,T,p); //在右子树中继续寻找,找后继结点

}

2)、插入函数

int Insert(BiTree *T,TElemType key)

//将一个结点插入到二叉树中

{

BiTree p, //定义指针

if(!Search(*T,key,NULL,&p))

{

s=(BiTree)malloc(sizeof(BiTNode)); s->data=key;

//建立一个新结点

18

s->lchild=s->rchild=NULL;

if(!p)

*T=s;

else if (keydata)

p->lchild=s;

else

p->rchild=s;

return TRUE;

}

else

return FALSE;

}

3)、删除函数B

19

int DeleteB(BiTree *T,int key)

//寻找要删除的数据在二叉树中所在的结点

{

if(!*T) //判断是否为空树

return FALSE;

else

{

if(key==(*T)->data) //判断该结点是否为指定的结点

return Delete(T);

else if(key<(*T)->data)

return DeleteB(&(*T)->lchild,key); //在左子树中继续寻找

else

return DeleteB(&(*T)->rchild,key); //在左子树中继续寻找

20

}

}

4、删除函数

int Delete(BiTree *p)

//该函数用于删除指定的结点

{

BiTree q,s;

if((*p)->rchild==NULL)

{

q=*p;

*p=(*p)->lchild;

free(q);

}

21

else if((*p)->lchild==NULL)

{

q=*p;

*p=(*p)->rchild;

free(q);

}

else

{

q=*p;

s=(*p)->lchild;

while(s->rchild)

{

q=s;

22

s->rchild;

}

(*p)->data=s->data;

if(q!=*p)

q->rchild=s->lchild;

else

q->lchild=s->lchild;

free(s);

}

return TRUE;

}

5、排序函数

int Sort(int b[],int Num)

23

//该函数将数据由小到大排序

3.3 程序运行结果

24

4、第四次上机作业

25

4.1、作业要求:用半边结构表示正二十面体

4.2、核心代码说明:

typedef CVec3T Vec3f;

typedef CVec4T Vec4f;

namespace WindowParams {

static int WindowWidth = 800;

static int WindowHeight = 600;

static int MainWindow;

};

using namespace std;

using std::ifstream;

struct Vertex{

struct HalfEdge *startEdge;

Vec3f coord;

26

int id;

};

struct Face{

struct HalfEdge *firstEdge;

struct Vertex *ver;

int nPolygon;

};

struct HalfEdge{

struct Vertex *head;

struct Face *leftf;

struct HalfEdge *sym;

struct HalfEdge *next;

};

27

typedef std::map > EdgeMap;

EdgeMap edgemap;

Vertex *vertices;

Face *faces;

HalfEdge *he;

int nFace; int selectedPoly = -1 ;

Vec3f CameraPosition(5,5,5);

Vec3f SphereCenter(0,0,0);

float SphereRadius = 2;

float ExaminerRotAngle = 0;

Vec3f ExaminerRotAxis(0,1,0);

HMatrix ExaminerRotation;

28

//对当前对象的面数

//绘制的对象载入OBJ文件

void DrawObj()

{

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

gluLookAt(CameraPosition.x(),CameraPosition.y(),CameraPosition.z(),0,0,0,0,1,0);

glPushMatrix();

glMultMatrixf(ExaminerRotation);

glEnable(GL_LIGHTING);

for(int i = 0; i < nFace ; i ++){

//在面阵列的每个面使用名称索引

glPushName((GLuint)i)

//如果面对选择,强调

29

if(selectedPoly == i){

glDisable(GL_LIGHTING);

glColor3f(1.0, 0.0, 0.0);

}

Vec3fnormal=cross(faces[i].ver[1].coord-faces[i].ver[0].coord, faces[i].ver[2].coord-faces[i].ver[1].coord);

glBegin(GL_POLYGON);

glNormal3f(normal.x(),normal.y(),normal.z());

for(int j =0 ; j < faces[i].nPolygon; j++){ );

glVertex3f(faces[i].ver[j].coord.x(),faces[i].ver[j].coord.y(),faces[i].ver[j].coord.z()

}

glEnd();

glEnable(GL_LIGHTING);

glPopName();

30

}

glDisable(GL_LIGHTING);

glPopMatrix();

glFlush();

}

static void setupCameraView( void )

// 此程序集的投影,摄像机的位置,和方向.

{

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(40,

WindowParams::WindowWidth/float(WindowParams::WindowHeight), 1, 10);

}

void Reshape(int width, int height)

31

{

WindowParams::WindowWidth = width;

WindowParams::WindowHeight = height;

glViewport(0,0,width,height);

}

void Draw()

{

setupCameraView();

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

gluLookAt(CameraPosition.x(),CameraPosition.y(),CameraPosition.z(),0,0,0,0,1,0);

glClearColor( 0.6, 0.6,0.6,0);

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

32

glEnable(GL_DEPTH_TEST);

//使法线的自动缩放到单位长度

glEnable(GL_NORMALIZE);

glEnable(GL_LIGHT0);

glEnable(GL_LIGHT1);

// 定向(W = 0)沿Z轴

glLightfv(GL_LIGHT0,GL_DIFFUSE, Vec4f(1, 1, 1,1));

glLightfv(GL_LIGHT0,GL_POSITION, Vec4f(0, 0, 1,0));

glLightfv(GL_LIGHT1,GL_DIFFUSE,Vec4f(1, 1, 1,1));

glLightfv(GL_LIGHT1,GL_POSITION, Vec4f(0, 0, -1,0));

glPushMatrix();

glMultMatrixf(ExaminerRotation);

glColor3f(1.0,1.0,1.0);

33

glutWireSphere(SphereRadius,10,10);

DrawObj();

glPopMatrix();

glutSwapBuffers();

}

Vec3f ScreenToWorld(int windowid, int x, int y)

{

glutSetWindow(windowid);

GLdouble modelview[16];

GLdouble projection[16];

GLint viewport[4];

double world_x, world_y, world_z;

// 获取当前的模型视图,投影变换和视口

34

glGetDoublev(GL_MODELVIEW_MATRIX,modelview);

glGetDoublev(GL_PROJECTION_MATRIX,projection);

glGetIntegerv(GL_VIEWPORT,viewport);

// 这个函数计算逆VPM和将其应用于(X,Y,0)将从像素到球坐标

// 计算对应于像素的圆台平面附近的点的坐标(x,y)

gluUnProject(x,y,0,modelview,projection,viewport, &world_x,&world_y,&world_z);

return Vec3f(world_x,world_y,world_z);

}

bool SpherePoint(const Vec3f& center, float r, const Vec3f& pscreen, Vec3f& psphere) {

Vec3f v = (pscreen- CameraPosition).dir();

Vec3f d = CameraPosition-center;

float ddotv = d.dot(v);

35

float D = ddotv*ddotv-d.dot() +r*r;

if (D < 0) return false;

float t = -ddotv-sqrt(D);

psphere = CameraPosition+v*t;

return true;

}

//from hit_sample

static void processHits( int hits, GLuint *buffer )

// 个函数的步骤通过选择缓冲区,并更新

//任何信息,用新采摘的场景中的物体的影响。

//重要的:这是一个简单的实现(它不会做任何事)和

//许多它的东西是不是真的需要在这种情况下

//点击:点击发生数

36

//缓冲区:一个指向选择缓冲区

{

int i, j;

GLuint *ptr = buffer;

GLuint nameStackDepth, currname, zmin=0, zmax=0;

GLuint zminimum=UNSIGNED_INT_MAX, //存储深度至少到目前为止

finalName = -1; //存储靠近相机的ID

for( i = 0; i < hits; i++ )

{

nameStackDepth = *ptr++;

zmin = *ptr++;

zmax = *ptr++;

for( j = 0; j < nameStackDepth; j++ )

37

{

currname = *ptr++;

if(zmin < zminimum){

zminimum = zmin;

finalName = currname;

}

}

}

if(finalName!= -1){

if(selectedPoly == finalName)

selectedPoly = -1;

//检查它是否是更接近相机

38

else

selectedPoly = finalName;

}

glutPostRedisplay();

} #define BUFSIZE 256 //from hit_sample

static void checkHits( int x, int y )

//这功能把采摘和呼叫处理功能

// x,y:位置在其中挑选要执行

{

GLuint selectBuf[BUFSIZE];

GLint hits;

// 结束processhits端功能

// 选择将256个缓冲区大小

39

GLint viewport[4];

GLdouble matrix[16];

glGetIntegerv( GL_VIEWPORT, viewport );

glSelectBuffer( BUFSIZE, selectBuf );

glRenderMode( GL_SELECT );

glInitNames();

glMatrixMode( GL_PROJECTION );

glPushMatrix();

setupCameraView();

glMatrixMode( GL_PROJECTION );

glGetDoublev( GL_PROJECTION_MATRIX, matrix );

glLoadIdentity();

gluPickMatrix( (double)x, (double)y,

40

X_PICK_SIZE, Y_PICK_SIZE, viewport );

// 创建采摘区附近的光标位置

glMultMatrixd( matrix );

DrawObj();

glMatrixMode( GL_PROJECTION );

glPopMatrix();

hits = glRenderMode( GL_RENDER );

processHits( hits, selectBuf );checkHit

}

// 结束checkHit端功能

// 鼠标按钮被按下或释放

Vec3f CurrentPsphere;

Vec3f NewPsphere;

41

void MouseMotion(int x, int y) {

y = WindowParams::WindowHeight - y-1;

Vec3f psphere;

if(SpherePoint(SphereCenter,SphereRadius,ScreenToWorld(WindowParams::MainWindow,x,y),psphere)) {

ExaminerRotAxis psphere-SphereCenter);

= cross(CurrentPsphere-SphereCenter,

ExaminerRotAngle=acos((CurrentPsphere-SphereCenter).dot(psphere-SphereCenter)/SphereRadius/SphereRadius);

ExaminerRotation =

HMatrix::Rotation(ExaminerRotAngle,ExaminerRotAxis)*ExaminerRotation;

CurrentPsphere = psphere;

}

glutPostRedisplay();

}

42

void MouseClick (int button, int state, int x, int y)

{

y = WindowParams::WindowHeight - y-1;

if(state == GLUT_DOWN)

{

Vec3f psphere;

if(SpherePoint(SphereCenter,SphereRadius,ScreenToWorld(WindowParams::MainWindow,x,y),psphere)) {

CurrentPsphere = psphere;

NewPsphere = psphere;

}

glutPostRedisplay();

//选择

checkHits(x, y);

43

}

if(state == GLUT_UP) {

CurrentPsphere = NewPsphere;

}

}

//载入OBJ文件和构建数据结构

void LoadFile()

{

char type;

ifstream file(\"dodecahedron.obj\

if(!file)

{

cerr<<\"File could not be found.\"<44

exit(1);

}

int numOfVertices=0;

int numOfFaces=0;

while(file>>type)

{

if(type =='v')

numOfVertices++; else if(type == 'f')

numOfFaces++;

else

cout<<\"not valid input\"<file.ignore(100,'\\n');

45

}

file.clear();

file.seekg(0); //重置文件位置

vertices = new Vertex[numOfVertices];

faces = new Face[numOfFaces];

nFace = numOfFaces;

float x, y, z;

for(int i=0 ; i{

file>>type;

file>>x>>y>>z;

file.ignore(100,'\\n');

Vec3f v(x,y,z);

46

vertices[i].coord = v;

}

file.setf(ios::skipws);

for(i=0; istd::vector v; std::vector::const_iterator p;

file>>type;

while(file>>vi)

{

v.push_back(vi);

}

faces[i].ver = new Vertex[v.size()];

//利用矢量存储顶点的身份目前的面由47

faces[i].nPolygon = v.size();

he = new HalfEdge[v.size()];

int j = 0;

for(p= v.begin(); p != v.end(); p++)

{

faces[i].ver[j] = vertices[*p-1]; //接入点从阵列的顶点根据其身份

faces[i].ver[j].id = *p; //存储它的id

j++;

}

faces[i].firstEdge = &he[0];

//构建半边

for(j=0, p=v.begin() ; jfaces[i].ver[j].startEdge = &he[j];

48

he[j].head = &faces[i].ver[(j+1)%v.size()];

he[j].leftf = &faces[i];

he[j].next = &he[(j+1)%v.size()];

if((p+1)!= v.end())

{

Pair pair(*p, *(p+1));

edgemap.insert(EdgeMap::value_type(pair, &he[j])); }

else

{

Pair pair(*p, *v.begin());

edgemap.insert(EdgeMap::value_type(pair, &he[j])); }

49

//insert to edgemap

//insert to edgemap

}

file.clear();

}

EdgeMap::const_iterator iter;

//建立半边符号指针

for(iter = edgemap.begin(); iter != edgemap.end(); iter++)

{

EdgeMap::const_iterator iter1;

EdgeMap::const_iterator iter2;

Pair p1(iter->first.a,iter->first.b);

Pair p2(iter->first.b,iter->first.a);

iter1 = edgemap.find(p1);

iter2 = edgemap.find(p2);

50

iter1->second->sym = iter2->second;

}

}

void triangulate(){

int newNumOfFaces = 0; for(int i = 0 ; i< nFace ; i++){

if(faces[i].nPolygon > 3){

newNumOfFaces += faces[i].nPolygon - 2;

}

else

newNumOfFaces ++;

}

Face *newFaces;

51

//在三角面总数量

newFaces = new Face[newNumOfFaces];

int index = 0;

for(i = 0 ; i< nFace; i++){

if(faces[i].nPolygon >3)

{ //,如果它由3个以上的顶点

for(int j = 0 ; j< faces[i].nPolygon-2; j++){

newFaces[index+j].nPolygon = 3;

newFaces[index+j].ver = new Vertex[3];

for(int k=0 ; k<3; k++){

if(k==0){

newFaces[index+j].ver[k] = faces[i].ver[0];

newFaces[index+j].ver[k].id = faces[i].ver[0].id;

}

52

else{

newFaces[index+j].ver[k] = faces[i].ver[k+j];

newFaces[index+j].ver[k].id = faces[i].ver[k+j].id;

}

}

}

index += faces[i].nPolygon -2;

}

else

{

newFaces[index].nPolygon = 3;

newFaces[index].ver = new Vertex[3];

for(int k=0 ; k<3; k++){

53

newFaces[index].ver[k] = faces[i].ver[k];

newFaces[index].ver[k].id = faces[i].ver[k].id;

}

index += 1;

}

}

HalfEdge newHE[3];

//半边图重构

for(i = 0; inewFaces[i].firstEdge = &newHE[0];

for(int j=0 ; j<3; j++){

newFaces[i].ver[j].startEdge = &newHE[j];

newHE[j].head = &newFaces[i].ver[(j+1)%3];

54

newHE[j].leftf = &newFaces[i];

newHE[j].next = &newHE[(j+1)%3];

Pair pair(newFaces[i].ver[j].id, newFaces[i].ver[(j+1)%3].id);

edgemap.insert(EdgeMap::value_type(pair, &newHE[j]));

}

}

//建立半边符号指针

EdgeMap::const_iterator iter;

for(iter = edgemap.begin(); iter != edgemap.end(); iter++){

EdgeMap::const_iterator iter1;

EdgeMap::const_iterator iter2;

Pair p1(iter->first.a,iter->first.b);

Pair p2(iter->first.b,iter->first.a);

55

iter1 = edgemap.find(p1);

iter2 = edgemap.find(p2);

iter1->second->sym = iter2->second;

}

nFace = newNumOfFaces;

faces = newFaces;

selectedPoly = -1;

}

void deleteFace()

{

//检查是否面临选择

if(selectedPoly >= 0){

//调整edgemap

56

for(int i = 0; iPair

p(faces[selectedPoly].ver[i].id,faces[selectedPoly].ver[(i+1)%(faces[selectedPoly].nPolygon)].id);

EdgeMap::const_iterator iter;

iter = edgemap.find(p);

iter->second->leftf = NULL;

}

for(i= selectedPoly; ifaces[i].firstEdge = faces[i+1].firstEdge;

faces[i].ver = faces[i+1].ver;

faces[i].nPolygon = faces[i+1].nPolygon;

}

nFace = nFace -1;

57

selectedPoly = -1;

}

}

void subdivision()

{

triangulate();

}

void keyboard(unsigned char key, int x, int y)

{

switch(key){

case 't':

case 'T':

triangulate();

58

glutPostRedisplay();

break;

case 'd':

case 'D':

deleteFace();

glutPostRedisplay();

break;

case 's':

case 'S':

subdivision();

glutPostRedisplay();

break;

default:

59

break;

}

}

int main(int argc, char* argv[])

{

glutInit(&argc, argv);

// 初始化显示模式:4个颜色分量,双缓冲,深度缓冲区

glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);

glutInitWindowSize(WindowParams::WindowWidth,WindowParams::WindowHeight);

WindowParams::MainWindow = glutCreateWindow(\"Trackball\");

LoadFile();

glutDisplayFunc(Draw);

60

glutReshapeFunc(Reshape);

//获取当鼠标按钮被按下或释放

glutMouseFunc(MouseClick);

glutMotionFunc(MouseMotion);

glutKeyboardFunc(keyboard);

// 这是一个无限循环获取事件-事件不会返回

glutMainLoop();

return 0;

}

4.3 程序运行结果

61

5. 结课大作业

5.1 作业要求:三阶魔方还原

5.2 核心代码说明

bool cube::input_cube(){

cout<<\"输入魔方颜色(蓝色:B,橙色:O,绿色:G,红色:R,白色:W,黄色:Y):\"<cout<<\"输入顶面色块(请从左上角起一排一排输入,共9块):\"<//输入魔方顶面色块

62

cin>>vertex[0][0]>>edge[0][0]>>vertex[1][0];

cin>>edge[3][0]>>center[0]>>edge[1][0];

cin>>vertex[3][0]>>edge[2][0]>>vertex[2][0];

cout<<\"输入侧面第一层色块(从正面左上角开始逆时针输入,共12块):\"<//输入魔方侧面第一层色块

cin>>vertex[3][1]>>edge[2][1]>>vertex[2][2];

cin>>vertex[2][1]>>edge[1][1]>>vertex[1][2];

cin>>vertex[1][1]>>edge[0][1]>>vertex[0][2];

cin>>vertex[0][1]>>edge[3][1]>>vertex[3][2];

cout<<\"输入侧面第二层色块(从正面左起第一个开始逆时针输入,共12块):\"<//输入魔方侧面第二层色块

cin>>edge[7][0]>>center[4]>>edge[6][1];

cin>>edge[6][0]>>center[3]>>edge[5][1];

63

cin>>edge[5][0]>>center[2]>>edge[4][1];

cin>>edge[4][0]>>center[1]>>edge[7][1];

cout<<\"输入侧面第三层色块(从正面左下角开始逆时针输入,共12块):\"<//输入魔方侧面第三层色块

cin>>vertex[7][1]>>edge[10][1]>>vertex[6][2];

cin>>vertex[6][1]>>edge[9][1]>>vertex[5][2];

cin>>vertex[5][1]>>edge[8][1]>>vertex[4][2];

cin>>vertex[4][1]>>edge[11][1]>>vertex[7][2];

cout<<\"输入底面色块(将魔方向后翻滚180度,从左上角起一排一排输入,共9块):\"<//输入魔方底面色块

cin>>vertex[7][0]>>edge[10][0]>>vertex[6][0];

cin>>edge[11][0]>>center[5]>>edge[9][0];

cin>>vertex[4][0]>>edge[8][0]>>vertex[5][0];

cout<while(getchar()!=10)continue;

return 1;

}

void cube::output_cube(){

// 在完成一个步骤输出魔方各面色块的函数

cout<<\"正面:\"<cout<cout<cout<cout<<\"背面:\"<cout<cout<65

cout<cout<<\"右面:\"<cout<cout<cout<cout<<\"左面\"<cout<cout<cout<cout<<\"顶面:\"<cout<cout<cout<66

cout<<\"底面:\"<cout<cout<cout<}

void cube::basic_move_R(){

char t1[3];

for(int i=0;i<3;i++)

t1[i]=vertex[1][i];

vertex[1][0]=vertex[2][2];vertex[1][1]=vertex[2][0];vertex[1][2]=vertex[2][1];

vertex[2][0]=vertex[6][2];vertex[2][1]=vertex[6][1];vertex[2][2]=vertex[6][0];

vertex[6][0]=vertex[5][1];vertex[6][1]=vertex[5][2];vertex[6][2]=vertex[5][0];

vertex[5][0]=t1[1];vertex[5][1]=t1[0];vertex[5][2]=t1[2];

67

char t2[2];

t2[0]=edge[1][0];t2[1]=edge[1][1];

edge[1][0]=edge[6][1];edge[1][1]=edge[6][0];

edge[6][0]=edge[9][1];edge[6][1]=edge[9][0];

edge[9][0]=edge[5][0];edge[9][1]=edge[5][1];

edge[5][0]=t2[0];edge[5][1]=t2[1];

}

void cube::basic_move_L(){

char t[3];

t[0]=vertex[3][1];t[1]=edge[7][0];t[2]=vertex[7][1];

vertex[3][1]=vertex[7][0];edge[7][0]=edge[11][0];vertex[7][1]=vertex[4][0];

vertex[7][0]=vertex[4][2];edge[11][0]=edge[4][1];vertex[4][0]=vertex[0][2];

vertex[4][2]=vertex[0][0];edge[4][1]=edge[3][0];vertex[0][2]=vertex[3][0];

68

vertex[0][0]=t[0];edge[3][0]=t[1];vertex[3][0]=t[2];

t[0]=vertex[0][1];t[1]=edge[3][1];t[2]=vertex[3][2];

vertex[0][1]=vertex[3][2];edge[3][1]=edge[7][1];vertex[3][2]=vertex[7][2];

vertex[3][2]=vertex[7][2];edge[7][1]=edge[11][1];vertex[7][2]=vertex[4][1];

vertex[7][2]=vertex[4][1];edge[11][1]=edge[4][0];vertex[4][1]=vertex[0][1];

vertex[4][1]=t[0];edge[4][0]=t[1];vertex[0][1]=t[2];

}

void cube::basic_move_U()

{

char

c1=vertex[3][1],c2=vertex[3][2],c3=edge[3][1],c4=vertex[3][0],c5=edge[3][0];

for(int i=3;i>0;i--)

{

vertex[i][1]=vertex[i-1][1];vertex[i][2]=vertex[i-1][2];vertex[i][0]=vertex[i-1][0];

69

edge[i][1]=edge[i-1][1];edge[i][0]=edge[i-1][0];

}

vertex[0][1]=c1;vertex[0][2]=c2;vertex[0][0]=c4;

edge[0][1]=c3;edge[0][0]=c5;

}

void cube::basic_move_D()

{

char

c1=vertex[7][1],c2=vertex[7][2],c3=edge[11][1],c4=vertex[7][0],c5=edge[11][0];

for(int i=7;i>4;i--)

{

vertex[i][1]=vertex[i-1][1];vertex[i][2]=vertex[i-1][2];vertex[i][0]=vertex[i-1][0];

edge[i+4][1]=edge[i+3][1];edge[i+4][0]=edge[i+3][0];

}

70

vertex[4][1]=c1;vertex[4][2]=c2;vertex[4][0]=c4;

edge[8][1]=c3;edge[8][0]=c5;

}

void cube::basic_move_M_h()

{

char c1=edge[7][0],c2=edge[7][1],c3=center[4];

for(int i=3;i>0;i--)

{

edge[i+4][0]=edge[i+3][0];

edge[i+4][1]=edge[i+3][1];

center[i+1]=center[i];

}

edge[4][0]=c1;edge[4][1]=c2;center[1]=c3;

71

}

void cube::basic_move_M_v()

{

char t[3];

t[0]=edge[2][1];t[1]=center[4];t[2]=edge[10][1];

edge[2][1]=edge[10][0];center[4]=center[5];edge[10][1]=edge[8][0];

edge[10][0]=edge[8][1];center[5]=center[2];edge[8][0]=edge[0][1];

edge[8][1]=edge[0][0];center[2]=center[0];edge[0][1]=edge[2][0];

edge[0][0]=t[0];center[0]=t[1];edge[2][0]=t[2];

}

void cube::basic_move_r()

{

basic_move_R();

72

basic_move_M_v();

}

void cube::basic_move_F()

{

basic_move_x();basic_move_U();

basic_move_x();basic_move_x();basic_move_x();

}

void cube::basic_move_f()

{

basic_move_x();basic_move_u();

basic_move_x();basic_move_x();basic_move_x();

}

void cube::basic_move_B()

73

{

basic_move_x();basic_move_x();

basic_move_F();

basic_move_x();basic_move_x();

}

void cube::basic_move_b()

{

basic_move_x();basic_move_x();

basic_move_f();

basic_move_x();basic_move_x();

}

void cube::basic_move_u()

{

74

basic_move_U();

basic_move_M_h();

}

void cube::basic_move_d()

{

basic_move_D();

basic_move_M_h();

}

void cube::basic_move_x()

{

basic_move_M_v();

basic_move_R();

basic_move_L();

75

}

void cube::basic_move_y()

{

basic_move_U();

basic_move_M_h();

basic_move_D();

}

void cube::basic_move_z()

{

basic_move_f();

basic_move_B();basic_move_B();basic_move_B();

}

void cube::R()

76

{

cout<NUM++;

basic_move_R();

}

void cube::R2()

{

cout<NUM++;

basic_move_R();basic_move_R();

}

void cube::R_()

{

77

cout<NUM++;

basic_move_R();basic_move_R();basic_move_R();

}

void cube::L()

{

cout<NUM++;

basic_move_L();basic_move_L();basic_move_L();

}

void cube::L2()

{

cout<78

NUM++;

basic_move_L();basic_move_L();

}

void cube::L_()

{

cout<NUM++;

basic_move_L();

}

void cube::r()

{

cout<NUM++;

79

basic_move_r();

}

void cube::r2()

{

cout<NUM++;

basic_move_r();basic_move_r();

}

void cube::r_()

{

cout<NUM++;

basic_move_r();basic_move_r();basic_move_r();

80

}

void cube::F()

{

cout<NUM++;

basic_move_F();

}

void cube::F2()

{

cout<NUM++;

basic_move_F();basic_move_F();

}

81

void cube::F_()

{

cout<NUM++;

basic_move_F();basic_move_F();basic_move_F();

}

void cube::f()

{

cout<NUM++;

basic_move_f();

}

void cube::f2()

82

{

cout<NUM++;

basic_move_f();basic_move_f();

}

void cube::f_()

{

cout<NUM++;

basic_move_f();basic_move_f();basic_move_f();

}

void cube::B()

{

83

cout<NUM++;

basic_move_B();basic_move_B();basic_move_B();

}

void cube::B2()

{

cout<NUM++;

basic_move_B();basic_move_B();

}

void cube::B_()

{

cout<84

NUM++;

basic_move_B();

}

void cube::U()

{

cout<NUM++;

basic_move_U();

}

void cube::U2()

{

cout<NUM++;

85

basic_move_U();basic_move_U();

}

void cube::U_()

{

cout<NUM++;

basic_move_U();basic_move_U();basic_move_U();

}

void cube::u()

{

cout<NUM++;

basic_move_u();

86

}

void cube::u2()

{

cout<NUM++;

basic_move_u();basic_move_u();

}

void cube::u_()

{

cout<NUM++;

basic_move_u();basic_move_u();basic_move_u();

}

87

void cube::D()

{

cout<NUM++;

basic_move_D();

}

void cube::D2()

{

cout<NUM++;

basic_move_D();basic_move_D();

}

void cube::D_()

88

{

cout<NUM++;

basic_move_D();basic_move_D();basic_move_D();

}

void cube::M_h()

{

cout<NUM++;

basic_move_M_h();

}

void cube::M_h2()

{

cout<NUM++;

basic_move_M_h();basic_move_M_h();

}

void cube::M_h_()

{

cout<NUM++;

basic_move_M_h();basic_move_M_h();basic_move_M_h();

}

void cube::M_v()

{

cout<90

\"<NUM++;

basic_move_M_v();

}

void cube::M_v2()

{

cout<NUM++;

basic_move_M_v();basic_move_M_v();

}

void cube::M_v_()

{

cout<91

NUM++;

basic_move_M_v();basic_move_M_v();basic_move_M_v();

}

void cube::x()

{

cout<NUM++;

basic_move_x();

}

void cube::x2()

{

cout<NUM++;

92

basic_move_x();basic_move_x();

}

void cube::x_()

{

cout<NUM++;

basic_move_x();basic_move_x();basic_move_x();

}

void cube::y()

{

cout<NUM++;

93

basic_move_y();

}

void cube::y2()

{

cout<NUM++;

basic_move_y();basic_move_y();

}

void cube::y_()

{

cout<NUM++;

basic_move_y();basic_move_y();basic_move_y();

94

}

void cube::z()

{

cout<NUM++;

basic_move_z();

}

void cube::z2()

{

cout<NUM++;

basic_move_z();basic_move_z();

}

95

void cube::z_()

{

cout<NUM++;

basic_move_z();basic_move_z();basic_move_z();

}

void cube::bottom_cross()

{

//该函数用来还原顶面的十字架

//在底面及第一、二层还原后进行该步骤

NUM=1;

for(int count=0;count<4;count++)

{

96

int loc;char c1=center[4],c2=center[0];

for(loc=0;loc<12;loc++)

{

if(edge[loc][0]==c1||edge[loc][0]==c2)

if(edge[loc][1]==c1||edge[loc][1]==c2)

break;

}

if(loc>=0&&loc<=3)

{

if(edge[loc][0]==center[0])

{

if(count==0)

{

97

switch(loc)

{case 0:U2();break;case 1:U();break;case 2:break;case 3:U_();break;}

y();continue;

}

else

if(loc==2)

{y();continue;}

}

switch(loc)

{case 0:B2();break;case 1:R2();break;case 2:F2();break;case 3:L2();break;}

count--;continue;

}

else if(loc>=4&&loc<=7)

98

{

switch(loc)

{case 4:M_h_();F_();M_h();break;case 5:M_h();F();M_h_();break;case

6:F();break;case 7:F_();break;}

count--;continue;

}

else if(loc>=8&&loc<=11)

{

if(edge[loc][0]==center[0])

{

switch (loc)

{case 8:D2();break;case 9:D();break;case 10:break;case 11:D_();break;}

F2();

}

99

else

{

switch (loc)

{case 8:D_();break;case 9:D2();break;case 10:D();break;case 11:;break;}

L_();F();L();

}

}

y();cout<}

cout<<\"顶面十字还原成功,按回车键继续下一步,输入a显示此时魔方各面情况\"<}

void cube::bottom_vertex()

{

100

// 将顶面四角对齐并将顶面转至底面

NUM=1;

for(int count=0;count<4;count++)

{

int loc;char c1=center[0],c2=edge[2][1],c3=edge[1][1];

for(loc=0;loc<8;loc++)

{

if(vertex[loc][0]==c1||vertex[loc][0]==c2||vertex[loc][0]==c3)

if(vertex[loc][1]==c1||vertex[loc][1]==c2||vertex[loc][1]==c3)

if(vertex[loc][2]==c1||vertex[loc][2]==c2||vertex[loc][2]==c3)

break;

}

if(loc>=0&&loc<=3)

101

{

if(loc==2&&vertex[loc][1]==edge[1][1]&&vertex[loc][2]==edge[2][1]&&vertex[loc][0]==center[0])

{y();continue;}

else

{

switch(loc)

{case 0:{

if(vertex[0][0]==center[0]||vertex[0][2]==center[0])

{B_();D_();B();}

else

{L_();D();L();}

}break;

case 1:{

102

if(vertex[1][0]==center[0]||vertex[1][1]==center[0])

{B();D();B_();}

else

{R();D_();R_();}

}break;

case 2:{

if(vertex[2][0]==center[0]||vertex[2][1]==center[0])

{R_();D();R();}

else

{F();D_();F_();}

}break;

case 3:{

if(vertex[3][0]==center[0]||vertex[3][2]==center[0])

103

{L();D_();L_();}

else

{F_();D();F();}

}break;

}

count--;continue;

}

}

else if(loc>=4&&loc<=7)

{

if(vertex[loc][0]==center[0])

{

switch(loc)

104

{case 4:D2();break;case 5:D();break;case 6:break;case 7:D_();break;}

F();D();F_();

count--;continue;

}

else if(vertex[loc][1]==center[0])

{

switch(loc)

{case 4:D2();break;case 5:D();break;case 6:break;case 7:D_();break;}

R_();D();R();

}

else

{

switch(loc)

105

{case 4:D_();break;case 5:D2();break;case 6:D();break;case 7:break;}

R_();D_();R();

}

}

y();

cout<}

x2();

cout<<\"魔方底层还原成功,按回车键继续下一步,输入a显示此时魔方各面情况\"<}

void cube::middlelayer()

{

// 还原第二层

106

NUM=1;

for(int count=0;count<4;count++)

{

int loc;

for(loc=0;loc<7;loc++)

{

if(edge[loc][0]==center[4]||edge[loc][0]==center[3])

if(edge[loc][1]==center[4]||edge[loc][1]==center[3])

break;

}

if(loc>=0&&loc<=3)

{

if(edge[loc][1]==center[4])

107

{

switch(loc)

{case 0:U_();break;case 1:U2();break;case 2:U();break;case 3:break;}

R();U_();R_();U_();F_();U();F();

}

else if(edge[loc][1]=center[3])

{

switch(loc)

{case 0:;break;case 1:U_();break;case 2:U2();break;case 3:U();break;}

F_();U();F();U();R();U_();R_();

}

}

else if(loc>=4&&loc<=7)

108

{

if(edge[loc][0]==center[3]&&edge[loc][1]==center[4]&&loc==6)

{y();continue;}

switch(loc)

{case 4:y2();break;case 5:y();break;case 6:break;case 7:y_();break;}

int loc1;

for(loc1=0;loc1<4;loc1++)

{

if(edge[loc1][0]==center[0]||edge[loc1][1]==center[0])

break;

}

loc1=(loc1==4)?2:loc1;

switch(loc1)

109

{case 0:U2();break;case 1:U();break;case 2:break;case 3:U_();break;}

U();R();U_();R_();U_();F_();U();F();

switch(loc)

{case 4:y2();break;case 5:y_();break;case 6:break;case 7:y();break;}

count--;continue;

}

y();

cout<}

cout<<\"魔方第二层还原成功,按回车键继续下一步,输入a显示此时魔方各面情况\"<}

void cube::top_cross()

{

110

cout<NUM=1;

int num=0;

for(int i=0;i<4;i++)

{

if(edge[i][0]==center[0])

num++;

}

if(num==0)

{F();R();U();R_();U_();F_();num=2;}

if(num==2)

{

int loc[2]={0,0};

111

for(int i=0,j=0;i<4;i++)

{

if(edge[i][0]==center[0])

{loc[j]=i;j++;}

}

if(loc[1]-loc[0]==2)

{

switch(loc[0])

{case 0:U();break;case 1:break;}

F();R();U();R_();U_();F_();

}

else

{

112

switch(loc[0])

{case 0:{

if(loc[1]==3)

U2();

else

U();

}break;

case 1:break;case 2:U_();break;}

f();R();U();R_();U_();f_();

}

}

cout<<\"魔方顶层十字还原成功,按回车键继续下一步,输入a显示此时魔方各面情况\"<NUM=1;

113

}

void cube::top_face()

{

cout<NUM=1;

int num=0;

for(int i=0;i<4;i++)

{

if(vertex[i][0]==center[0])

num++;

}

if(num==0)

{

114

int loc1=0,loc2=0;

loc1=(vertex[0][1]==center[0])?1:2;

loc2=(vertex[2][1]==center[0])?1:2;

if(loc1==loc2)

{

switch(loc1)

{case 1:U();break;case 2:break;}

R();U2();R_();U_();R();U();R_();U_();R();U_();R_();

}

else

{

switch(loc1)

{case 1:{

115

if(vertex[3][1]==center[0])

U();

};break;

case 2:{

if(vertex[3][1]==center[0])

U2();

else

U_();

}break;

}

R();U2();R2();U_();R2();U_();R2();U2();R();

}

}

116

else if(num==1)

{

int loc1,loc2;

for(int i=0;i<4;i++)

{

if(vertex[i][0]!=center[0])

loc1=(vertex[i][1]==center[0])?1:2;

else

loc2=i;

}

if(loc1==1)

{

switch(loc2)

117

{case 0:U();break;case 1:break;case 2:U_();break;case 3:U2();break;}

R();U2();R_();U_();R();U_();R_();

}

else

{

switch(loc2)

{case 0:U2();break;case 1:U();break;case 2:break;case 3:U_();break;}

R_();U2();R();U();R_();U();R();

}

}

else if(num==2)

{

int loc[2];

118

for(int i=0,j=0;i<4;i++)

{

if(vertex[i][0]!=center[0])

{loc[j]=i;j++;}

}

if(loc[1]-loc[0]==2)

{

int loc1;

loc1=(vertex[loc[0]][1]==center[0])?loc[1]:loc[0];

switch(loc1)

{case 0:U2();break;case 1:U();break;case 2:break;case 3:U_();break;}

F_();r();U();R_();U_();r_();F();R();

}

119

else

{

switch(loc[0])

{case 0:{

if(loc[1]==3)

U_();

else

U2();

}break;

case 1:U();break;case 2:break;

}

if(vertex[2][1]==center[0])

{U();r();U();R_();U_();r_();F();R();F_();}

120

else

{R();U();R_();U();R();U2();R_();U();R();U2();R_();U_();R();U_();R_();}

}

}

cout<<\"魔方顶面颜色统一成功,按回车键继续下一步,输入a显示此时魔方各面情况\"<NUM=1;

}

void cube::top_vertex()

{

cout<NUM=1;

int loc[2]={-1,-1};int num=0;

x:

121

for(int i=0;i<4;i++)

{

if(vertex[i][2]==vertex[(i+1)%4][1])

{

num++;

if(num==1)

{loc[0]=i;loc[1]=(i+1)%4;}

}

}

if(num==0)

{

x_();R2();D2();R_();U_();R();D2();R_();U();R_();x();

goto x;

122

}

else if(num!=4)

{

switch(loc[0])

{case 0:U();break;case 1:break;case 2:U_();break;case 3:U2();break;}

x_();R2();D2();R_();U_();R();D2();R_();U();R_();x();

}

int loc1;

for(loc1=1;loc1<5;loc1++)

{

if(vertex[3][2]==center[loc1])

break;

}

123

switch(loc1)

{case 1:break;case 2:U();break;case 3:U2();break;case 4:U_();break;}

cout<<\"顶面各角排序完成,按回车键继续下一步,输入a显示此时魔方各面情况\"<NUM=1;

}

void cube::top_edge()

{

cout<NUM=1;

int num=0;

for(int i=0;i<3;i++)

{

if(edge[i][1]!=center[i+2])

124

num++;

}

if(edge[3][1]!=center[1])

num++;

if(num==3)

{

int loc;

for(loc=0;loc<3;loc++)

{

if(edge[loc][1]==center[loc+2])

break;

}

if(edge[3][1]==center[0])

125

loc=3;

switch(loc)

{case 0:break;case 1:y_();break;case 2:y2();break;case 3:y();break;}

if(edge[1][1]==center[4])

{R2();U();R();U();R_();U_();R_();U_();R_();U();R_();}

else

{R();U_();R();U();R();U();R();U_();R_();U_();R2();}

}

else if(num==4)

{

int loc;

for(loc=1;loc<5;loc++)

{

126

if(edge[0][1]==center[loc])

break;

}

if(loc==4)

{

M_v2();U();M_v2();U2();M_v2();U();M_v2();

}

else

{

if(loc==3)

U_();

U();R_();U_();R();U_();R();U();R();U_();

R_();U();R();U();R2();U_();R_();U();

127

}

}

int loc1;

for(loc1=1;loc1<5;loc1++)

{

if(vertex[3][2]==center[loc1])

break;

}

switch(loc1)

{case 1:break;case 2:U();break;case 3:U2();break;case 4:U_();break;}

cout<<\"魔方还原成功\"<}

void cube::RUN()

128

{

input_cube();

getchar();

bottom_cross();

if(getchar()!=10)

{

output_cube();

while(getchar()!=10)continue;

cout<getchar();

}

bottom_vertex();

if(getchar()!=10)

129

{

output_cube();

while(getchar()!=10)continue;

cout<getchar();

}

middlelayer();

if(getchar()!=10)

{

output_cube();

while(getchar()!=10)continue;

cout<getchar();

130

}

top_cross();

if(getchar()!=10)

{

output_cube();

while(getchar()!=10)continue;

cout<getchar();

}

top_face();

if(getchar()!=10)

{

output_cube();

131

while(getchar()!=10)continue;

cout<getchar();

}

top_vertex();

if(getchar()!=10)

{

output_cube();

while(getchar()!=10)continue;

cout<getchar();

}

top_edge();

132

output_cube();

}

#endif

#include

void introductions();

int main()

{

cube c;

c.RUN();

while(getchar()!=10)continue;

cout<<\"魔方复原!\"<return 0;

}

133

5.3 程序运行结果

134

6. 课程总结

在上学期学了C语言之后,我初步学习到了编程的知识,但我也只是初步认识而已,只知道编程语言的一些很基本的知识,觉得C语言就是一些简单的数学应用题,根本不知道编程到底用在什么地方。认为学习C语言就是上课听一听,稍微复习一下就好。

但通过小学期的C++学习中,由于课程难度的加大和作业范围的扩广,我逐渐地感觉到了编程语言的学习并不是那么简单,它的用途更是广泛。通过对C++课程的学习,也让我对计算机更加充满兴趣,学习过程中,我深深体会到了C++语言的灵活与高效。我既学到了如何运用所学知识来解决实际问题,又学到了如何耐心的分析问题,同时,我还锻炼出了良好的逻辑思维能力。

在一个多月的C++学习中,我总结了几点学习编程语言的方法:第一、是要加强实践,这是最重要的。C++是一门实践性非常强的课程,若要真正学好编程技术,必须在理论学习的基础下,通过上机不断来加强编程技术能力。第二、要学好相关的平台技术及数

135

据结构,在编程过程中需要各种知识来辅助。第三、要多看一些有关C++语言的书本及资料,通过学习更多的知识来充实自己的语言能力。

虽然在这一个月的学习中,我学的不是很认真,但我在今后会继续学习C++及其相关的知识,我相信即使以后我从事的领域跟编程关系不一定很大,但它一定能在一些方面上对我起到作用。

136

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- obuygou.com 版权所有 赣ICP备2024042798号-5

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务