C語言實現簡單網絡版五子棋(服務器與客戶端)

本小遊戲是在Linux下實現的(因爲我不會Windows網絡編程),這次實現的僅僅是服務器與客戶端之間進行互動,彼此只要互相發送下點的座標就ok,用結構體存放座標,各自收到座標後進行下子,以及判斷結果。
本篇文章裏只涉及部分代碼,更多是步驟介紹,實現方法以及思路
源碼在這裏()->https://github.com/Xiaoyejun/learngit/commit/44caec515cb7194eb8119ba4c4b3d75473e729d1(綠色部分)

小遊戲介紹

五子棋大家肯定都玩過,無非就是你下子來我來賭,能贏全靠運氣(這裏說的是本人)。要想實現一個簡易的五子棋小遊戲,需要的也就是三點 : 1、棋盤 2、黑子/白子(這裏我們用兩個不同的字符區分黑白方) 3、遊戲規則

遊戲實現

  • 首先我們打印一張棋盤,範圍自己控制,我這裏是10*10的棋盤,打印前進行初始化
void InitBoard(char board[ROWS][COLS],int row, int col)
{
//每個座標的初始值我用空格代替
    memset(board,' ',row*col*sizeof(char));
}
//打印棋盤
void PrintBoard(char board[ROWS][COLS],int row,int col)
{
    int  i = 0;
    printf("    1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10\n");
    for(; i < row;i++)
    {
        printf("%2d ",i+1);
        int j = 0;
        for(; j < col;j++)
        {
            if( j == col-1 )
            {
                printf(" %c \n",board[i][j]);
                if(i != row-1)
                    printf("   ---|---|---|---|---|---|---|---|---|---\n");
                break;
            }
            printf(" %c ",board[i][j]);
            printf("|");
        }

    }
}     

結果
這裏寫圖片描述

  • 遊戲規則:
    • 不能下到邊界外
    • 不能下到已有子處
    • 有一方贏遊戲就結束,或者雙方平局

看起來是不是很簡單,實際上它就是很簡單,因爲這只是1.0版本的,以後我會努力推出高級版本,大家拭目以待。

玩家移動代碼:

//移動
void CommonMove(char board[ROWS][COLS],Point* point,char ch) 
{
    if(point == NULL)
    {   
        return;
    }   
    int x = point->row;
    int y = point->col;
    //如果棋盤滿了的話就退出循環,也就是不能再下子了
    while(1)
    {   
        if(x >= 0 && x < ROWS && y >= 0 && y < COLS){
            if(board[x][y] == ' ')
            {   
                board[x][y] = ch; 
                point->row = x;
                point->col = y;
                break;
            }   
            else
            {   
                printf("座標輸入有誤,請重新輸入座標: ");
                scanf("%d%d",&x,&y);
                x--;
                y--;
            }
        }
        else{
            printf("座標輸入有誤,請重新輸入座標: ");
            scanf("%d%d",&x,&y);
            x--;                                                                                                                        
            y--;
        }
    }
    }
//客戶端移動
void ClientMove(char board[ROWS][COLS],Point* point)
{
    CommonMove(board,point,'X');
}

//服務器移動
void ServerMove(char board[ROWS][COLS],Point* point)
{
    CommonMove(board,point,'O');
}

客戶端和服務器下棋的具體操作是一樣的,只不過需要傳入不一樣的標誌。

  • 輸贏判斷

這裏寫圖片描述

  • 實現網絡版

我用的是tcp套接字編程,客戶端和服務器建立連接後,客戶端顯示遊戲菜單,進入遊戲後,客戶端先下棋,然後把下子的座標通過一個結構體發給服務器,服務器向客戶端發送座標時也是如此。

