任务:使用java语言实现五子棋功能单机版和联机版。
目的意义:让学生通过该实验能加强对java的使用,能够将所学知识串联起来融会贯通,加强自身的逻辑能力。同时让学生在实现中认识到自己在java中有哪些方面有不足,使学生能真正熟练使用java语言。
1. 类的设计(系统设计哪些类、类的主要作用、类的主要属性成员及其意义、类的主要方法及其作用)
主类T,主方法,T类不处理其他逻辑,只负责执行布局类的方法
窗口类FrameWithNullLayout,继承自JFrame,除了负责将布局显示在窗口上,五子棋的大部分逻辑处理都在这个类里面
其成员包括:
LocationManager[][] locationArr
LocationManager temp//棋盘管理类对象数组及其临时对象
String model="offline";//联机状态
String ip="106.53.107.158";//联机服务器IP
int port=23333;//联机服务器端口
String linkID;//联机暗号
char serverChessColor='n';//联机棋子颜色
boolean waitForServer=true;//等待服务器的状态
SocketHelper socketHelper;//Socket帮助类对象
RoomMessage tempMessage;//房间信息对象
ChessPad chessPad;//棋盘布局对象
MyButton myButton;//状态栏布局对象
BottomBar bottomBar;//底部联机栏布局对象
boolean _WhiteChess=true;//黑棋先手
String state=COMMAND_NONE;//棋盘状态
MouseListener listen=new MouseListener()//鼠标监听
其主要方法包括:
public String getChessColor()//获取当前棋子颜色
public String getLastChess()//获取上一个棋子颜色
public String getServerChessColor()//获取服务器棋子颜色
public void display()//显示棋盘并进行初始化
private void initStateView()//获取各个子布局中的对象
public void reLoad()//重置棋盘
public void back()//悔棋
private void reDraw()//重新绘制棋子
LocationManager[][] initLocateArray(LocationManager[][] a)//初始化棋盘对象数组
private void initButton()//初始化窗口中的按钮
LocationManager类,棋子管理类,用于棋子位置的管理与信息的存储
主要成员:
int x;//棋子在屏幕上的横坐标
int y;//纵坐标
int cX;//棋盘点坐标(横)
int cY;//纵坐标
char chess;//棋子属性:n(无棋子)w(白棋)b(黑棋)
主要方法:
public void setX(int x) {//设置像素坐标
public void setY(int y) {
public void setcX(int cX) {//设置点坐标
public void setcY(int cY) {
public void setChess(char chess) {//设置棋子颜色
public int getX() {//获取像素坐标
public int getY() {
public int getcX() {//获取点坐标
public int getcY() {
public char getChess() {//获取棋子颜色
ScoreManager类,这个类用来判断是否五子连棋
主要成员:
int x;//点坐标
int y;
LocationManager[][] chessArr;//棋盘对象数组(棋盘)
主要方法
public boolean ScoreCheck(int x,int y,LocationManager[][] chessArr){//判断是否五子连棋
private int checkX(){//横向判断
private int checkY(){//纵向判断
private int checkL(){//左斜向判断
private int checkR(){//右斜向判断
SocketHelper类,这个类用来连接、断开服务端,创建对象流并发送RoomMessage的对象
成员变量:
String ip;//服务器IP(远程主机,需启动服务端)
int port;//远程主机服务端的端口
Socket socket=null;//socket对象
DataOutputStream outputStream=null;//数据输出流
ObjectOutputStream objectOutputStream=null;//对象输出流
DataInputStream inputStream=null;//数据输入流
ObjectInputStream objectInputStream=null;//数据输出流
主要方法:
SocketHelper(String ip,int port){//构造方法
public boolean socketStart(RoomMessage message){//连接到服务器并创建对象流
public boolean sendMessage(RoomMessage message){//向服务器发送信息
public Boolean close(RoomMessage message){//断开与服务器的连接并关闭所有流
RoomMessage类,主要用于存储与服务器交流所需的的信息
主要成员:
String head;//请求头
String linkID;//暗号
String message;//对话框信息
String command;//指令
LocationManager temp;//棋子的临时对象
主要方法
RoomMessage(String linkID,String head,String message,LocationManager temp){//构造方法
RoomMessage(String linkID,String head,String message,String command){//构造方法
public String getLinkID() {//获取暗号
public String getHead() {//获取请求头
public String getMessage() {//获取对话框信息
public String getCommand() {//获取指令
public LocationManager getTemp() {//获取棋子临时对象
public void setLinkID(String linkID) {//设置暗号
public void setHead(String head) {//设置请求头
public void setMessage(String message) {//设置对话框信息
public void setCommand(String command) {//设置指令
public void setTemp(LocationManager temp) {//赋值给棋子临时对象
MyButton类,状态栏布局,主要包含控制状态需要的按钮,在后期还加上了聊天框功能,可以相互发送信息
主要成员:
JButton button1;//开始按钮
JButton button2;//认输按钮
JButton button3;//重置按钮
JButton button4;//悔棋按钮
JButton button5;//发送信息按钮
JTextArea jt;//聊天框区域
JScrollPane jScrollPane;//滚动布局
JTextField jTextField;//聊天信息输入框
主要方法
MyButton(){//构造方法
ChessPad类,棋盘类,用于绘制棋盘,也可以绘制棋子
主要方法:
ChessPad(){//构造方法
protected void paintComponent(Graphics g) {//重写父类方法,用于绘制棋盘
public void paintChess(int x,int y,boolean colorWhite){//通过输入的参数绘制棋子
BottomBar类,底部联机栏类,主要用于让用户输入联机暗号开始联机,同时也具备了提示用户当前棋手棋子颜色的功能
主要成员:
JLabel tv_tips;//输入暗号提示
JLabel chessColor;//联机棋子颜色提示
JButton bt1;//开始联机按钮
JButton bt2;//备用按钮
JTextField jtf;//联机暗号输入框
主要方法
BottomBar(){//构造方法
以下为服务端独占类:(非独占类有LocationManager和RoomMessage)
服务端的主类为T,T类只负责启动服务端
Server类,服务端独占类,主要用于与客户端建立连接并通过暗号和连接顺序将各个客户端分配到相应的房间(房间共10个,可自行设置)
主要成员:
int port=23333;//服务器端口信息
Room[][] rooms=new Room[10][2];//房间对象数组(10个房间,每个房间上限2人)
ServerSocket serverSocket=null;//服务器socket
ExecutorService executorService=null;//线程池
Class ServerThread//服务器线程类(类中类)
Room room;//临时房间对象
Socket socket;//客户端socket
DataInputStream inputStream;//数据输出流
ObjectInputStream objectInputStream;//对象输出流
主要方法
Server(){//构造方法
Room[][] initRooms(Room[][] rooms){//初始化房间数据
Class ServerThread//服务器线程类(类中类)的主要方法:
ServerThread(Socket socket){//构造方法,获取客户端信息并分配到合适的房间,完成后开启线程
public void run() {//线程开始,线程的主要作用是客户端持续接受和发送信息
public void sendMessage(RoomMessage message) throws IOException {//向同一房间的客户端发送信息
Room类,房间类,这个类主要用于存储和处理客户端在的信息,在使用对象数组后可形成房间组,方便服务器处理和发送玩家信息
主要成员:
Socket socket;//客户端Socket
String linkID;//房间的暗号
DataOutputStream dataOutputStream;//数据输出流
ObjectOutputStream objectOutputStream;//对象输出流
boolean used;//房间是否被使用
int roomNum;//房间号
int num;//玩家号
主要方法:
Room(){//构造方法
public void close() throws IOException {//关闭房间(原理是清空成员信息并关闭socket)
public void setStream(DataOutputStream outputStream) throws IOException {//获取并存储对象输出流
public ObjectOutputStream getStream(){//获取对象输出流
public Socket getSocket() {//获取客户端socket
public String getLinkID() {//获取暗号
public boolean getUsed(){//检查房间是否被使用
public int getNum() {//获取玩家号
public int getRoomNum() {//获取房间号
public void setLinkID(String linkID) {//设置暗号
public void setSocket(Socket socket) {//设置客户端socket
public void setUsed(boolean used) {//设置房间是否被使用
public void setNum(int num) {//设置玩家号
public void setRoomNum(int roomNum) {//设置房间号
2. 算法描述-用程序流程图或伪代码来描述重要的算法实现过程,如:如何判断五子连棋
import javax.swing.*;
/**
* 裁判类
*/
public class ScoreManager {
int x;//点坐标
int y;
LocationManager[][] chessArr;//棋盘
//判断是否五子连棋
public boolean ScoreCheck(int x,int y,LocationManager[][] chessArr){
this.x=x;
this.y=y;
this.chessArr=chessArr;
int score=0;
if (score<checkX()){score=checkX();}
if (score<checkY()){score=checkY();}
if (score<checkL()){score=checkL();}
if (score<checkR()){score=checkR();}//找出棋子四方的相邻同色棋子数的最大值
if (score>=4)//如果棋子相邻同色棋子有大于四的返回true
{
return true;
}else
return false;
}
//横向判断
private int checkX(){
int score=0;
int left = 1;
int right = 1;
while(true){
if (x-left==-1){break;}//左边界判断
if (chessArr[x-left][y].getChess()==chessArr[x][y].getChess()){
score+=1;//该棋子的左边的棋子与其同色则score加一
left++;//继续向左探寻
}else break;//如果左边出现不同色或没有棋子就跳出循环
}
while(true){
if (x+right==15){break;}//右边界判断
if (chessArr[x+right][y].getChess()==chessArr[x][y].getChess()){
score+=1;//该棋子的右边的棋子与其同色则score加一
right++;//继续向右探寻
}else break;//如果右边出现不同色或没有棋子就跳出循环
}
return score;//返回该棋子左右相邻同色的棋子数
}
//纵向判断
private int checkY(){
int score=0;
int up = 1;
int down = 1;
while(true){
if (y-down==-1){break;}//下边界判断
if (chessArr[x][y-down].getChess()==chessArr[x][y].getChess()){
score+=1;//该棋子的下边的棋子与其同色则score加一
down++;//继续向下探寻
}else break;//如果下边出现不同色或没有棋子就跳出循环
}
while(true){
if (y+up==15){break;}//上边界判断
if (chessArr[x][y+up].getChess()==chessArr[x][y].getChess()){
score+=1;//该棋子的上边的棋子与其同色则score加一
up++;//继续向上探寻
}else break;//如果上边出现不同色或没有棋子就跳出循环
}
return score;//返回该棋子上下相邻同色的棋子数
}
//左斜向判断
private int checkL(){
int score=0;
int up = 1;
int down = 1;
while(true){
if (x+down==15){break;}
if (y-down==-1){break;}//边界判断
if (chessArr[x+down][y-down].getChess()==chessArr[x][y].getChess()){
score+=1;//该棋子的斜右下边的棋子与其同色则score加一
down++;//继续向斜右下探寻
}else break;//如果斜右下边出现不同色或没有棋子就跳出循环
}
while(true){
if (x-up==-1){break;}
if (y+up==15){break;}//边界判断
if (chessArr[x-up][y+up].getChess()==chessArr[x][y].getChess()){
score+=1;//该棋子的斜左上边的棋子与其同色则score加一
up++;//继续斜向左上探寻
}else break;//如果斜左上边出现不同色或没有棋子就跳出循环
}
return score;//返回该棋子左斜边相邻同色的棋子数
}
//右斜向判断
private int checkR(){
int score=0;
int up = 1;
int down = 1;
while(true){
if (x-down==-1){break;}
if (y-down==-1){break;}//边界判断
if (chessArr[x-down][y-down].getChess()==chessArr[x][y].getChess()){
score+=1;//该棋子的斜左下边的棋子与其同色则score加一
down++;//继续向斜左下探寻
}else break;//如果斜左下边出现不同色或没有棋子就跳出循环
}
while(true){
if (x+up==15){break;}
if (y+up==15){break;}
if (chessArr[x+up][y+up].getChess()==chessArr[x][y].getChess()){
score+=1;//该棋子的斜右上边的棋子与其同色则score加一
up++;//继续向斜右上探寻
}else break;//如果右上边出现不同色或没有棋子就跳出循环
}
return score;
}
}
3. 源代码(要有良好的编程风格,有必要的注释)
T类
package TT;
public class T {
public static void main(String[] args) {
new FrameWithNullLayout().display();
}
}