Android實(shí)現(xiàn)中國象棋游戲(局域網(wǎng)版)
本文實(shí)例為大家分享了Android實(shí)現(xiàn)中國象棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
實(shí)現(xiàn)環(huán)境: android studio 3.2.1, 手機(jī)分辨率為: 1920 * 1080
局域網(wǎng) UDP 連接
分主活動類,棋類,主機(jī)類
代碼如下:
清單文件要添加的權(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 { ? ? // 標(biāo)記當(dāng)前棋的顏色是紅棋還是黑棋 ? ? public static final int BLACK = 1; ? ? public static final int RED = 2; ? ? // 存儲當(dāng)前棋子是紅棋還是黑棋 ? ? private int player; ? ? // 當(dāng)前棋子的名字 ? ? 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; ? ? // 當(dāng)前棋在棋盤中的位置,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ù)當(dāng)前棋的顏色來匹配不同的圖片 ? ? ? ? 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è)置棋的行列坐標(biāo) ? ? public void setPos(int posX, int posY) { ? ? ? ? this.posX = posX; ? ? ? ? this.posY = posY; ? ? } ? ? // 設(shè)置棋的航坐標(biāo) ? ? public int getPosX() { ? ? ? ? return posX; ? ? } ? ? // 設(shè)置棋的列坐標(biāo) ? ? public int getPosY() { ? ? ? ? return posY; ? ? } ? ? // 將當(dāng)前的棋坐標(biāo)水平翻轉(zhuǎn) ? ? public void reverse() { ? ? ? ? posX = 9 - posX; ? ? } }
主機(jī)類:
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; ? ? // 沒有棋的棋盤坐標(biāo)的標(biāo)記 ? ? 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]; ? ? // 當(dāng)前是否可以點(diǎn)擊 ? ? private boolean canPlay; ? ? // 判斷是否移動了,只可處理點(diǎn)擊事件 ? ? private boolean isMove; ? ? // 設(shè)置我方的棋的顏色 ? ? private int player; ? ? // 記錄第一次選擇的棋 ? ? private Chess firstSelect; ? ? // 用于提示消息 ? ? private TextView tvTip; ? ? // 判斷當(dāng)前是否贏了 ? ? private boolean isWin; ?? ? ?? ?private Button btnNewGame; ?? ? ? ? // 通過構(gòu)造方法將一些重要參數(shù)傳入進(jìn)來 ? ? 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); ? ? ? ? // 開始游戲后才可以點(diǎn)擊 ?? ??? ?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) { ? ? ? ? ? ? ? ? // 若當(dāng)前不可以點(diǎn)擊則不執(zhí)行點(diǎn)擊事件 ? ? ? ? ? ? ? ? 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) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 獲取點(diǎn)擊的 x 坐標(biāo) ? ? ? ? ? ? ? ? ? ? ? ? ? ? int x = ((int) event.getX() - MARGINLEFT); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 獲取點(diǎn)擊的 y 坐標(biāo) ? ? ? ? ? ? ? ? ? ? ? ? ? ? int y = ((int) event.getY() - MARGINTOP - MARGINLEFT); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 轉(zhuǎn)化為棋盤的 col 列坐標(biāo) ? ? ? ? ? ? ? ? ? ? ? ? ? ? // x % W > W / 2 ? 1 : 0 為當(dāng)前的位置的求模后是否滿足大于一半的寬度, ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若大于則把它安排到下一個位置,否則不變 ? ? ? ? ? ? ? ? ? ? ? ? ? ? x = x / W + (x % W > W / 2 ? 1 : 0); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 轉(zhuǎn)化為棋盤的 row 行坐標(biāo) ? ? ? ? ? ? ? ? ? ? ? ? ? ? y = y / W + (y % W > W / 2 ? 1 : 0); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若超出棋盤邊界則不執(zhí)行 ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (x < 0 || x >= COL || y < 0 || y >= ROW) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 如果為第一次點(diǎn)擊 ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (firstSelect == null) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若當(dāng)前點(diǎn)擊的位置是空的 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (map[y][x] == NULL) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 創(chuàng)建一個臨時變量來存儲當(dāng)前位置上的棋 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Chess temp = allChess[map[y][x]]; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若點(diǎn)擊的是對方的棋 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (temp.getPlayer() != player) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 存起來 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? firstSelect = temp; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 更新視圖 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? invalidate(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 已選擇第一個棋后 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若當(dāng)前位置為空棋時 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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)楫?dāng)前位置 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? firstSelect.setPos(y, x); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 輪到對方下 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? canPlay = false; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 將存儲的第一個棋置空 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? firstSelect = null; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 發(fā)送我方移動信息給客戶單,“|” 為分隔符,用于分割信息, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 最后要用 "|" 結(jié)尾,不然最后一個信息個出錯 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sendMes("move|" + pos + "|" + y + "|" + x + "|"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 設(shè)置提示消息 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tvTip.setText("對方下"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 更新視圖 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? invalidate(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若當(dāng)前的位置不為空棋 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 獲取當(dāng)前的棋編號 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int pos = map[y][x]; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若當(dāng)前的棋為我方棋時,則把第一次選擇的棋替換為當(dāng)前棋 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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)楫?dāng)前位置 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? firstSelect.setPos(y, x); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 發(fā)送我方移動信息給客戶單 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sendMes("move|" + firstSelect.getNum() + "|" + y + "|" + x + "|"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 若當(dāng)前吃掉的棋為帥時 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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(); ? ? ? ? // 存儲第一次的行坐標(biāo) ? ? ? ? int r1 = firstSelect.getPosX(); ? ? ? ? // 存儲第一次的列坐標(biāo) ? ? ? ? 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; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? // 標(biāo)記兩個帥之間是否有棋子,若有,則不可以移動 ? ? ? ? ? ? ? ? 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 坐標(biāo),紅棋先 ? ? ? ? // 前16個棋的 x 坐標(biāo) ? ? ? ? int[] mapX = {4, 3, 5, 2, 6, 1, 7, 0, 8, 1, 7, 0, 2, 4, 6, 8}; ? ? ? ? // 前16個棋的 y 坐標(biāo) ? ? ? ? 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; ? ? ? ? // 默認(rèn)為黑下紅上 ? ? ? ? // 主機(jī)為黑下紅上 ? ? ? ? // 客戶端為黑上紅下,所以是客戶端時將雙方棋的位置換一下 ? ? ? ? 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è)置棋盤圖片,寬高視手機(jī)分辨率而定 ? ? ? ? canvas.drawBitmap(getBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bg), 1080, 1195), 0, MARGINTOP, paint); ? ? ? ? // 畫棋 ? ? ? ? for (Chess allChes : allChess) { ? ? ? ? ? ? // 若沒有被吃掉 ? ? ? ? ? ? if (allChes != null) { ? ? ? ? ? ? ? ? // x 坐標(biāo)為列坐標(biāo)乘以格子的寬度然后減去一半的格子寬度,讓棋子的中心對齊坐標(biāo)頂點(diǎn) ? ? ? ? ? ? ? ? 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]) { ? ? ? ? ? ? ? ? ? ? ? ? // 只有主機(jī)才會接收到 ? ? ? ? ? ? ? ? ? ? ? ? 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]); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 要走的行坐標(biāo) ? ? ? ? ? ? ? ? ? ? ? ? ? ? int y2 = ROW - Integer.valueOf(array[2]) - 1; ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 要走的列坐標(biāo) ? ? ? ? ? ? ? ? ? ? ? ? ? ? int x2 = Integer.valueOf(array[3]); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 我方當(dāng)前的對方要走的棋行列坐標(biāo) ? ? ? ? ? ? ? ? ? ? ? ? ? ? int y1 = allChess[originalPos].getPosX(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? int x1 = allChess[originalPos].getPosY(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 存儲要走向的坐標(biāo)在棋盤的編號 ? ? ? ? ? ? ? ? ? ? ? ? ? ? int movePos = map[y2][x2]; ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 將原來的位置置空 ? ? ? ? ? ? ? ? ? ? ? ? ? ? map[y1][x1] = NULL; ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 要走的位置設(shè)置為對方的棋編號 ? ? ? ? ? ? ? ? ? ? ? ? ? ? map[y2][x2] = originalPos; ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 更新其坐標(biāo) ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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漲姿勢知識點(diǎn)之你沒用過的BadgeDrawable
現(xiàn)在Android中有許多的應(yīng)用仿蘋果的在應(yīng)用圖標(biāo)上顯示小紅點(diǎn),下面這篇文章主要給大家介紹了關(guān)于Android漲姿勢知識點(diǎn)之你沒用過的BadgeDrawable的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09android的RecyclerView實(shí)現(xiàn)拖拽排序和側(cè)滑刪除示例
在平時開發(fā)應(yīng)用的時候,經(jīng)常會遇到列表排序、滑動刪除的需求。這篇文章主要介紹了android的RecyclerView實(shí)現(xiàn)拖拽排序和側(cè)滑刪除示例,有興趣的可以了解一下。2017-02-02Android RecyclerView添加頭部和底部實(shí)例詳解
這篇文章主要介紹了Android RecyclerView添加頭部和底部實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06android獲取監(jiān)聽SD Card狀態(tài)的方法
這篇文章主要介紹了android獲取監(jiān)聽SD Card狀態(tài)的方法,涉及Android實(shí)現(xiàn)SD Card監(jiān)聽的技巧,非常具有實(shí)用價值,需要的朋友可以參考下2015-04-04Android ImageView隨手勢變化動態(tài)縮放圖片
這篇文章主要為大家詳細(xì)介紹了Android ImageView隨手勢變化動態(tài)縮放圖片的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-05-05Android 5.0及以上編程實(shí)現(xiàn)屏幕截圖功能的方法
這篇文章主要介紹了Android 5.0及以上編程實(shí)現(xiàn)屏幕截圖功能的方法,結(jié)合實(shí)例形式分析了Android5.0以上實(shí)現(xiàn)截圖功能的相關(guān)類、函數(shù)及權(quán)限控制等操作技巧,需要的朋友可以參考下2018-01-01