Linux网络编程10——使用UDP实现五子棋对战

时间:2022-11-08 09:58:49

思路

1. 通信

为了同步双方的棋盘,每当一方在棋盘上落子之后,都需要发送给对方一个msg消息,让对方知道落子位置。msg结构体如下:

/* 用于发给对方的信息 */
typedef struct tag_msg
{
int msg_type; /* 悔棋? */
int msg_color;
int msg_row;
int msg_col;
}MSG, *pMSG;

2. 悔棋

用链表头插法来模拟栈,链表记录了双方下子的轨迹。结构如下:

/* 记录每一步的轨迹 */
typedef struct tag_trace
{
int tr_cow;
int tr_col;
char tr_before[4]; /* 记录原来该位置的内容。注意要存下之前的!! */
struct tag_trace* tr_next;
}TRACE, *pTRACE;

使用两个链表,一个链表用于记录自己下棋的轨迹,便于自己悔棋;另一个链表用于记录对方下棋的轨迹,便于对方悔棋。

3. 判断胜负

以水平方向为例:需要判断该棋子(包括该子)左边有多少相同颜色的棋子相连,以及右边有多少相同颜色的棋子相连,两者相加如果和大于等于5,则判赢。其余3个方向类似。具体可以参加代码。

4. 本代码用到了Linux网络编程9——对TCP与UDP的简易封装2.0中的动态库文件。

代码

chess.h

#ifndef __MY_CHESS_H__
#define __MY_CHESS_H__
#include "my_socket.h"
#include <pthread.h> #define MSG_NORMAL 1
#define MSG_BACK 2
#define CH_BLACK 1
#define CH_WHITE 2
#define ROW 19
#define COL 19
#define WHITE_CHESS "○"
#define BLACK_CHESS "●" typedef struct tag_msg
{
int msg_type ;
int msg_color ;
int msg_row ;
int msg_col ;
}MSG, *pMSG ; typedef struct tag_trace
{
int tr_row ;
int tr_col ;
char tr_before[4] ;
struct tag_trace* tr_next ;
}TRACE, *pTRACE; void chess_show(char ch[][COL][4], int row);
int chess_win(char arr[][COL][4], int row, int pos_x, int pos_y, char* color); #endif

chess.c

/*************************************************************************
> File Name: chess.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Wed 03 Sep 2014 09:35:57 PM CST
************************************************************************/
#include "chess.h" void chess_show(char arr[][COL][4], int row_cnt)
{
int row, col ;
printf(" ");
for(col = 0; col < COL ; col ++)
{
printf("%2d", col + 1);
}
printf("\n");
for(row = 0; row < row_cnt ; row ++)
{
printf("%3d ", row + 1);
for(col = 0; col < COL ; col ++)
{
printf("%s", arr[row][col]);
if(col != row_cnt -1 )
{
printf("-");
}
}
printf("\n");
}
printf("\n"); }
int chess_win(char arr[][COL][4], int row, int pos_x, int pos_y, char* color)
{
// level
int cnt1, cnt2 ;
int index_x, index_y ;
for(cnt1 = 0,index_x = pos_x, index_y = pos_y; index_y < COL; index_y ++)
{
if(strcmp(arr[index_x][index_y], color) == 0)
{
cnt1 ++ ;
}else
{
break ;
}
}
for(cnt2 = 0, index_x = pos_x , index_y = pos_y - 1 ; index_y >= 0; index_y --)
{
if(strcmp(arr[index_x][index_y], color) == 0)
{
cnt2 ++ ;
}else
{
break ;
}
}
if(cnt1 + cnt2 >= 5)
{
return 1 ;
}
// vertical
for(cnt1 = 0,index_x = pos_x, index_y = pos_y; index_x >= 0; index_x --)
{
if(strcmp(arr[index_x][index_y], color) == 0)
{
cnt1 ++ ;
}else
{
break ;
}
}
for(cnt2 = 0, index_x = pos_x + 1 , index_y = pos_y ; index_x < row ; index_x ++)
{
if(strcmp(arr[index_x][index_y], color) == 0)
{
cnt2 ++ ;
}else
{
break ;
}
}
if(cnt1 + cnt2 >= 5)
{
return 1 ;
}
// + ==
int sum = pos_x + pos_y ;
for(cnt1 = 0, index_x = pos_x; index_x >= 0 && sum - index_x < COL; index_x --)
{
if(strcmp(arr[index_x][sum - index_x], color) == 0)
{
cnt1 ++ ;
}else
{
break ;
}
}
for(cnt2 = 0, index_x = pos_x + 1; index_x < row && index_x <= sum ; index_x ++ )
{
if(strcmp(arr[index_x][sum - index_x], color) == 0)
{
cnt2 ++ ;
}else
{
break ;
}
}
if(cnt1 + cnt2 >= 5)
{
return 1 ;
}
// abs - ==
int delt ;
if(pos_x > pos_y)
{
delt = pos_x - pos_y ;
for(cnt1 = 0 , index_x = pos_x; index_x >=0 && index_x >= delt; index_x --)
{
if(strcmp(arr[index_x][index_x - delt], color) == 0)
{
cnt1 ++ ;
}else
{
break ;
}
}
for(cnt2 = 0, index_x = pos_x + 1; index_x < row ; index_x ++)
{
if(strcmp(arr[index_x][index_x - delt], color) == 0)
{
cnt2 ++ ;
}else
{
break ;
}
}
}else// pos_y >= pos_x
{
delt = pos_y - pos_x ;
for(cnt1 = 0 , index_x = pos_x; index_x >=0 ; index_x --)
{
if(strcmp(arr[index_x][index_x + delt], color) == 0)
{
cnt1 ++ ;
}else
{
break ;
}
}
for(cnt2 = 0, index_x = pos_x + 1; index_x < row && index_x + delt < COL ; index_x ++)
{
if(strcmp(arr[index_x][index_x + delt], color) == 0)
{
cnt2 ++ ;
}else
{
break ;
}
}
}
if(cnt1 + cnt2 >= 5)
{
return 1 ;
}
return 0;
}

