基于TCP实现网络版三子棋小游戏

注:经大佬建议,该版本较low。只适用于客户端与服务器之间。应改成客户端与客户端之间的。接下来继续研究。争取做到最好!

学习了UDP与TCP协议后,利用这个我们可以简单的实现一些网络小游戏。比如说三子棋。这里不对其做过多的赘述,直接贴上源码。如果有错误,请及时指出。感谢各位老铁!

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>

#define ROW 3
#define COL 3

typedef struct Coord{
  int x;
  int y;
} Coord;

void InitBoard(char board[ROW][COL], int row, int col);//初始化棋盘
void Printf_Board(char board[ROW][COL], int row, int col);//打印棋盘
void EnterCoord(Coord* c, char board[ROW][COL], int row, int col);//移动
void ServerMove(Coord* c, char board[ROW][COL]);//Server走
void ClientMove(Coord* c, char board[ROW][COL]);//Client走
char CheckWin(char board[ROW][COL], int row, int col);//判断输赢
void Statement();//声明游戏规则
int Win(char board[ROW][COL], int row, int col);//封装一个判断输赢的函数
void menu();//菜单
//game.c

#include "game.h"

void Printf_Board(char board[ROW][COL], int row, int col)//打印棋盘
{
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++) {
    for (j = 0; j < col; j++) {
      printf(" %c ",board[i][j]);
      if (j < col - 1) {
        printf("|");   
      } 
    }
    printf("\n");
    if (i < row - 1) {
      printf("---|---|---\n");
    }
  }
  printf("\n");
  return;
}

void InitBoard(char board[ROW][COL], int row, int col)//初始化棋盘
{
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++) {
    for (j = 0; j < col; j++) {
      board[i][j] = ' ';
    }
  }
  return;
}

void ServerMove(Coord* c, char board[ROW][COL])
{
  board[c->x - 1][c->y - 1] = 'X';
}

void ClientMove(Coord* c, char board[ROW][COL])
{
  board[c->x - 1][c->y - 1] = 'O';
}

void EnterCoord(Coord* c, char board[ROW][COL], int row, int col)
{
  printf("You Run!\n");
  while (1) {
    printf("enter->");
    scanf("%d%d", &c->x, &c->y);
    if (board[c->x - 1][c->y - 1] == ' ' && c->x >= 1 && 
        c->x <= row && c->y >= 1 && c->y <= col) {
      break;
    }
    else
      printf("Coord error!Please enter again!\n");
  }
  return;
}

int IsFull(char board[ROW][COL], int row, int col)//判断棋盘是否满
{
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++) {
    for (j = 0; j < col; j++) {
      if (board[i][j] == ' ') {
        return 0;
      }
    }
  }
  return 1;
}

char CheckWin(char board[ROW][COL], int row, int col)//判断输赢
{
  //判断胜利的条件:行、列、两个对角线
  //1.行
  int i = 0;
  for (i = 0; i < row; i++) {
    if (board[i][0] == board[i][1] && board[i][1] == board[i][2]) {
      return board[i][1];
    }
  }

  //2.列
  for (i = 0; i < col; i++) {
    if (board[0][i] == board[1][i] && board[1][i] == board[2][i]) {
      return board[1][i];
    }
  }

  //3.对角线
  if (board[0][0] == board[1][1] && board[1][1] == board[2][2]) {
    return board[1][1];
  } else if (board[0][2] == board[1][1] && board[1][1] == board[2][0]) {
    return board[1][1];
  } else if (IsFull(board, ROW, COL) == 1) {
    return 'P';
  } else {
    return ' ';
  }
}

void Statement()
{
  printf("==============声明============\n");
  printf("这里默认让Server先走,走完之后\n");
  printf("Client再接着走,Server的落子为\n");
  printf("X,Client落子为O!\n");
}

int Win(char board[ROW][COL], int row, int col)
{
  char win = CheckWin(board, row, col);//此处可封装
  if (win == 'X') {
    printf("Server Win!\n");
    return 1;
  } else if (win == 'O') {
    printf("Client Win!\n");
    return 2;
  } else if (win == 'P') {
    printf("平局!\n");
    return 3;
  }
  return 0;
}

void menu(void)
{
  printf("*********************************\n");
  printf("*****  1.play game  0.exit  *****\n");
  printf("*********************************\n");
}


//server.c

#include "game.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
  if(argc != 3) {
    printf("usage %s [IP][port]\n",argv[0]);
    return 1;
  }
  int listen_sock = socket(AF_INET, SOCK_STREAM, 0);

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

  if(bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0) {
    printf("bind error!\n");
    return 2;
  }

  if(listen(listen_sock, 5) < 0) {
    printf("listen error!\n");
    return 3;
  }

  struct Coord c;
  char board[ROW][COL];
  InitBoard(board, ROW, COL);

  struct sockaddr_in client_addr;
  socklen_t len = sizeof(client_addr);

  while(1) {
    int input = 0;
    menu();
    printf("Please choose->");
    fflush(stdout);
    scanf("%d",&input);
    if(input == 1) {
      printf("Waiting for client...\n");
      sleep(2);
      int sock = accept(listen_sock, (struct sockaddr*)&client_addr, &len);
      if(sock > 0) {
        printf("Client comming!\n");
      }
      Statement();
      Printf_Board(board, ROW, COL);
      while(1) {
        EnterCoord(&c, board, ROW, COL);
        ServerMove(&c, board);
        Printf_Board(board, ROW, COL);
        write(sock, &c, sizeof(c));
        int ret = Win(board, ROW, COL);
        if(ret != 0) {
          break;
        }
        printf("Waiting Client Run!\n");
        read(sock, &c, sizeof(c));
        ClientMove(&c, board);
        Printf_Board(board, ROW, COL);
        ret = Win(board, ROW, COL);
        if(ret != 0) {
          break;
        }
      }
      close(sock);
    } else if(input == 0) {
      printf("exit!\n");
      break;
    } else {
      printf("Enter error! Please choose again!\n");
      continue;
    }
  }
  close(listen_sock);

  return 0;
}

//client.c

#include "game.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
  if(argc != 3) {
    printf("usage %s [IP][port]\n",argv[0]);
    return 1;
  }

  int sock = socket(AF_INET, SOCK_STREAM, 0);
  if(sock < 0) {
    printf("socket error!\n");
    return 2;
  }

  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]));

  struct Coord c;
  char board[ROW][COL];
  InitBoard(board, ROW, COL);

  while(1) {
    menu();
    int input = 0;
    printf("Please choose->");
    fflush(stdout);
    scanf("%d",&input);
    if(input == 1) {
      if(connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
        printf("connect error!\n");
        return 3;
      } 
      Statement();
      Printf_Board(board, ROW, COL);
      while(1) {
        printf("Waiting Server Run!\n");
        read(sock, &c, sizeof(c));
        ServerMove(&c, board);
        Printf_Board(board, ROW, COL);
        int ret = Win(board, ROW, COL);
        if(ret != 0) {
          break;
        }
        EnterCoord(&c, board, ROW, COL);
        ClientMove(&c, board);
        write(sock, &c, sizeof(c));
        Printf_Board(board, ROW, COL);
        ret = Win(board, ROW, COL);
        if(ret != 0) {
          break;
        }
      }
    } else if(input == 0) {
      printf("exit!\n");
      break;
    } else {
      printf("Enter error! Please choose again!\n");
      continue;
    }
  }
  close(sock);

  return 0;
}

下面附上游戏截图:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述


欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!

猜你喜欢

转载自blog.csdn.net/liuchenxia8/article/details/80288118