用C语言写一个多线程,TCP的21点游戏程序
时间: 2023-12-08 21:03:06 浏览: 160
好的,我可以为您提供一份基本的参考代码。请注意,这只是一个示例,您可能需要根据实际情况进行修改和优化。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT 8888
#define MAX_CLIENTS 5
// 定义卡牌数据结构
typedef struct {
char name[10]; // 卡牌名称
int point; // 点数
} Card;
// 定义全局变量
Card deck[52]; // 卡牌堆
int deck_index = 0; // 卡牌堆索引
int dealer_cards[10]; // 庄家手牌
int dealer_cards_index = 0; // 庄家手牌索引
int client_cards[MAX_CLIENTS][10]; // 玩家手牌
int client_cards_index[MAX_CLIENTS] = {0}; // 玩家手牌索引
int client_scores[MAX_CLIENTS] = {0}; // 玩家分数
bool client_status[MAX_CLIENTS] = {false}; // 玩家状态(是否已停牌)
pthread_mutex_t mutex; // 互斥锁
// 初始化卡牌堆
void init_deck() {
char names[4][10] = {"Spades", "Hearts", "Diamonds", "Clubs"};
int values[13] = {2,3,4,5,6,7,8,9,10,10,10,10,11};
int index = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 13; j++) {
strcpy(deck[index].name, names[i]);
deck[index].point = values[j];
index++;
}
}
}
// 洗牌
void shuffle_deck() {
srand(time(NULL));
for (int i = 0; i < 52; i++) {
int j = rand() % 52;
Card temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
// 发牌
void deal_card(int player) {
pthread_mutex_lock(&mutex);
client_cards[player][client_cards_index[player]] = deck[deck_index].point;
client_cards_index[player]++;
client_scores[player] += deck[deck_index].point;
deck_index++;
pthread_mutex_unlock(&mutex);
}
// 发庄家的牌
void deal_dealer_card() {
pthread_mutex_lock(&mutex);
dealer_cards[dealer_cards_index] = deck[deck_index].point;
dealer_cards_index++;
if (dealer_cards_index == 1) {
printf("Dealer's card: %d\n", dealer_cards[0]);
} else {
printf("Dealer's card: X\n");
}
deck_index++;
pthread_mutex_unlock(&mutex);
}
// 计算手牌分数
int get_score(int player) {
int score = 0;
for (int i = 0; i < client_cards_index[player]; i++) {
score += client_cards[player][i];
}
return score;
}
// 判断是否爆牌
bool is_busted(int player) {
return (client_scores[player] > 21);
}
// 判断是否为21点
bool is_blackjack(int player) {
return (client_scores[player] == 21);
}
// 判断是否已停牌
bool is_stopped(int player) {
return client_status[player];
}
// 玩家操作
void player_turn(int player, int client_sock) {
char buffer[1024];
int n;
while (true) {
// 发送当前的手牌
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "Your cards: ");
for (int i = 0; i < client_cards_index[player]; i++) {
char card[10];
sprintf(card, "%d ", client_cards[player][i]);
strcat(buffer, card);
}
strcat(buffer, "\n");
write(client_sock, buffer, strlen(buffer));
// 发送当前的分数
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "Your score: %d\n", client_scores[player]);
write(client_sock, buffer, strlen(buffer));
// 接收操作指令
memset(buffer, 0, sizeof(buffer));
n = read(client_sock, buffer, sizeof(buffer));
if (n <= 0) {
break;
}
// 处理操作指令
if (strcmp(buffer, "hit") == 0) {
deal_card(player);
if (is_busted(player)) {
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "Busted! Your score: %d\n", client_scores[player]);
write(client_sock, buffer, strlen(buffer));
break;
}
} else if (strcmp(buffer, "stand") == 0) {
client_status[player] = true;
break;
} else {
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "Invalid command!\n");
write(client_sock, buffer, strlen(buffer));
}
}
}
// 庄家操作
void dealer_turn() {
while (get_score(0) < 17) {
deal_card(0);
}
}
// 比较分数
void compare_scores(int client_sock) {
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
// 判断庄家是否爆牌
if (is_busted(0)) {
sprintf(buffer, "Dealer's score: %d\n", get_score(0));
strcat(buffer, "Dealer is busted! You win!\n");
write(client_sock, buffer, strlen(buffer));
} else {
// 比较玩家和庄家的分数
for (int i = 1; i < MAX_CLIENTS; i++) {
if (client_status[i]) {
if (is_busted(i)) {
sprintf(buffer, "Player %d is busted!\n", i);
write(client_sock, buffer, strlen(buffer));
} else if (is_blackjack(i) && !is_blackjack(0)) {
sprintf(buffer, "Player %d has blackjack! You win!\n", i);
write(client_sock, buffer, strlen(buffer));
} else if (is_blackjack(0) && !is_blackjack(i)) {
sprintf(buffer, "Dealer has blackjack! You lose!\n");
write(client_sock, buffer, strlen(buffer));
} else if (get_score(i) > get_score(0)) {
sprintf(buffer, "Player %d wins! Your score: %d, dealer's score: %d\n", i, get_score(i), get_score(0));
write(client_sock, buffer, strlen(buffer));
} else if (get_score(i) < get_score(0)) {
sprintf(buffer, "Dealer wins! Your score: %d, dealer's score: %d\n", get_score(i), get_score(0));
write(client_sock, buffer, strlen(buffer));
} else {
sprintf(buffer, "Player %d ties with dealer! Your score: %d\n", i, get_score(i));
write(client_sock, buffer, strlen(buffer));
}
}
}
}
}
// 线程函数
void *client_handler(void *arg) {
int client_sock = *((int *)arg);
int player = -1;
// 寻找空闲的玩家位置
for (int i = 1; i < MAX_CLIENTS; i++) {
if (!client_status[i]) {
player = i;
break;
}
}
// 如果没有空闲位置,则拒绝连接
if (player == -1) {
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "Sorry, the game is full!\n");
write(client_sock, buffer, strlen(buffer));
close(client_sock);
return NULL;
}
// 发送欢迎消息和玩家编号
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "Welcome to 21 point game! You are player %d\n", player);
write(client_sock, buffer, strlen(buffer));
// 等待其他玩家连接
while (true) {
int count = 0;
for (int i = 1; i < MAX_CLIENTS; i++) {
if (client_status[i]) {
count++;
}
}
if (count == MAX_CLIENTS - 1) {
break;
}
sleep(1);
}
// 发牌
deal_dealer_card();
deal_card(player);
deal_card(player);
deal_card(0);
deal_card(0);
// 玩家操作
player_turn(player, client_sock);
// 庄家操作
dealer_turn();
// 比较分数
compare_scores(client_sock);
// 关闭连接
close(client_sock);
// 重置玩家状态
client_cards_index[player] = 0;
client_scores[player] = 0;
client_status[player] = false;
return NULL;
}
int main() {
// 初始化卡牌堆
init_deck();
// 创建套接字
int server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 绑定地址
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(PORT);
if (bind(server_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
// 监听连接
if (listen(server_sock, MAX_CLIENTS) == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
// 等待连接
pthread_mutex_init(&mutex, NULL);
while (true) {
struct sockaddr_in client_addr;
int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, (socklen_t *)&sizeof(client_addr));
if (client_sock == -1) {
perror("accept");
continue;
}
// 创建线程处理连接
pthread_t tid;
int *ptr = malloc(sizeof(int));
*ptr = client_sock;
if (pthread_create(&tid, NULL, client_handler, ptr) != 0) {
perror("pthread_create");
continue;
}
pthread_detach(tid);
}
// 关闭套接字
close(server_sock);
return 0;
}
```
这是一个基本的21点游戏程序,使用了多线程和TCP协议。在这个程序中,每个客户端都会被分配一个玩家位置,最多支持5个客户端同时进行游戏。程序启动后,等待客户端连接,当有足够的玩家连接后,开始发牌并进行游戏。每个客户端都可以进行hit和stand操作,当所有玩家都停牌后,庄家开始操作。最后比较各玩家的分数和庄家的分数,输出结果,并重置玩家状态,等待下一局游戏。
阅读全文