server.c
int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        printf("Usage: ./server [ip] [port]\n");
        exit(1);
    }

    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(argv[1]);                                                                                        
    server.sin_port = htons(atoi(argv[2]));

    int ret = bind(sock,(const struct sockaddr*)&server,sizeof(server));
    if(ret < 0)
    {
        perror("bind");
        exit(2);
    }
    ret = listen(sock,5);
        if(ret < 0)
    {
        perror("listen");
        exit(3);
    }

    for(;;)
    {
        struct sockaddr_in client;
        socklen_t len;
        int client_sock = accept(sock,(struct sockaddr*)&client,&len);
        if(client_sock < 0)
        {
            continue;
        }
        ssize_t s;
        Point point_server,point_client;
        char board[ROWS][COLS];
        InitBoard(board,ROWS,COLS);
        int x,y;
        while(1){
            s = read(client_sock,(void*)&point_client,sizeof(point_client));
            if(s == 0)
            {
                printf("Client quit...\n");
                close(client_sock);
            }
            ClientMove(board,&point_client);                                                                                            
            PrintBoard(board,ROWS,COLS);
            if(GameState(board,&point_client) == 'X')
            {
               printf("Client win!\n");
                break;
            }
            else if(GameState(board,&point_client) == 'p')
            {
                printf("平局!\n");
                break;
            }
            printf("請下子(輸入座標)> ");
            scanf("%d%d",&x,&y);
            point_server.row = x-1;
            point_server.col = y-1;
            ServerMove(board,&point_server);
            PrintBoard(board,ROWS,COLS);
            write(client_sock,(void*)&point_server,sizeof(point_server));
            if(GameState(board,&point_client) == 'O')
            {
                printf("You win!\n");
                break;
            }
            else if(GameState(board,&point_client) == 'p')
            {
                printf("平局!\n");
                break;
            }

        }//遊戲下完了
    }
    close(sock);
    return 0;
}
client.c
void Menu()
{
    printf("==================================\n");
    printf("||  1.開始遊戲   0.退出遊戲     ||\n");
    printf("==================================\n");
}
void Game(int sock)
{
    Point point_server,point_client;
    char board[ROWS][COLS];
    InitBoard(board,ROWS,COLS);
    PrintBoard(board,ROWS,COLS);
    ssize_t s;
    int x,y;
    while(1){
        printf("請下子(輸入座標)> ");
        scanf("%d%d",&x,&y);
        point_client.row = x-1;
        point_client.col = y-1;
        ClientMove(board,&point_client);
        PrintBoard(board,ROWS,COLS);
        write(sock,(void*)&point_client,sizeof(point_client));
        if(GameState(board,&point_client) == 'X')
        {
            printf("You win!\n");
            break;
        }
        else if(GameState(board,&point_client) == 'p')
        {
            printf("平局!\n");
            break;                                                                                                                      
        }
        s = read(sock,(void*)&point_server,sizeof(point_server));
        if(s == 0)
       {
            printf("Server quit\n");
            return;
        }
        ServerMove(board,&point_server);
        PrintBoard(board,ROWS,COLS);
        if(GameState(board,&point_server) == 'O')
        {
            printf("Server win!\n");
            break;
        }
        else if(GameState(board,&point_server) == 'p')
        {
            printf("平局!\n");
            break;
        }
    }
}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        printf("Usage: ./server [ip] [port]\n");
        exit(1);
    }

    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0)
    {
        perror("socket");                                                                                                               
        exit(1);
    }
        struct sockaddr_in client;
    client.sin_family = AF_INET;
    client.sin_addr.s_addr = inet_addr(argv[1]);
    client.sin_port = htons(atoi(argv[2]));
    int ret = connect(sock,(const struct sockaddr*)&client,sizeof(client));
    if(ret < 0)
    {
        perror("connect");
        exit(2);
    }
    Menu();
    int state;
    while(1)
    {
        printf("請做出你的選擇> ");
        scanf("%d",&state);
        if(state == 1)
        {
            Game(sock);
        }else if(state == 0)
        {
            break;
        }
        else
        {
            printf("選擇錯誤\n");
            Menu();
            sleep(2);
        }
    }

    close(sock);
    return 0;                                                                                                                           
}

  • 部分結果演示

客戶端先下棋
這裏寫圖片描述
下了一會兒以後。。。

客戶端:
這裏寫圖片描述

服務器:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章