zoukankan      html  css  js  c++  java
  • c++提高学习笔记——05-c++STLday13_贪吃蛇案例

    在学习c++提高-STL总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

    05-c++STLday13_贪吃蛇案例

    目录:
    一、上节作业——综合案例(学校演讲比赛)
    二、贪食蛇案例

    一、上节作业——综合案例(学校演讲比赛

    》比赛规则:某市举行一场演讲比赛( speech_contest ),共有24个人参加。比赛共三轮,前两轮为淘汰赛,第三轮为决赛。

    》比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛;

    >第一轮分为4个小组,每组6个人。比如编号为: 100-123.  整体进行抽签(draw)后顺序演讲。当小组演讲完后,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。

    >第二轮分为2个小组,每组6人。比赛完毕,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。

    >第三轮只剩下1组6个人,本轮为决赛,选出前三名。
        
    》比赛评分:10个评委打分,去除最低、最高分,求平均分每个选手演讲完由10个评委分别打分。该选手的最终得分是去掉一个最高分和一个最低分,求得剩下的8个成绩的平均分。选手的名次按得分降序排列。

    用STL编程,求解这个问题
    1)请打印出所有选手的名字与参赛号,并以参赛号的升序排列。
    2)打印每一轮比赛后,小组比赛成绩和小组晋级名单



    需求分析
    1) 产生选手 ( ABCDEFGHIJKLMNOPQRSTUVWX ) 姓名、得分;选手编号
    2) 第1轮    选手抽签 选手比赛 查看比赛结果
    3) 第2轮    选手抽签 选手比赛 查看比赛结果
    4) 第3轮    选手抽签 选手比赛 查看比赛结果

    实现思路
    需要把选手信息、选手得分信息、选手比赛抽签信息、选手的晋级信息保存在容器中,需要涉及到各个容器的选型。
    选手可以设计一个类Speaker(姓名和得分)
    所有选手的编号可以单独放在一个vector容器中,做抽签用

    所有选手编号和选手信息,可以放在容器内:map<int, Speaker>

    所有选手的编号名单,可以放在容器:vecter<int> v1中

    第1轮晋级编号名单,可以放在容器vecter<int> v2中

    第2轮晋级编号名单,可以放在容器vecter<int> v3中

    第3轮前三名名单,可以放在容器vecter<int> v4中

    每个小组的比赛得分信息,按照从大到小的顺序放在multimap<成绩, 编号, greater<int>>中

    每个选手的得分,可以放在容器deque<int> dscore; 方便去除最低最高分.


    代码如下:

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<iostream>
      3 using namespace std;
      4 #include<vector>
      5 #include<map>
      6 #include<string>
      7 #include<algorithm>
      8 #include<deque>
      9 #include<numric>
     10 #include<functional>
     11 #inlcude<ctime>
     12 
     13 /*
     14 需求分析:
     15 1) 产生选手 ( ABCDEFGHIJKLMNOPQRSTUVWX ) 姓名、得分;选手编号
     16 
     17 2) 第1轮    选手抽签 选手比赛 查看比赛结果 
     18 3) 第2轮    选手抽签 选手比赛 查看比赛结果
     19 4) 第3轮    选手抽签 选手比赛 查看比赛结果
     20 
     21 */
     22 class Speaker
     23 {
     24 public:
     25     
     26     string m_Name;//姓名
     27     int m_Score[3];//得分数组
     28 };
     29 
     30 void createSpeaker(vector<int>& v, map<int, Speaker>& m)
     31 {
     32     string nameSeed = "ABCDEFGHIJKLMNOPQRSTUVWX";
     33     for(int i = 0; i < nameSeed.size(); i++)
     34     {
     35         string name = "选手";
     36         name += nameSeed[i];
     37         
     38         Speaker sp;
     39         sp.m_Name = name;
     40         for(int j = 0; j < 3; j++)
     41         {
     42             sp.m_Score[j] = 0;
     43         }
     44         
     45         v.push_back(i + 100);//编号100~123
     46         m.insert(make_pair(i + 100, sp));
     47     }
     48     
     49 }
     50 
     51 //抽签
     52 void speechDraw(vector<int>v)
     53 {
     54     //洗牌
     55     random_shuffle(v.begin(), v.end());
     56 }
     57 
     58 //index存放第几轮,v1存放比赛选手编号,m是选手编号和具体选手,v2存放晋级选手编号容器
     59 void speechContest(int index,vector<int>& v1, map<int, Speaker>& m, vector<int>& v2)
     60 {
     61     //临时容器:key 分数,value 编号
     62     multimap<int, int, greater<int>>groupMap;
     63     int num = 0;
     64     for(vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
     65     {
     66         num++;
     67         deque<int>d;
     68         for(int i = 0; i < 10; i++)
     69         {
     70             int score = rand() % 41 + 60;//60~100
     71             d.push_back(score);
     72         }
     73         //排序
     74         sort(d.begin(), d.end());
     75         //去除最高最低分
     76         d.pop_back();
     77         d.pop_front();
     78         //累积分数
     79         int sum = accumulate(d.begin(), d.end(), 0);
     80         int avg = sum / d.size();
     81         
     82         //将平均分放入到m容器中
     83         m[*it].m_Score[index - 1] = avg;
     84         
     85         //每6个人,取前三名晋级
     86         //临时容器,保存6个人
     87         //临时容器,存入数据
     88         groupMap.insert(make_pair(avg, *it));
     89         
     90         if(num % 6 == 0)
     91         {
     92             /*
     93             cout << "各个小组比赛成绩如下:" << endl;
     94             for(multimap<int, int, greater>:: iterator mit = groupMap.begin(); mit != groupMap.end(); mit++)
     95             {
     96                 cout << "选手编号:" << mit->second << "  姓名:" << m[mit->second].m_Name << "  得分:" << m[mit->second].m_Score[index-1] << endl;
     97             }
     98             */
     99             
    100             //取前三名
    101             int count = 0;
    102             for(multimap<int, int, greater>:: iterator mit = groupMap.begin(); mit != groupMap.end(), count < 3; mit++, count++)
    103             {
    104                 //晋级容器,获取数据
    105                 v2.push_back(mit->second);
    106             }
    107             
    108             groupMap.clear();//清空临时容器
    109         }
    110     }
    111     
    112     
    113     
    114 }
    115 
    116 
    117 void showScore(int index, vector<int>& v, map<int, Speaker>& m)
    118 {
    119     cout << "" << index << "轮,比赛成绩如下:" << endl;
    120     
    121     for(map<int, Speaker>::iterator it = m.begin(); it != m.end(); it++)
    122     {
    123         cout << "选手编号:" << it->first << "姓名:" << it->second.m_Name << "分数:" << it->second.m_Score[index-1] << endl;
    124     }
    125     
    126     cout << "晋级选手编号" << endl;
    127     for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
    128     {
    129         cout << *it << endl;
    130     }
    131     
    132 }
    133 
    134 
    135 
    136 void test01()
    137 {
    138     //最后添加随机数种子
    139     srand((unsigned int)time(NULL));
    140     
    141     vector<int>v1;//选手编号
    142     
    143     map<int, Speaker>m;//存放选手编号和对应的具体的选手
    144     
    145     //创建选手
    146     createSpeaker(v1, m);
    147     
    148     /*
    149     //测试
    150     for(map<int, Speaker>::iterator it = m.begin(); it!= m.end(); it++)
    151     {
    152         cout << "选手编号:" << it->first << "姓名:" << it->second.m_Name << endl;
    153     }
    154     */
    155     
    156     //抽签
    157     speechDraw(v1);
    158     
    159     vector<int>v2;//进入下一轮比赛的人员编号
    160     
    161     //第一轮比赛
    162     speechContest(1, v1, m, v2);
    163     
    164     //显示比赛结果
    165     showScore(1, v2, m);//轮数 晋级编号 具体人员信息
    166     
    167     //第二轮比赛
    168     speechDraw(v2);
    169     vector<int>v3;//进入下一轮比赛的人员编号
    170     speechContest(2, v2, m, v3);
    171     showScore(2, v3, m);
    172     
    173     //第三轮比赛
    174     speechDraw(v3);
    175     vector<int>v4;//进入下一轮比赛的人员编号
    176     speechContest(3, v3, m, v4);
    177     showScore(3, v4, m);
    178     
    179 }
    180 
    181 int main()
    182 {
    183     test01();
    184     
    185     system("pause");
    186     return EXIT_SUCCESS;
    187 }

    二、贪食蛇案例

    总结:

    1、玩法介绍

    2、具体实现

    3、墙模块

    3.1 二维数组维护,游戏内容

    3.2 初始化二维数组:initwall

    3.3 画出墙壁 drawwall

    3.4 提供对外接口setwall、getwall

    3.5测试

    4、蛇模块

    4.1 初始化蛇

    4.2 销毁所有结点

    4.3 添加新结点

    5、食物模块

    5.1 foodX、foodY位置

    5.2 setFood对外接口,可以设置食物

    5.3 随机出两个可以放置的位置,设置#

    6、删除结点和移动蛇的封装

    6.1 删除结点,通过两个临时结点,删除尾结点

    6.2 移动,判断用户输入内容,然后进行移动操作

    7、接收用户输入

    7.1 接收一个字符,让蛇移动第一步

    7.2 用户输入按键后,进行自动移动

    8、解决bug

    8.1 按键冲突

    8.2 180度不可以转

    8.3 死亡撞墙,多走一步

    8.4 循环追尾,不要进入死亡判断

    9、辅助玩法

    9.1 难度设定,根据蛇身段,产生不同难度

    9.2 分数设定

    10、优化游戏

    代码如下:

    game.cpp

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<iostream>
      3 using namespace std;
      4 #include"wall.h"
      5 #include"snake.h"
      6 #include"food.h"
      7 #include<ctime>
      8 #include<conio.h>
      9 #include<window.h>
     10 
     11 void gotoxy(HANDLE hOut, int x, int y)
     12 {
     13     COORD pos;
     14     pos.X = x;             //横坐标
     15     pos.Y = y;            //纵坐标
     16     SetConsoleCursorPosition(hOut, pos);
     17 }
     18 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
     19 
     20 
     21 
     22 void test01()
     23 {
     24     //添加随机种子
     25     srand((unsigned int)time(NULL));
     26     
     27     //是否死亡的标识
     28     bool isDead = false;
     29     
     30     //上一步的标识
     31     char preKey = NULL;
     32     
     33     Wall wall;
     34     wall.initWall();
     35     wall.drawWall();
     36     
     37     /*
     38     //测试
     39     wall.setWall(5, 4, '=');
     40     wall.setWall(5, 5, '=');
     41     wall.setWall(5, 6, '@');
     42     
     43     wall.drawWall();
     44     
     45     cout << wall.getWall(0, 0) << endl;
     46     cout << wall.getWall(5, 4) << endl;
     47     cout << wall.getWall(5, 6) << endl;
     48     cout << wall.getWall(1, 1) << endl;
     49     */
     50     Food food(wall);
     51     food.setFood();
     52     
     53     Snake snake(wall, food);
     54     snake.initSnake();
     55     
     56     /*
     57     //测试
     58     snake.move('w');
     59     snake.move('w');
     60     snake.move('a');
     61     */
     62     //snake.delPoint();//测试删结点
     63     
     64     //wall.drawWall();
     65     gotoxy(hOut, 0, Wall::ROW);
     66     
     67     cout << "得分:" << snake.getScore() << "" << endl;
     68     
     69     //gotoxy(hOut, 10, 5);//坐标系相反;y*2,x
     70     
     71     //接收用户的输入
     72     while(!isDead)
     73     {
     74         char key = _getch();
     75         
     76         //判断,如果是第一次按了左键,才不能激活游戏
     77         //判断上一次移动方向
     78         if(preKey == NULL && key == snake.LEFT)
     79         {
     80             continue;
     81         }
     82         
     83         do
     84         {
     85             if(key == snake.UP || key == snake.DOWN || key == snake.LEFT || key == snake.RIGHT)
     86             {
     87                 //判断本次按键是否与上次冲突
     88                 if((key == snake.LEFT && preKey == snake.RIGHT)||(key == snake.RIGHT && preKey == snake.LEFT)||(key == snake.UP && preKey == snake.DOWN)||(key == snake.DOWN && preKey == snake.UP))
     89                 {
     90                     key = preKey;
     91                 }
     92                 else
     93                 {
     94                     preKey = key; //不是冲突按键,可以更新按键
     95                 }
     96                 
     97                 if(snake.move(key) == true)
     98                 {
     99                     //移动成功 代码
    100                     //system("cls");
    101                     //wall.drawWall();
    102                     gotoxy(hOut, 0, Wall::ROW);
    103                     
    104                     cout << "得分:" << snake.getScore() << "" << endl;
    105                     Sleep(snake.getSleepTime());
    106                 }
    107                 else
    108                 {
    109                     isDead = true;
    110                     break;
    111                 }
    112             }
    113             else
    114             {
    115                 key = preKey;//强制将错误按键变为上一次移动的方向
    116             }
    117     
    118         }while(!_kbhit());//当没有键盘输入的时候,返回0
    119         
    120 
    121     }
    122 
    123     
    124 }
    125 
    126 int main()
    127 {
    128     test01();
    129     
    130     system("pause");
    131     return EXIT_SUCCESS;
    132 }

    wall.cpp

     1 #include"wall.h"
     2 
     3 
     4 void Wall::initWall()
     5 {
     6     for(int i = 0; i < ROW; i++)
     7     {
     8         for(int j = 0; j < COL; j++)
     9         {
    10             //放墙壁
    11             if(i == 0 || j == 0 || i == ROW - 1 || j == COL -1)
    12             {
    13                 gameArray[i][j] = '*';
    14             }
    15             else
    16             {
    17                 gameArray[i][j] = ' ';
    18             }
    19         }
    20         
    21     }
    22 }
    23 
    24 
    25 void Wall::drawWall()
    26 {
    27     for(int i = 0; i < ROW; i++)
    28     {
    29         for(int j = 0; j < COL; j++)
    30         {
    31             cout << gameArray[i][j] << " ";
    32         }
    33         if(i == 5)
    34         {
    35             cout << "create by wp";
    36         }
    37         if(i == 6)
    38         {
    39             cout << "a:left";
    40         }
    41         if(i == 7)
    42         {
    43             cout << "d:right";
    44         }
    45         if(i == 8)
    46         {
    47             cout << "w:up";
    48         }
    49         if(i == 9)
    50         {
    51             cout << "s:down";
    52         }
    53 
    54         
    55         cout << endl;
    56     }
    57 }
    58 
    59 
    60 void Wall::setWall(int x, int y, char c)
    61 {
    62     gameArray[x][y] = c;
    63 }
    64 
    65 char Wall::getWall(int x, int y)
    66 {
    67     return gameArray[x][y];
    68 }

    wall.h

     1 #ifndef _WALL_HEAD
     2 #define _WALL_HEAD
     3 #include<iostream>
     4 using namespace std;
     5 
     6 class Wall
     7 {
     8 public:
     9     enum{ROW = 26, COL = 26};
    10     
    11     //初始化墙壁
    12     void initWall();
    13     
    14     //画出墙壁
    15     void drawWall();
    16     
    17     //根据索引设置二维数组里的内容
    18     void setWall(int x, int y, char c);
    19     
    20     //根据索引获取当前位置的符号
    21     char getWall(int x, int y);
    22     
    23 private:
    24     char gameArray[ROW][COL];
    25     
    26 };
    27 
    28 
    29 
    30 
    31 
    32 
    33 #endif

    snake.cpp

      1 #include"snake.h"
      2 #include<window.h>
      3 
      4 void gotoxy1(HANDLE hOut1, int x, int y)
      5 {
      6     COORD pos;
      7     pos.X = x;             //横坐标
      8     pos.Y = y;            //纵坐标
      9     SetConsoleCursorPosition(hOut1, pos);
     10 }
     11 HANDLE hOut1 = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
     12 
     13 Snake::Snake(Wall& tempWall, Food& tmpFood):wall(tempWall),food(tmpFood)
     14 {
     15     pHead = NULL;
     16     isRool = false;
     17 }
     18 
     19 void Snake::initSnake()
     20 {
     21     destroyPoint();
     22     addPoint(5, 3);
     23     addPoint(5, 4);
     24     addPoint(5, 5);
     25 }
     26 
     27 void Snake::destroyPoint()
     28 {
     29     Point* pCur = pHead;
     30     
     31     while(pHead != NULL)
     32     {
     33         pCur = pHead->next;
     34         delete pHead;
     35         
     36         pHead = pCur;
     37     }
     38     
     39 }
     40 
     41 void Snake::addPoint(int x, int y)
     42 {
     43     //创建新结点
     44     Point* newPoint = new Point;
     45     newPoint->x = x;
     46     newPoint->y = y;
     47     newPoint->next = NULL;
     48     
     49     //如果原来头不为空,改为身子
     50     if(pHead != NULL)
     51     {
     52         wall.setWall(pHead->x, pHead->y, '=');
     53         
     54         gotoxy1(hOut1, pHead->y * 2, pHead->x);
     55         cout << "=";
     56     }
     57     
     58     newPoint->next = pHead;
     59     
     60     pHead = newPoint;//更新头部
     61     
     62     wall.setWall(pHead->x, pHead->y, '@');
     63     
     64     gotoxy1(hOut1, pHead->y * 2, pHead->x);
     65     cout << "@";
     66 }
     67 
     68 void Snake::delPoint()
     69 {
     70     //两个结点以上,才去做删除操作
     71     if(pHead == NULL || pHead->next == NULL)
     72     {
     73         return;
     74     }
     75     
     76     Point* pCur = pHead->next;
     77     Point* pPre = pHead;
     78     
     79     while(pCur->next != NULL)
     80     {
     81         pPre = pPre->next;
     82         pCur = pCur->next;
     83     }
     84     //删除尾结点
     85     
     86     wall.setWall(pCur->x, pCur->y, ' ');
     87     gotoxy1(hOut1, pCur->y * 2, pCur->x);
     88     cout << " ";
     89     
     90     delete pCur;
     91     pCur = NULL;
     92     pPre->next = NULL;
     93 }
     94 
     95 bool Snake::move(char key)
     96 {
     97     int x = pHead->x;
     98     int y = pHead->y;
     99     
    100     switch(key)
    101     {
    102         case UP:
    103             x--;
    104             break;
    105         case DOWN:
    106             x++;
    107             break;
    108         case LEFT:
    109             y--;
    110             break;
    111         case RIGHT:
    112             y++;
    113             break;
    114         default:
    115             break;
    116     }
    117     
    118     //判断:如果是下一步碰到的尾巴,不应该死亡
    119     Point* pCur = pHead->next;
    120     Point* pPre = pHead;
    121     
    122     while(pCur->next != NULL)
    123     {
    124         pPre = pPre->next;
    125         pCur = pCur->next;
    126     }
    127     if(pCur->x == x && pCur->y == y)
    128     {
    129         //碰到尾巴,成为循环
    130         isRool = true;
    131     }
    132     else
    133     {
    134         //判断用户到达位置是否成功
    135         if(wall.getWall(x, y) == '*' || wall.getWall(x, y) = '=')
    136         {
    137             addPoint(x,y);//如果是*的话,再多走一步,但是吃掉自己也会出问题,可以更改上面的if分开进行判断
    138             delPoint();
    139             system("cls");
    140             wall.drawWall();
    141             
    142             cout << "得分:" << getScore() << "" << endl;
    143             cout << "GAME OVER!!!" << endl;
    144             return false;
    145         }
    146     }
    147 
    148     
    149     //移动成功分两种
    150     //吃到食物 未吃到食物
    151     if(wall.getWall(x, y) == '#')
    152     {
    153         addPoint(x, y);
    154         
    155         //重新设置食物
    156         food.setFood();
    157     }
    158     else
    159     {
    160         addPoint(x, y);
    161         delPoint();
    162         if(isRool == true)
    163         {
    164             wall.setWall(x, y, '@');
    165             gotoxy1(hOut1, y * 2, x);
    166             cout << "@";
    167         }
    168     }
    169     return true;
    170 }
    171 
    172 int Snake::getSleepTime()
    173 {
    174     int sleepTime = 0;
    175     int size = countList();
    176     if(size < 5)
    177     {
    178         sleepTime = 300;
    179     }
    180     else if(size >= 5 && size <= 8)
    181     {
    182         sleepTime = 200;
    183     }
    184     else
    185     {
    186         sleepTime = 100;
    187     }
    188     return sleepTime;
    189 }
    190 int Snake::countList()
    191 {
    192     int size = 0;
    193     Point* curPoint = pHead;
    194     while(curPoint != NULL)
    195     {
    196         size++;
    197         curPoint = curPoint->next;
    198     }
    199     return size;
    200 }
    201 
    202 int Snake::getScore()
    203 {
    204     int size = countList();
    205     
    206     int score = (size - 3) * 100;
    207     
    208     return score;
    209 }

    snake.h

     1 #pragma once
     2 #include<iostream>
     3 using namespace std;
     4 #include"wall.h"
     5 #include"food.h"
     6 
     7 class Snake
     8 {
     9 public:
    10     
    11     Snake(Wall& tempWall, Food& food);
    12     
    13     enum{ UP = 'w', DOWN = 's', LEFT = 'a', RIGHT = 'd'};
    14     
    15     
    16     //结点
    17     struct Point
    18     {
    19         //数据域
    20         int x;
    21         int y;
    22         
    23         //指针域
    24         Point* next;
    25     };
    26     
    27     //初始化
    28     void initSnake();
    29     
    30     //销毁所有结点
    31     void destroyPoint();
    32     
    33     //添加结点
    34     void addPoint(int x, int y);
    35     
    36     //删除结点
    37     void delPoint();
    38     
    39     //移动蛇操作
    40     //返回值代表移动是否成功
    41     bool move(char key);
    42     
    43     //设定难度
    44     //设定刷屏时间
    45     int getSleepTime();
    46     //获取蛇身段
    47     int countList();
    48     
    49     //获取分数
    50     int getScore();
    51     
    52     Point* pHead;
    53     
    54     Wall& wall;
    55     
    56     Food& food;
    57     
    58     bool isRool;//判断碰到尾巴的标识
    59 };

    food.cpp

     1 #pragma once
     2 #include<iostream>
     3 using namespace std;
     4 #include"wall.h"
     5 
     6 class Food
     7 {
     8 public:
     9     Food(Wall& tempWall);
    10     
    11     //设置食物
    12     void setFood();
    13     
    14     int foodX;
    15     int foodY;
    16     
    17     Wall& wall;
    18 };

    food.h

     1 #include"food.h"
     2 #include<window.h>
     3 
     4 void gotoxy2(HANDLE hOut2, int x, int y)
     5 {
     6     COORD pos;
     7     pos.X = x;             //横坐标
     8     pos.Y = y;            //纵坐标
     9     SetConsoleCursorPosition(hOut2, pos);
    10 }
    11 HANDLE hOut2 = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
    12 
    13 Food::Food(Wall& tempWall):wall(tempWall)
    14 {
    15     
    16 }
    17 
    18 void Food::setFood()
    19 {
    20     
    21     while(true)
    22     {
    23         foodX = rand() % (Wall::ROW - 2) + 1;
    24         foodY = rand() % (Wall::COL - 2) + 1;
    25         
    26         //如果随机的位置是蛇头或蛇身,就重新生成随机数
    27         if(wall.getWall(foodX, foodY) == ' ')
    28         {
    29             wall.setWall(foodX, foodY, '#');
    30             gotoxy2(hOut2, foodY * 2, foodX);
    31             cout << "#";
    32             break;
    33         }
    34     }
    35 }

    在学习c++提高-STL总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

  • 相关阅读:
    Linux命令-read
    pytest8-skip与xfail
    python模块-contextlib
    python中eval的使用
    python学习-面向对象(六)
    java学习-IDEA运行java程序报错
    nginx 使用SSL证书 代理https
    BC30560: “ExtensionAttribute”在命名空间“System.Runtime.CompilerServices”中不明确。
    nginx 代理相对路径使用不起
    nginx 解决不同web服务器 在同一服务器使用80端口问题
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_ImprovedLearning_04.html
Copyright © 2011-2022 走看看