main.c

/*************************************************************************
> File Name: main.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Wed 03 Sep 2014 10:04:07 PM CST
************************************************************************/
#include "chess.h"
#define B_IP "127.0.0.1"
#define B_PORT 8888
#define W_IP "127.0.0.1"
#define W_PORT 6666
#define POS_TRANS(pos) (pos -1)
#define IS_OK(row, col) ( row >= 0 && col >= 0 && col <= 18 &&row <= 18 &&strcmp(my_chess[row][col], WHITE_CHESS) != 0 && strcmp(my_chess[row][col], BLACK_CHESS) != 0)
int main(int argc, char* argv[])
{
char my_chess[ROW][COL][4] =
{
"┌","┬","┬","┬","┬","┬","┬","┬","┬","┬","┬","┬","┬","┬","┬","┬","┬","┬","┐" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"├","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┼","┤" ,
"└","┴","┴","┴","┴","┴","┴","┴","┴","┴","┴","┴","┴","┴","┴","┴","┴","┴","┘" };
int sfd ;
pTRACE my_tr, peer_tr, pStep, pTmp ; my_tr = NULL ;
peer_tr = NULL ;
#ifdef FIRST
my_socket(&sfd, MY_UDP, B_IP, B_PORT);
#else
my_socket(&sfd, MY_UDP, W_IP, W_PORT);
#endif
int row, col ;
MSG my_msg ;
#ifdef FIRST
chess_show(my_chess, ROW);
while(1)// 0, 0
{
do
{
printf(">>");
scanf("%d%d", &row, &col);
if(row == 0 || col == 0)
{
break ;
}
}while( !IS_OK(POS_TRANS(row), POS_TRANS(col))) ;
if(row !=0 && col != 0)// normal
{
my_msg.msg_type = MSG_NORMAL ;
my_msg.msg_color = CH_BLACK ;
my_msg.msg_row = POS_TRANS(row) ;
my_msg.msg_col = POS_TRANS(col) ;
my_sendto(NULL, sfd, &my_msg, sizeof(MSG), W_IP, W_PORT); pStep = (pTRACE)calloc(1, sizeof(TRACE)) ;
pStep ->tr_row = POS_TRANS(row) ;
pStep ->tr_col = POS_TRANS(col) ;
strcpy(pStep ->tr_before, my_chess[POS_TRANS(row)][POS_TRANS(col)]) ; pStep -> tr_next = my_tr ;
my_tr = pStep ; strcpy(my_chess[POS_TRANS(row)][POS_TRANS(col)], BLACK_CHESS); system("clear");
chess_show(my_chess, ROW);
if(chess_win(my_chess, ROW, POS_TRANS(row), POS_TRANS(col), BLACK_CHESS))
{
printf("black win !");
exit(1);
}
}else
{
if(my_tr == NULL)
{
continue ;
}else
{
memset(&my_msg, 0, sizeof(MSG));
my_msg.msg_type = MSG_BACK ;
my_sendto(NULL, sfd, &my_msg, sizeof(MSG), W_IP, W_PORT);
strcpy(my_chess[my_tr -> tr_row][my_tr -> tr_col], my_tr ->tr_before);
system("clear");
chess_show(my_chess, ROW); pTmp = my_tr ;
my_tr = my_tr -> tr_next ;
free(pTmp);
pTmp = NULL ; /* 本方悔棋后,需要在下一次 */
do{
printf(">>");
scanf("%d%d", &row, &col);
}while( !IS_OK(POS_TRANS(row), POS_TRANS(col))) ; my_msg.msg_type = MSG_NORMAL ;
my_msg.msg_color = CH_BLACK ;
my_msg.msg_row = POS_TRANS(row) ;
my_msg.msg_col = POS_TRANS(col) ;
my_sendto(NULL, sfd, &my_msg, sizeof(MSG), W_IP, W_PORT); pStep = (pTRACE)calloc(1, sizeof(TRACE)) ;
pStep ->tr_row = POS_TRANS(row) ;
pStep ->tr_col = POS_TRANS(col) ;
strcpy(pStep ->tr_before, my_chess[POS_TRANS(row)][POS_TRANS(col)]) ; pStep -> tr_next = my_tr ;
my_tr = pStep ; strcpy(my_chess[POS_TRANS(row)][POS_TRANS(col)], BLACK_CHESS); system("clear");
chess_show(my_chess, ROW);
if(chess_win(my_chess, ROW, POS_TRANS(row), POS_TRANS(col), BLACK_CHESS))
{
printf("black win !");
exit(1);
} }
} memset(&my_msg, 0, sizeof(MSG));
my_recvfrom(NULL, sfd, &my_msg, sizeof(MSG), NULL, NULL);
if(my_msg.msg_type == MSG_NORMAL)
{
pStep = (pTRACE)calloc(1, sizeof(TRACE)) ;
pStep ->tr_row = my_msg.msg_row ;
pStep ->tr_col = my_msg.msg_col ;
strcpy(pStep ->tr_before, my_chess[my_msg.msg_row][my_msg.msg_col]) ;
pStep -> tr_next = peer_tr;
peer_tr = pStep ; strcpy(my_chess[my_msg.msg_row][my_msg.msg_col], WHITE_CHESS);
system("clear");
chess_show(my_chess, ROW);
if(chess_win(my_chess, ROW, my_msg.msg_row, my_msg.msg_col, WHITE_CHESS))
{
printf("white win !");
exit(1);
}
}else if(my_msg.msg_type == MSG_BACK)
{
strcpy(my_chess[peer_tr -> tr_row][peer_tr -> tr_col], peer_tr ->tr_before);
system("clear");
chess_show(my_chess, ROW); pTmp = peer_tr ;
peer_tr = peer_tr -> tr_next ;
free(pTmp);
pTmp = NULL ; /* 对方悔棋后,本方需要再收一次 */
memset(&my_msg, 0, sizeof(MSG));
my_recvfrom(NULL, sfd, &my_msg, sizeof(MSG), NULL, NULL); pStep = (pTRACE)calloc(1, sizeof(TRACE)) ;
pStep ->tr_row = my_msg.msg_row ;
pStep ->tr_col = my_msg.msg_col ;
strcpy(pStep ->tr_before, my_chess[my_msg.msg_row][my_msg.msg_col]) ;
pStep -> tr_next = peer_tr;
peer_tr = pStep ; strcpy(my_chess[my_msg.msg_row][my_msg.msg_col], WHITE_CHESS);
system("clear");
chess_show(my_chess, ROW);
if(chess_win(my_chess, ROW, my_msg.msg_row, my_msg.msg_col, WHITE_CHESS))
{
printf("white win !");
exit(1);
}
}
}
#else
{
chess_show(my_chess, ROW);
while(1)
{
memset(&my_msg, 0, sizeof(MSG));
my_recvfrom(NULL, sfd, &my_msg, sizeof(MSG), NULL, NULL);
if(my_msg.msg_type == MSG_NORMAL)
{ pStep = (pTRACE)calloc(1, sizeof(TRACE)) ;
pStep ->tr_row = my_msg.msg_row ;
pStep ->tr_col = my_msg.msg_col ;
strcpy(pStep ->tr_before, my_chess[my_msg.msg_row][my_msg.msg_col]) ;
pStep -> tr_next = peer_tr;
peer_tr = pStep ; strcpy(my_chess[my_msg.msg_row][my_msg.msg_col], BLACK_CHESS);
system("clear");
chess_show(my_chess, ROW);
if(chess_win(my_chess, ROW, my_msg.msg_row, my_msg.msg_col, BLACK_CHESS))
{
printf("black win !");
exit(1);
} }else if(my_msg.msg_type == MSG_BACK)
{
strcpy(my_chess[peer_tr -> tr_row][peer_tr -> tr_col], peer_tr ->tr_before);
system("clear");
chess_show(my_chess, ROW); pTmp = peer_tr ;
peer_tr = peer_tr -> tr_next ;
free(pTmp);
pTmp = NULL ; memset(&my_msg, 0, sizeof(MSG));
my_recvfrom(NULL, sfd, &my_msg, sizeof(MSG), NULL, NULL); pStep = (pTRACE)calloc(1, sizeof(TRACE)) ;
pStep ->tr_row = my_msg.msg_row ;
pStep ->tr_col = my_msg.msg_col ;
strcpy(pStep ->tr_before, my_chess[my_msg.msg_row][my_msg.msg_col]) ;
pStep -> tr_next = peer_tr;
peer_tr = pStep ; strcpy(my_chess[my_msg.msg_row][my_msg.msg_col], BLACK_CHESS);
system("clear");
chess_show(my_chess, ROW);
if(chess_win(my_chess, ROW, my_msg.msg_row, my_msg.msg_col, BLACK_CHESS))
{
printf("black win !");
exit(1);
} } do{
printf(">>");
scanf("%d%d", &row, &col);
if(row == 0 || col == 0)
{
break ;
}
}while(!IS_OK(POS_TRANS(row), POS_TRANS(col))) ;
if(row != 0 && col != 0 )//normal
{
my_msg.msg_type = MSG_NORMAL ;
my_msg.msg_color = CH_WHITE ;
my_msg.msg_row = POS_TRANS(row) ;
my_msg.msg_col = POS_TRANS(col) ;
my_sendto(NULL, sfd, &my_msg, sizeof(MSG), B_IP, B_PORT); pStep = (pTRACE)calloc(1, sizeof(TRACE)) ;
pStep ->tr_row = POS_TRANS(row) ;
pStep ->tr_col = POS_TRANS(col) ;
strcpy(pStep ->tr_before, my_chess[POS_TRANS(row)][POS_TRANS(col)]) ; pStep -> tr_next = my_tr ;
my_tr = pStep ; strcpy(my_chess[POS_TRANS(row)][POS_TRANS(col)], WHITE_CHESS);
system("clear");
chess_show(my_chess, ROW);
if(chess_win(my_chess, ROW, POS_TRANS(row), POS_TRANS(col), WHITE_CHESS))
{
printf("white win !");
exit(1);
} }else
{
if(my_tr == NULL)
{
continue ;
}else
{
memset(&my_msg, 0, sizeof(MSG));
my_msg.msg_type = MSG_BACK ;
my_sendto(NULL, sfd, &my_msg, sizeof(MSG), B_IP, B_PORT);
strcpy(my_chess[my_tr -> tr_row][my_tr -> tr_col], my_tr ->tr_before);
system("clear");
chess_show(my_chess, ROW); pTmp = my_tr ;
my_tr = my_tr -> tr_next ;
free(pTmp);
pTmp = NULL ; do{
printf(">>");
scanf("%d%d", &row, &col);
}while(!IS_OK(POS_TRANS(row), POS_TRANS(col)) ); my_msg.msg_type = MSG_NORMAL ;
my_msg.msg_color = CH_WHITE ;
my_msg.msg_row = POS_TRANS(row) ;
my_msg.msg_col = POS_TRANS(col) ;
my_sendto(NULL, sfd, &my_msg, sizeof(MSG), B_IP, B_PORT); pStep = (pTRACE)calloc(1, sizeof(TRACE)) ;
pStep ->tr_row = POS_TRANS(row) ;
pStep ->tr_col = POS_TRANS(col) ;
strcpy(pStep ->tr_before, my_chess[POS_TRANS(row)][POS_TRANS(col)]) ; pStep -> tr_next = my_tr ;
my_tr = pStep ; strcpy(my_chess[POS_TRANS(row)][POS_TRANS(col)], WHITE_CHESS);
system("clear");
chess_show(my_chess, ROW);
if(chess_win(my_chess, ROW, POS_TRANS(row), POS_TRANS(col), WHITE_CHESS))
{
printf("white win !");
exit(1);
} } }
} }
#endif
return 0 ;
}

