OpenGL实现3D魔方游戏源代码


首先这个程序是建立的是Windows应用程序,建立控制台程序是不能运行的,另外,项目——项目属性——配置属性——常规-----使用多字节字符集,这样编译才能够通过的,否则如果选择使用 Unicode 字符集,编译会有错误提示:error C2440: “初始化”: 无法从“const char [8]”转换为“LPCTSTR”,另外,链接器----输入----附加依赖项要加入:“opengl32.lib glu32.lib”的lib库。。

cubemanage.h文件为:

  1. #ifndef CUBEMANAGE_H   
  2. #define CUBEMANAGE_H   
  3.   
  4. #include <windows.h>   
  5. #include <gl/gl.h>   
  6. #include <gl/glu.h>   
  7. #include <math.h>   
  8.   
  9. #include "wcgcube.h"   
  10.   
  11. #define CUBE_SIZE  3   
  12. #define ORIENTX 0   
  13. #define ORIENTY 0   
  14. #define ORIENTZ 0   
  15.   
  16. class CubeManage {  
  17. public:   
  18.     CubeManage();  
  19.     ~CubeManage();  
  20.       
  21.     void turn(int rotateType);  
  22.     void turnByXShun(int x);  
  23.     void turnByXNi(int x);  
  24.     void turnByYShun(int y);  
  25.     void turnByYNi(int y);  
  26.     void turnByZShun(int z);  
  27.     void turnByZNi(int z);  
  28.     void output(int scr,int site);  
  29.     void output();  
  30.     void draw(int rotateType,GLfloat rotate);  
  31.       
  32. private:  
  33.     WcgCube *cubes[CUBE_SIZE][CUBE_SIZE][CUBE_SIZE];  
  34.       
  35.     void goStep(int *leftLeg,int *rightLeg,int *goDirection,int step,int leftEdge,int rightEdge);  
  36. };  
  37.   
  38. #endif  

wcgcube.h文件为:

  1. #ifndef WCGCUBE_H   
  2. #define WCGCUBE_H   
  3.   
  4. #include <windows.h>   
  5. #include <gl/gl.h>   
  6. #include <gl/glu.h>   
  7. #include <math.h>   
  8.   
  9. #include "iostream"   
  10. using namespace std;  
  11.   
  12. #define X 1   
  13. #define Y 2   
  14. #define Z 3   
  15.   
  16. class WcgCube {  
  17. public:  
  18.     WcgCube();    
  19.     ~WcgCube();  
  20.       
  21.     void turnByXShun(int x);  
  22.     void turnByXNi(int x);  
  23.     void turnByYShun(int y);  
  24.     void turnByYNi(int y);  
  25.     void turnByZShun(int z);  
  26.     void turnByZNi(int z);  
  27.     void output(int sign);  
  28.     void output();  
  29.     void draw(GLfloat x0,GLfloat y0,GLfloat z0);  
  30.       
  31. private:  
  32.     int direct[6];  
  33.     GLfloat sideColor[6][3];  
  34.       
  35.     void turnByX(int x,int sign);  
  36.     void turnByY(int y,int sign);  
  37.     void turnByZ(int z,int sign);  
  38. };  
  39.   
  40. #endif  

