Android实现中国象棋游戏(局域网版)

作者:hellolxb 时间:2023-11-22 16:07:07 

本文实例为大家分享了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();
? ? }
}

布局:

Android实现中国象棋游戏(局域网版)

<?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);
? ? ? ? ? ? }
? ? ? ? });
? ? }
}

来源:https://blog.csdn.net/weixin_44116706/article/details/100591304

标签:Android,中国象棋
0
投稿

猜你喜欢

  • Spring实战之SpEl语法实例详解

    2023-09-18 07:56:03
  • C#检查字符串是否是合法URL地址的方法

    2022-08-09 16:24:06
  • c# 组合模式

    2022-07-07 09:04:09
  • C#获取指定PDF文件页数的方法

    2021-10-10 17:15:43
  • Java判断两个日期相差天数的方法

    2021-11-29 05:55:07
  • Android 悬浮按钮之实现兔兔按钮示例

    2022-04-09 13:12:23
  • Java字符串的intern方法有何奥妙之处

    2022-07-21 13:38:16
  • C#下实现创建和删除目录的实例代码

    2021-10-21 16:04:31
  • 教你怎么用Java回溯算法解数独

    2021-12-14 02:27:18
  • android编程实现sd卡读取数据库的方法

    2021-10-03 12:26:31
  • 基于C#调用c++Dll结构体数组指针的问题详解

    2021-12-10 23:16:41
  • C#操作注册表之Registry类

    2023-02-24 00:23:33
  • C# 运用params修饰符来实现变长参数传递的方法

    2023-07-21 22:27:55
  • Java中用enum结合testng实现数据驱动的方法示例

    2021-08-04 07:44:21
  • java获取json中的全部键值对实例

    2023-08-23 19:53:03
  • 深入理解C++中public、protected及private用法

    2023-07-02 11:30:17
  • java8中:: 用法示例(JDK8双冒号用法)

    2023-11-25 06:21:21
  • 一文搞懂Java中的注解和反射

    2022-04-04 20:55:31
  • 详解配置spring-boot-actuator时候遇到的一些小问题

    2022-03-17 17:04:08
  • MyBatis-Plus 集成动态多数据源的实现示例

    2023-06-26 17:56:35
  • asp之家 软件编程 m.aspxhome.com