编译如下:

gcc -o black *.c -DFIRST -lmy_socket -I/home/purple/include
gcc -o white *.c -lmy_socket -I/home/purple/include

Linux网络编程10——使用UDP实现五子棋对战的更多相关文章

  1. Linux网络编程四、UDP,广播和组播

    一.UDP UDP:是一个支持无连接的传输协议,全称是用户数据包协议(User Datagram Protocol).UDP协议无需像TCP一样要建立连接后才能发送封装的IP数据报,也是因此UDP相较 ...

  2. Linux 网络编程五(UDP协议)

    UDP和TCP的对比 --UDP处理的细节比TCP少. --UDP不能保证消息被传送到目的地. --UDP不能保证数据包的传递顺序. --TCP处理UDP不处理的细节. --TCP是面向连接的协议 - ...

  3. Linux网络编程:基于UDP的程序开发回顾篇

    基于无连接的UDP程序设计 同样,在开发基于UDP的应用程序时,其主要流程如下:   对于面向无连接的UDP应用程序在开发过程中服务端和客户端的操作流程基本差不多.对比面向连接的TCP程序,服务端少了 ...

  4. Linux网络编程5&mdash&semi;&mdash&semi;使用UDP协议实现群聊

    引言 本文实现的功能类似于我之前所写的一篇博文(Linux之select系统调用_2),区别在于进程之间的通信方式有所不同.之前的文章中,我所使用的是管道,而本文我将会使用socket接口. 需求 客 ...

  5. Linux网络编程入门 &lpar;转载&rpar;

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  6. &lbrack;转&rsqb; - Linux网络编程 -- 网络知识介绍

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  7. 【转】Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  8. 《转》Linux网络编程入门

    原地址:http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html (一)Linux网络编程--网络知识介绍 Linux网络编程-- ...

  9. Linux网络编程学习路线

    转载自:https://blog.csdn.net/lianghe_work/article 一.网络应用层编程   1.Linux网络编程01——网络协议入门 2.Linux网络编程02——无连接和 ...

