本文实例为大家分享了Android实现中国象棋游戏的具体代码,供大家参考,具体内容如下
实现环境: android studio 3.2.1, 手机分辨率为: 1920 * 1080
局域网 UDP 连接
分主活动类,棋类,主机类
代码如下:
清单文件要添加的权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
主活动:
package chinachess; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView tvMyIp; private EditText editIp; private EditText editReceiverPort; private EditText editSendrPort; private Button btnConn; private TextView tvTitle; private TextView tvTitle2; private TextView tvTitle3; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { tvMyIp = (TextView) findViewById(R.id.tvMyIp); editIp = (EditText) findViewById(R.id.editIp); editReceiverPort = (EditText) findViewById(R.id.editReceiverPort); editSendrPort = (EditText) findViewById(R.id.editSendrPort); btnConn = (Button) findViewById(R.id.btnConn); btnConn.setOnClickListener(this); tvTitle = (TextView) findViewById(R.id.tvTitle); tvTitle2 = (TextView) findViewById(R.id.tvTitle2); tvTitle3 = (TextView) findViewById(R.id.tvTitle3); getIp(); } // 将用于连接的控件隐藏掉 public void uiGone() { tvMyIp.setVisibility(View.GONE); editIp.setVisibility(View.GONE); editReceiverPort.setVisibility(View.GONE); editSendrPort.setVisibility(View.GONE); btnConn.setVisibility(View.GONE); btnConn.setVisibility(View.GONE); tvTitle.setVisibility(View.GONE); tvTitle2.setVisibility(View.GONE); tvTitle3.setVisibility(View.GONE); } // 获取局域网 ip 的方法 private void getIp() { String s; try { for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { NetworkInterface face = en.nextElement(); for (Enumeration<InetAddress> enAddr = face.getInetAddresses(); enAddr.hasMoreElements(); ){ InetAddress addr = enAddr.nextElement(); if (!addr.isLoopbackAddress()) { s = addr.getHostAddress(); // 只获取区域网 ip 地址 if ("192".equals(s.substring(0, 3))) { tvMyIp.setText("IP: " + s); } } } } } catch (SocketException e) { e.printStackTrace(); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnConn: submit(); break; } } private void submit() { // validate String ip = editIp.getText().toString().trim(); if (TextUtils.isEmpty(ip)) { Toast.makeText(this, "IP不可为空!", Toast.LENGTH_SHORT).show(); return; } String receiverPort = editReceiverPort.getText().toString().trim(); if (TextUtils.isEmpty(receiverPort)) { Toast.makeText(this, "接收端口不可为空!", Toast.LENGTH_SHORT).show(); return; } String sendPort = editSendrPort.getText().toString().trim(); if (TextUtils.isEmpty(sendPort)) { Toast.makeText(this, "发送端口不可为空!", Toast.LENGTH_SHORT).show(); return; } // TODO validate success, do something // 开启服务器或客户端,并添加到主活动中 ServerView server = new ServerView(this, Integer.valueOf(receiverPort), Integer.valueOf(sendPort), ip); ViewGroup.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); addContentView(server, params); server.startServer(); } }
布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp" tools:context=".MainActivity"> <TextView android:id="@+id/tvTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="UDP" android:textColor="#000" android:textSize="22dp" /> <TextView android:id="@+id/tvMyIp" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="IP" android:textColor="#000" android:textSize="18sp" /> <EditText android:id="@+id/editIp" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="IP" android:text="192.168." android:textColor="#000" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center"> <TextView android:id="@+id/tvTitle2" android:textSize="18sp" android:textColor="#000" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="接收端口: " /> <EditText android:id="@+id/editReceiverPort" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:hint="IP" android:inputType="number" android:text="10001" android:textColor="#000" /> <TextView android:id="@+id/tvTitle3" android:textSize="18sp" android:textColor="#000" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送端口: " /> <EditText android:id="@+id/editSendrPort" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:hint="IP" android:inputType="number" android:text="10000" android:textColor="#000" /> </LinearLayout> <Button android:id="@+id/btnConn" android:textSize="18sp" android:textStyle="bold" android:textColor="#FFF5C3" android:text="连接" android:background="@drawable/btn_blue" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
btn_blue.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="5dp" /> <gradient android:startColor="#0000a1" android:centerColor="#1f6ed4" android:angle="315" android:endColor="#39BAE8" /> </shape>
棋类:
package chinachess; public class Chess { // 标记当前棋的颜色是红棋还是黑棋 public static final int BLACK = 1; public static final int RED = 2; // 存储当前棋子是红棋还是黑棋 private int player; // 当前棋子的名字 private String name; // 图片 id private int imageId; // 图片编号 // 0-15 红色,16-31 黑色 // 0-帅 // 1,2-士 // 3,4-相 // 5,6-马 // 7,8-车 // 9,10-炮 // 11-15-卒 // 16-黑帅 // ... private int num; // 当前棋在棋盘中的位置,posX 为行,posY 为列 private int posX, posY; public Chess(int player, String name, int num) { this.player = player; this.name = name; this.num = num; // 红旗的图片 id int[] redId = {R.drawable.shuai, R.drawable.shi, R.drawable.xiang, R.drawable.ma, R.drawable.che, R.drawable.pao, R.drawable.bing}; // 黑旗的图片 id int[] blackId = {R.drawable.shuai1, R.drawable.shi1, R.drawable.xiang1, R.drawable.ma1, R.drawable.che1, R.drawable.pao1, R.drawable.bing1}; // 所有的棋的种类 String[] names = {"帅", "士", "相", "马", "车", "炮", "卒"}; // 根据当前棋的颜色来匹配不同的图片 if (player == RED) { for (int i = 0; i < names.length; i++) { if (names[i].equals(name)) { imageId = redId[i]; break; } } } else { for (int i = 0; i < names.length; i++) { if (names[i].equals(name)) { imageId = blackId[i]; break; } } } } // 获取棋编号 public int getNum() { return num; } // 获取棋的颜色 public int getPlayer() { return player; } // 获取棋名 public String getName() { return name; } // 获取棋的图片id public int getImageId() { return imageId; } // 设置棋的行列坐标 public void setPos(int posX, int posY) { this.posX = posX; this.posY = posY; } // 设置棋的航坐标 public int getPosX() { return posX; } // 设置棋的列坐标 public int getPosY() { return posY; } // 将当前的棋坐标水平翻转 public void reverse() { posX = 9 - posX; } }
主机类:
package chinachess; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import chinachess.Chess; import chinachess.MainActivity; import com.example.l_b.chinachess.R; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class ServerView extends View { // private static final String TAG = "qaq"; // 棋的颜色 public static final int BLACK = 1; public static final int RED = 2; // 设置棋盘的位置,视情况而定 public static final int MARGINTOP = 150; public static final int MARGINLEFT = 83; // 每个格子的宽度 public static final int W = 114; // 棋的总数 public static final int ALLCHESS = 32; // 棋盘的行 public static final int ROW = 10; // 棋盘的列 public static final int COL = 9; // 没有棋的棋盘坐标的标记 public static final int NULL = -1; // 接受消息端口 private int receiverPort; // 发送消息端口 private int sendPort; // 对方 ip private String ip; // 主活动 private MainActivity context; // 所有的棋 private Chess[] allChess = new Chess[ALLCHESS]; // 棋盘 private int[][] map = new int[ROW][COL]; // 当前是否可以点击 private boolean canPlay; // 判断是否移动了,只可处理点击事件 private boolean isMove; // 设置我方的棋的颜色 private int player; // 记录第一次选择的棋 private Chess firstSelect; // 用于提示消息 private TextView tvTip; // 判断当前是否赢了 private boolean isWin; private Button btnNewGame; // 通过构造方法将一些重要参数传入进来 public ServerView(Context context, int receiverPort, int sendPort, String ip) { super(context); this.receiverPort = receiverPort; this.sendPort = sendPort; this.ip = ip; this.context = (MainActivity) context; // 添加一个可以重新开始的按钮 ViewGroup.LayoutParams param = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 120); btnNewGame = new Button(context); // 开始游戏后才可以点击 btnNewGame。setEnabled(false); btnNewGame.setX(10); btnNewGame.setY(10); btnNewGame.setBackgroundResource(R.drawable.btn_blue); btnNewGame.setText("重新开始"); btnNewGame.setTextColor(Color.WHITE); btnNewGame.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 重新开始游戏 restartGame(); sendMes("restart|"); } }); this.context.addContentView(btnNewGame, param); // 添加用于提示的文本框 tvTip = new TextView(context); tvTip.setX(300); tvTip.setY(10); this.context.addContentView(tvTip, param); // 初始化棋盘 initMapAndChess(); // 设置触屏事件 setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // 若当前不可以点击则不执行点击事件 if (!canPlay) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isMove = false; break; case MotionEvent.ACTION_MOVE: // 若有滑动事件则会执行 isMove = true; break; case MotionEvent.ACTION_UP: if (!isMove) { // 获取点击的 x 坐标 int x = ((int) event.getX() - MARGINLEFT); // 获取点击的 y 坐标 int y = ((int) event.getY() - MARGINTOP - MARGINLEFT); // 转化为棋盘的 col 列坐标 // x % W > W / 2 ? 1 : 0 为当前的位置的求模后是否满足大于一半的宽度, // 若大于则把它安排到下一个位置,否则不变 x = x / W + (x % W > W / 2 ? 1 : 0); // 转化为棋盘的 row 行坐标 y = y / W + (y % W > W / 2 ? 1 : 0); // 若超出棋盘边界则不执行 if (x < 0 || x >= COL || y < 0 || y >= ROW) { break; } // 如果为第一次点击 if (firstSelect == null) { // 若当前点击的位置是空的 if (map[y][x] == NULL) { break; } // 创建一个临时变量来存储当前位置上的棋 Chess temp = allChess[map[y][x]]; // 若点击的是对方的棋 if (temp.getPlayer() != player) { break; } // 存起来 firstSelect = temp; // 更新视图 invalidate(); } else { // 已选择第一个棋后 // 若当前位置为空棋时 if (map[y][x] == NULL) { // 若能移动 if (canMove(y, x)) { // 获取第一次选择的棋的编号, 范围为 0,1,2,3...31; int pos = map[firstSelect.getPosX()][firstSelect.getPosY()]; // 将第一次选择的棋编号给第二次选择的位置 map[y][x] = pos; // 将第一次选择的棋编号置空 map[firstSelect.getPosX()][firstSelect.getPosY()] = NULL; // 将第一次选择的棋的位置改变为当前位置 firstSelect.setPos(y, x); // 轮到对方下 canPlay = false; // 将存储的第一个棋置空 firstSelect = null; // 发送我方移动信息给客户单,“|” 为分隔符,用于分割信息, // 最后要用 "|" 结尾,不然最后一个信息个出错 sendMes("move|" + pos + "|" + y + "|" + x + "|"); // 设置提示消息 tvTip.setText("对方下"); // 更新视图 invalidate(); } } else { // 若当前的位置不为空棋 // 获取当前的棋编号 int pos = map[y][x]; // 若当前的棋为我方棋时,则把第一次选择的棋替换为当前棋 if (allChess[pos].getPlayer() == player) { firstSelect = allChess[pos]; invalidate(); } else { // 是否可以移动 if (canMove(y, x)) { // 将第一次选择的棋编号置空 map[firstSelect.getPosX()][firstSelect.getPosY()] = NULL; // 将第一次选择的棋编号给第二次选择的位置 map[y][x] = firstSelect.getNum(); // 将第一次选择的棋的位置改变为当前位置 firstSelect.setPos(y, x); // 发送我方移动信息给客户单 sendMes("move|" + firstSelect.getNum() + "|" + y + "|" + x + "|"); // 若当前吃掉的棋为帅时 if ("帅".equals(allChess[pos].getName())) { sendMes("winner|"); tvTip.setText("我方获胜"); } else { tvTip.setText("对方下"); } // 将存储的第一个棋置空 firstSelect = null; // 将吃掉得棋置空 allChess[pos] = null; // 轮到对方下 canPlay = false; invalidate(); } } } } } } return true; } }); } // 判断是否可以移动 private boolean canMove(int r2, int c2) { // 要移动的棋名 String name = firstSelect.getName(); // 存储第一次的行坐标 int r1 = firstSelect.getPosX(); // 存储第一次的列坐标 int c1 = firstSelect.getPosY(); if ("帅".equals(name)) { // 只能直线移动 if (r1 != r2 && c1 != c2) { return false; } // 判断是否可以将军 if (map[r2][c2] != NULL && "帅".equals(allChess[map[r2][c2]].getName())) { // 保持 r1 一定小于 r2 // c1 一定等于 c2 if (r1 > r2) { int t = r1; r1 = r2; r2 = t; } // 标记两个帅之间是否有棋子,若有,则不可以移动 boolean flag = true; for (int i = r1 + 1; i < r2 && flag; i++) { if (map[i][c1] != NULL) { flag = false; } } return flag; // 只可移动一格 } else if (Math.abs(c1 - c2) != 1 && Math.abs(r2 - r1) != 1) { return false; } // 只可在田字中移动 return r2 >= 7 && c2 >= 3 && c2 <= 5; } else if ("士".equals(name)) { // 不能直线移动 if (r1 == r2 || c1 == c2) { return false; } // 只能移动一格 if (Math.abs(r1 - r2) != 1 || Math.abs(c1 - c2) != 1) { return false; } // 只可在田字中移动 return r2 >= 7 && c2 >= 3 && c2 <= 5; } else if ("相".equals(name)) { // 不可以过河,越界 if (r2 <= 4) { return false; } // 只能走田字 if (Math.abs(r1 - r2) != 2 || Math.abs(c1 - c2) != 2) { return false; } // 是否被挡住了 return map[(r1 + r2) / 2][(c1 + c2) / 2] == NULL; } else if ("马".equals(name)) { // 只能走 日 字 if (Math.abs(r1 - r2) * Math.abs(r1 - r2) + Math.abs(c1 - c2) * Math.abs(c1 - c2) != 5) { return false; } // 向下走时 if (r2 - r1 == 2) { // 是否被挡住了 if (map[r1 + 1][c1] != NULL) { return false; } // 向上走时 } else if (r2 - r1 == -2) { if (map[r1 - 1][c1] != NULL) { return false; } // 向左走时 } else if (c2 - c1 == 2) { if (map[r1][c1 + 1] != NULL) { return false; } // 向右走时 } else if (c2 - c1 == -2) { if (map[r1][c1 - 1] != NULL) { return false; } } } else if ("车".equals(name)) { // 只能直线移动 if (r2 != r1 && c2 != c1) { return false; } // 一个临时变量 int t; // 左右走 if (r2 == r1) { // 确保 c1 一定 小于 c2 if (c1 > c2) { t = c1; c1 = c2; c2 = t; } // 之间是否被挡住了 for (int i = c1 + 1; i < c2; i++) { if (map[r1][i] != NULL) { return false; } } } else { // 上下走 // 确保 r1 一定 小于 r2 if (r1 > r2) { t = r1; r1 = r2; r2 = t; } for (int i = r1 + 1; i < r2; i++) { if (map[i][c1] != NULL) { return false; } } } } else if ("炮".equals(name)) { // 只能走直线 if (r1 != r2 && c1 != c2) { return false; } int t; // 平常走时,跟车一样 if (map[r2][c2] == NULL) { if (r2 == r1) { // 确保 c1 一定在 c2 的上面 if (c1 > c2) { t = c1; c1 = c2; c2 = t; } for (int i = c1 + 1; i < c2; i++) { if (map[r1][i] != NULL) { return false; } } } else { if (r1 > r2) { t = r1; r1 = r2; r2 = t; } for (int i = r1 + 1; i < r2; i++) { if (map[i][c1] != NULL) { return false; } } } // 可以吃子时 } else { // 用于记录之间有几个棋子,只能为一 int count = 0; if (r2 == r1) { // 确保 c1 一定在 c2 的上面 if (c1 > c2) { t = c1; c1 = c2; c2 = t; } for (int i = c1 + 1; i < c2; i++) { if (map[r1][i] != NULL) { count++; if (count > 1) { return false; } } } } else { if (r1 > r2) { t = r1; r1 = r2; r2 = t; } for (int i = r1 + 1; i < r2; i++) { if (map[i][c1] != NULL) { count++; if (count > 1) { return false; } } } } if (count != 1) { return false; } } } else if ("卒".equals(name)) { // 只能往前走 if (r2 > r1) { return false; } // 若过河了 if (r1 <= 4) { // 只能走直线 if (r2 != r1 && c2 != c1) { return false; } // 只能走一格 if (Math.abs(c1 - c2) != 1 && r1 - r2 != 1) { return false; } } else { // 若没有过河,则只能前走一格 if (c2 != c1 || r1 - r2 != 1) { return false; } } } return true; } private void initMapAndChess() { // 将编号全置空 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { map[i][j] = NULL; } } // 将,两士,两相,两马,两车,两炮,五卒 // 32 个棋子在地图上的 x 坐标,红棋先 // 前16个棋的 x 坐标 int[] mapX = {4, 3, 5, 2, 6, 1, 7, 0, 8, 1, 7, 0, 2, 4, 6, 8}; // 前16个棋的 y 坐标 int[] mapY = {0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 3, 3, 3}; // 前16个棋的棋名 String[] strings = {"帅", "士", "士", "相", "相", "马", "马", "车", "车", "炮", "炮", "卒", "卒", "卒", "卒", "卒"}; // 临时存储行和列 int row, col; for (int i = 0; i < allChess.length; i++) { // 小于16为红旗 if (i < 16) { row = mapY[i]; col = mapX[i]; // 初始化棋子 allChess[i] = new Chess(RED, strings[i], i); // 给相应的棋盘位置安排编号 map[row][col] = i; // 设置棋子在棋盘中的初始位置 allChess[i].setPos(row, col); } else { row = ROW - mapY[i - 16] - 1; col = COL - mapX[i - 16] - 1; allChess[i] = new Chess(BLACK, strings[i - 16], i); map[row][col] = i; allChess[i].setPos(row, col); } } // showChess(); } // private void showChess() { // String s; // for (int i = 0; i < ROW; i++) { // s = ""; // for (int j = 0; j < COL; j++) { // s += map[i][j] + " "; // } // Log.d(TAG, "showChess: " + s); // } // for (int i = 0; i < allChess.length; i++) { // Log.d(TAG, "showChess: " + allChess[i].getName() + "-" + allChess[i].getNum() + "-" + allChess[i].getPosX() + "-" + allChess[i].getPosY()); // } // } // 翻转棋盘 private void reverseMap() { int t; // 默认为黑下红上 // 主机为黑下红上 // 客户端为黑上红下,所以是客户端时将双方棋的位置换一下 for (int i = 0; i < ROW / 2; i++) { for (int j = 0; j < COL; j++) { t = map[i][j]; map[i][j] = map[ROW - i - 1][j]; map[ROW - i - 1][j] = t; } } for (Chess c : allChess) { c.reverse(); } // showChess(); } public void startServer() { // 将主活动的辅助控件隐藏掉 context.uiGone(); tvTip.setText("等待连接..."); // 开启接收信息的线程 new MessageThread().start(); } public void sendMes(final String s) { // 发送信息,要在线程里执行(异步执行) new Thread(new Runnable() { @Override public void run() { DatagramSocket ds = null; try { ds = new DatagramSocket(); byte[] buffer; buffer = s.getBytes(); InetAddress ia = InetAddress.getByName(ip); DatagramPacket dp = new DatagramPacket(buffer, buffer.length, ia, sendPort); ds.send(dp); } catch (IOException e) { e.printStackTrace(); } finally { if (ds != null) { ds.close(); } } } }).start(); } // 每次调用 invalidate 就会执行这个方法 @Override protected void onDraw(Canvas canvas) { // 画笔,用于设置线条样式 Paint paint = new Paint(); paint.setStrokeWidth(5); paint.setStyle(Paint.Style.STROKE); // 设置棋盘图片,宽高视手机分辨率而定 canvas.drawBitmap(getBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bg), 1080, 1195), 0, MARGINTOP, paint); // 画棋 for (Chess allChes : allChess) { // 若没有被吃掉 if (allChes != null) { // x 坐标为列坐标乘以格子的宽度然后减去一半的格子宽度,让棋子的中心对齐坐标顶点 int x = allChes.getPosY() * W + MARGINLEFT - W / 2; int y = allChes.getPosX() * W + MARGINTOP + MARGINLEFT - W / 2; canvas.drawBitmap(getBitmap(BitmapFactory.decodeResource(getResources(), allChes.getImageId()), W, W), x, y, paint); } } // 若第一次选择了则画一个矩阵边框来显示已选中 if (firstSelect != null) { paint.setColor(Color.RED); int x = firstSelect.getPosY() * W + MARGINLEFT - W / 2; int y = firstSelect.getPosX() * W + MARGINTOP + MARGINLEFT - W / 2; // 画线 int[] posX = {x, x + W, x + W, x, x}; int[] posY = {y, y, y + W, y + W, y}; Path path = new Path(); path.moveTo(posX[0], posY[0]); for (int i = 1; i < posX.length; i++) { path.lineTo(posX[i], posY[i]); } canvas.drawPath(path, paint); } } // 自定义图片宽高 private Bitmap getBitmap(Bitmap rootImg, int w, int h) { int rW = rootImg.getWidth(); int rH = rootImg.getHeight(); Matrix matrix = new Matrix(); matrix.postScale(w * 1.0f / rW, h * 1.0f / rH); return Bitmap.createBitmap(rootImg, 0, 0, rW, rH, matrix, true); } // 重新开始游戏 private void restartGame() { // 重新初始化棋盘 initMapAndChess(); // 若是黑棋则先下 canPlay = true; String tip = "已重新开始游戏,我下"; if (player == RED) { reverseMap(); canPlay = false; tip = "已重新开始游戏,对方下"; } isWin = false; // 给提示,在线程中更新 UI 时需转到主线程上 setTip(tip); // 刷新视图 updateOnUI(); } // 接受信息的线程 class MessageThread extends Thread { @Override public void run() { try { DatagramSocket ds = new DatagramSocket(receiverPort); byte[] buffer = new byte[100]; DatagramPacket dp = new DatagramPacket(buffer, buffer.length); // 发送加入信息 sendMes("join|"); while (true) { ds.receive(dp); String s = new String(buffer); // 指定分割符分割信息 String[] array = s.split("\\|"); switch (array[0]) { // 只有主机才会接收到 case "join": player = BLACK; canPlay = true; sendMes("conn|"); setTip("我是黑棋,我下"); context.runOnUiThread(new Runnable() { @Override public void run() { btnNewGame.setEnabled(true); } }); break; // 只有客户端才会接收到 case "conn": player = RED; // 要翻转棋盘 reverseMap(); updateOnUI(); canPlay = false; setTip("我是红棋,对方下"); context.runOnUiThread(new Runnable() { @Override public void run() { btnNewGame.setEnabled(true); } }); break; // 接受到了移动信息 case "move": // 判断是否赢了,若赢了则后面的不执行 if (isWin) { continue; } // 对方走的棋编号 int originalPos = Integer.valueOf(array[1]); // 要走的行坐标 int y2 = ROW - Integer.valueOf(array[2]) - 1; // 要走的列坐标 int x2 = Integer.valueOf(array[3]); // 我方当前的对方要走的棋行列坐标 int y1 = allChess[originalPos].getPosX(); int x1 = allChess[originalPos].getPosY(); // 存储要走向的坐标在棋盘的编号 int movePos = map[y2][x2]; // 将原来的位置置空 map[y1][x1] = NULL; // 要走的位置设置为对方的棋编号 map[y2][x2] = originalPos; // 更新其坐标 allChess[originalPos].setPos(y2, x2); // 判断要走的位置是否有棋,若有,则置空 if (movePos != NULL && allChess[movePos] != null) { allChess[movePos] = null; } // 更新视图 updateOnUI(); // 我方可以下棋 canPlay = true; setTip("我下"); break; // 对方赢了 case "winner": isWin = true; whoWin(); break; // 重新开始游戏 case "restart": restartGame(); break; } } } catch (IOException e) { e.printStackTrace(); } } } // 有赢家后 private void whoWin() { canPlay = false; setTip("对方获胜"); } // 更新视图 private void updateOnUI() { context.runOnUiThread(new Runnable() { @Override public void run() { invalidate(); } }); } // 设置提示信息 private void setTip(final String s) { context.runOnUiThread(new Runnable() { @Override public void run() { tvTip.setText(s); } }); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。