020-29133788
    资 讯
    您的位置:首页 >> 资 讯 >> 软件应用 >> 编程开发 >> 正文
    ][C/C++]井字游戏

    点击:   发布日期:2013-01-18

    本文来自 www.020fix.com

    进来看的,不准出现无意义回覆、注音文、推推、谢谢等字眼,否则依版规处置。
    版本一说明:单人版井字游戏,只能一个人玩。
    版本二说明:非物件版本的使用者与电脑对抗。
    版本三说明:物件版本的使用者与电脑对抗。
    PS:这三个程式是帮小学妹们写的,前前后后一共花了小弟将近10个小时(虽然写的不是很好|40|),请好好的爱护"它们"OK???!|44||44|
    版本一:
    复制内容到剪贴板
    代码:
    //此为单人版井字游戏
    #include<iostream>
    #include<iomanip>
    #include<cstdlib>
    using namespace std;

    void draw_prompt_map(char map[3][3]);//画出提示图,告诉使用者游戏玩法         

    bool judge_repeat(char map[3][3],int location,int sign);//判断是否有重复画记号

    void draw_map(char map[3][3]);//画出游戏中的井字图

    bool judge_line(char map[3][3],int* sign);//判断各种连线状况

    void clear_map(char map[3][3]);//将阵列中的字元全部指定成空白字元,以便重新游戏

    int main()
    {
        char map[3][3];
        char ch;
        int sign,location;
        do{
            cout<<"*******************欢迎光临井字游戏******************\n"<<endl;
            cout<<"输入1,可以使用o来画记号。"<<endl;
            cout<<"输入2,可以使用x来画记号。"<<endl;
            cin>>sign;
            if(sign==1 || sign ==2) break;
        }while(sign!=1 && sign!=2);//预防使用输入1,2以外的数字
       
        draw_prompt_map(map);
       do{
          
           clear_map(map);//将阵列中的字元全部指定成空白字元
          
              do{
                   cout<<"请选择您要画记号的位置?"<<endl;
                   cin>>location;
                   if(sign==1 && !judge_repeat(map,location,sign))
                   {
                     draw_map(map);
                   }
                   else if(sign==2 && !judge_repeat(map,location,sign))
                     draw_map(map);
               
                  } while(!judge_line(map,&sign));
                  cout<<"恭喜你!!你赢了囉^_^!!!"<<endl;
            cout<<"要继续玩吗??(y)继续 or (n)结束)"<<endl;
            cin>>ch;
            system("cls");//清除萤幕
        }while(ch=='y' || ch=='Y');     
                
        system("pause");      
    }   

    //画出提示图,告诉使用者游戏玩法   
    void draw_prompt_map(char map[3][3])
    {
        int num = 1;
        cout<<"\n格子中的数字代表输入代号!"<<endl;
        for(int row=0; row<3; row++)
        {
            for(int column=0; column<3; column++,num++)
            {
                //int的整数值加上48之后,等于char的同等整数(由ascii表得知)
                map[row][column] = num+48;
                cout<<"  "<<map[row][column]<< setw(4);
                if(column<=1)cout<<"|";
                map[row][column] = ' ';
            }
            cout<<endl;
            if(row<=1)cout<<"--------------------";
            cout<<endl;
        }
    }
    //判断是否有重复画记号
    bool judge_repeat(char map[3][3],int location,int sign)
    {
        int row,column;
        do{
            row = location/3 ;//将输入的数字换成表格 列 座标
            column = location % 3;//将输入的数字换成表格 行 座标
            if(map[row][column]== ' ')
            {
                map[row][column] =( sign == 1 ? 'O':'X');//画上记号
                return false;//代表没有重复
            }
            else
            {
                cout<<"该位置可能不存在或是已经被画上记号了!!"<<endl;
                cout<<"请重新输入位置!!!"<<endl;
                cin>>location;
            }   
        }while(1);//一直检验,直到记号位置不重复,自然由上方的return 指令跳出
                        
    }  
    //画出游戏中的井字图
    void draw_map(char map[3][3])      
    {
        int row,column;
       
        for(row=0; row<3; row++)
        {
            for(column=0; column<3; column++)
            {
                cout<<"  "<<map[row][column]<< setw(4);
                if(column<=1)cout<<"|";   
            }
            cout<<endl;
            if(row<=1)cout<<"--------------------";
            cout<<endl;
        }
    }   

      //判断各种连线状况  
    bool judge_line(char map[3][3],int* sign)
    {
        int counter=0,row,column;
        char user_sign = (*sign==1?'O':'X');
        for(row=0 ;row<3; row++)//判断每行是否有连线
        {               
             for(column=0; column<3 ; column++)
             {
                if(map[row][column]==user_sign)
                    counter++;
                if(counter==3)/*连线成功*/
                    return true;
             }
             counter = 0;
        }   
          for(column=0; column<3 ; column++) //判断每列是否有连线
          {
             for(row=0 ;row<3; row++)
             {
               if(map[row][column]==user_sign)
                  counter++;
               if(counter==3)/*连线成功*/
                    return true;
             }
             counter = 0;
          }
          
         counter=0;
         for(row=0 ;row<3; row++)//判断右下方向对角线是否有连线
        {
            if(map[row][row]==user_sign)
            {
                counter++;
             if(counter==3)/*连线成功*/
               return true;
            }  
        }   
        //判断右上方向对角线是否有连线
        if(map[0][2]==map[1][1] && map[1][1]==map[2][0] && map[2][0]==user_sign)
        {
            return true;/*连线成功*/
        }        
         
        return false;
    }   

    //将阵列中的字元全部指定成空白字元
    void clear_map(char map[3][3])
    {
        for(int row=0; row<3; row++)
        {
            for(int column=0; column<3; column++)
            {
                map[row][column]=' ';
            }
        }
    }            
    版本二:
    复制内容到剪贴板
    代码:
    /*程式介绍:此为使用者与电脑之双方井字游戏,使用者透过输入1-9的数字来换算成实际的
    阵列座标,而电脑则是使用乱数法则来取1-9的数字并且一样换算成阵列座标

    ps:此程式并没有加入AI人工智慧的部分!!!
    */

    #include<iostream>
    #include<iomanip>
    #include<cstdlib>
    #include<ctime>
    using namespace std;

    bool user_play(char map[3][3],bool user_sign);//使用者游戏

    bool pc_play(char map[3][3],bool pc_sign);//电脑游戏

    void draw_prompt_map(char map[3][3]);//画出提示图,告诉使用者游戏玩法         

    bool judge_repeat(char map[3][3],int location,bool sign);//判断是否有重复画记号

    void draw_map(char map[3][3]);//画出游戏中的井字图

    bool judge_line(char map[3][3],bool sign);//判断各种连线状况

    void clear_map(char map[3][3]);//将阵列中的字元全部指定成空白字元,以便重新游戏

    bool full_map(char map[3][3]);//当表格全满的时候,传回true

    int main()
    {
        bool user_win = false;
        bool pc_win = false;
        bool user_sign,pc_sign;//判断使用者的符号与电脑的符号
        char map[3][3];
        char ch;//辅助字元
        int location;
         
            cout<<"*******************欢迎光临井字游戏******************\n"<<endl;
         do{
            cout<<"输入1,可以使用o来画记号。"<<endl;
            cout<<"输入2,可以使用x来画记号。"<<endl;
            cin>>ch;
            if(ch=='1')
            {
                user_sign = true;
                pc_sign = false;
            }   
            else if(ch=='2')
            {
                user_sign = false;
                pc_sign = true;
            }
         }while(ch!='1' && ch!='2');//当使用输入1或2以外的数字时,会要求使用重新输入
               
        draw_prompt_map(map);
       do{
          
           clear_map(map);//将阵列中的字元全部指定成空白字元
          
              do{
                   user_win = user_play(map,user_sign);
                    if(full_map(map))
                   {
                       break;//表格全满时,跳出迴圈   
                   }
                   pc_win = pc_play(map,pc_sign);
                   if(full_map(map))
                   {
                       break;//表格全满时,跳出迴圈
                   }                                 
               
               } while(!user_win && !pc_win);//当双方都还没有赢的时候,继续游戏
            if(user_win)
                    cout<<"恭喜你!!你赢了囉^_^!!!"<<endl;
            else if(pc_win)
                    cout<<"你输囉~~~~>.<~~~"<<endl;
            else
                    cout<<"平手喔@_@..."<<endl;
                   
            cout<<"要继续玩吗??(y)继续 or (n)结束)"<<endl;
            cin>>ch;
            system("cls");//清除萤幕
        }while(ch=='y' || ch=='Y');     
                
        system("pause");      
    }   

    bool user_play(char map[3][3],bool user_sign)
    {
           int location;
           bool user_or_pc = true;//判断目前正在游戏的一方,true为使用者
           cout<<"请选择您要画记号的位置?"<<endl;
           cin>>location;
           while(judge_repeat(map,location,user_sign))//当判断位置重复时候,重新输入位置
           {
               cout<<"请输入您要画记号的位置?"<<endl;
               cin>>location;   
           }
           draw_map(map);

           if(judge_line(map,user_sign))//当判断连线成功的时候,传回true
           {
                  return true;
           }  
           return false;
    }
    bool pc_play(char map[3][3],bool pc_sign)
    {
        int location ;
        bool user_or_pc = false;//判断目前正在游戏的一方,false为电脑
        srand(time(0));
        location = rand()%9+1;
       
        //当判断重复的时候,再一次使用乱数来取位置
        while(judge_repeat(map,location,pc_sign))
        {
            location = rand()%9+1;
        }     
             draw_map(map);      
        if(judge_line(map,pc_sign))//当电脑连线成功的时候,传回true
        {
            return true;
        }  
           return false;
       }   
       
    //画出提示图,告诉使用者游戏玩法   
    void draw_prompt_map(char map[3][3])
    {
        int num = 1;
        cout<<"\n格子中的数字代表输入代号!"<<endl;
        for(int row=0; row<3; row++)//利用迴圈来画出井字表格
        {
            for(int column=0; column<3; column++,num++)
            {
                //int的整数值加上48之后,等于char的同等整数(由ascii表得知)
                map[row][column] = num+48;
                cout<<"  "<<map[row][column]<< setw(4);
                if(column<=1)cout<<"|";
                map[row][column] = ' ';
            }
            cout<<endl;
            if(row<=1)cout<<"--------------------";
            cout<<endl;
        }
    }
    //判断是否有重复画记号
    bool judge_repeat(char map[3][3],int location,bool sign)
    {
        int row,column;
        //由于阵列索引值是从0开始,但是位置的数字是从1开始,所以要减1才能符合阵列索引规则
        location--;
       
            row = location/3 ;//将输入的数字换成表格 列 座标
            column = location % 3;//将输入的数字换成表格 行 座标   
            if(map[row][column]== ' ')
            {
                if(sign==true)//判断传入的sign是true就画上O
                {
                    map[row][column] ='O';//画上记号
                }
                else //反之,就画上X
                {
                    map[row][column] ='X';//画上记号   
                }                 
                return false;//代表没有重复
            }
            else
            {
                return  true;
            }   
                        
    }  
    //画出游戏中的井字图
    void draw_map(char map[3][3])      
    {
        int row,column;
       
        for(row=0; row<3; row++)//利用迴圈来设置表格
        {
            for(column=0; column<3; column++)
            {
                cout<<setw(3)<<map[row][column]<< setw(4);
                if(column<=1)cout<<"|";   
            }
            cout<<endl;
            if(row<=1)cout<<"--------------------";
            cout<<endl;
        }
    }   

      //判断各种连线状况  
    bool judge_line(char map[3][3],bool sign)
    {
        int counter=0,row,column;
        char process_sign;
        if(sign==true)
        {
            process_sign ='O';//决定要判断是否连线的符号
        }
        else
        {
            process_sign ='X';//决定要判断是否连线的符号
        }      
            
        for(row=0 ;row<3; row++)//判断每行是否有连线
        {               
             for(column=0; column<3 ; column++)
             {
                if(map[row][column]==process_sign)
                    counter++;
                if(counter==3)/*连线成功*/
                    return true;
             }
             counter = 0;
        }   
          for(column=0; column<3 ; column++) //判断每列是否有连线
          {
             for(row=0 ;row<3; row++)
             {
               if(map[row][column]==process_sign)
                  counter++;
               if(counter==3)/*连线成功*/
                    return true;
             }
             counter = 0;
          }
          
         counter=0;
         for(row=0 ;row<3; row++)//判断右下方向对角线是否有连线
        {
            if(map[row][row]==process_sign)
            {
                counter++;
             if(counter==3)/*连线成功*/
               return true;
            }  
        }   
        //判断右上方向对角线是否有连线
        if(map[0][2]==map[1][1] && map[1][1]==map[2][0] && map[2][0]==process_sign)
        {
            return true;/*连线成功*/
        }        
         
        return false;
    }   

    //将阵列中的字元全部指定成空白字元
    void clear_map(char map[3][3])
    {
        for(int row=0; row<3; row++)
        {
            for(int column=0; column<3; column++)
            {
                map[row][column]=' ';
            }
        }
    }            
    //计算表格是否全满
    bool full_map(char map[3][3])
    {
        int no_white_space=0;
        for(int row=0; row<3; row++)
        {
            for(int column=0; column<3; column++)
            {
                if(map[row][column]!=' ')
                {
                    no_white_space++;
                }
            }
        }
        //当表格没有任何的white space 时,代表全满,并且传回true
        if(no_white_space==9)
        {
            return true;
        }
        else
            return false;   
    }                 
    版本三:
    复制内容到剪贴板
    代码:
    /*物件导向版本的井字游戏
    程式介绍:此为使用者与电脑之双方井字游戏,使用者透过输入1-9的数字来换算成实际的
    阵列座标,而电脑则是使用乱数法则来取1-9的数字并且一样换算成阵列座标
    ps:此程式并没有加入AI人工智慧的部分!!!
    */
    #include<iostream>
    #include<iomanip>
    #include<cstdlib>
    using namespace std;

    class tictactoe
    {
        private:
          int table[3][3];//此为游戏的表格   
          
        public:
            tictactoe();//建构子
            void draw_prompt_table();//画出提示图,告诉使用者游戏玩法
            bool user_playing(int input_sign);//使用者游戏
            bool pc_playing(int input_sign);//电脑游戏
            bool judge_repeat(int location,int sign);//判断是否有重复画记号
            bool judge_line(int process_sign);//判断各种连线状况
            void draw_table();//画出游戏中的井字图
            bool full_table();//当表格全满的时候,传回true
            void clear_table();//将阵列中数值重新规零,以便重新游戏
        };
       
    //建构子,作为初始化表格为零   
    tictactoe::tictactoe()
    {
        int row,column;
        for(row=0; row<3; row++)
        {
            for(column=0; column<3; column++)
            {
                table[row][column] = 0;
             }   
        }
    }
    //画出提示图,告诉使用者如何游戏
    void tictactoe::draw_prompt_table()
    {
        int num = 1;
        cout<<"\n格子中的数字代表输入代号!"<<endl;
        for(int row=0; row<3; row++)//利用迴圈来画出井字表格
        {
            for(int column=0; column<3; column++,num++)
            {
                table[row][column] = num;
                cout<<"  "<<table[row][column]<< setw(4);
                if(column<=1)cout<<"|";
                table[row][column] = 0;
            }
            cout<<endl;
            if(row<=1)cout<<"--------------------";
            cout<<endl;
        }
    }

    bool tictactoe::user_playing(int input_sign)
    {
        int location;
       
        cout<<"请输入位置"<<endl;
        cin>>location;
        while(judge_repeat(--location,input_sign))//将位置减一化成与阵列相对的索引值
        {
            cout<<"位置重复,请输入位置"<<endl;
            cin>>location;
        }
        draw_table();//画出目前的游戏图
        if(judge_line(input_sign))//判断是否连线
        {
            return true;
        }
        else
            return false;
    }   
    bool tictactoe::pc_playing(int input_sign)
    {
        int location;
        location = rand()%9+1;
       
         //当判断重复的时候,再一次使用乱数来取位置
        while(judge_repeat(--location,input_sign))
        {
            location = rand()%9+1;
        }     
             draw_table();      
        if(judge_line(input_sign))//当电脑连线成功的时候,传回true
        {
            return true;
        }  
           return false;
       }   
         
                
    bool tictactoe::judge_repeat(int location,int sign)
    {
        int row,column;
        //由于阵列索引值是从0开始,但是位置的数字是从1开始,所以要减1才能符合阵列索引规则
       
        row = location/3 ;//将输入的数字换成表格 列 座标
        column = location % 3;//将输入的数字换成表格 行 座标   
        if(table[row][column]==0)
        {
            table[row][column] =sign;//画上记号               
                return false;//代表没有重复
        }
        else
        {
                return  true;//有重复
        }                    
    }  
       
         
       
    bool tictactoe::judge_line(int process_sign)
    {
        int counter=0,row,column;
       
        for(row=0 ;row<3; row++)//判断每行是否有连线
        {               
             for(column=0; column<3 ; column++)
             {
                if(table[row][column]==process_sign)
                    counter++;
                if(counter==3)/*连线成功*/
                    return true;
             }
             counter = 0;
        }   
          for(column=0; column<3 ; column++) //判断每列是否有连线
          {
             for(row=0 ;row<3; row++)
             {
               if(table[row][column]==process_sign)
                  counter++;
               if(counter==3)/*连线成功*/
                    return true;
             }
             counter = 0;
          }
          
         counter=0;
         for(row=0 ;row<3; row++)//判断右下方向对角线是否有连线
        {
            if(table[row][row]==process_sign)
            {
                counter++;
             if(counter==3)/*连线成功*/
               return true;
            }  
        }   
        //判断右上方向对角线是否有连线
        if(table[0][2]==table[1][1] && table[1][1]==table[2][0] && table[2][0]==process_sign)
        {
            return true;/*连线成功*/
        }        
         
        return false;   
    }   
    void tictactoe::draw_table()
    {
            int row,column;
       
        for(row=0; row<3; row++)//利用迴圈来设置表格
        {
            for(column=0; column<3; column++)
            {
                cout<<setw(3)<<table[row][column]<< setw(4);
                if(column<=1)cout<<"|";   
            }
            cout<<endl;
            if(row<=1)cout<<"--------------------";
            cout<<endl;
        }
    }   
       
    bool tictactoe:: full_table()
    {
        int no_white_space=0;
        for(int row=0; row<3; row++)
        {
            for(int column=0; column<3; column++)
            {
                if(table[row][column]!= 0)
                {
                    no_white_space++;
                }
             }
         }
    //当表格没有任何的white space 时,代表全满,并且传回true
        if(no_white_space==9)
        {
            return true;
        }
        else
            return false;   
    }              

    void tictactoe:: clear_table()
    {
        for(int row=0; row<3; row++)
        {
            for(int column=0; column<3; column++)
            {
                table[row][column]= 0;
            }
        }
    }   
    //使用者优先的模式
    bool user_first_mode(tictactoe& board, bool& user_win,bool& pc_win, int& user_sign, int& pc_sign);

    //电脑优先的模式
    bool pc_first_mode(tictactoe& board, bool& user_win,bool& pc_win, int& user_sign, int& pc_sign);

    int main()
    {
        tictactoe board;//建立井字游戏物件
       
        int user_sign,pc_sign;
        bool user_win = false;
        bool pc_win = false;
        bool full_table = false;//判断表格是否全满
        char choice,go_on;
         
        board.draw_prompt_table();//画出提示图
       
        cout<<"你要先玩吗??(y/n)"<<endl;
        cin>>choice;
       
        if(choice=='y'||choice=='Y')
        {
            cout<<"请输入你要的记号,请选择1或是2"<<endl;
            cin>>user_sign;
            while(user_sign!=1 && user_sign!=2)
            {
                cout<<"无效的输入请重新选择1或是2"<<endl;
                cin>>user_sign ;
            }      
            pc_sign = (user_sign==1? 2 : 1);
        }   
        else
        {
            srand(time(0));
            pc_sign = rand()%2+1;
            cout<<"电脑已经选择了使用数字"<<pc_sign<<"来画图"<<endl;
            user_sign = (pc_sign==1? 2 : 1);
        }            
       do{     
           board.clear_table();//将阵列中的数值指定为零
              do{
                   if(choice=='y'||choice=='Y')
                   {
                       full_table = user_first_mode(board,user_win, pc_win,user_sign,pc_sign);
                       if(full_table)break;
                   }
                   else
                   {
                       full_table = pc_first_mode(board,user_win,pc_win,user_sign,pc_sign);
                       if(full_table)break;
                   }   
                                                            
               } while(!user_win && !pc_win );//当双方都还没有赢的时候,继续游戏
               if(user_win)
                    cout<<"恭喜你!!你赢了囉^_^!!!"<<endl;
               else if(pc_win)
                    cout<<"你输囉~~~~>.<~~~"<<endl;
               else
                    cout<<"平手喔@_@..."<<endl;
                   
            cout<<"要继续玩吗??(y)继续 or (n)结束)"<<endl;
            cin>>go_on;
            system("cls");//清除萤幕
        }while(go_on=='y' || go_on=='Y');     
                
        system("pause");      
    }   

    bool user_first_mode(tictactoe& board, bool& user_win,bool& pc_win, int& user_sign, int& pc_sign)
    {
         user_win = board.user_playing(user_sign);//使用者先画图
         if(board.full_table())
         {
              return true;//表格全满时,跳出迴圈   
         }
             pc_win = board.pc_playing(pc_sign);//然后电脑画图
         if(board.full_table())
         {
              return true;//表格全满时,跳出迴圈
         }
         return false;
    }                     
    bool pc_first_mode(tictactoe& board, bool& user_win,bool& pc_win, int& user_sign, int& pc_sign)
    {
         pc_win = board.pc_playing(pc_sign);//电脑先画图
         if(board.full_table())
         {
              return true;//表格全满时,跳出迴圈
         }
         user_win = board.user_playing(user_sign);//然后使用者画图
         if(board.full_table())
         {
              return true;//表格全满时,跳出迴圈   
         }
         return false;
    }