随机推荐

  1. jsp实现简单的分页

    效果如下:<%-- Document : page Created on : 2014-11-18, 8:55:02 Author : HJZ --%> <%@page conten ...

  2. linux下mysql字符集编码问题的修改

    安装完的MySQL的默认字符集为 latin1 ,为了要将其字符集改为用户所需要的(比如utf8),就必须改其相关的配置文件:由于linux下MySQL的默认安装目录分布在不同的文件下:不像windo ...

  3. c&plus;&plus;需要注意的地方和小算法

    C++11的标准 auto //可以自动类型, auto cars=//自动转化为int 强制转换 (long)thorn =long (thorn) //前者是c标准,后者是c++ 还有一种 sta ...

  4. ISO&sol;IEC 14496 文档内容简介&comma; MPEG标准

    ISO/IEC 14496是MPEG专家组制定的MPEG-4标准于1998年10月公布第1版,1999年1月成为国际标准,1999年12月公布了第2版,2000年初成为国际标准. 全文分为21个部分: ...

  5. Objective-C中的协议&lpar;Protocol&rpar;和类别&lpar;Category&rpar;

    1.什么是协议? 2.协议与类别的声明和使用 1.什么是协议? 在Objective-C中,不支持多继承,即不允许一个类有多个父类,但是OC提供了类似的实现方法,也就是协议.协议有点类似于Java里的 ...

  6. Android Studio代码自动提示无效

    不生效的原因是因为你AS设置成了省电模式,设置成省电模式了的话,AS会禁掉一些辅助功能,达到省电的目的.所以代码自动提示也被禁掉了. 要修改回来的话,通过File选项,然后倒数第二项:Power Sa ...

  7. 002&lowbar;关于six版本过低报cannot import name urllib&lowbar;parse的问题

    一. 参考:https://github.com/Parsely/pykafka/issues/222 [root@jyall.com tmp]#python check.py #报错如下 Trace ...

  8. PHP设计模式系列 - 适配器

    什么是适配器: 适配器设计模式只是将某个对象的接口适配为另一个对象所期望的接口. 设计情景: 假如我们原始的有一个UserInfo的类,提供用户信息的类,早起设计该类的时候,只实现了一个getUser ...

  9. &lbrack;oracle&rsqb; oracle-ibatis-整理

    ① <!-- 复用sql代码 --> <sql id="CUSTOM_CABINET_INFO.QUERY_CABINET"> <dynamic pr ...

  10. 【转】深入理解Java的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...