CubeGame.cpp文件为:

  1. #include <windows.h>   
  2. #include <winuser.h>   
  3. #include <gl/gl.h>   
  4. #include <gl/glu.h>   
  5. #include <math.h>   
  6.   
  7. #include "iostream"   
  8. using namespace std;  
  9.   
  10. #include "cubemanage.h"   
  11. #include "wcgcube.h"   
  12.   
  13. static GLfloat PI=3.1415f;  
  14. // Rotation amounts   
  15. static GLfloat xRot = 0.0f;  
  16. static GLfloat yRot = 0.0f;  
  17.   
  18. static GLfloat rotate=0.0f;  
  19. static int rotateType=0;  
  20. static int rotateOK=0;  
  21. static int rotateRate=100;  
  22. static GLfloat rotateStep=5*PI/180;  
  23.   
  24. CubeManage cm;  
  25.   
  26.   
  27. HPALETTE hPalette = NULL;  
  28.   
  29. // Keep track of windows changing width and height   
  30. GLfloat windowWidth;  
  31. GLfloat windowHeight;  
  32.   
  33.   
  34. static LPCTSTR lpszAppName = "WcgCube";  
  35.   
  36. void exitGame(HWND hWnd,HDC hDC,HGLRC hRC);  
  37. // Declaration for Window procedure   
  38. LRESULT CALLBACK WndProc(   HWND    hWnd,  
  39.                             UINT    message,  
  40.                             WPARAM  wParam,  
  41.                             LPARAM  lParam);  
  42.   
  43. // Set Pixel Format function - forward declaration   
  44. void SetDCPixelFormat(HDC hDC);  
  45.   
  46.   
  47. void ChangeSize(GLsizei w, GLsizei h)  
  48.     {  
  49.     GLfloat nRange = 350.0f;  
  50.   
  51.     // Prevent a divide by zero   
  52.     if(h == 0)  
  53.         h = 1;  
  54.   
  55.     // Set Viewport to window dimensions   
  56.     glViewport(0, 0, w, h);  
  57.   
  58.     // Reset coordinate system   
  59.     glMatrixMode(GL_PROJECTION);  
  60.     glLoadIdentity();  
  61.   
  62.     // Establish clipping volume (left, right, bottom, top, near, far)   
  63.     if (w <= h)   
  64.         glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);  
  65.     else   
  66.         glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);  
  67.   
  68.     glMatrixMode(GL_MODELVIEW);  
  69.     glLoadIdentity();  
  70.     }  
  71.   
  72.   
  73. // Called by timer routine to effect movement of the rectangle.   
  74. void IdleFunction(void)  
  75.     {  
  76.     if (rotate>=PI/2) {  
  77.         cm.turn(rotateType);  
  78.         rotateType=0;  
  79.         rotateOK=0;  
  80.         rotate=0.0f;  
  81.         // Refresh the Window   
  82. //      glutPostRedisplay();   
  83.         return;  
  84.     }  
  85.     rotate+=rotateStep;  
  86.       
  87.     // Refresh the Window   
  88. //  glutPostRedisplay();   
  89.     }  
  90.   
  91.   
  92.   
  93. // Called by AUX library to draw scene   
  94. void RenderScene(void)  
  95.     {  
  96.     // Clear the window with current clearing color   
  97.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  98.       
  99.   glPushMatrix();  
  100.   
  101.   glRotatef(xRot, 1.0f, 0.0f, 0.0f);  
  102.     glRotatef(yRot, 0.0f, 1.0f, 0.0f);  
  103.   
  104.     cm.draw(rotateType,rotate);  
  105.   
  106.   glPopMatrix();  
  107.   
  108.     // Show the graphics   
  109. //  glutSwapBuffers();   
  110.     }  
  111.   
  112.   
  113.   
  114. // If necessary, creates a 3-3-2 palette for the device context listed.   
  115. HPALETTE GetOpenGLPalette(HDC hDC)  
  116.     {  
  117.     HPALETTE hRetPal = NULL;    // Handle to palette to be created   
  118.     PIXELFORMATDESCRIPTOR pfd;  // Pixel Format Descriptor   
  119.     LOGPALETTE *pPal;           // Pointer to memory for logical palette   
  120.     int nPixelFormat;           // Pixel format index   
  121.     int nColors;                // Number of entries in palette   
  122.     int i;                      // Counting variable   
  123.     BYTE RedRange,GreenRange,BlueRange;  
  124.                                 // Range for each color entry (7,7,and 3)   
  125.   
  126.   
  127.     // Get the pixel format index and retrieve the pixel format description   
  128.     nPixelFormat = GetPixelFormat(hDC);  
  129.     DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);  
  130.   
  131.     // Does this pixel format require a palette?  If not, do not create a   
  132.     // palette and just return NULL   
  133.     if(!(pfd.dwFlags & PFD_NEED_PALETTE))  
  134.         return NULL;  
  135.   
  136.     // Number of entries in palette.  8 bits yeilds 256 entries   
  137.     nColors = 1 << pfd.cColorBits;      
  138.   
  139.     // Allocate space for a logical palette structure plus all the palette entries   
  140.     pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +nColors*sizeof(PALETTEENTRY));  
  141.   
  142.     // Fill in palette header    
  143.     pPal->palVersion = 0x300;        // Windows 3.0   
  144.     pPal->palNumEntries = nColors; // table size   
  145.   
  146.     // Build mask of all 1's.  This creates a number represented by having   
  147.     // the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and   
  148.     // pfd.cBlueBits.     
  149.     RedRange = (1 << pfd.cRedBits) -1;  
  150.     GreenRange = (1 << pfd.cGreenBits) - 1;  
  151.     BlueRange = (1 << pfd.cBlueBits) -1;  
  152.   
  153.     // Loop through all the palette entries   
  154.     for(i = 0; i < nColors; i++)  
  155.         {  
  156.         // Fill in the 8-bit equivalents for each component   
  157.         pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange;  
  158.         pPal->palPalEntry[i].peRed = (unsigned char)(  
  159.             (double) pPal->palPalEntry[i].peRed * 255.0 / RedRange);  
  160.   
  161.         pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange;  
  162.         pPal->palPalEntry[i].peGreen = (unsigned char)(  
  163.             (double)pPal->palPalEntry[i].peGreen * 255.0 / GreenRange);  
  164.   
  165.         pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange;  
  166.         pPal->palPalEntry[i].peBlue = (unsigned char)(  
  167.             (double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange);  
  168.   
  169.         pPal->palPalEntry[i].peFlags = (unsigned char) NULL;  
  170.         }  
  171.           
  172.   
  173.     // Create the palette   
  174.     hRetPal = CreatePalette(pPal);  
  175.   
  176.     // Go ahead and select and realize the palette for this device context   
  177.     SelectPalette(hDC,hRetPal,FALSE);  
  178.     RealizePalette(hDC);  
  179.   
  180.     // Free the memory used for the logical palette structure   
  181.     free(pPal);  
  182.   
  183.     // Return the handle to the new palette   
  184.     return hRetPal;  
  185.     }  
  186.   
  187.   
  188. // Select the pixel format for a given device context   
  189. void SetDCPixelFormat(HDC hDC)  
  190.     {  
  191.     int nPixelFormat;  
  192.   
  193.     static PIXELFORMATDESCRIPTOR pfd = {  
  194.         sizeof(PIXELFORMATDESCRIPTOR),  // Size of this structure   
  195.         1,                              // Version of this structure       
  196.         PFD_DRAW_TO_WINDOW |            // Draw to Window (not to bitmap)   
  197.         PFD_SUPPORT_OPENGL |            // Support OpenGL calls in window   
  198.         PFD_DOUBLEBUFFER,               // Double buffered mode   
  199.         PFD_TYPE_RGBA,                  // RGBA Color mode   
  200.         32,                             // Want 32 bit color    
  201.         0,0,0,0,0,0,                    // Not used to select mode   
  202.         0,0,                            // Not used to select mode   
  203.         0,0,0,0,0,                      // Not used to select mode   
  204.         16,                             // Size of depth buffer   
  205.         0,                              // Not used to select mode   
  206.         0,                              // Not used to select mode   
  207.         0,                              // Not used to select mode   
  208.         0,                              // Not used to select mode   
  209.         0,0,0 };                        // Not used to select mode   
  210.   
  211.     // Choose a pixel format that best matches that described in pfd   
  212.     nPixelFormat = ChoosePixelFormat(hDC, &pfd);  
  213.   
  214.     // Set the pixel format for the device context   
  215.     SetPixelFormat(hDC, nPixelFormat, &pfd);  
  216.     }  
  217.   
  218. void dealKey(HWND hWnd,HDC hDC,HGLRC hRC,int wParam)  
  219. {  
  220.     switch (wParam)  
  221.     {  
  222.     case 27:  
  223.         exitGame(hWnd,hDC,hRC);  
  224.         break;  
  225.     case 113:                       //q   
  226.         if (rotateOK==1)  
  227.             return;  
  228.         rotateType=1;  
  229.         rotateOK=1;  
  230.         rotate=0.0f;  
  231.         break;  
  232.     case 119:                       //w   
  233.         if (rotateOK==1)  
  234.             return;  
  235.         rotateType=2;  
  236.         rotateOK=1;  
  237.         rotate=0.0f;  
  238.         break;  
  239.     case 101:                       //e   
  240.         if (rotateOK==1)  
  241.             return;  
  242.         rotateType=3;  
  243.         rotateOK=1;  
  244.         rotate=0.0f;  
  245.         break;  
  246.     case 114:                       //r   
  247.         if (rotateOK==1)  
  248.             return;  
  249.         rotateType=4;  
  250.         rotateOK=1;  
  251.         rotate=0.0f;  
  252.         break;  
  253.     case 116:                       //t   
  254.         if (rotateOK==1)  
  255.             return;  
  256.         rotateType=5;  
  257.         rotateOK=1;  
  258.         rotate=0.0f;  
  259.         break;  
  260.     case 121:                       //y   
  261.         if (rotateOK==1)  
  262.             return;  
  263.         rotateType=6;  
  264.         rotateOK=1;  
  265.         rotate=0.0f;  
  266.         break;  
  267.     case 97:                        //a   
  268.         if (rotateOK==1)  
  269.             return;  
  270.         rotateType=7;  
  271.         rotateOK=1;  
  272.         rotate=0.0f;  
  273.         break;  
  274.     case 115:                       //s   
  275.         if (rotateOK==1)  
  276.             return;  
  277.         rotateType=8;  
  278.         rotateOK=1;  
  279.         rotate=0.0f;  
  280.         break;  
  281.     case 100:                       //d   
  282.         if (rotateOK==1)  
  283.             return;  
  284.         rotateType=9;  
  285.         rotateOK=1;  
  286.         rotate=0.0f;  
  287.         break;  
  288.     case 102:                       //f   
  289.         if (rotateOK==1)  
  290.             return;  
  291.         rotateType=10;  
  292.         rotateOK=1;  
  293.         rotate=0.0f;  
  294.         break;  
  295.     case 103:                       //g   
  296.         if (rotateOK==1)  
  297.             return;  
  298.         rotateType=11;  
  299.         rotateOK=1;  
  300.         rotate=0.0f;  
  301.         break;  
  302.     case 104:                       //h   
  303.         if (rotateOK==1)  
  304.             return;  
  305.         rotateType=12;  
  306.         rotateOK=1;  
  307.         rotate=0.0f;  
  308.         break;  
  309.     case VK_UP:   
  310.         xRot-= 5.0f;  
  311.         break;  
  312.     case VK_DOWN:  
  313.         xRot += 5.0f;  
  314.         break;  
  315.     case VK_LEFT:  
  316.         yRot -= 5.0f;  
  317.         break;  
  318.     case VK_RIGHT:  
  319.         yRot += 5.0f;  
  320.         break;  
  321.     }  
  322.     if(xRot > 356.0f)  
  323.         xRot = 0.0f;  
  324.   
  325.     if(xRot < -1.0f)  
  326.         xRot = 355.0f;  
  327.   
  328.     if(yRot > 356.0f)  
  329.         yRot = 0.0f;  
  330.   
  331.     if(yRot < -1.0f)  
  332.         yRot = 355.0f;  
  333. }  
  334.   
  335. void exitGame(HWND hWnd,HDC hDC,HGLRC hRC)  
  336. {  
  337.             // Kill the timer that we created   
  338.             KillTimer(hWnd,101);  
  339.   
  340.             // Deselect the current rendering context and delete it   
  341.             wglMakeCurrent(hDC,NULL);  
  342.             wglDeleteContext(hRC);  
  343.   
  344.             // Delete the palette   
  345.             if(hPalette != NULL)  
  346.                 DeleteObject(hPalette);  
  347.   
  348.             // Tell the application to terminate after the window   
  349.             // is gone.   
  350.             PostQuitMessage(0);  
  351. }  
  352.   
  353. // Entry point of all Windows programs   
  354. int APIENTRY WinMain(   HINSTANCE   hInstance,  
  355.                         HINSTANCE   hPrevInstance,  
  356.                         LPSTR       lpCmdLine,  
  357.                         int         nCmdShow)  
  358.     {  
  359.     MSG         msg;        // Windows message structure   
  360.     WNDCLASS    wc;         // Windows class structure   
  361.     HWND        hWnd;       // Storeage for window handle   
  362.     HWND        hDesktopWnd;// Storeage for desktop window handle   
  363.     HDC         hDesktopDC; // Storeage for desktop window device context   
  364.     int         nScreenX, nScreenY; // Screen Dimensions   
  365.   
  366.     // Register Window style   
  367.     wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;  
  368.     wc.lpfnWndProc      = (WNDPROC) WndProc;  
  369.     wc.cbClsExtra       = 0;  
  370.     wc.cbWndExtra       = 0;  
  371.     wc.hInstance        = hInstance;  
  372.     wc.hIcon            = NULL;  
  373.     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);  
  374.       
  375.     // No need for background brush for OpenGL window   
  376.     wc.hbrBackground    = NULL;       
  377.       
  378.     wc.lpszMenuName     = NULL;  
  379.     wc.lpszClassName    = lpszAppName;  
  380.   
  381.     // Register the window class   
  382.     if(RegisterClass(&wc) == 0)  
  383.         return FALSE;  
  384.   
  385.     // Get he Window handle and Device context to the desktop   
  386.     hDesktopWnd = GetDesktopWindow();  
  387.     hDesktopDC = GetDC(hDesktopWnd);  
  388.   
  389.     // Get the screen size   
  390.     nScreenX = GetDeviceCaps(hDesktopDC, HORZRES);  
  391.     nScreenY = GetDeviceCaps(hDesktopDC, VERTRES);  
  392.   
  393.     // Release the desktop device context   
  394.     ReleaseDC(hDesktopWnd, hDesktopDC);  
  395.   
  396.     // Create the main application window   
  397.     hWnd = CreateWindow(  
  398.                 lpszAppName,  
  399.                 lpszAppName,  
  400.                   
  401.                 // OpenGL requires WS_CLIPCHILDREN and WS_CLIPSIBLINGS   
  402.                 WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,  
  403.       
  404.                 // Window position and size   
  405.                 0, 0,  
  406.                 nScreenX, nScreenY,  
  407.                 NULL,  
  408.                 NULL,  
  409.                 hInstance,  
  410.                 NULL);  
  411.   
  412.   
  413.     // If window was not created, quit   
  414.     if(hWnd == NULL)  
  415.         return FALSE;  
  416.   
  417.   
  418.     // Display the window   
  419.     ShowWindow(hWnd,SW_SHOW);  
  420.     UpdateWindow(hWnd);  
  421.   
  422.     // Process application messages until the application closes   
  423.     while( GetMessage(&msg, NULL, 0, 0))  
  424.         {  
  425.         TranslateMessage(&msg);  
  426.         DispatchMessage(&msg);  
  427.         }  
  428.   
  429.     return msg.wParam;  
  430.     }  
  431.   
  432.   
  433.   
  434. // Window procedure, handles all messages for this program   
  435. LRESULT CALLBACK WndProc(   HWND    hWnd,  
  436.                             UINT    message,  
  437.                             WPARAM  wParam,  
  438.                             LPARAM  lParam)  
  439.     {  
  440.     static HGLRC hRC;       // Permenant Rendering context   
  441.     static HDC hDC;         // Private GDI Device context   
  442.   
  443.     switch (message)  
  444.         {  
  445.         // Window creation, setup for OpenGL   
  446.         case WM_CREATE:  
  447.             // Store the device context   
  448.             hDC = GetDC(hWnd);        
  449.   
  450.             // Select the pixel format   
  451.             SetDCPixelFormat(hDC);        
  452.   
  453.             // Create the rendering context and make it current   
  454.             hRC = wglCreateContext(hDC);  
  455.             wglMakeCurrent(hDC, hRC);  
  456.   
  457.             // Create the palette   
  458.             hPalette = GetOpenGLPalette(hDC);  
  459.     // Black background   
  460.     glClearColor(0.0f, 0.0f, 0.0f, 1.0f );  
  461.   
  462.     glEnable(GL_DEPTH_TEST);      
  463. //  glEnable(GL_DITHER);   
  464.     glShadeModel(GL_SMOOTH);  
  465.   
  466.             // Create a timer that fires 30 times a second   
  467.             SetTimer(hWnd,33,1,NULL);  
  468.             break;  
  469.   
  470.         // Window is being destroyed, cleanup   
  471.         case WM_DESTROY:  
  472.             exitGame(hWnd,hDC,hRC);  
  473.             break;  
  474.           
  475.         case WM_KEYDOWN:  
  476.             dealKey(hWnd,hDC,hRC,wParam);  
  477.             InvalidateRect(hWnd,NULL,FALSE);  
  478.             break;  
  479.   
  480.         case WM_CHAR:  
  481.             dealKey(hWnd,hDC,hRC,wParam);  
  482.             InvalidateRect(hWnd,NULL,FALSE);  
  483.             break;  
  484.           
  485.         // Window is resized.   
  486.         case WM_SIZE:  
  487.             // Call our function which modifies the clipping   
  488.             // volume and viewport   
  489.             ChangeSize(LOWORD(lParam), HIWORD(lParam));  
  490.             break;  
  491.   
  492.         // Timer, moves and bounces the rectangle, simply calls   
  493.         // our previous OnIdle function, then invalidates the    
  494.         // window so it will be redrawn.   
  495.         case WM_TIMER:  
  496.             {  
  497.             IdleFunction();  
  498.           
  499.             InvalidateRect(hWnd,NULL,FALSE);  
  500.             }  
  501.             break;  
  502.   
  503.         // The painting function.  This message sent by Windows    
  504.         // whenever the screen needs updating.   
  505.         case WM_PAINT:  
  506.             {  
  507.             // Call OpenGL drawing code   
  508.             RenderScene();  
  509.   
  510.             // Call function to swap the buffers   
  511.             SwapBuffers(hDC);  
  512.   
  513.             // Validate the newly painted client area   
  514.             ValidateRect(hWnd,NULL);  
  515.             }  
  516.             break;  
  517.   
  518.   
  519.         // Windows is telling the application that it may modify   
  520.         // the system palette.  This message in essance asks the    
  521.         // application for a new palette.   
  522.         case WM_QUERYNEWPALETTE:  
  523.             // If the palette was created.   
  524.             if(hPalette)  
  525.                 {  
  526.                 int nRet;  
  527.   
  528.                 // Selects the palette into the current device context   
  529.                 SelectPalette(hDC, hPalette, FALSE);  
  530.   
  531.                 // Map entries from the currently selected palette to   
  532.                 // the system palette.  The return value is the number    
  533.                 // of palette entries modified.   
  534.                 nRet = RealizePalette(hDC);  
  535.   
  536.                 // Repaint, forces remap of palette in current window   
  537.                 InvalidateRect(hWnd,NULL,FALSE);  
  538.   
  539.                 return nRet;  
  540.                 }  
  541.             break;  
  542.   
  543.       
  544.         // This window may set the palette, even though it is not the    
  545.         // currently active window.   
  546.         case WM_PALETTECHANGED:  
  547.             // Don't do anything if the palette does not exist, or if   
  548.             // this is the window that changed the palette.   
  549.             if((hPalette != NULL) && ((HWND)wParam != hWnd))  
  550.                 {  
  551.                 // Select the palette into the device context   
  552.                 SelectPalette(hDC,hPalette,FALSE);  
  553.   
  554.                 // Map entries to system palette   
  555.                 RealizePalette(hDC);  
  556.                   
  557.                 // Remap the current colors to the newly realized palette   
  558.                 UpdateColors(hDC);  
  559.                 return 0;  
  560.                 }  
  561.             break;  
  562.   
  563.   
  564.         default:   // Passes it on if unproccessed   
  565.             return (DefWindowProc(hWnd, message, wParam, lParam));  
  566.   
  567.         }  
  568.   
  569.     return (0L);  
  570.     }  
  • 1
  • 2
  • 3
  • 下一页

相关内容