Android實現(xiàn)中國象棋游戲(局域網(wǎng)版)
本文實例為大家分享了Android實現(xiàn)中國象棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
實現(xiàn)環(huán)境: android studio 3.2.1, 手機分辨率為: 1920 * 1080
局域網(wǎng) UDP 連接
分主活動類,棋類,主機類
代碼如下:
清單文件要添加的權(quán)限:
<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);
? ? }
? ? // 獲取局域網(wǎng) 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();
? ? ? ? ? ? ? ? ? ? ? ? // 只獲取區(qū)域網(wǎng) 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, "發(fā)送端口不可為空!", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? // TODO validate success, do something
? ? ? ? // 開啟服務(wù)器或客戶端,并添加到主活動中
? ? ? ? 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="發(fā)送端口: " /> ? ? ? ? <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 = {"帥", "士", "相", "馬", "車", "炮", "卒"};
? ? ? ? // 根據(jù)當前棋的顏色來匹配不同的圖片
? ? ? ? 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;
? ? }
? ? // 設(shè)置棋的行列坐標
? ? public void setPos(int posX, int posY) {
? ? ? ? this.posX = posX;
? ? ? ? this.posY = posY;
? ? }
? ? // 設(shè)置棋的航坐標
? ? public int getPosX() {
? ? ? ? return posX;
? ? }
? ? // 設(shè)置棋的列坐標
? ? public int getPosY() {
? ? ? ? return posY;
? ? }
? ? // 將當前的棋坐標水平翻轉(zhuǎn)
? ? 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;
? ? // 設(shè)置棋盤的位置,視情況而定
? ? public static final int MARGINTOP = 150;
? ? public static final int MARGINLEFT = 83;
? ? // 每個格子的寬度
? ? public static final int W = 114;
? ? // 棋的總數(shù)
? ? 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;
? ? // 發(fā)送消息端口
? ? 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;
? ? // 設(shè)置我方的棋的顏色
? ? private int player;
? ? // 記錄第一次選擇的棋
? ? private Chess firstSelect;
? ? // 用于提示消息
? ? private TextView tvTip;
? ? // 判斷當前是否贏了
? ? private boolean isWin;
?? ?
?? ?private Button btnNewGame;
?? ?
? ? // 通過構(gòu)造方法將一些重要參數(shù)傳入進來
? ? 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();
? ? ? ? // 設(shè)置觸屏事件
? ? ? ? setOnTouchListener(new OnTouchListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean onTouch(View v, MotionEvent event) {
? ? ? ? ? ? ? ? // 若當前不可以點擊則不執(zhí)行點擊事件
? ? ? ? ? ? ? ? if (!canPlay) {
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? ? ? ? ? ? ? isMove = false;
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_MOVE:
? ? ? ? ? ? ? ? ? ? ? ? // 若有滑動事件則會執(zhí)行
? ? ? ? ? ? ? ? ? ? ? ? isMove = true;
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? ? ? ? ? ? ? if (!isMove) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 獲取點擊的 x 坐標
? ? ? ? ? ? ? ? ? ? ? ? ? ? int x = ((int) event.getX() - MARGINLEFT);
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 獲取點擊的 y 坐標
? ? ? ? ? ? ? ? ? ? ? ? ? ? int y = ((int) event.getY() - MARGINTOP - MARGINLEFT);
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 轉(zhuǎn)化為棋盤的 col 列坐標
? ? ? ? ? ? ? ? ? ? ? ? ? ? // x % W > W / 2 ? 1 : 0 為當前的位置的求模后是否滿足大于一半的寬度,
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若大于則把它安排到下一個位置,否則不變
? ? ? ? ? ? ? ? ? ? ? ? ? ? x = x / W + (x % W > W / 2 ? 1 : 0);
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 轉(zhuǎn)化為棋盤的 row 行坐標
? ? ? ? ? ? ? ? ? ? ? ? ? ? y = y / W + (y % W > W / 2 ? 1 : 0);
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若超出棋盤邊界則不執(zhí)行
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (x < 0 || x >= COL || y < 0 || y >= ROW) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 如果為第一次點擊
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (firstSelect == null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若當前點擊的位置是空的
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (map[y][x] == NULL) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 創(chuàng)建一個臨時變量來存儲當前位置上的棋
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 將第一次選擇的棋的位置改變?yōu)楫斍拔恢?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? firstSelect.setPos(y, x);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 輪到對方下
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? canPlay = false;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 將存儲的第一個棋置空
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? firstSelect = null;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 發(fā)送我方移動信息給客戶單,“|” 為分隔符,用于分割信息,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 最后要用 "|" 結(jié)尾,不然最后一個信息個出錯
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sendMes("move|" + pos + "|" + y + "|" + x + "|");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 設(shè)置提示消息
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 將第一次選擇的棋的位置改變?yōu)楫斍拔恢?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? firstSelect.setPos(y, x);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 發(fā)送我方移動信息給客戶單
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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);
? ? ? ? ? ? ? ? // 給相應(yīng)的棋盤位置安排編號
? ? ? ? ? ? ? ? map[row][col] = i;
? ? ? ? ? ? ? ? // 設(shè)置棋子在棋盤中的初始位置
? ? ? ? ? ? ? ? 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());
// ? ? ? ?}
// ? ?}
? ? // 翻轉(zhuǎn)棋盤
? ? 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) {
? ? ? ? // 發(fā)送信息,要在線程里執(zhí)行(異步執(zhí)行)
? ? ? ? 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();
? ? }
? ? // 每次調(diào)用 invalidate 就會執(zhí)行這個方法
? ? @Override
? ? protected void onDraw(Canvas canvas) {
? ? ? ? // 畫筆,用于設(shè)置線條樣式
? ? ? ? Paint paint = new Paint();
? ? ? ? paint.setStrokeWidth(5);
? ? ? ? paint.setStyle(Paint.Style.STROKE);
? ? ? ? // 設(shè)置棋盤圖片,寬高視手機分辨率而定
? ? ? ? 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 時需轉(zhuǎn)到主線程上
? ? ? ? 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);
? ? ? ? ? ? ? ? // 發(fā)送加入信息
? ? ? ? ? ? ? ? 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;
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 要翻轉(zhuǎn)棋盤
? ? ? ? ? ? ? ? ? ? ? ? ? ? reverseMap();
? ? ? ? ? ? ? ? ? ? ? ? ? ? updateOnUI();
? ? ? ? ? ? ? ? ? ? ? ? ? ? canPlay = false;
? ? ? ? ? ? ? ? ? ? ? ? ? ? setTip("我是紅棋,對方下");
? ? ? ? ? ? ? ? ? ? ? ? ? ? context.runOnUiThread(new Runnable() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? btnNewGame.setEnabled(true);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? // 接受到了移動信息
? ? ? ? ? ? ? ? ? ? ? ? case "move":
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 判斷是否贏了,若贏了則后面的不執(zhí)行
? ? ? ? ? ? ? ? ? ? ? ? ? ? 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;
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 要走的位置設(shè)置為對方的棋編號
? ? ? ? ? ? ? ? ? ? ? ? ? ? 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();
? ? ? ? ? ? }
? ? ? ? });
? ? }
?? ?// 設(shè)置提示信息
? ? private void setTip(final String s) {
? ? ? ? context.runOnUiThread(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? tvTip.setText(s);
? ? ? ? ? ? }
? ? ? ? });
? ? }
}以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android漲姿勢知識點之你沒用過的BadgeDrawable
現(xiàn)在Android中有許多的應(yīng)用仿蘋果的在應(yīng)用圖標上顯示小紅點,下面這篇文章主要給大家介紹了關(guān)于Android漲姿勢知識點之你沒用過的BadgeDrawable的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2022-09-09
android的RecyclerView實現(xiàn)拖拽排序和側(cè)滑刪除示例
在平時開發(fā)應(yīng)用的時候,經(jīng)常會遇到列表排序、滑動刪除的需求。這篇文章主要介紹了android的RecyclerView實現(xiàn)拖拽排序和側(cè)滑刪除示例,有興趣的可以了解一下。2017-02-02
Android RecyclerView添加頭部和底部實例詳解
這篇文章主要介紹了Android RecyclerView添加頭部和底部實例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06
android獲取監(jiān)聽SD Card狀態(tài)的方法
這篇文章主要介紹了android獲取監(jiān)聽SD Card狀態(tài)的方法,涉及Android實現(xiàn)SD Card監(jiān)聽的技巧,非常具有實用價值,需要的朋友可以參考下2015-04-04
Android ImageView隨手勢變化動態(tài)縮放圖片
這篇文章主要為大家詳細介紹了Android ImageView隨手勢變化動態(tài)縮放圖片的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-05-05
Android 5.0及以上編程實現(xiàn)屏幕截圖功能的方法
這篇文章主要介紹了Android 5.0及以上編程實現(xiàn)屏幕截圖功能的方法,結(jié)合實例形式分析了Android5.0以上實現(xiàn)截圖功能的相關(guān)類、函數(shù)及權(quán)限控制等操作技巧,需要的朋友可以參考下2018-01-01

